diff options
| author | Jeremy Morse <jeremy.morse@sony.com> | 2019-10-31 13:41:24 +0000 |
|---|---|---|
| committer | Jeremy Morse <jeremy.morse@sony.com> | 2019-10-31 13:49:47 +0000 |
| commit | f78c236efda85af1e526ac35ed535ef4786450e3 (patch) | |
| tree | 1ff1609178e085f58b46dfcbce21fd6b2ef40025 /debuginfo-tests/llgdb-tests | |
| parent | efacf2ce55d698e5df8173f0d4dacbc7d3c7fd34 (diff) | |
| download | bcm5719-llvm-f78c236efda85af1e526ac35ed535ef4786450e3.tar.gz bcm5719-llvm-f78c236efda85af1e526ac35ed535ef4786450e3.zip | |
Import Dexter to debuginfo-tests
Dexter (Debug Experience Tester) is a test-driver for our debug info
integration tests, reading a set of debug experience expectations and
comparing them with the actual behaviour of a program under a debugger.
More about Dexter can be found in the RFC:
http://lists.llvm.org/pipermail/llvm-dev/2019-October/135773.html
and the phab review in D68708. Not all the debuginfo tests have been
transformed into Dexter tests, and we look forwards to doing that
incrementally.
This commit mostly aims to flush out buildbots that are running
debuginfo-tests but don't have python 3 installed, possibly
green-dragon and some windows bots.
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 00000000000..4a73afe8011 --- /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 00000000000..33f44cd6659 --- /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 00000000000..f3f55aae0ff --- /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 00000000000..96dffb348d4 --- /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 00000000000..7ec786f1798 --- /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 00000000000..8e5a2121320 --- /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 00000000000..2e3c312c877 --- /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 00000000000..132420009bd --- /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 00000000000..725aa59ab59 --- /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 00000000000..5f14497f628 --- /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 00000000000..7533e6a8151 --- /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 00000000000..ba8d9d42f6f --- /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 00000000000..cf3efc75239 --- /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 00000000000..4edb2b060f1 --- /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 00000000000..1d8ad62c5b8 --- /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 00000000000..e4c2a5ea24c --- /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; +} |

