diff options
Diffstat (limited to 'debuginfo-tests/llgdb-tests')
-rw-r--r-- | debuginfo-tests/llgdb-tests/apple-accel.cpp | 24 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/asan-blocks.c | 41 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/asan-deque.cpp | 46 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/asan.c | 31 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/block_var.m | 32 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/blocks.m | 43 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/foreach.m | 31 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/forward-declare-class.cpp | 27 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/lit.local.cfg | 5 | ||||
-rwxr-xr-x | debuginfo-tests/llgdb-tests/llgdb.py | 162 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/nested-struct.cpp | 21 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/nrvo-string.cpp | 52 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/safestack.c | 52 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/static-member-2.cpp | 39 | ||||
-rw-r--r-- | debuginfo-tests/llgdb-tests/static-member.cpp | 36 | ||||
-rwxr-xr-x | debuginfo-tests/llgdb-tests/test_debuginfo.pl | 81 |
16 files changed, 723 insertions, 0 deletions
diff --git a/debuginfo-tests/llgdb-tests/apple-accel.cpp b/debuginfo-tests/llgdb-tests/apple-accel.cpp new file mode 100644 index 000000000000..4a73afe80113 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/apple-accel.cpp @@ -0,0 +1,24 @@ +// REQUIRES: system-darwin +// Test that clang produces the __apple accelerator tables, +// e.g., __apple_types, correctly. +// These sections are going to be retired in DWARF 5, so we hardcode +// the DWARF version in the tests. +// RUN: %clang %s %target_itanium_abi_host_triple -gdwarf-2 -O0 -c -g -o %t-ex +// RUN: llvm-objdump -section-headers %t-ex | FileCheck %s +// RUN: %clang %s %target_itanium_abi_host_triple -gdwarf-4 -O0 -c -g -o %t-ex +// RUN: llvm-objdump -section-headers %t-ex | FileCheck %s + +// A function in a different section forces the compiler to create the +// __debug_ranges section. +__attribute__((section("1,__text_foo"))) void foo() {} +int main (int argc, char const *argv[]) { return argc; } + +// CHECK: __debug_str +// CHECK-NEXT: __debug_abbrev +// CHECK-NEXT: __debug_info +// CHECK-NEXT: __debug_ranges +// CHECK-NEXT: __debug_macinfo +// CHECK-NEXT: __apple_names +// CHECK-NEXT: __apple_objc +// CHECK-NEXT: __apple_namespac +// CHECK-NEXT: __apple_types diff --git a/debuginfo-tests/llgdb-tests/asan-blocks.c b/debuginfo-tests/llgdb-tests/asan-blocks.c new file mode 100644 index 000000000000..33f44cd66590 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/asan-blocks.c @@ -0,0 +1,41 @@ +// RUN: %clang -fblocks %target_itanium_abi_host_triple -arch x86_64 %s -o %t.out -g -fsanitize=address +// RUN: %test_debuginfo %s %t.out +// FIXME: Remove system-darwin when we build BlocksRuntime everywhere. +// REQUIRES: !asan, system-darwin +// Zorg configures the ASAN stage2 bots to not build the asan +// compiler-rt. Only run this test on non-asanified configurations. +void b(); +struct S { + int a[8]; +}; + +int f(struct S s, unsigned i) { + // DEBUGGER: break 17 + // DEBUGGER: r + // DEBUGGER: p s + // CHECK: a = ([0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7) + return s.a[i]; +} + +int main(int argc, const char **argv) { + struct S s = {{0, 1, 2, 3, 4, 5, 6, 7}}; + if (f(s, 4) == 4) { + // DEBUGGER: break 27 + // DEBUGGER: c + // DEBUGGER: p s + // CHECK: a = ([0] = 0, [1] = 1, [2] = 2, [3] = 3, [4] = 4, [5] = 5, [6] = 6, [7] = 7) + b(); + } + return 0; +} + +void c() {} + +void b() { + // DEBUGGER: break 40 + // DEBUGGER: c + // DEBUGGER: p x + // CHECK: 42 + __block int x = 42; + c(); +} diff --git a/debuginfo-tests/llgdb-tests/asan-deque.cpp b/debuginfo-tests/llgdb-tests/asan-deque.cpp new file mode 100644 index 000000000000..f3f55aae0ff6 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/asan-deque.cpp @@ -0,0 +1,46 @@ +// RUN: %clangxx -arch x86_64 %target_itanium_abi_host_triple -O1 -g %s -o %t.out -fsanitize=address +// RUN: %test_debuginfo %s %t.out +// REQUIRES: !asan +// Zorg configures the ASAN stage2 bots to not build the asan +// compiler-rt. Only run this test on non-asanified configurations. +// UNSUPPORTED: apple-lldb-pre-1000 +#include <deque> + +struct A { + int a; + A(int a) : a(a) {} +}; + +using log_t = std::deque<A>; + +static void __attribute__((noinline, optnone)) escape(log_t &log) { + static volatile log_t *sink; + sink = &log; +} + +int main() { + log_t log; + log.push_back(1234); + log.push_back(56789); + escape(log); + // DEBUGGER: break 25 + while (!log.empty()) { + auto record = log.front(); + log.pop_front(); + escape(log); + // DEBUGGER: break 30 + } +} + +// DEBUGGER: r + +// (at line 25) +// DEBUGGER: p log +// CHECK: 1234 +// CHECK: 56789 + +// DEBUGGER: c + +// (at line 30) +// DEBUGGER: p log +// CHECK: 56789 diff --git a/debuginfo-tests/llgdb-tests/asan.c b/debuginfo-tests/llgdb-tests/asan.c new file mode 100644 index 000000000000..96dffb348d43 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/asan.c @@ -0,0 +1,31 @@ +// RUN: %clang -fblocks %target_itanium_abi_host_triple -arch x86_64 %s -o %t.out -g -fsanitize=address +// RUN: %test_debuginfo %s %t.out +// REQUIRES: !asan +// Zorg configures the ASAN stage2 bots to not build the asan +// compiler-rt. Only run this test on non-asanified configurations. +// + +struct S { + int a[8]; +}; + +int f(struct S s, unsigned i) { + // DEBUGGER: break 14 + return s.a[i]; +} + +int main(int argc, const char **argv) { + struct S s = {{0, 1, 2, 3, 4, 5, 6, 7}}; + if (f(s, 4) == 4) + return f(s, 0); + return 0; +} + +// DEBUGGER: r +// DEBUGGER: p s +// CHECK: a = +// DEBUGGER: p s.a[0] +// CHECK: = 0 +// DEBUGGER: p s.a[1] +// CHECK: = 1 +// DEBUGGER: p s.a[7] diff --git a/debuginfo-tests/llgdb-tests/block_var.m b/debuginfo-tests/llgdb-tests/block_var.m new file mode 100644 index 000000000000..7ec786f17987 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/block_var.m @@ -0,0 +1,32 @@ +// RUN: %clang %target_itanium_abi_host_triple -O0 -g %s -c -o %t.o +// RUN: %clang %target_itanium_abi_host_triple %t.o -o %t.out -framework Foundation +// RUN: %test_debuginfo %s %t.out + +// REQUIRES: system-darwin + +// DEBUGGER: break 24 +// DEBUGGER: r +// DEBUGGER: p result +// CHECK: ${{[0-9]}} = 42 + +void doBlock(void (^block)(void)) +{ + block(); +} + +int I(int n) +{ + __block int result; + int i = 2; + doBlock(^{ + result = n; + }); + return result + i; /* Check value of 'result' */ +} + + +int main (int argc, const char * argv[]) { + return I(42); +} + + diff --git a/debuginfo-tests/llgdb-tests/blocks.m b/debuginfo-tests/llgdb-tests/blocks.m new file mode 100644 index 000000000000..8e5a21213200 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/blocks.m @@ -0,0 +1,43 @@ +// RUN: %clang %target_itanium_abi_host_triple -O0 -g %s -c -o %t.o +// RUN: %clang %target_itanium_abi_host_triple %t.o -o %t.out -framework Foundation +// RUN: %test_debuginfo %s %t.out + +// REQUIRES: system-darwin +// Radar 9279956 + +// DEBUGGER: break 31 +// DEBUGGER: r +// DEBUGGER: p m2 +// CHECK: ${{[0-9]}} = 1 +// DEBUGGER: p dbTransaction +// CHECK: ${{[0-9]}} = 0 +// DEBUGGER: p master +// CHECK: ${{[0-9]}} = 0 + +#include <Cocoa/Cocoa.h> + +extern void foo(void(^)(void)); + +@interface A:NSObject @end +@implementation A +- (void) helper { + int master = 0; + __block int m2 = 0; + __block int dbTransaction = 0; + int (^x)(void) = ^(void) { (void) self; + (void) master; + (void) dbTransaction; + m2++; + return m2; + }; + master = x(); +} +@end + +void foo(void(^x)(void)) {} + +int main() { + A *a = [A alloc]; + [a helper]; + return 0; +} diff --git a/debuginfo-tests/llgdb-tests/foreach.m b/debuginfo-tests/llgdb-tests/foreach.m new file mode 100644 index 000000000000..2e3c312c877c --- /dev/null +++ b/debuginfo-tests/llgdb-tests/foreach.m @@ -0,0 +1,31 @@ +// RUN: %clang %target_itanium_abi_host_triple -O0 -g %s -c -o %t.o +// RUN: %clang %target_itanium_abi_host_triple %t.o -o %t.out -framework Foundation +// RUN: %test_debuginfo %s %t.out +// +// REQUIRES: system-darwin +// Radar 8757124 + +// DEBUGGER: break 25 +// DEBUGGER: r +// DEBUGGER: po thing +// CHECK: aaa + +#import <Foundation/Foundation.h> + +int main (int argc, const char * argv[]) { + + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSArray *things = [NSArray arrayWithObjects:@"one", @"two", @"three" , nil]; + for (NSString *thing in things) { + NSLog (@"%@", thing); + } + + things = [NSArray arrayWithObjects:@"aaa", @"bbb", @"ccc" , nil]; + for (NSString *thing in things) { + NSLog (@"%@", thing); + } + [pool release]; + return 0; +} + + diff --git a/debuginfo-tests/llgdb-tests/forward-declare-class.cpp b/debuginfo-tests/llgdb-tests/forward-declare-class.cpp new file mode 100644 index 000000000000..132420009bd1 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/forward-declare-class.cpp @@ -0,0 +1,27 @@ +// RUN: %clangxx %target_itanium_abi_host_triple -O0 -g %s -c -o %t.o +// RUN: %test_debuginfo %s %t.o +// Radar 9168773 + +// DEBUGGER: ptype A +// Work around a gdb bug where it believes that a class is a +// struct if there aren't any methods - even though it's tagged +// as a class. +// CHECK: type = {{struct|class}} A { +// CHECK-NEXT: {{(public:){0,1}}} +// CHECK-NEXT: int MyData; +// CHECK-NEXT: } +class A; +class B { +public: + void foo(const A *p); +}; + +B iEntry; + +class A { +public: + int MyData; +}; + +A irp; + diff --git a/debuginfo-tests/llgdb-tests/lit.local.cfg b/debuginfo-tests/llgdb-tests/lit.local.cfg new file mode 100644 index 000000000000..725aa59ab593 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/lit.local.cfg @@ -0,0 +1,5 @@ +# debuginfo-tests are not expected to pass in a cross-compilation setup. +if 'native' not in config.available_features or config.is_msvc: + config.unsupported = True + + diff --git a/debuginfo-tests/llgdb-tests/llgdb.py b/debuginfo-tests/llgdb-tests/llgdb.py new file mode 100755 index 000000000000..5f14497f628f --- /dev/null +++ b/debuginfo-tests/llgdb-tests/llgdb.py @@ -0,0 +1,162 @@ +#!/bin/env python +""" +A gdb-compatible frontend for lldb that implements just enough +commands to run the tests in the debuginfo-tests repository with lldb. +""" + +# ---------------------------------------------------------------------- +# Auto-detect lldb python module. +import commands, platform, os, sys +try: + # Just try for LLDB in case PYTHONPATH is already correctly setup. + import lldb +except ImportError: + lldb_python_dirs = list() + # lldb is not in the PYTHONPATH, try some defaults for the current platform. + platform_system = platform.system() + if platform_system == 'Darwin': + # On Darwin, try the currently selected Xcode directory + xcode_dir = commands.getoutput("xcode-select --print-path") + if xcode_dir: + lldb_python_dirs.append(os.path.realpath(xcode_dir + +'/../SharedFrameworks/LLDB.framework/Resources/Python')) + lldb_python_dirs.append(xcode_dir + +'/Library/PrivateFrameworks/LLDB.framework/Resources/Python') + lldb_python_dirs.append( +'/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python') + success = False + for lldb_python_dir in lldb_python_dirs: + if os.path.exists(lldb_python_dir): + if not (sys.path.__contains__(lldb_python_dir)): + sys.path.append(lldb_python_dir) + try: + import lldb + except ImportError: + pass + else: + print 'imported lldb from: "%s"' % (lldb_python_dir) + success = True + break + if not success: + print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly" + sys.exit(1) +# ---------------------------------------------------------------------- + +# Command line option handling. +import argparse +parser = argparse.ArgumentParser(description=__doc__) +parser.add_argument('--quiet', '-q', action="store_true", help='ignored') +parser.add_argument('-batch', action="store_true", + help='exit after processing comand line') +parser.add_argument('-n', action="store_true", help='ignore .lldb file') +parser.add_argument('-x', dest='script', type=file, help='execute commands from file') +parser.add_argument("target", help="the program to debug") +args = parser.parse_args() + + +# Create a new debugger instance. +debugger = lldb.SBDebugger.Create() +debugger.SkipLLDBInitFiles(args.n) + +# Make sure to clean up the debugger on exit. +import atexit +def on_exit(): + debugger.Terminate() +atexit.register(on_exit) + +# Don't return from lldb function calls until the process stops. +debugger.SetAsync(False) + +# Create a target from a file and arch. +arch = os.popen("file "+args.target).read().split()[-1] +target = debugger.CreateTargetWithFileAndArch(args.target, arch) + +if not target: + print "Could not create target", args.target + sys.exit(1) + +if not args.script: + print "Interactive mode is not implemented." + sys.exit(1) + +import re +for command in args.script: + # Strip newline and whitespaces and split into words. + cmd = command[:-1].strip().split() + if not cmd: + continue + + print '> %s'% command[:-1] + + try: + if re.match('^r|(run)$', cmd[0]): + error = lldb.SBError() + launchinfo = lldb.SBLaunchInfo([]) + launchinfo.SetWorkingDirectory(os.getcwd()) + process = target.Launch(launchinfo, error) + print error + if not process or error.fail: + state = process.GetState() + print "State = %d" % state + print """ +ERROR: Could not launch process. +NOTE: There are several reasons why this may happen: + * Root needs to run "DevToolsSecurity --enable". + * Older versions of lldb cannot launch more than one process simultaneously. +""" + sys.exit(1) + + elif re.match('^b|(break)$', cmd[0]) and len(cmd) == 2: + if re.match('[0-9]+', cmd[1]): + # b line + mainfile = target.FindFunctions('main')[0].compile_unit.file + print target.BreakpointCreateByLocation(mainfile, int(cmd[1])) + else: + # b file:line + file, line = cmd[1].split(':') + print target.BreakpointCreateByLocation(file, int(line)) + + elif re.match('^ptype$', cmd[0]) and len(cmd) == 2: + # GDB's ptype has multiple incarnations depending on its + # argument (global variable, function, type). The definition + # here is for looking up the signature of a function and only + # if that fails it looks for a type with that name. + # Type lookup in LLDB would be "image lookup --type". + for elem in target.FindFunctions(cmd[1]): + print elem.function.type + continue + print target.FindFirstType(cmd[1]) + + elif re.match('^po$', cmd[0]) and len(cmd) > 1: + try: + opts = lldb.SBExpressionOptions() + opts.SetFetchDynamicValue(True) + opts.SetCoerceResultToId(True) + print target.EvaluateExpression(' '.join(cmd[1:]), opts) + except: + # FIXME: This is a fallback path for the lab.llvm.org + # buildbot running OS X 10.7; it should be removed. + thread = process.GetThreadAtIndex(0) + frame = thread.GetFrameAtIndex(0) + print frame.EvaluateExpression(' '.join(cmd[1:])) + + elif re.match('^p|(print)$', cmd[0]) and len(cmd) > 1: + thread = process.GetThreadAtIndex(0) + frame = thread.GetFrameAtIndex(0) + print frame.EvaluateExpression(' '.join(cmd[1:])) + + elif re.match('^n|(next)$', cmd[0]): + thread = process.GetThreadAtIndex(0) + thread.StepOver() + + elif re.match('^q|(quit)$', cmd[0]): + sys.exit(0) + + else: + print debugger.HandleCommand(' '.join(cmd)) + + except SystemExit: + raise + except: + print 'Could not handle the command "%s"' % ' '.join(cmd) + diff --git a/debuginfo-tests/llgdb-tests/nested-struct.cpp b/debuginfo-tests/llgdb-tests/nested-struct.cpp new file mode 100644 index 000000000000..7533e6a81518 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/nested-struct.cpp @@ -0,0 +1,21 @@ +// RUN: %clangxx %target_itanium_abi_host_triple -O0 -g %s -c -o %t.o +// RUN: %test_debuginfo %s %t.o +// Radar 9440721 +// If debug info for my_number() is emitted outside function foo's scope +// then a debugger may not be able to handle it. At least one version of +// gdb crashes in such cases. + +// DEBUGGER: ptype foo +// CHECK: int (void) + +int foo() { + struct Local { + static int my_number() { + return 42; + } + }; + + int i = 0; + i = Local::my_number(); + return i + 1; +} diff --git a/debuginfo-tests/llgdb-tests/nrvo-string.cpp b/debuginfo-tests/llgdb-tests/nrvo-string.cpp new file mode 100644 index 000000000000..ba8d9d42f6f4 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/nrvo-string.cpp @@ -0,0 +1,52 @@ +// This ensures that DW_OP_deref is inserted when necessary, such as when NRVO +// of a string object occurs in C++. +// +// RUN: %clangxx -O0 -fno-exceptions %target_itanium_abi_host_triple %s -o %t.out -g +// RUN: %test_debuginfo %s %t.out +// RUN: %clangxx -O1 -fno-exceptions %target_itanium_abi_host_triple %s -o %t.out -g +// RUN: %test_debuginfo %s %t.out +// +// PR34513 +volatile int sideeffect = 0; +void __attribute__((noinline)) stop() { sideeffect++; } + +struct string { + string() {} + string(int i) : i(i) {} + ~string() {} + int i = 0; +}; +string get_string() { + string unused; + string result = 3; + // DEBUGGER: break 23 + stop(); + return result; +} +void some_function(int) {} +struct string2 { + string2() = default; + string2(string2 &&other) { i = other.i; } + int i; +}; +string2 get_string2() { + string2 result; + result.i = 5; + some_function(result.i); + // Test that the debugger can get the value of result after another + // function is called. + // DEBUGGER: break 39 + stop(); + return result; +} +int main() { + get_string(); + get_string2(); +} + +// DEBUGGER: r +// DEBUGGER: print result.i +// CHECK: = 3 +// DEBUGGER: c +// DEBUGGER: print result.i +// CHECK: = 5 diff --git a/debuginfo-tests/llgdb-tests/safestack.c b/debuginfo-tests/llgdb-tests/safestack.c new file mode 100644 index 000000000000..cf3efc75239a --- /dev/null +++ b/debuginfo-tests/llgdb-tests/safestack.c @@ -0,0 +1,52 @@ +// RUN: %clang %target_itanium_abi_host_triple -arch x86_64 %s -o %t.out -g -fsanitize=safe-stack +// RUN: %test_debuginfo %s %t.out +// UNSUPPORTED: system-darwin +// REQUIRES: !asan +// Zorg configures the ASAN stage2 bots to not build the +// safestack compiler-rt. Only run this test on +// non-asanified configurations. + +struct S { + int a[8]; +}; + +int f(struct S s, unsigned i); + +int main(int argc, const char **argv) { + struct S s = {{0, 1, 2, 3, 4, 5, 6, 7}}; + // DEBUGGER: break 17 + f(s, 4); + // DEBUGGER: break 19 + return 0; +} + +int f(struct S s, unsigned i) { + // DEBUGGER: break 24 + return s.a[i]; +} + +// DEBUGGER: r +// DEBUGGER: p s +// CHECK: a = +// DEBUGGER: p s.a[0] +// CHECK: = 0 +// DEBUGGER: p s.a[1] +// CHECK: = 1 +// DEBUGGER: p s.a[7] +// CHECK: = 7 +// DEBUGGER: c +// DEBUGGER: p s +// CHECK: a = +// DEBUGGER: p s.a[0] +// CHECK: = 0 +// DEBUGGER: p s.a[1] +// CHECK: = 1 +// DEBUGGER: p s.a[7] +// DEBUGGER: c +// DEBUGGER: p s +// CHECK: a = +// DEBUGGER: p s.a[0] +// CHECK: = 0 +// DEBUGGER: p s.a[1] +// CHECK: = 1 +// DEBUGGER: p s.a[7] diff --git a/debuginfo-tests/llgdb-tests/static-member-2.cpp b/debuginfo-tests/llgdb-tests/static-member-2.cpp new file mode 100644 index 000000000000..4edb2b060f1a --- /dev/null +++ b/debuginfo-tests/llgdb-tests/static-member-2.cpp @@ -0,0 +1,39 @@ +// RUN: %clangxx %target_itanium_abi_host_triple -O0 -g %s -o %t -c +// RUN: %clangxx %target_itanium_abi_host_triple %t -o %t.out +// RUN: %test_debuginfo %s %t.out + +// FIXME: LLDB finds the wrong symbol for "C". rdar://problem/14933867 +// XFAIL: darwin + +// DEBUGGER: delete breakpoints +// DEBUGGER: break static-member.cpp:33 +// DEBUGGER: r +// DEBUGGER: ptype C +// CHECK: {{struct|class}} C { +// CHECK: static const int a; +// CHECK-NEXT: static int b; +// CHECK-NEXT: static int c; +// CHECK-NEXT: int d; +// CHECK-NEXT: } +// DEBUGGER: p C::a +// CHECK: ${{[0-9]}} = 4 +// DEBUGGER: p C::c +// CHECK: ${{[0-9]}} = 15 + +// PR14471, PR14734 + +class C { +public: + const static int a = 4; + static int b; + static int c; + int d; +}; + +int C::c = 15; +const int C::a; + +int main() { + C instance_C; + return C::a; +} diff --git a/debuginfo-tests/llgdb-tests/static-member.cpp b/debuginfo-tests/llgdb-tests/static-member.cpp new file mode 100644 index 000000000000..1d8ad62c5b88 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/static-member.cpp @@ -0,0 +1,36 @@ +// RUN: %clangxx %target_itanium_abi_host_triple -O0 -g %s -o %t -c +// RUN: %clangxx %target_itanium_abi_host_triple %t -o %t.out +// RUN: %test_debuginfo %s %t.out + +// DEBUGGER: delete breakpoints +// DEBUGGER: break static-member.cpp:33 +// DEBUGGER: r +// DEBUGGER: ptype MyClass +// CHECK: {{struct|class}} MyClass { +// CHECK: static const int a; +// CHECK-NEXT: static int b; +// CHECK-NEXT: static int c; +// CHECK-NEXT: int d; +// CHECK-NEXT: } +// DEBUGGER: p MyClass::a +// CHECK: ${{[0-9]}} = 4 +// DEBUGGER: p MyClass::c +// CHECK: ${{[0-9]}} = 15 + +// PR14471, PR14734 + +class MyClass { +public: + const static int a = 4; + static int b; + static int c; + int d; +}; + +int MyClass::c = 15; +const int MyClass::a; + +int main() { + MyClass instance_MyClass; + return MyClass::a; +} diff --git a/debuginfo-tests/llgdb-tests/test_debuginfo.pl b/debuginfo-tests/llgdb-tests/test_debuginfo.pl new file mode 100755 index 000000000000..e4c2a5ea24c1 --- /dev/null +++ b/debuginfo-tests/llgdb-tests/test_debuginfo.pl @@ -0,0 +1,81 @@ +#!/usr/bin/perl +# +# This script tests debugging information generated by a compiler. +# Input arguments +# - Input source program. Usually this source file is decorated using +# special comments to communicate debugger commands. +# - Executable file. This file is generated by the compiler. +# +# This perl script extracts debugger commands from input source program +# comments in a script. A debugger is used to load the executable file +# and run the script generated from source program comments. Finally, +# the debugger output is checked, using FileCheck, to validate +# debugging information. +# +# On Darwin the default is to use the llgdb.py wrapper script which +# translates gdb commands into their lldb equivalents. + +use File::Basename; +use Config; +use Cwd; + +my $testcase_file = $ARGV[0]; +my $executable_file = $ARGV[1]; + +my $input_filename = basename $testcase_file; +my $output_dir = dirname $executable_file; + +my $debugger_script_file = "$output_dir/$input_filename.debugger.script"; +my $output_file = "$output_dir/$input_filename.gdb.output"; + +my %cmd_map = (); +# Assume lldb to be the debugger on Darwin. +my $use_lldb = 0; +$use_lldb = 1 if ($Config{osname} eq "darwin"); + +# Extract debugger commands from testcase. They are marked with DEBUGGER: +# at the beginning of a comment line. +open(INPUT, $testcase_file); +open(OUTPUT, ">$debugger_script_file"); +while(<INPUT>) { + my($line) = $_; + $i = index($line, "DEBUGGER:"); + if ( $i >= 0) { + $l = length("DEBUGGER:"); + $s = substr($line, $i + $l); + print OUTPUT "$s"; + } +} +print OUTPUT "\n"; +print OUTPUT "quit\n"; +close(INPUT); +close(OUTPUT); + +# setup debugger and debugger options to run a script. +my $my_debugger = $ENV{'DEBUGGER'}; +if (!$my_debugger) { + if ($use_lldb) { + my $path = dirname(Cwd::abs_path($0)); + # At least on darwin, LLDB needs te system python. + $my_debugger = "/usr/bin/python $path/llgdb.py"; + } else { + $my_debugger = "gdb"; + } +} + +# quiet / exit after cmdline / no init file / execute script +my $debugger_options = "-q -batch -n -x"; + +# run debugger and capture output. +system("$my_debugger $debugger_options $debugger_script_file $executable_file > $output_file 2>&1"); + +# validate output. +system("FileCheck", "-input-file", "$output_file", "$testcase_file"); +if ($?>>8 == 1) { + print "Debugger output was:\n"; + system("cat", "$output_file"); + exit 1; +} +else { + exit 0; +} |