diff options
Diffstat (limited to 'lldb/packages/Python/lldbsuite/test/commands/expression')
261 files changed, 6988 insertions, 0 deletions
diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/.categories b/lldb/packages/Python/lldbsuite/test/commands/expression/.categories new file mode 100644 index 00000000000..897e40a99dd --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/.categories @@ -0,0 +1 @@ +expression diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/anonymous-struct/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/anonymous-struct/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/anonymous-struct/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/anonymous-struct/TestCallUserAnonTypedef.py b/lldb/packages/Python/lldbsuite/test/commands/expression/anonymous-struct/TestCallUserAnonTypedef.py new file mode 100644 index 00000000000..1108b121532 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/anonymous-struct/TestCallUserAnonTypedef.py @@ -0,0 +1,45 @@ +""" +Test calling user defined functions using expression evaluation. +This test checks that typesystem lookup works correctly for typedefs of +untagged structures. + +Ticket: https://llvm.org/bugs/show_bug.cgi?id=26790 +""" + +from __future__ import print_function + +import lldb + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestExprLookupAnonStructTypedef(TestBase): + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + TestBase.setUp(self) + # Find the breakpoint + self.line = line_number('main.cpp', '// lldb testsuite break') + + @expectedFailureAll( + oslist=['linux'], + archs=['arm'], + bugnumber="llvm.org/pr27868") + def test(self): + """Test typedeffed untagged struct arguments for function call expressions""" + self.build() + + self.runCmd("file "+self.getBuildArtifact("a.out"), + CURRENT_EXECUTABLE_SET) + lldbutil.run_break_set_by_file_and_line( + self, + "main.cpp", + self.line, + num_expected_locations=-1, + loc_exact=True + ) + + self.runCmd("run", RUN_SUCCEEDED) + self.expect("expr multiply(&s)", substrs=['$0 = 1']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/anonymous-struct/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/anonymous-struct/main.cpp new file mode 100644 index 00000000000..5b170c5f943 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/anonymous-struct/main.cpp @@ -0,0 +1,26 @@ +#include <tgmath.h> + +typedef struct { + float f; + int i; +} my_untagged_struct; + +double multiply(my_untagged_struct *s) +{ + return s->f * s->i; +} + +double multiply(my_untagged_struct *s, int x) +{ + return multiply(s) * x; +} + +int main(int argc, char **argv) +{ + my_untagged_struct s = { + .f = (float)argc, + .i = argc, + }; + // lldb testsuite break + return !(multiply(&s, argc) == pow(argc, 3)); +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/argument_passing_restrictions/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/argument_passing_restrictions/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/argument_passing_restrictions/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/argument_passing_restrictions/TestArgumentPassingRestrictions.py b/lldb/packages/Python/lldbsuite/test/commands/expression/argument_passing_restrictions/TestArgumentPassingRestrictions.py new file mode 100644 index 00000000000..858f2785be8 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/argument_passing_restrictions/TestArgumentPassingRestrictions.py @@ -0,0 +1,33 @@ +""" +This is a test to ensure that both lldb is reconstructing the right +calling convention for a CXXRecordDecl as represented by: + + DW_CC_pass_by_reference + DW_CC_pass_by_value + +and to also make sure that the ASTImporter is copying over this +setting when importing the CXXRecordDecl via setArgPassingRestrictions. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestArgumentPassingRestrictions(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIf(compiler="clang", compiler_version=['<', '7.0']) + def test_argument_passing_restrictions(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp")) + + self.expect("expr returnPassByRef()", + substrs=['(PassByRef)', '= 11223344']) + + self.expect("expr takePassByRef(p)", + substrs=['(int)', '= 42']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/argument_passing_restrictions/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/argument_passing_restrictions/main.cpp new file mode 100644 index 00000000000..4b3b6950455 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/argument_passing_restrictions/main.cpp @@ -0,0 +1,19 @@ +// This structure has a non-trivial copy constructor so +// it needs to be passed by reference. +struct PassByRef { + PassByRef() = default; + PassByRef(const PassByRef &p){x = p.x;}; + + int x = 11223344; +}; + +PassByRef returnPassByRef() { return PassByRef(); } +int takePassByRef(PassByRef p) { + return p.x; +} + +int main() { + PassByRef p = returnPassByRef(); + p.x = 42; + return takePassByRef(p); // break here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/calculator_mode/TestCalculatorMode.py b/lldb/packages/Python/lldbsuite/test/commands/expression/calculator_mode/TestCalculatorMode.py new file mode 100644 index 00000000000..46ea111bf03 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/calculator_mode/TestCalculatorMode.py @@ -0,0 +1,27 @@ +""" +Test calling an expression without a target. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestCalculatorMode(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def test__calculator_mode(self): + """Test calling expressions in the dummy target.""" + self.expect("expression 11 + 22", "11 + 22 didn't get the expected result", substrs=["33"]) + # Now try it with a specific language: + self.expect("expression -l c -- 11 + 22", "11 + 22 didn't get the expected result", substrs=["33"]) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/Makefile new file mode 100644 index 00000000000..9d4f3b7f141 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules + +clean:: + rm -rf $(wildcard *.o *.d *.dSYM) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallBuiltinFunction.py b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallBuiltinFunction.py new file mode 100644 index 00000000000..87787f3479a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallBuiltinFunction.py @@ -0,0 +1,53 @@ +""" +Tests calling builtin functions using expression evaluation. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandCallBuiltinFunction(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # Builtins are expanded by Clang, so debug info shouldn't matter. + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number( + 'main.cpp', + '// Please test these expressions while stopped at this line:') + + def test(self): + self.build() + + # Set breakpoint in main and run exe + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + interp = self.dbg.GetCommandInterpreter() + result = lldb.SBCommandReturnObject() + + # Test different builtin functions. + + interp.HandleCommand("expr __builtin_isinf(0.0f)", result) + self.assertEqual(result.GetOutput(), "(int) $0 = 0\n") + + interp.HandleCommand("expr __builtin_isnormal(0.0f)", result) + self.assertEqual(result.GetOutput(), "(int) $1 = 0\n") + + interp.HandleCommand("expr __builtin_constant_p(1)", result) + self.assertEqual(result.GetOutput(), "(int) $2 = 1\n") + + interp.HandleCommand("expr __builtin_abs(-14)", result) + self.assertEqual(result.GetOutput(), "(int) $3 = 14\n") diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallStdStringFunction.py b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallStdStringFunction.py new file mode 100644 index 00000000000..8f2ea371f2b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallStdStringFunction.py @@ -0,0 +1,57 @@ +""" +Test calling std::String member functions. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandCallFunctionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number( + 'main.cpp', + '// Please test these expressions while stopped at this line:') + + @expectedFailureAll( + compiler="icc", + bugnumber="llvm.org/pr14437, fails with ICC 13.1") + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") + def test_with(self): + """Test calling std::String member function.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), + CURRENT_EXECUTABLE_SET) + + # Some versions of GCC encode two locations for the 'return' statement + # in main.cpp + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + self.expect("print str", + substrs=['Hello world']) + + # Calling this function now succeeds, but we follow the typedef return type through to + # const char *, and thus don't invoke the Summary formatter. + + # clang's libstdc++ on ios arm64 inlines std::string::c_str() always; + # skip this part of the test. + triple = self.dbg.GetSelectedPlatform().GetTriple() + do_cstr_test = True + if triple == "arm64-apple-ios" or triple == "arm64-apple-tvos" or triple == "armv7k-apple-watchos" or triple == "arm64-apple-bridgeos": + do_cstr_test = False + if do_cstr_test: + self.expect("print str.c_str()", + substrs=['Hello world']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallStopAndContinue.py b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallStopAndContinue.py new file mode 100644 index 00000000000..d832983bdb6 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallStopAndContinue.py @@ -0,0 +1,53 @@ +""" +Test calling a function, stopping in the call, continue and gather the result on stop. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandCallStopContinueTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number( + 'main.cpp', + '// Please test these expressions while stopped at this line:') + self.func_line = line_number('main.cpp', '{5, "five"}') + + def test(self): + """Test gathering result from interrupted function call.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + # Some versions of GCC encode two locations for the 'return' statement + # in main.cpp + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + lldbutil.run_break_set_by_file_and_line( + self, + "main.cpp", + self.func_line, + num_expected_locations=-1, + loc_exact=True) + + self.expect("expr -i false -- returnsFive()", error=True, + substrs=['Execution was interrupted, reason: breakpoint']) + + self.runCmd("continue", "Continue completed") + self.expect( + "thread list", + substrs=[ + 'stop reason = User Expression thread plan', + r'Completed expression: (Five) $0 = (number = 5, name = "five")']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallUserDefinedFunction.py b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallUserDefinedFunction.py new file mode 100644 index 00000000000..0eb7086b616 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/TestCallUserDefinedFunction.py @@ -0,0 +1,58 @@ +""" +Test calling user defined functions using expression evaluation. + +Note: + LLDBs current first choice of evaluating functions is using the IR interpreter, + which is only supported on Hexagon. Otherwise JIT is used for the evaluation. + +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandCallUserDefinedFunction(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number( + 'main.cpp', + '// Please test these expressions while stopped at this line:') + + def test(self): + """Test return values of user defined function calls.""" + self.build() + + # Set breakpoint in main and run exe + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # Test recursive function call. + self.expect("expr fib(5)", substrs=['$0 = 5']) + + # Test function with more than one paramter + self.expect("expr add(4,8)", substrs=['$1 = 12']) + + # Test nesting function calls in function paramters + self.expect("expr add(add(5,2),add(3,4))", substrs=['$2 = 14']) + self.expect("expr add(add(5,2),fib(5))", substrs=['$3 = 12']) + + # Test function with pointer paramter + self.expect( + "exp stringCompare((const char*) \"Hello world\")", + substrs=['$4 = true']) + self.expect( + "exp stringCompare((const char*) \"Hellworld\")", + substrs=['$5 = false']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/main.cpp new file mode 100644 index 00000000000..cc5f52dbf56 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-function/main.cpp @@ -0,0 +1,53 @@ +#include <iostream> +#include <string> +#include <cstring> + +struct Five +{ + int number; + const char *name; +}; + +Five +returnsFive() +{ + Five my_five = {5, "five"}; + return my_five; +} + +unsigned int +fib(unsigned int n) +{ + if (n < 2) + return n; + else + return fib(n - 1) + fib(n - 2); +} + +int +add(int a, int b) +{ + return a + b; +} + +bool +stringCompare(const char *str) +{ + if (strcmp( str, "Hello world" ) == 0) + return true; + else + return false; +} + +int main (int argc, char const *argv[]) +{ + std::string str = "Hello world"; + std::cout << str << std::endl; + std::cout << str.c_str() << std::endl; + Five main_five = returnsFive(); +#if 0 + print str + print str.c_str() +#endif + return 0; // Please test these expressions while stopped at this line: +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-overridden-method/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/call-overridden-method/Makefile new file mode 100644 index 00000000000..9d4f3b7f141 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-overridden-method/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules + +clean:: + rm -rf $(wildcard *.o *.d *.dSYM) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-overridden-method/TestCallOverriddenMethod.py b/lldb/packages/Python/lldbsuite/test/commands/expression/call-overridden-method/TestCallOverriddenMethod.py new file mode 100644 index 00000000000..1e61aa9f46e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-overridden-method/TestCallOverriddenMethod.py @@ -0,0 +1,49 @@ +""" +Test calling an overriden method. + +Note: + This verifies that LLDB is correctly building the method overrides table. + If this table is not built correctly then calls to overridden methods in + derived classes may generate references to non-existant vtable entries, + as the compiler treats the overridden method as a totally new virtual + method definition. + <rdar://problem/14205774> + +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class ExprCommandCallOverriddenMethod(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number('main.cpp', '// Set breakpoint here') + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") + def test(self): + """Test calls to overridden methods in derived classes.""" + self.build() + + # Set breakpoint in main and run exe + self.runCmd("file " + self.getBuildArtifact("a.out"), + CURRENT_EXECUTABLE_SET) + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=-1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # Test call to method in base class (this should always work as the base + # class method is never an override). + self.expect("expr b->foo()") + + # Test call to overridden method in derived class (this will fail if the + # overrides table is not correctly set up, as Derived::foo will be assigned + # a vtable entry that does not exist in the compiled program). + self.expect("expr d.foo()") diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-overridden-method/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/call-overridden-method/main.cpp new file mode 100644 index 00000000000..54ae705d297 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-overridden-method/main.cpp @@ -0,0 +1,16 @@ +class Base { +public: + virtual ~Base() {} + virtual void foo() {} +}; + +class Derived : public Base { +public: + virtual void foo() {} +}; + +int main() { + Derived d; + Base *b = &d; + return 0; // Set breakpoint here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-restarts/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/call-restarts/Makefile new file mode 100644 index 00000000000..1c93ae1de43 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-restarts/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := lotta-signals.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-restarts/TestCallThatRestarts.py b/lldb/packages/Python/lldbsuite/test/commands/expression/call-restarts/TestCallThatRestarts.py new file mode 100644 index 00000000000..1182b156e80 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-restarts/TestCallThatRestarts.py @@ -0,0 +1,166 @@ +""" +Test calling a function that hits a signal set to auto-restart, make sure the call completes. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandThatRestartsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.main_source = "lotta-signals.c" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + @skipIfFreeBSD # llvm.org/pr19246: intermittent failure + @skipIfDarwin # llvm.org/pr19246: intermittent failure + @skipIfWindows # Test relies on signals, unsupported on Windows + @expectedFlakeyAndroid(bugnumber="llvm.org/pr19246") + def test(self): + """Test calling function that hits a signal and restarts.""" + self.build() + self.call_function() + + def check_after_call(self, num_sigchld): + after_call = self.sigchld_no.GetValueAsSigned(-1) + self.assertTrue( + after_call - + self.start_sigchld_no == num_sigchld, + "Really got %d SIGCHLD signals through the call." % + (num_sigchld)) + self.start_sigchld_no = after_call + + # Check that we are back where we were before: + frame = self.thread.GetFrameAtIndex(0) + self.assertTrue( + self.orig_frame_pc == frame.GetPC(), + "Restored the zeroth frame correctly") + + def call_function(self): + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Stop here in main.', self.main_source_spec) + + # Make sure the SIGCHLD behavior is pass/no-stop/no-notify: + return_obj = lldb.SBCommandReturnObject() + self.dbg.GetCommandInterpreter().HandleCommand( + "process handle SIGCHLD -s 0 -p 1 -n 0", return_obj) + self.assertTrue(return_obj.Succeeded(), "Set SIGCHLD to pass, no-stop") + + # The sigchld_no variable should be 0 at this point. + self.sigchld_no = target.FindFirstGlobalVariable("sigchld_no") + self.assertTrue( + self.sigchld_no.IsValid(), + "Got a value for sigchld_no") + + self.start_sigchld_no = self.sigchld_no.GetValueAsSigned(-1) + self.assertTrue( + self.start_sigchld_no != -1, + "Got an actual value for sigchld_no") + + options = lldb.SBExpressionOptions() + # processing 30 signals takes a while, increase the expression timeout + # a bit + options.SetTimeoutInMicroSeconds(3000000) # 3s + options.SetUnwindOnError(True) + + frame = self.thread.GetFrameAtIndex(0) + # Store away the PC to check that the functions unwind to the right + # place after calls + self.orig_frame_pc = frame.GetPC() + + num_sigchld = 30 + value = frame.EvaluateExpression( + "call_me (%d)" % + (num_sigchld), options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) + + self.check_after_call(num_sigchld) + + # Okay, now try with a breakpoint in the called code in the case where + # we are ignoring breakpoint hits. + handler_bkpt = target.BreakpointCreateBySourceRegex( + "Got sigchld %d.", self.main_source_spec) + self.assertTrue(handler_bkpt.GetNumLocations() > 0) + options.SetIgnoreBreakpoints(True) + options.SetUnwindOnError(True) + + value = frame.EvaluateExpression( + "call_me (%d)" % + (num_sigchld), options) + + self.assertTrue(value.IsValid() and value.GetError().Success()) + self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) + self.check_after_call(num_sigchld) + + # Now set the signal to print but not stop and make sure that calling + # still works: + self.dbg.GetCommandInterpreter().HandleCommand( + "process handle SIGCHLD -s 0 -p 1 -n 1", return_obj) + self.assertTrue( + return_obj.Succeeded(), + "Set SIGCHLD to pass, no-stop, notify") + + value = frame.EvaluateExpression( + "call_me (%d)" % + (num_sigchld), options) + + self.assertTrue(value.IsValid() and value.GetError().Success()) + self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) + self.check_after_call(num_sigchld) + + # Now set this unwind on error to false, and make sure that we still + # complete the call: + options.SetUnwindOnError(False) + value = frame.EvaluateExpression( + "call_me (%d)" % + (num_sigchld), options) + + self.assertTrue(value.IsValid() and value.GetError().Success()) + self.assertTrue(value.GetValueAsSigned(-1) == num_sigchld) + self.check_after_call(num_sigchld) + + # Okay, now set UnwindOnError to true, and then make the signal behavior to stop + # and see that now we do stop at the signal point: + + self.dbg.GetCommandInterpreter().HandleCommand( + "process handle SIGCHLD -s 1 -p 1 -n 1", return_obj) + self.assertTrue( + return_obj.Succeeded(), + "Set SIGCHLD to pass, stop, notify") + + value = frame.EvaluateExpression( + "call_me (%d)" % + (num_sigchld), options) + self.assertTrue( + value.IsValid() and value.GetError().Success() == False) + + # Set signal handling back to no-stop, and continue and we should end + # up back in out starting frame: + self.dbg.GetCommandInterpreter().HandleCommand( + "process handle SIGCHLD -s 0 -p 1 -n 1", return_obj) + self.assertTrue( + return_obj.Succeeded(), + "Set SIGCHLD to pass, no-stop, notify") + + error = process.Continue() + self.assertTrue( + error.Success(), + "Continuing after stopping for signal succeeds.") + + frame = self.thread.GetFrameAtIndex(0) + self.assertTrue( + frame.GetPC() == self.orig_frame_pc, + "Continuing returned to the place we started.") diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-restarts/lotta-signals.c b/lldb/packages/Python/lldbsuite/test/commands/expression/call-restarts/lotta-signals.c new file mode 100644 index 00000000000..f5c15b41e2d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-restarts/lotta-signals.c @@ -0,0 +1,61 @@ +#include <unistd.h> +#include <stdio.h> +#include <signal.h> + +static int sigchld_no; +static int nosig_no; +static int weird_value; + +void +sigchld_handler (int signo) +{ + sigchld_no++; + printf ("Got sigchld %d.\n", sigchld_no); +} + +int +call_me (int some_value) +{ + int ret_val = 0; + int i; + for (i = 0; i < some_value; i++) + { + int result = 0; + if (i%2 == 0) + result = kill (getpid(), SIGCHLD); + else + sigchld_no++; + + usleep(1000); + if (result == 0) + ret_val++; + } + usleep (10000); + return ret_val; +} + +int +call_me_nosig (int some_value) +{ + int ret_val = 0; + int i; + for (i = 0; i < some_value; i++) + weird_value += i % 4; + + nosig_no += some_value; + return some_value; +} + +int +main () +{ + int ret_val; + signal (SIGCHLD, sigchld_handler); + + ret_val = call_me (2); // Stop here in main. + + ret_val = call_me_nosig (10); + + return 0; + +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-throws/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/call-throws/Makefile new file mode 100644 index 00000000000..ac07b31c48c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-throws/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +OBJC_SOURCES := call-throws.m + +include $(LEVEL)/Makefile.rules +LDFLAGS += -framework Foundation diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-throws/TestCallThatThrows.py b/lldb/packages/Python/lldbsuite/test/commands/expression/call-throws/TestCallThatThrows.py new file mode 100644 index 00000000000..c6b90ba5ba0 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-throws/TestCallThatThrows.py @@ -0,0 +1,104 @@ +""" +Test calling a function that throws an ObjC exception, make sure that it doesn't propagate the exception. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandWithThrowTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.main_source = "call-throws.m" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + @skipUnlessDarwin + def test(self): + """Test calling a function that throws and ObjC exception.""" + self.build() + self.call_function() + + def check_after_call(self): + # Check that we are back where we were before: + frame = self.thread.GetFrameAtIndex(0) + self.assertTrue( + self.orig_frame_pc == frame.GetPC(), + "Restored the zeroth frame correctly") + + def call_function(self): + """Test calling function that throws.""" + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'I am about to throw.', self.main_source_spec) + + options = lldb.SBExpressionOptions() + options.SetUnwindOnError(True) + + frame = self.thread.GetFrameAtIndex(0) + # Store away the PC to check that the functions unwind to the right + # place after calls + self.orig_frame_pc = frame.GetPC() + + value = frame.EvaluateExpression("[my_class callMeIThrow]", options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success() == False) + + self.check_after_call() + + # Okay, now try with a breakpoint in the called code in the case where + # we are ignoring breakpoint hits. + handler_bkpt = target.BreakpointCreateBySourceRegex( + "I felt like it", self.main_source_spec) + self.assertTrue(handler_bkpt.GetNumLocations() > 0) + options.SetIgnoreBreakpoints(True) + options.SetUnwindOnError(True) + + value = frame.EvaluateExpression("[my_class callMeIThrow]", options) + + self.assertTrue( + value.IsValid() and value.GetError().Success() == False) + self.check_after_call() + + # Now set the ObjC language breakpoint and make sure that doesn't + # interfere with the call: + exception_bkpt = target.BreakpointCreateForException( + lldb.eLanguageTypeObjC, False, True) + self.assertTrue(exception_bkpt.GetNumLocations() > 0) + + options.SetIgnoreBreakpoints(True) + options.SetUnwindOnError(True) + + value = frame.EvaluateExpression("[my_class callMeIThrow]", options) + + self.assertTrue( + value.IsValid() and value.GetError().Success() == False) + self.check_after_call() + + # Now turn off exception trapping, and call a function that catches the exceptions, + # and make sure the function actually completes, and we get the right + # value: + options.SetTrapExceptions(False) + value = frame.EvaluateExpression("[my_class iCatchMyself]", options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertTrue(value.GetValueAsUnsigned() == 57) + self.check_after_call() + options.SetTrapExceptions(True) + + # Now set this unwind on error to false, and make sure that we stop + # where the exception was thrown + options.SetUnwindOnError(False) + value = frame.EvaluateExpression("[my_class callMeIThrow]", options) + + self.assertTrue( + value.IsValid() and value.GetError().Success() == False) + self.check_after_call() diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/call-throws/call-throws.m b/lldb/packages/Python/lldbsuite/test/commands/expression/call-throws/call-throws.m new file mode 100644 index 00000000000..a184718be7d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/call-throws/call-throws.m @@ -0,0 +1,47 @@ +#import <Foundation/Foundation.h> + +@interface MyClass : NSObject +{ +} +- (int) callMeIThrow; +- (int) iCatchMyself; +@end + +@implementation MyClass +- (int) callMeIThrow +{ + NSException *e = [NSException + exceptionWithName:@"JustForTheHeckOfItException" + reason:@"I felt like it" + userInfo:nil]; + @throw e; + return 56; +} + +- (int) iCatchMyself +{ + int return_value = 55; + @try + { + return_value = [self callMeIThrow]; + } + @catch (NSException *e) + { + return_value = 57; + } + return return_value; +} +@end + +int +main () +{ + int return_value; + MyClass *my_class = [[MyClass alloc] init]; + + NSLog (@"I am about to throw."); + + return_value = [my_class iCatchMyself]; + + return return_value; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/cast_int_to_anonymous_enum/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/cast_int_to_anonymous_enum/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/cast_int_to_anonymous_enum/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/cast_int_to_anonymous_enum/TestCastIntToAnonymousEnum.py b/lldb/packages/Python/lldbsuite/test/commands/expression/cast_int_to_anonymous_enum/TestCastIntToAnonymousEnum.py new file mode 100644 index 00000000000..b8eaf51d3e2 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/cast_int_to_anonymous_enum/TestCastIntToAnonymousEnum.py @@ -0,0 +1,22 @@ +""" +Test Expression Parser regression text to ensure that we handle anonymous +enums importing correctly. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestCastIntToAnonymousEnum(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_cast_int_to_anonymous_enum(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + self.expect("expr (flow_e)0", substrs=['(flow_e) $0 = A']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/cast_int_to_anonymous_enum/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/cast_int_to_anonymous_enum/main.cpp new file mode 100644 index 00000000000..7ae4c1735db --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/cast_int_to_anonymous_enum/main.cpp @@ -0,0 +1,9 @@ +enum flow_e { + A=0, +}; + +int main() { + flow_e f; + + return 0; // break here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/char/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/char/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/char/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/char/TestExprsChar.py b/lldb/packages/Python/lldbsuite/test/commands/expression/char/TestExprsChar.py new file mode 100644 index 00000000000..a9679b7dd36 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/char/TestExprsChar.py @@ -0,0 +1,67 @@ +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCharTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + def do_test(self, dictionary=None): + """These basic expression commands should work as expected.""" + self.build(dictionary=dictionary) + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) + + value = frame.EvaluateExpression("foo(c)") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(0), 1) + + value = frame.EvaluateExpression("foo(sc)") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(0), 2) + + value = frame.EvaluateExpression("foo(uc)") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(0), 3) + + def test_default_char(self): + self.do_test() + + @expectedFailureAll( + archs=[ + "arm", + "aarch64", + "powerpc64le", + "s390x"], + bugnumber="llvm.org/pr23069") + def test_signed_char(self): + self.do_test(dictionary={'CFLAGS_EXTRAS': '-fsigned-char'}) + + @expectedFailureAll( + archs=[ + "i[3-6]86", + "x86_64", + "arm64", + 'armv7', + 'armv7k'], + bugnumber="llvm.org/pr23069, <rdar://problem/28721938>") + @expectedFailureAll(triple='mips*', bugnumber="llvm.org/pr23069") + def test_unsigned_char(self): + self.do_test(dictionary={'CFLAGS_EXTRAS': '-funsigned-char'}) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/char/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/char/main.cpp new file mode 100644 index 00000000000..c8b0beb1b35 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/char/main.cpp @@ -0,0 +1,10 @@ +int foo(char c) { return 1; } +int foo(signed char c) { return 2; } +int foo(unsigned char c) { return 3; } + +int main() { + char c = 0; + signed char sc = 0; + unsigned char uc = 0; + return 0; // Break here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/class_template_specialization_empty_pack/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/class_template_specialization_empty_pack/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/class_template_specialization_empty_pack/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/class_template_specialization_empty_pack/TestClassTemplateSpecializationParametersHandling.py b/lldb/packages/Python/lldbsuite/test/commands/expression/class_template_specialization_empty_pack/TestClassTemplateSpecializationParametersHandling.py new file mode 100644 index 00000000000..d1974d05a24 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/class_template_specialization_empty_pack/TestClassTemplateSpecializationParametersHandling.py @@ -0,0 +1,23 @@ +""" +Test Expression Parser code gen for ClassTemplateSpecializationDecl to insure +that we generate a TemplateTypeParmDecl in the TemplateParameterList for empty +variadic packs. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestClassTemplateSpecializationParametersHandling(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_class_template_specialization(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + self.expect("expr -u 0 -- b.foo()", substrs=['$0 = 1']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/class_template_specialization_empty_pack/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/class_template_specialization_empty_pack/main.cpp new file mode 100644 index 00000000000..bc831604aed --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/class_template_specialization_empty_pack/main.cpp @@ -0,0 +1,9 @@ +template <typename N, class... P> +struct A { + int foo() { return 1;} +}; + +int main() { + A<int> b; + return b.foo(); // break here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/Makefile new file mode 100644 index 00000000000..82355a233cf --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/TestCompletionCrashIncompleteRecord.py b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/TestCompletionCrashIncompleteRecord.py new file mode 100644 index 00000000000..68bd864c008 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/TestCompletionCrashIncompleteRecord.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIf(bugnumber="rdar://53756116")]) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/main.cpp new file mode 100644 index 00000000000..f7ca83c6540 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-incomplete-record/main.cpp @@ -0,0 +1,11 @@ +int i; +struct F { + int &r; + F() : r(i) {} +}; +template <class T> struct unique_ptr { + F i; + unique_ptr() : i() {//%self.dbg.GetCommandInterpreter().HandleCompletion("e ", len("e "), 0, -1, lldb.SBStringList()) +} +}; +int main() {unique_ptr<F> u; } diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-lambda/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-lambda/Makefile new file mode 100644 index 00000000000..82355a233cf --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash-lambda/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash1/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash1/Makefile new file mode 100644 index 00000000000..82355a233cf --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash1/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash1/TestCompletionCrash1.py b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash1/TestCompletionCrash1.py new file mode 100644 index 00000000000..3f2a6100607 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash1/TestCompletionCrash1.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIf(bugnumber="rdar://53659341")]) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash1/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash1/main.cpp new file mode 100644 index 00000000000..7b123c0662d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash1/main.cpp @@ -0,0 +1,12 @@ +namespace std { +struct a { + a() {} + a(a &&); +}; +template <class> struct au { + a ay; + ~au() { //%self.dbg.GetCommandInterpreter().HandleCompletion("e ", len("e "), 0, -1, lldb.SBStringList()) + } +}; +} +int main() { std::au<int>{}; } diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/Makefile new file mode 100644 index 00000000000..82355a233cf --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/TestCompletionCrash2.py b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/TestCompletionCrash2.py new file mode 100644 index 00000000000..922347aa781 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/TestCompletionCrash2.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), [decorators.skipIf(bugnumber="rdar://53754063")]) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/main.cpp new file mode 100644 index 00000000000..02f15c295c2 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-crash2/main.cpp @@ -0,0 +1,11 @@ +namespace n { +template <class> class a {}; +template <class b> struct shared_ptr { + template <class...> + static void make_shared() { //%self.dbg.GetCommandInterpreter().HandleCompletion("e ", len("e "), 0, -1, lldb.SBStringList()) + typedef a<b> c; + c d; + } +}; +} // namespace n +int main() { n::shared_ptr<int>::make_shared(); } diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-in-lambda-and-unnnamed-class/TestCompletionInLambdaAndUnnamedClass.py b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-in-lambda-and-unnnamed-class/TestCompletionInLambdaAndUnnamedClass.py new file mode 100644 index 00000000000..57fb94b6d66 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-in-lambda-and-unnnamed-class/TestCompletionInLambdaAndUnnamedClass.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(),) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion-in-lambda-and-unnnamed-class/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-in-lambda-and-unnnamed-class/main.cpp new file mode 100644 index 00000000000..a3d8ab6532e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion-in-lambda-and-unnnamed-class/main.cpp @@ -0,0 +1,11 @@ +int main() { + []() + { //%self.dbg.GetCommandInterpreter().HandleCompletion("e ", len("e "), 0, -1, lldb.SBStringList()) + } + (); + struct { + void f() + { //%self.dbg.GetCommandInterpreter().HandleCompletion("e ", len("e "), 0, -1, lldb.SBStringList()) + } + } A; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion/.categories b/lldb/packages/Python/lldbsuite/test/commands/expression/completion/.categories new file mode 100644 index 00000000000..3a3f4df6416 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion/.categories @@ -0,0 +1 @@ +cmdline diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/completion/Makefile new file mode 100644 index 00000000000..6fc26a9193f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp other.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion/TestExprCompletion.py b/lldb/packages/Python/lldbsuite/test/commands/expression/completion/TestExprCompletion.py new file mode 100644 index 00000000000..33a423c806b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion/TestExprCompletion.py @@ -0,0 +1,255 @@ +""" +Test the lldb command line completion mechanism for the 'expr' command. +""" + +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbplatform +from lldbsuite.test import lldbutil + +class CommandLineExprCompletionTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_expr_completion(self): + self.build() + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + + # Try the completion before we have a context to complete on. + self.assume_no_completions('expr some_expr') + self.assume_no_completions('expr ') + self.assume_no_completions('expr f') + + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + + # Completing member functions + self.complete_exactly('expr some_expr.FooNoArgs', + 'expr some_expr.FooNoArgsBar()') + self.complete_exactly('expr some_expr.FooWithArgs', + 'expr some_expr.FooWithArgsBar(') + self.complete_exactly('expr some_expr.FooWithMultipleArgs', + 'expr some_expr.FooWithMultipleArgsBar(') + self.complete_exactly('expr some_expr.FooUnderscore', + 'expr some_expr.FooUnderscoreBar_()') + self.complete_exactly('expr some_expr.FooNumbers', + 'expr some_expr.FooNumbersBar1()') + self.complete_exactly('expr some_expr.StaticMemberMethod', + 'expr some_expr.StaticMemberMethodBar()') + + # Completing static functions + self.complete_exactly('expr Expr::StaticMemberMethod', + 'expr Expr::StaticMemberMethodBar()') + + # Completing member variables + self.complete_exactly('expr some_expr.MemberVariab', + 'expr some_expr.MemberVariableBar') + + # Multiple completions + self.completions_contain('expr some_expr.', + ['some_expr.FooNumbersBar1()', + 'some_expr.FooUnderscoreBar_()', + 'some_expr.FooWithArgsBar(', + 'some_expr.MemberVariableBar']) + + self.completions_contain('expr some_expr.Foo', + ['some_expr.FooNumbersBar1()', + 'some_expr.FooUnderscoreBar_()', + 'some_expr.FooWithArgsBar(']) + + self.completions_contain('expr ', + ['static_cast', + 'reinterpret_cast', + 'dynamic_cast']) + + self.completions_contain('expr 1 + ', + ['static_cast', + 'reinterpret_cast', + 'dynamic_cast']) + + # Completion expr without spaces + # This is a bit awkward looking for the user, but that's how + # the completion API works at the moment. + self.completions_contain('expr 1+', + ['1+some_expr', "1+static_cast"]) + + # Test with spaces + self.complete_exactly('expr some_expr .FooNoArgs', + 'expr some_expr .FooNoArgsBar()') + self.complete_exactly('expr some_expr .FooNoArgs', + 'expr some_expr .FooNoArgsBar()') + self.complete_exactly('expr some_expr .FooNoArgs', + 'expr some_expr .FooNoArgsBar()') + self.complete_exactly('expr some_expr. FooNoArgs', + 'expr some_expr. FooNoArgsBar()') + self.complete_exactly('expr some_expr . FooNoArgs', + 'expr some_expr . FooNoArgsBar()') + self.complete_exactly('expr Expr :: StaticMemberMethod', + 'expr Expr :: StaticMemberMethodBar()') + self.complete_exactly('expr Expr ::StaticMemberMethod', + 'expr Expr ::StaticMemberMethodBar()') + self.complete_exactly('expr Expr:: StaticMemberMethod', + 'expr Expr:: StaticMemberMethodBar()') + + # Test that string literals don't break our parsing logic. + self.complete_exactly('expr const char *cstr = "some_e"; char c = *cst', + 'expr const char *cstr = "some_e"; char c = *cstr') + self.complete_exactly('expr const char *cstr = "some_e" ; char c = *cst', + 'expr const char *cstr = "some_e" ; char c = *cstr') + # Requesting completions inside an incomplete string doesn't provide any + # completions. + self.complete_exactly('expr const char *cstr = "some_e', + 'expr const char *cstr = "some_e') + + # Completing inside double dash should do nothing + self.assume_no_completions('expr -i0 -- some_expr.', 10) + self.assume_no_completions('expr -i0 -- some_expr.', 11) + + # Test with expr arguments + self.complete_exactly('expr -i0 -- some_expr .FooNoArgs', + 'expr -i0 -- some_expr .FooNoArgsBar()') + self.complete_exactly('expr -i0 -- some_expr .FooNoArgs', + 'expr -i0 -- some_expr .FooNoArgsBar()') + + # Addrof and deref + self.complete_exactly('expr (*(&some_expr)).FooNoArgs', + 'expr (*(&some_expr)).FooNoArgsBar()') + self.complete_exactly('expr (*(&some_expr)) .FooNoArgs', + 'expr (*(&some_expr)) .FooNoArgsBar()') + self.complete_exactly('expr (* (&some_expr)) .FooNoArgs', + 'expr (* (&some_expr)) .FooNoArgsBar()') + self.complete_exactly('expr (* (& some_expr)) .FooNoArgs', + 'expr (* (& some_expr)) .FooNoArgsBar()') + + # Addrof and deref (part 2) + self.complete_exactly('expr (&some_expr)->FooNoArgs', + 'expr (&some_expr)->FooNoArgsBar()') + self.complete_exactly('expr (&some_expr) ->FooNoArgs', + 'expr (&some_expr) ->FooNoArgsBar()') + self.complete_exactly('expr (&some_expr) -> FooNoArgs', + 'expr (&some_expr) -> FooNoArgsBar()') + self.complete_exactly('expr (&some_expr)-> FooNoArgs', + 'expr (&some_expr)-> FooNoArgsBar()') + + # Builtin arg + self.complete_exactly('expr static_ca', + 'expr static_cast') + + # From other files + self.complete_exactly('expr fwd_decl_ptr->Hidden', + 'expr fwd_decl_ptr->HiddenMember') + + + # Types + self.complete_exactly('expr LongClassNa', + 'expr LongClassName') + self.complete_exactly('expr LongNamespaceName::NestedCla', + 'expr LongNamespaceName::NestedClass') + + # Namespaces + self.complete_exactly('expr LongNamespaceNa', + 'expr LongNamespaceName::') + + # Multiple arguments + self.complete_exactly('expr &some_expr + &some_e', + 'expr &some_expr + &some_expr') + self.complete_exactly('expr SomeLongVarNameWithCapitals + SomeLongVarName', + 'expr SomeLongVarNameWithCapitals + SomeLongVarNameWithCapitals') + self.complete_exactly('expr SomeIntVar + SomeIntV', + 'expr SomeIntVar + SomeIntVar') + + # Multiple statements + self.complete_exactly('expr long LocalVariable = 0; LocalVaria', + 'expr long LocalVariable = 0; LocalVariable') + + # Custom Decls + self.complete_exactly('expr auto l = [](int LeftHandSide, int bx){ return LeftHandS', + 'expr auto l = [](int LeftHandSide, int bx){ return LeftHandSide') + self.complete_exactly('expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.Mem', + 'expr struct LocalStruct { long MemberName; } ; LocalStruct S; S.MemberName') + + # Completing function call arguments + self.complete_exactly('expr some_expr.FooWithArgsBar(some_exp', + 'expr some_expr.FooWithArgsBar(some_expr') + self.complete_exactly('expr some_expr.FooWithArgsBar(SomeIntV', + 'expr some_expr.FooWithArgsBar(SomeIntVar') + self.complete_exactly('expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVa', + 'expr some_expr.FooWithMultipleArgsBar(SomeIntVar, SomeIntVar') + + # Function return values + self.complete_exactly('expr some_expr.Self().FooNoArgs', + 'expr some_expr.Self().FooNoArgsBar()') + self.complete_exactly('expr some_expr.Self() .FooNoArgs', + 'expr some_expr.Self() .FooNoArgsBar()') + self.complete_exactly('expr some_expr.Self(). FooNoArgs', + 'expr some_expr.Self(). FooNoArgsBar()') + + def test_expr_completion_with_descriptions(self): + self.build() + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + self.dbg.CreateTarget(self.getBuildArtifact("a.out")) + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + + self.check_completion_with_desc("expr ", [ + # VarDecls have their type as description. + ["some_expr", "Expr &"], + # builtin types have no description. + ["int", ""], + ["float", ""] + ]) + self.check_completion_with_desc("expr some_expr.", [ + # Functions have their signature as description. + ["some_expr.Self()", "Expr &Self()"], + ["some_expr.operator=(", "inline Expr &operator=(const Expr &)"], + ["some_expr.FooNumbersBar1()", "int FooNumbersBar1()"], + ["some_expr.StaticMemberMethodBar()", "static int StaticMemberMethodBar()"], + ["some_expr.FooWithArgsBar(", "int FooWithArgsBar(int)"], + ["some_expr.FooNoArgsBar()", "int FooNoArgsBar()"], + ["some_expr.FooUnderscoreBar_()", "int FooUnderscoreBar_()"], + ["some_expr.FooWithMultipleArgsBar(", "int FooWithMultipleArgsBar(int, int)"], + ["some_expr.~Expr()", "inline ~Expr()"], + # FieldDecls have their type as description. + ["some_expr.MemberVariableBar", "int"], + ]) + + def assume_no_completions(self, str_input, cursor_pos = None): + interp = self.dbg.GetCommandInterpreter() + match_strings = lldb.SBStringList() + if cursor_pos is None: + cursor_pos = len(str_input) + num_matches = interp.HandleCompletion(str_input, cursor_pos, 0, -1, match_strings) + + available_completions = [] + for m in match_strings: + available_completions.append(m) + + self.assertEquals(num_matches, 0, "Got matches, but didn't expect any: " + str(available_completions)) + + def completions_contain(self, str_input, items): + interp = self.dbg.GetCommandInterpreter() + match_strings = lldb.SBStringList() + num_matches = interp.HandleCompletion(str_input, len(str_input), 0, -1, match_strings) + common_match = match_strings.GetStringAtIndex(0) + + for item in items: + found = False + for m in match_strings: + if m == item: + found = True + if not found: + # Transform match_strings to a python list with strings + available_completions = [] + for m in match_strings: + available_completions.append(m) + self.assertTrue(found, "Couldn't find completion " + item + " in completions " + str(available_completions)) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/completion/main.cpp new file mode 100644 index 00000000000..908bebbebff --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion/main.cpp @@ -0,0 +1,35 @@ +namespace LongNamespaceName { class NestedClass { long m; }; } + +// Defined in other.cpp, we only have a forward declaration here. +struct ForwardDecl; +extern ForwardDecl fwd_decl; + +class LongClassName { long i ; }; + +class Expr { +public: + int FooNoArgsBar() { return 1; } + int FooWithArgsBar(int i) { return i; } + int FooWithMultipleArgsBar(int i, int j) { return i + j; } + int FooUnderscoreBar_() { return 4; } + int FooNumbersBar1() { return 8; } + int MemberVariableBar = 0; + Expr &Self() { return *this; } + static int StaticMemberMethodBar() { return 82; } +}; + +int main() +{ + LongClassName a; + LongNamespaceName::NestedClass NestedFoo; + long SomeLongVarNameWithCapitals = 44; + int SomeIntVar = 33; + Expr some_expr; + some_expr.FooNoArgsBar(); + some_expr.FooWithArgsBar(1); + some_expr.FooUnderscoreBar_(); + some_expr.FooNumbersBar1(); + Expr::StaticMemberMethodBar(); + ForwardDecl *fwd_decl_ptr = &fwd_decl; + return 0; // Break here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/completion/other.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/completion/other.cpp new file mode 100644 index 00000000000..1f8a488639b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/completion/other.cpp @@ -0,0 +1,4 @@ +struct ForwardDecl { + long HiddenMemberName; +}; +ForwardDecl fwd_decl; diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/context-object-objc/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object-objc/Makefile new file mode 100644 index 00000000000..b6592745356 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object-objc/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules +LDFLAGS += -framework Foundation diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/context-object-objc/TestContextObjectObjc.py b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object-objc/TestContextObjectObjc.py new file mode 100644 index 00000000000..4ae4fd8680d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object-objc/TestContextObjectObjc.py @@ -0,0 +1,78 @@ +""" +Tests expression evaluation in context of an objc class. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + +class ContextObjectObjcTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + def test_context_object_objc(self): + """Tests expression evaluation in context of an objc class.""" + self.build() + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, '// Break here', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) + + # + # Test objc class variable + # + + obj_val = frame.FindVariable("objcClass") + self.assertTrue(obj_val.IsValid()) + obj_val = obj_val.Dereference() + self.assertTrue(obj_val.IsValid()) + + # Test an empty expression evaluation + value = obj_val.EvaluateExpression("") + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + # Test retrieving of a field (not a local with the same name) + value = obj_val.EvaluateExpression("field") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 1111) + + # Test if the self pointer is properly evaluated + + # Test retrieving of an objcClass's property through the self pointer + value = obj_val.EvaluateExpression("self.property") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 2222) + + # Test objcClass's methods evaluation through the self pointer + value = obj_val.EvaluateExpression("[self method]") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 3333) + + # Test if we can use a computation result reference object correctly + + obj_val = frame.EvaluateExpression("[ObjcClass createNew]") + self.assertTrue(obj_val.IsValid()) + obj_val = obj_val.Dereference() + self.assertTrue(obj_val.IsValid()) + + # Test an expression evaluation on it + value = obj_val.EvaluateExpression("1") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + + # Test retrieving of a field on it + value = obj_val.EvaluateExpression("field") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 1111) + + def setUp(self): + TestBase.setUp(self) + + self.main_source = "main.m" + self.main_source_spec = lldb.SBFileSpec(self.main_source) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/context-object-objc/main.m b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object-objc/main.m new file mode 100644 index 00000000000..5c495b24894 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object-objc/main.m @@ -0,0 +1,47 @@ +#import <Foundation/Foundation.h> + +@interface ObjcClass : NSObject { + int field; +} + +@property int property; + ++(ObjcClass*)createNew; + +-(id)init; + +-(int)method; + +@end + +@implementation ObjcClass + ++(ObjcClass*)createNew { + return [ObjcClass new]; +} + +-(id)init { + self = [super init]; + if (self) { + field = 1111; + _property = 2222; + } + return self; +} + +-(int)method { + return 3333; +} + +@end + +int main() +{ + @autoreleasepool { + ObjcClass* objcClass = [ObjcClass new]; + + int field = 4444; + + return 0; // Break here + } +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/context-object/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/context-object/TestContextObject.py b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object/TestContextObject.py new file mode 100644 index 00000000000..02b8162aad6 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object/TestContextObject.py @@ -0,0 +1,145 @@ +""" +Tests expression evaluation in context of an object. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ContextObjectTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_context_object(self): + """Tests expression evaluation in context of an object.""" + self.build() + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, '// Break here', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) + + # + # Test C++ struct variable + # + + obj_val = frame.FindVariable("cpp_struct") + self.assertTrue(obj_val.IsValid()) + + # Test an empty expression evaluation + value = obj_val.EvaluateExpression("") + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + # Test retrieveing of a field (not a local with the same name) + value = obj_val.EvaluateExpression("field") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 1111) + + # Test functions evaluation + value = obj_val.EvaluateExpression("function()") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 2222) + + # Test that we retrieve the right global + value = obj_val.EvaluateExpression("global.field") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 1111) + + # + # Test C++ union variable + # + + obj_val = frame.FindVariable("cpp_union") + self.assertTrue(obj_val.IsValid()) + + # Test retrieveing of a field + value = obj_val.EvaluateExpression("field_int") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 5555) + + # + # Test C++ scalar + # + + obj_val = frame.FindVariable("cpp_scalar") + self.assertTrue(obj_val.IsValid()) + + # Test an expression evaluation + value = obj_val.EvaluateExpression("1") + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + # + # Test C++ array + # + + obj_val = frame.FindVariable("cpp_array") + self.assertTrue(obj_val.IsValid()) + + # Test an expression evaluation + value = obj_val.EvaluateExpression("1") + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + # Test retrieveing of an element's field + value = obj_val.GetValueForExpressionPath("[7]").EvaluateExpression("field") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 1111) + + # + # Test C++ pointer + # + + obj_val = frame.FindVariable("cpp_pointer") + self.assertTrue(obj_val.IsValid()) + + # Test an expression evaluation + value = obj_val.EvaluateExpression("1") + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + # Test retrieveing of a dereferenced object's field + value = obj_val.Dereference().EvaluateExpression("field") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 1111) + + # + # Test C++ computation result + # + + obj_val = frame.EvaluateExpression("cpp_namespace::GetCppStruct()") + self.assertTrue(obj_val.IsValid()) + + # Test an expression evaluation + value = obj_val.EvaluateExpression("1") + self.assertTrue(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + # + # Test C++ computation result located in debuggee memory + # + + obj_val = frame.EvaluateExpression("cpp_namespace::GetCppStructPtr()") + self.assertTrue(obj_val.IsValid()) + + # Test an expression evaluation + value = obj_val.EvaluateExpression("1") + self.assertFalse(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + # Test retrieveing of a dereferenced object's field + value = obj_val.Dereference().EvaluateExpression("field") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 1111) + + def setUp(self): + TestBase.setUp(self) + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/context-object/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object/main.cpp new file mode 100644 index 00000000000..098b6089fce --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/context-object/main.cpp @@ -0,0 +1,46 @@ +namespace cpp_namespace { + struct CppStruct { + int field = 1111; + + int function() { + return 2222; + } + }; + + union CppUnion { + char field_char; + short field_short; + int field_int; + }; + + CppStruct GetCppStruct() { + return CppStruct(); + } + + CppStruct global; + + CppStruct *GetCppStructPtr() { + return &global; + } +} + +int global = 3333; + +int main() +{ + cpp_namespace::CppStruct cpp_struct = cpp_namespace::GetCppStruct(); + cpp_struct.function(); + + int field = 4444; + + cpp_namespace::CppUnion cpp_union; + cpp_union.field_int = 5555; + + int cpp_scalar = 6666; + + cpp_namespace::CppStruct cpp_array[16]; + + cpp_namespace::CppStruct *cpp_pointer = cpp_namespace::GetCppStructPtr(); + + return 0; // Break here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/dollar-in-variable/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/dollar-in-variable/Makefile new file mode 100644 index 00000000000..f5a47fcc46c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/dollar-in-variable/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +C_SOURCES := main.c +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/dollar-in-variable/TestDollarInVariable.py b/lldb/packages/Python/lldbsuite/test/commands/expression/dollar-in-variable/TestDollarInVariable.py new file mode 100644 index 00000000000..7458867527d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/dollar-in-variable/TestDollarInVariable.py @@ -0,0 +1,5 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + [lldbinline.expectedFailureAll(oslist=["windows"])]) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/dollar-in-variable/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/dollar-in-variable/main.c new file mode 100644 index 00000000000..e5fec25b35b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/dollar-in-variable/main.c @@ -0,0 +1,21 @@ +// Make sure we correctly handle $ in variable names. + +int main() { + // Some variables that might conflict with our variables below. + int __lldb_expr_result = 2; + int $$foo = 1; + int R0 = 2; + + // Some variables with dollar signs that should work (and shadow + // any built-in LLDB variables). + int $__lldb_expr_result = 11; + int $foo = 12; + int $R0 = 13; + int $0 = 14; + + //%self.expect("expr $__lldb_expr_result", substrs=['(int) $0 = 11']) + //%self.expect("expr $foo", substrs=['(int)', ' = 12']) + //%self.expect("expr $R0", substrs=['(int)', ' = 13']) + //%self.expect("expr int $foo = 123", error=True, substrs=["declaration conflicts"]) + return 0; //%self.expect("expr $0", substrs=['(int)', ' = 14']) +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/dont_allow_jit/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/dont_allow_jit/Makefile new file mode 100644 index 00000000000..50d4ab65a6e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/dont_allow_jit/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +C_SOURCES := main.c +CFLAGS_EXTRAS += -std=c99 + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/dont_allow_jit/TestAllowJIT.py b/lldb/packages/Python/lldbsuite/test/commands/expression/dont_allow_jit/TestAllowJIT.py new file mode 100644 index 00000000000..19d9fa7e425 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/dont_allow_jit/TestAllowJIT.py @@ -0,0 +1,87 @@ +""" +Test that --allow-jit=false does disallow JITting: +""" + +from __future__ import print_function + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * +from lldbsuite.test.decorators import * + +class TestAllowJIT(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # If your test case doesn't stress debug info, the + # set this to true. That way it won't be run once for + # each debug info format. + NO_DEBUG_INFO_TESTCASE = True + + def test_allow_jit_expr_command(self): + """Test the --allow-jit command line flag""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + self.expr_cmd_test() + + def test_allow_jit_options(self): + """Test the SetAllowJIT SBExpressionOption setting""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + self.expr_options_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def expr_cmd_test(self): + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file) + + frame = thread.GetFrameAtIndex(0) + + # First make sure we can call the function with + interp = self.dbg.GetCommandInterpreter() + self.expect("expr --allow-jit 1 -- call_me(10)", + substrs = ["(int) $", "= 18"]) + # Now make sure it fails with the "can't IR interpret message" if allow-jit is false: + self.expect("expr --allow-jit 0 -- call_me(10)", + error=True, + substrs = ["Can't run the expression locally"]) + + def expr_options_test(self): + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file) + + frame = thread.GetFrameAtIndex(0) + + # First make sure we can call the function with the default option set. + options = lldb.SBExpressionOptions() + # Check that the default is to allow JIT: + self.assertEqual(options.GetAllowJIT(), True, "Default is true") + + # Now use the options: + result = frame.EvaluateExpression("call_me(10)", options) + self.assertTrue(result.GetError().Success(), "expression succeeded") + self.assertEqual(result.GetValueAsSigned(), 18, "got the right value.") + + # Now disallow JIT and make sure it fails: + options.SetAllowJIT(False) + # Check that we got the right value: + self.assertEqual(options.GetAllowJIT(), False, "Got False after setting to False") + + # Again use it and ensure we fail: + result = frame.EvaluateExpression("call_me(10)", options) + self.assertTrue(result.GetError().Fail(), "expression failed with no JIT") + self.assertTrue("Can't run the expression locally" in result.GetError().GetCString(), "Got right error") + + # Finally set the allow JIT value back to true and make sure that works: + options.SetAllowJIT(True) + self.assertEqual(options.GetAllowJIT(), True, "Set back to True correctly") + + # And again, make sure this works: + result = frame.EvaluateExpression("call_me(10)", options) + self.assertTrue(result.GetError().Success(), "expression succeeded") + self.assertEqual(result.GetValueAsSigned(), 18, "got the right value.") + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/dont_allow_jit/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/dont_allow_jit/main.c new file mode 100644 index 00000000000..ebd8ae11a73 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/dont_allow_jit/main.c @@ -0,0 +1,15 @@ +#include <stdio.h> + +int +call_me(int input) +{ + return printf("I was called: %d.\n", input); +} + +int +main() +{ + int test_var = 10; + printf ("Set a breakpoint here: %d.\n", test_var); + return call_me(100); +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/entry-bp/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/entry-bp/Makefile new file mode 100644 index 00000000000..0d70f259501 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/entry-bp/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/entry-bp/TestExprEntryBP.py b/lldb/packages/Python/lldbsuite/test/commands/expression/entry-bp/TestExprEntryBP.py new file mode 100644 index 00000000000..56abc19f4f3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/entry-bp/TestExprEntryBP.py @@ -0,0 +1,34 @@ +""" +Tests expressions evaluation when the breakpoint on module's entry is set. +""" + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + +class ExprEntryBPTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + def test_expr_entry_bp(self): + """Tests expressions evaluation when the breakpoint on module's entry is set.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, "Set a breakpoint here", self.main_source_file) + + self.assertEqual(1, bkpt.GetNumLocations()) + entry = bkpt.GetLocationAtIndex(0).GetAddress().GetModule().GetObjectFileEntryPointAddress() + self.assertTrue(entry.IsValid(), "Can't get a module entry point") + + entry_bp = target.BreakpointCreateBySBAddress(entry) + self.assertTrue(entry_bp.IsValid(), "Can't set a breakpoint on the module entry point") + + result = target.EvaluateExpression("sum(7, 1)") + self.assertTrue(result.IsValid(), "Can't evaluate expression") + self.assertEqual(8, result.GetValueAsSigned()) + + def setUp(self): + TestBase.setUp(self) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/entry-bp/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/entry-bp/main.c new file mode 100644 index 00000000000..168fc9c8ccb --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/entry-bp/main.c @@ -0,0 +1,10 @@ +#include <stdio.h> + +int sum(int x, int y) { + return x + y; +} + +int main() { + printf("Set a breakpoint here.\n"); + return sum(-1, 1); +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/expr-in-syscall/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/expr-in-syscall/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/expr-in-syscall/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/expr-in-syscall/TestExpressionInSyscall.py b/lldb/packages/Python/lldbsuite/test/commands/expression/expr-in-syscall/TestExpressionInSyscall.py new file mode 100644 index 00000000000..6a7e6075253 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/expr-in-syscall/TestExpressionInSyscall.py @@ -0,0 +1,92 @@ +"""Test that we are able to evaluate expressions when the inferior is blocked in a syscall""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprSyscallTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + oslist=["windows"], + bugnumber="llvm.org/pr21765, getpid() does not exist on Windows") + @expectedFailureNetBSD + def test_setpgid(self): + self.build() + self.expr_syscall() + + def expr_syscall(self): + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + listener = lldb.SBListener("my listener") + + # launch the inferior and don't wait for it to stop + self.dbg.SetAsync(True) + error = lldb.SBError() + process = target.Launch(listener, + None, # argv + None, # envp + None, # stdin_path + None, # stdout_path + None, # stderr_path + None, # working directory + 0, # launch flags + False, # Stop at entry + error) # error + + self.assertTrue(process and process.IsValid(), PROCESS_IS_VALID) + + event = lldb.SBEvent() + + # Give the child enough time to reach the syscall, + # while clearing out all the pending events. + # The last WaitForEvent call will time out after 2 seconds. + while listener.WaitForEvent(2, event): + pass + + # now the process should be running (blocked in the syscall) + self.assertEqual( + process.GetState(), + lldb.eStateRunning, + "Process is running") + + # send the process a signal + process.SendAsyncInterrupt() + while listener.WaitForEvent(2, event): + pass + + # as a result the process should stop + # in all likelihood we have stopped in the middle of the sleep() + # syscall + self.assertEqual( + process.GetState(), + lldb.eStateStopped, + PROCESS_STOPPED) + thread = process.GetSelectedThread() + + # try evaluating a couple of expressions in this state + self.expect("expr release_flag = 1", substrs=[" = 1"]) + self.expect("print (int)getpid()", + substrs=[str(process.GetProcessID())]) + + # and run the process to completion + process.Continue() + + # process all events + while listener.WaitForEvent(10, event): + new_state = lldb.SBProcess.GetStateFromEvent(event) + if new_state == lldb.eStateExited: + break + + self.assertEqual(process.GetState(), lldb.eStateExited) + self.assertEqual(process.GetExitStatus(), 0) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/expr-in-syscall/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/expr-in-syscall/main.cpp new file mode 100644 index 00000000000..743b69434d5 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/expr-in-syscall/main.cpp @@ -0,0 +1,12 @@ +#include <chrono> +#include <thread> + +volatile int release_flag = 0; + +int main(int argc, char const *argv[]) +{ + while (! release_flag) // Wait for debugger to attach + std::this_thread::sleep_for(std::chrono::seconds(3)); + + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/fixits/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/fixits/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/fixits/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/fixits/TestFixIts.py b/lldb/packages/Python/lldbsuite/test/commands/expression/fixits/TestFixIts.py new file mode 100644 index 00000000000..9aa28f77a3f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/fixits/TestFixIts.py @@ -0,0 +1,72 @@ +""" +Test calling an expression with errors that a FixIt can fix. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandWithFixits(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + @skipUnlessDarwin + def test_with_target(self): + """Test calling expressions with errors that can be fixed by the FixIts.""" + self.build() + self.try_expressions() + + def test_with_dummy_target(self): + """Test calling expressions in the dummy target with errors that can be fixed by the FixIts.""" + ret_val = lldb.SBCommandReturnObject() + result = self.dbg.GetCommandInterpreter().HandleCommand("expression ((1 << 16) - 1))", ret_val) + self.assertEqual(result, lldb.eReturnStatusSuccessFinishResult, "The expression was successful.") + self.assertTrue("Fix-it applied" in ret_val.GetError(), "Found the applied FixIt.") + + def try_expressions(self): + """Test calling expressions with errors that can be fixed by the FixIts.""" + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Stop here to evaluate expressions', self.main_source_spec) + + options = lldb.SBExpressionOptions() + options.SetAutoApplyFixIts(True) + + frame = self.thread.GetFrameAtIndex(0) + + # Try with one error: + value = frame.EvaluateExpression("my_pointer.first", options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertTrue(value.GetValueAsUnsigned() == 10) + + # Try with two errors: + two_error_expression = "my_pointer.second->a" + value = frame.EvaluateExpression(two_error_expression, options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertTrue(value.GetValueAsUnsigned() == 20) + + # Now turn off the fixits, and the expression should fail: + options.SetAutoApplyFixIts(False) + value = frame.EvaluateExpression(two_error_expression, options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Fail()) + error_string = value.GetError().GetCString() + self.assertTrue( + error_string.find("fixed expression suggested:") != -1, + "Fix was suggested") + self.assertTrue( + error_string.find("my_pointer->second.a") != -1, + "Fix was right") diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/fixits/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/fixits/main.cpp new file mode 100644 index 00000000000..371d8333763 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/fixits/main.cpp @@ -0,0 +1,25 @@ +#include <stdio.h> + +struct SubStruct +{ + int a; + int b; +}; + +struct MyStruct +{ + int first; + struct SubStruct second; +}; + +int +main() +{ + struct MyStruct my_struct = {10, {20, 30}}; + struct MyStruct *my_pointer = &my_struct; + printf ("Stop here to evaluate expressions: %d %d %p\n", my_pointer->first, my_pointer->second.a, my_pointer); + return 0; +} + + + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/TestFormatters.py b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/TestFormatters.py new file mode 100644 index 00000000000..b13d6555f33 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/TestFormatters.py @@ -0,0 +1,287 @@ +""" +Test using LLDB data formatters with frozen objects coming from the expression parser. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprFormattersTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.cpp. + self.line = line_number('main.cpp', + '// Stop here') + + @skipIfFreeBSD # llvm.org/pr24691 skipping to avoid crashing the test runner + @expectedFailureNetBSD + @expectedFailureAll( + oslist=['freebsd'], + bugnumber='llvm.org/pr19011 Newer Clang omits C1 complete object constructor') + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") + @skipIfTargetAndroid() # skipping to avoid crashing the test runner + @expectedFailureAndroid('llvm.org/pr24691') # we hit an assertion in clang + def test(self): + """Test expr + formatters for good interoperability.""" + self.build() + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type summary clear', check=False) + self.runCmd('type synthetic clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + """Test expr + formatters for good interoperability.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + self.runCmd("command script import formatters.py") + self.runCmd("command script import foosynth.py") + + if self.TraceOn(): + self.runCmd("frame variable foo1 --show-types") + self.runCmd("frame variable foo1.b --show-types") + self.runCmd("frame variable foo1.b.b_ref --show-types") + + self.filecheck("expression --show-types -- *(new foo(47))", __file__, + '-check-prefix=EXPR-TYPES-NEW-FOO') + # EXPR-TYPES-NEW-FOO: (foo) ${{.*}} = { + # EXPR-TYPES-NEW-FOO-NEXT: (int) a = 47 + # EXPR-TYPES-NEW-FOO-NEXT: (int *) a_ptr = 0x + # EXPR-TYPES-NEW-FOO-NEXT: (bar) b = { + # EXPR-TYPES-NEW-FOO-NEXT: (int) i = 94 + # EXPR-TYPES-NEW-FOO-NEXT: (int *) i_ptr = 0x + # EXPR-TYPES-NEW-FOO-NEXT: (baz) b = { + # EXPR-TYPES-NEW-FOO-NEXT: (int) h = 97 + # EXPR-TYPES-NEW-FOO-NEXT: (int) k = 99 + # EXPR-TYPES-NEW-FOO-NEXT: } + # EXPR-TYPES-NEW-FOO-NEXT: (baz &) b_ref = 0x + # EXPR-TYPES-NEW-FOO-NEXT: } + # EXPR-TYPES-NEW-FOO-NEXT: } + + self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") + + self.expect("expression new int(12)", + substrs=['(int *) $', ' = 0x']) + + self.runCmd( + "type summary add -s \"${var%pointer} -> ${*var%decimal}\" \"int *\"") + + self.expect("expression new int(12)", + substrs=['(int *) $', '= 0x', ' -> 12']) + + self.expect("expression foo1.a_ptr", + substrs=['(int *) $', '= 0x', ' -> 13']) + + self.filecheck("expression foo1", __file__, '-check-prefix=EXPR-FOO1') + # EXPR-FOO1: (foo) $ + # EXPR-FOO1-SAME: a = 12 + # EXPR-FOO1-SAME: a_ptr = {{[0-9]+}} -> 13 + # EXPR-FOO1-SAME: i = 24 + # EXPR-FOO1-SAME: i_ptr = {{[0-9]+}} -> 25 + # EXPR-FOO1-SAME: b_ref = {{[0-9]+}} + # EXPR-FOO1-SAME: h = 27 + # EXPR-FOO1-SAME: k = 29 + + self.filecheck("expression --ptr-depth=1 -- new foo(47)", __file__, + '-check-prefix=EXPR-PTR-DEPTH1') + # EXPR-PTR-DEPTH1: (foo *) $ + # EXPR-PTR-DEPTH1-SAME: a = 47 + # EXPR-PTR-DEPTH1-SAME: a_ptr = {{[0-9]+}} -> 48 + # EXPR-PTR-DEPTH1-SAME: i = 94 + # EXPR-PTR-DEPTH1-SAME: i_ptr = {{[0-9]+}} -> 95 + + self.filecheck("expression foo2", __file__, '-check-prefix=EXPR-FOO2') + # EXPR-FOO2: (foo) $ + # EXPR-FOO2-SAME: a = 121 + # EXPR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122 + # EXPR-FOO2-SAME: i = 242 + # EXPR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243 + # EXPR-FOO2-SAME: h = 245 + # EXPR-FOO2-SAME: k = 247 + + object_name = self.res.GetOutput() + object_name = object_name[7:] + object_name = object_name[0:object_name.find(' =')] + + self.filecheck("frame variable foo2", __file__, '-check-prefix=VAR-FOO2') + # VAR-FOO2: (foo) foo2 + # VAR-FOO2-SAME: a = 121 + # VAR-FOO2-SAME: a_ptr = {{[0-9]+}} -> 122 + # VAR-FOO2-SAME: i = 242 + # VAR-FOO2-SAME: i_ptr = {{[0-9]+}} -> 243 + # VAR-FOO2-SAME: h = 245 + # VAR-FOO2-SAME: k = 247 + + # The object is the same as foo2, so use the EXPR-FOO2 checks. + self.filecheck("expression $" + object_name, __file__, + '-check-prefix=EXPR-FOO2') + + self.runCmd("type summary delete foo") + self.runCmd( + "type synthetic add --python-class foosynth.FooSyntheticProvider foo") + + self.expect("expression --show-types -- $" + object_name, + substrs=['(foo) $', ' = {', '(int) *i_ptr = 243']) + + self.runCmd("n") + self.runCmd("n") + + self.runCmd("type synthetic delete foo") + self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") + + self.expect( + "expression foo2", + substrs=[ + '(foo) $', + 'a = 7777', + 'a_ptr = ', + ' -> 122', + 'i = 242', + 'i_ptr = ', + ' -> 8888']) + + self.expect("expression $" + object_name + '.a', + substrs=['7777']) + + self.expect("expression *$" + object_name + '.b.i_ptr', + substrs=['8888']) + + self.expect( + "expression $" + + object_name, + substrs=[ + '(foo) $', + 'a = 121', + 'a_ptr = ', + ' -> 122', + 'i = 242', + 'i_ptr = ', + ' -> 8888', + 'h = 245', + 'k = 247']) + + self.runCmd("type summary delete foo") + self.runCmd( + "type synthetic add --python-class foosynth.FooSyntheticProvider foo") + + self.expect("expression --show-types -- $" + object_name, + substrs=['(foo) $', ' = {', '(int) *i_ptr = 8888']) + + self.runCmd("n") + + self.runCmd("type synthetic delete foo") + self.runCmd("type summary add -F formatters.foo_SummaryProvider foo") + + self.expect( + "expression $" + + object_name, + substrs=[ + '(foo) $', + 'a = 121', + 'a_ptr = ', + ' -> 122', + 'i = 242', + 'i_ptr = ', + ' -> 8888', + 'k = 247']) + + process = self.dbg.GetSelectedTarget().GetProcess() + thread = process.GetThreadAtIndex(0) + frame = thread.GetSelectedFrame() + + frozen = frame.EvaluateExpression("$" + object_name + ".a_ptr") + + a_data = frozen.GetPointeeData() + + error = lldb.SBError() + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 0) == 122, + '*a_ptr = 122') + + self.runCmd("n") + self.runCmd("n") + self.runCmd("n") + + self.expect("frame variable numbers", + substrs=['1', '2', '3', '4', '5']) + + self.expect("expression numbers", + substrs=['1', '2', '3', '4', '5']) + + frozen = frame.EvaluateExpression("&numbers") + + a_data = frozen.GetPointeeData(0, 1) + + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 0) == 1, + 'numbers[0] == 1') + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 4) == 2, + 'numbers[1] == 2') + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 8) == 3, + 'numbers[2] == 3') + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 12) == 4, + 'numbers[3] == 4') + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 16) == 5, + 'numbers[4] == 5') + + frozen = frame.EvaluateExpression("numbers") + + a_data = frozen.GetData() + + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 0) == 1, + 'numbers[0] == 1') + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 4) == 2, + 'numbers[1] == 2') + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 8) == 3, + 'numbers[2] == 3') + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 12) == 4, + 'numbers[3] == 4') + self.assertTrue( + a_data.GetUnsignedInt32( + error, + 16) == 5, + 'numbers[4] == 5') diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/foosynth.py b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/foosynth.py new file mode 100644 index 00000000000..7b1284d2a76 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/foosynth.py @@ -0,0 +1,33 @@ +import lldb + + +class FooSyntheticProvider: + + def __init__(self, valobj, dict): + self.valobj = valobj + self.update() + + def update(self): + self.adjust_for_architecture() + + def num_children(self): + return 1 + + def get_child_at_index(self, index): + if index != 0: + return None + return self.i_ptr.Dereference() + + def get_child_index(self, name): + if name == "*i_ptr": + return 0 + return None + + def adjust_for_architecture(self): + self.lp64 = ( + self.valobj.GetTarget().GetProcess().GetAddressByteSize() == 8) + self.is_little = (self.valobj.GetTarget().GetProcess( + ).GetByteOrder() == lldb.eByteOrderLittle) + self.pointer_size = self.valobj.GetTarget().GetProcess().GetAddressByteSize() + self.bar = self.valobj.GetChildMemberWithName('b') + self.i_ptr = self.bar.GetChildMemberWithName('i_ptr') diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/formatters.py b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/formatters.py new file mode 100644 index 00000000000..dae84988af9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/formatters.py @@ -0,0 +1,17 @@ +def foo_SummaryProvider(valobj, dict): + a = valobj.GetChildMemberWithName('a') + a_ptr = valobj.GetChildMemberWithName('a_ptr') + bar = valobj.GetChildMemberWithName('b') + i = bar.GetChildMemberWithName('i') + i_ptr = bar.GetChildMemberWithName('i_ptr') + b_ref = bar.GetChildMemberWithName('b_ref') + b_ref_ptr = b_ref.AddressOf() + b_ref = b_ref_ptr.Dereference() + h = b_ref.GetChildMemberWithName('h') + k = b_ref.GetChildMemberWithName('k') + return 'a = ' + str(a.GetValueAsUnsigned(0)) + ', a_ptr = ' + \ + str(a_ptr.GetValueAsUnsigned(0)) + ' -> ' + str(a_ptr.Dereference().GetValueAsUnsigned(0)) + \ + ', i = ' + str(i.GetValueAsUnsigned(0)) + \ + ', i_ptr = ' + str(i_ptr.GetValueAsUnsigned(0)) + ' -> ' + str(i_ptr.Dereference().GetValueAsUnsigned(0)) + \ + ', b_ref = ' + str(b_ref.GetValueAsUnsigned(0)) + \ + ', h = ' + str(h.GetValueAsUnsigned(0)) + ' , k = ' + str(k.GetValueAsUnsigned(0)) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/main.cpp new file mode 100644 index 00000000000..1b8ce48041f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/formatters/main.cpp @@ -0,0 +1,48 @@ +#include <iostream> +#include <string> + +struct baz + { + int h; + int k; + baz(int a, int b) : h(a), k(b) {} + }; + +struct bar + { + int i; + int* i_ptr; + baz b; + baz& b_ref; + bar(int x) : i(x),i_ptr(new int(x+1)),b(i+3,i+5),b_ref(b) {} + }; + +struct foo + { + int a; + int* a_ptr; + bar b; + + foo(int x) : a(x), + a_ptr(new int(x+1)), + b(2*x) {} + + }; + +int main(int argc, char** argv) +{ + foo foo1(12); + foo foo2(121); + + foo2.a = 7777; // Stop here + *(foo2.b.i_ptr) = 8888; + foo2.b.b.h = 9999; + + *(foo1.a_ptr) = 9999; + foo1.b.i = 9999; + + int numbers[5] = {1,2,3,4,5}; + + return 0; + +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/function_template_specialization_temp_args/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/function_template_specialization_temp_args/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/function_template_specialization_temp_args/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/function_template_specialization_temp_args/TestFunctionTemplateSpecializationTempArgs.py b/lldb/packages/Python/lldbsuite/test/commands/expression/function_template_specialization_temp_args/TestFunctionTemplateSpecializationTempArgs.py new file mode 100644 index 00000000000..bd5bc0ec72a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/function_template_specialization_temp_args/TestFunctionTemplateSpecializationTempArgs.py @@ -0,0 +1,17 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestFunctionTemplateSpecializationTempArgs(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_function_template_specialization_temp_args(self): + self.build() + + (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + self.expect("expr p0", + substrs=['(VType) $0 = {}']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/function_template_specialization_temp_args/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/function_template_specialization_temp_args/main.cpp new file mode 100644 index 00000000000..6d01288259a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/function_template_specialization_temp_args/main.cpp @@ -0,0 +1,17 @@ +template <typename T> struct M {}; + +template <typename T> void f(T &t); + +template <> void f<int>(int &t) { + typedef M<int> VType; + + VType p0; // break here +} + +int main() { + int x; + + f(x); + + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/TestImportStdModule.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/TestImportStdModule.py new file mode 100644 index 00000000000..19e02ca84c9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/TestImportStdModule.py @@ -0,0 +1,56 @@ +""" +Test importing the 'std' C++ module and evaluate expressions with it. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ImportStdModule(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + # Activate importing of std module. + self.runCmd("settings set target.import-std-module true") + # Calling some normal std functions that return non-template types. + self.expect("expr std::abs(-42)", substrs=['(int) $0 = 42']) + self.expect("expr std::div(2, 1).quot", substrs=['(int) $1 = 2']) + # Using types from std. + self.expect("expr (std::size_t)33U", substrs=['(size_t) $2 = 33']) + # Calling templated functions that return non-template types. + self.expect("expr char char_a = 'b'; char char_b = 'a'; std::swap(char_a, char_b); char_a", + substrs=["(char) $3 = 'a'"]) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test_non_cpp_language(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + # Activate importing of std module. + self.runCmd("settings set target.import-std-module true") + # These languages don't support C++ modules, so they shouldn't + # be able to evaluate the expression. + self.expect("expr -l C -- std::abs(-42)", error=True) + self.expect("expr -l C99 -- std::abs(-42)", error=True) + self.expect("expr -l C11 -- std::abs(-42)", error=True) + self.expect("expr -l ObjC -- std::abs(-42)", error=True) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/main.cpp new file mode 100644 index 00000000000..2f6d078daa3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/basic/main.cpp @@ -0,0 +1,7 @@ +// We need to import any std module. It doesn't matter which one. +#include <iostream> + +int main(int argc, char **argv) { + std::cout << "Test" << std::endl; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/TestStdModuleWithConflicts.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/TestStdModuleWithConflicts.py new file mode 100644 index 00000000000..2abaece27fe --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/TestStdModuleWithConflicts.py @@ -0,0 +1,36 @@ +""" +Test importing the 'std' C++ module and check if we can handle +prioritizing the conflicting functions from debug info and std +module. + +See also import-std-module/basic/TestImportStdModule.py for +the same test on a 'clean' code base without conflicts. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestImportStdModuleConflicts(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + self.expect("expr std::abs(-42)", substrs=['(int) $0 = 42']) + self.expect("expr std::div(2, 1).quot", substrs=['(int) $1 = 2']) + self.expect("expr (std::size_t)33U", substrs=['(size_t) $2 = 33']) + self.expect("expr char char_a = 'b'; char char_b = 'a'; std::swap(char_a, char_b); char_a", + substrs=["(char) $3 = 'a'"]) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/main.cpp new file mode 100644 index 00000000000..e49b862a36c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/conflicts/main.cpp @@ -0,0 +1,10 @@ +#include <cstdlib> +#include <utility> + +int main(int argc, char **argv) { + std::size_t f = argc; + f = std::abs(argc); + f = std::div(argc * 2, argc).quot; + std::swap(f, f); + return f; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/TestBasicDeque.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/TestBasicDeque.py new file mode 100644 index 00000000000..0ede19e8350 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/TestBasicDeque.py @@ -0,0 +1,41 @@ +""" +Test basic std::list functionality. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestBasicDeque(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3']) + self.expect("expr (int)a.front()", substrs=['(int) $1 = 3']) + self.expect("expr (int)a.back()", substrs=['(int) $2 = 2']) + + self.expect("expr std::sort(a.begin(), a.end())") + self.expect("expr (int)a.front()", substrs=['(int) $3 = 1']) + self.expect("expr (int)a.back()", substrs=['(int) $4 = 3']) + + self.expect("expr std::reverse(a.begin(), a.end())") + self.expect("expr (int)a.front()", substrs=['(int) $5 = 3']) + self.expect("expr (int)a.back()", substrs=['(int) $6 = 1']) + + self.expect("expr (int)(*a.begin())", substrs=['(int) $7 = 3']) + self.expect("expr (int)(*a.rbegin())", substrs=['(int) $8 = 1']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/main.cpp new file mode 100644 index 00000000000..5bed55674bf --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-basic/main.cpp @@ -0,0 +1,6 @@ +#include <deque> + +int main(int argc, char **argv) { + std::deque<int> a = {3, 1, 2}; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py new file mode 100644 index 00000000000..eeea34819dd --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/TestDbgInfoContentDeque.py @@ -0,0 +1,37 @@ +""" +Test std::deque functionality with a decl from dbg info as content. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestDbgInfoContentDeque(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3']) + self.expect("expr (int)a.front().a", substrs=['(int) $1 = 3']) + self.expect("expr (int)a.back().a", substrs=['(int) $2 = 2']) + + self.expect("expr std::reverse(a.begin(), a.end())") + self.expect("expr (int)a.front().a", substrs=['(int) $3 = 2']) + self.expect("expr (int)a.back().a", substrs=['(int) $4 = 3']) + + self.expect("expr (int)(a.begin()->a)", substrs=['(int) $5 = 2']) + self.expect("expr (int)(a.rbegin()->a)", substrs=['(int) $6 = 3']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/main.cpp new file mode 100644 index 00000000000..f8fd1fb2dd9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/deque-dbg-info-content/main.cpp @@ -0,0 +1,10 @@ +#include <deque> + +struct Foo { + int a; +}; + +int main(int argc, char **argv) { + std::deque<Foo> a = {{3}, {1}, {2}}; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/TestBasicForwardList.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/TestBasicForwardList.py new file mode 100644 index 00000000000..528d555e0af --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/TestBasicForwardList.py @@ -0,0 +1,34 @@ +""" +Test basic std::forward_list functionality. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestBasicForwardList(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (size_t)std::distance(a.begin(), a.end())", substrs=['(size_t) $0 = 3']) + self.expect("expr (int)a.front()", substrs=['(int) $1 = 3']) + + self.expect("expr a.sort()") + self.expect("expr (int)a.front()", substrs=['(int) $2 = 1']) + + self.expect("expr (int)(*a.begin())", substrs=['(int) $3 = 1']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/main.cpp new file mode 100644 index 00000000000..4f5e30f0629 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-basic/main.cpp @@ -0,0 +1,6 @@ +#include <forward_list> + +int main(int argc, char **argv) { + std::forward_list<int> a = {3, 1, 2}; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py new file mode 100644 index 00000000000..a2fc5598930 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/TestDbgInfoContentForwardList.py @@ -0,0 +1,31 @@ +""" +Test std::forward_list functionality with a decl from debug info as content. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestDbgInfoContentForwardList(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (size_t)std::distance(a.begin(), a.end())", substrs=['(size_t) $0 = 3']) + self.expect("expr (int)a.front().a", substrs=['(int) $1 = 3']) + + self.expect("expr (int)(a.begin()->a)", substrs=['(int) $2 = 3']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/main.cpp new file mode 100644 index 00000000000..b1ffc4b24cd --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/forward_list-dbg-info-content/main.cpp @@ -0,0 +1,10 @@ +#include <forward_list> + +struct Foo { + int a; +}; + +int main(int argc, char **argv) { + std::forward_list<Foo> a = {{3}, {1}, {2}}; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/TestBasicList.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/TestBasicList.py new file mode 100644 index 00000000000..154c8ed7bd0 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/TestBasicList.py @@ -0,0 +1,41 @@ +""" +Test basic std::list functionality. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestBasicList(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3']) + self.expect("expr (int)a.front()", substrs=['(int) $1 = 3']) + self.expect("expr (int)a.back()", substrs=['(int) $2 = 2']) + + self.expect("expr a.sort()") + self.expect("expr (int)a.front()", substrs=['(int) $3 = 1']) + self.expect("expr (int)a.back()", substrs=['(int) $4 = 3']) + + self.expect("expr std::reverse(a.begin(), a.end())") + self.expect("expr (int)a.front()", substrs=['(int) $5 = 3']) + self.expect("expr (int)a.back()", substrs=['(int) $6 = 1']) + + self.expect("expr (int)(*a.begin())", substrs=['(int) $7 = 3']) + self.expect("expr (int)(*a.rbegin())", substrs=['(int) $8 = 1']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/main.cpp new file mode 100644 index 00000000000..e54719a02fb --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-basic/main.cpp @@ -0,0 +1,6 @@ +#include <list> + +int main(int argc, char **argv) { + std::list<int> a = {3, 1, 2}; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py new file mode 100644 index 00000000000..713ec1abb85 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/TestDbgInfoContentList.py @@ -0,0 +1,38 @@ +""" +Test basic std::list functionality but with a declaration from +the debug info (the Foo struct) as content. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestDbgInfoContentList(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3']) + self.expect("expr (int)a.front().a", substrs=['(int) $1 = 3']) + self.expect("expr (int)a.back().a", substrs=['(int) $2 = 2']) + + self.expect("expr std::reverse(a.begin(), a.end())") + self.expect("expr (int)a.front().a", substrs=['(int) $3 = 2']) + self.expect("expr (int)a.back().a", substrs=['(int) $4 = 3']) + + self.expect("expr (int)(a.begin()->a)", substrs=['(int) $5 = 2']) + self.expect("expr (int)(a.rbegin()->a)", substrs=['(int) $6 = 3']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/main.cpp new file mode 100644 index 00000000000..3cfb35f8c6b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/list-dbg-info-content/main.cpp @@ -0,0 +1,10 @@ +#include <list> + +struct Foo { + int a; +}; + +int main(int argc, char **argv) { + std::list<Foo> a = {{3}, {1}, {2}}; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/TestMissingStdModule.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/TestMissingStdModule.py new file mode 100644 index 00000000000..f4d3d1fd492 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/TestMissingStdModule.py @@ -0,0 +1,40 @@ +""" +Test that importing the std module on a compile unit +that doesn't use the std module will not break LLDB. + +It's not really specified at the moment what kind of +error we should report back to the user in this +situation. Currently Clang will just complain that +the std module doesn't exist or can't be loaded. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class STLTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + # Activate importing of std module. + self.runCmd("settings set target.import-std-module true") + + # Run some commands that should all fail without our std module. + self.expect("expr std::abs(-42)", error=True) + self.expect("expr std::div(2, 1).quot", error=True) + self.expect("expr (std::size_t)33U", error=True) + self.expect("expr char a = 'b'; char b = 'a'; std::swap(a, b); a", + error=True) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/main.cpp new file mode 100644 index 00000000000..c93e9d0ec8a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/no-std-module/main.cpp @@ -0,0 +1,5 @@ +// We don't import any std module here. + +int main(int argc, char **argv) { + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/TestQueue.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/TestQueue.py new file mode 100644 index 00000000000..aad1b11719b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/TestQueue.py @@ -0,0 +1,47 @@ +""" +Tests std::queue functionality. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestQueue(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + # Test std::queue functionality with a std::deque. + self.expect("expr q_deque.pop()") + self.expect("expr q_deque.push({4})") + self.expect("expr (size_t)q_deque.size()", substrs=['(size_t) $0 = 1']) + self.expect("expr (int)q_deque.front().i", substrs=['(int) $1 = 4']) + self.expect("expr (int)q_deque.back().i", substrs=['(int) $2 = 4']) + self.expect("expr q_deque.empty()", substrs=['(bool) $3 = false']) + self.expect("expr q_deque.pop()") + self.expect("expr q_deque.emplace(5)") + self.expect("expr (int)q_deque.front().i", substrs=['(int) $4 = 5']) + + # Test std::queue functionality with a std::list. + self.expect("expr q_list.pop()") + self.expect("expr q_list.push({4})") + self.expect("expr (size_t)q_list.size()", substrs=['(size_t) $5 = 1']) + self.expect("expr (int)q_list.front().i", substrs=['(int) $6 = 4']) + self.expect("expr (int)q_list.back().i", substrs=['(int) $7 = 4']) + self.expect("expr q_list.empty()", substrs=['(bool) $8 = false']) + self.expect("expr q_list.pop()") + self.expect("expr q_list.emplace(5)") + self.expect("expr (int)q_list.front().i", substrs=['(int) $9 = 5']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/main.cpp new file mode 100644 index 00000000000..66e8f02c273 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/queue/main.cpp @@ -0,0 +1,16 @@ +#include <deque> +#include <list> +#include <queue> + +struct C { + // Constructor for testing emplace. + C(int i) : i(i) {}; + int i; +}; + +int main(int argc, char **argv) { + // std::deque is the default container. + std::queue<C> q_deque({{1}}); + std::queue<C, std::list<C>> q_list({{1}}); + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py new file mode 100644 index 00000000000..028798f72f3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/TestSharedPtrDbgInfoContent.py @@ -0,0 +1,33 @@ +""" +Test std::shared_ptr functionality with a class from debug info as content. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestSharedPtrDbgInfoContent(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (int)s->a", substrs=['(int) $0 = 3']) + self.expect("expr (int)(s->a = 5)", substrs=['(int) $1 = 5']) + self.expect("expr (int)s->a", substrs=['(int) $2 = 5']) + self.expect("expr (bool)s", substrs=['(bool) $3 = true']) + self.expect("expr s.reset()") + self.expect("expr (bool)s", substrs=['(bool) $4 = false']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/main.cpp new file mode 100644 index 00000000000..73664f1c83a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr-dbg-info-content/main.cpp @@ -0,0 +1,11 @@ +#include <memory> + +struct Foo { + int a; +}; + +int main(int argc, char **argv) { + std::shared_ptr<Foo> s(new Foo); + s->a = 3; + return s->a; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/TestSharedPtr.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/TestSharedPtr.py new file mode 100644 index 00000000000..6f1e7b12d1f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/TestSharedPtr.py @@ -0,0 +1,33 @@ +""" +Test basic std::shared_ptr functionality. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestSharedPtr(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (int)*s", substrs=['(int) $0 = 3']) + self.expect("expr (int)(*s = 5)", substrs=['(int) $1 = 5']) + self.expect("expr (int)*s", substrs=['(int) $2 = 5']) + self.expect("expr (bool)s", substrs=['(bool) $3 = true']) + self.expect("expr s.reset()") + self.expect("expr (bool)s", substrs=['(bool) $4 = false']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/main.cpp new file mode 100644 index 00000000000..cb81754087f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/shared_ptr/main.cpp @@ -0,0 +1,7 @@ +#include <memory> + +int main(int argc, char **argv) { + std::shared_ptr<int> s(new int); + *s = 3; + return *s; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/TestStack.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/TestStack.py new file mode 100644 index 00000000000..1c2e5da54ed --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/TestStack.py @@ -0,0 +1,49 @@ +""" +Tests std::stack functionality. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestStack(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + # Test std::stack functionality with a std::deque. + self.expect("expr s_deque.pop()") + self.expect("expr s_deque.push({4})") + self.expect("expr (size_t)s_deque.size()", substrs=['(size_t) $0 = 3']) + self.expect("expr (int)s_deque.top().i", substrs=['(int) $1 = 4']) + self.expect("expr s_deque.emplace(5)") + self.expect("expr (int)s_deque.top().i", substrs=['(int) $2 = 5']) + + # Test std::stack functionality with a std::vector. + self.expect("expr s_vector.pop()") + self.expect("expr s_vector.push({4})") + self.expect("expr (size_t)s_vector.size()", substrs=['(size_t) $3 = 3']) + self.expect("expr (int)s_vector.top().i", substrs=['(int) $4 = 4']) + self.expect("expr s_vector.emplace(5)") + self.expect("expr (int)s_vector.top().i", substrs=['(int) $5 = 5']) + + # Test std::stack functionality with a std::list. + self.expect("expr s_list.pop()") + self.expect("expr s_list.push({4})") + self.expect("expr (size_t)s_list.size()", substrs=['(size_t) $6 = 3']) + self.expect("expr (int)s_list.top().i", substrs=['(int) $7 = 4']) + self.expect("expr s_list.emplace(5)") + self.expect("expr (int)s_list.top().i", substrs=['(int) $8 = 5']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/main.cpp new file mode 100644 index 00000000000..0ce94990733 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/stack/main.cpp @@ -0,0 +1,17 @@ +#include <list> +#include <stack> +#include <vector> + +struct C { + // Constructor for testing emplace. + C(int i) : i(i) {}; + int i; +}; + +int main(int argc, char **argv) { + // std::deque is the default container. + std::stack<C> s_deque({{1}, {2}, {3}}); + std::stack<C, std::vector<C>> s_vector({{1}, {2}, {3}}); + std::stack<C, std::list<C>> s_list({{1}, {2}, {3}}); + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/Makefile new file mode 100644 index 00000000000..e04d73ea487 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/Makefile @@ -0,0 +1,10 @@ +LEVEL = ../../../make +# We don't have any standard include directories, so we can't +# parse the test_common.h header we usually inject as it includes +# system headers. +NO_TEST_COMMON_H := 1 + +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXXFLAGS += -I $(SRCDIR)/root/usr/include/c++/include/ -I $(SRCDIR)/root/usr/include/ -nostdinc -nostdinc++ -nostdlib++ +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/TestStdModuleSysroot.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/TestStdModuleSysroot.py new file mode 100644 index 00000000000..dfd90e80e45 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/TestStdModuleSysroot.py @@ -0,0 +1,34 @@ +""" +Test that we respect the sysroot when building the std module. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil +import os + +class ImportStdModule(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + sysroot = os.path.join(os.getcwd(), "root") + + # Set the sysroot. + self.runCmd("platform select --sysroot '" + sysroot + "' host", CURRENT_EXECUTABLE_SET) + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + # Call our custom function in our sysroot std module. + # If this gives us the correct result, then we used the sysroot. + self.expect("expr std::myabs(-42)", substrs=['(int) $0 = 42']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/main.cpp new file mode 100644 index 00000000000..2fbc76b9a76 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/main.cpp @@ -0,0 +1,6 @@ +#include <algorithm> + +int main(int argc, char **argv) { + libc_struct s; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/root/usr/include/c++/include/algorithm b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/root/usr/include/c++/include/algorithm new file mode 100644 index 00000000000..e8cbcca8e84 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/root/usr/include/c++/include/algorithm @@ -0,0 +1,7 @@ +#include "libc_header.h" + +namespace std { + int myabs(int i) { + return i < 0 ? -i : i; + } +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/root/usr/include/c++/include/module.modulemap b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/root/usr/include/c++/include/module.modulemap new file mode 100644 index 00000000000..0eb48492a65 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/root/usr/include/c++/include/module.modulemap @@ -0,0 +1,3 @@ +module std { + module "algorithm" { header "algorithm" export * } +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/root/usr/include/libc_header.h b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/root/usr/include/libc_header.h new file mode 100644 index 00000000000..47525c9db34 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/sysroot/root/usr/include/libc_header.h @@ -0,0 +1 @@ +struct libc_struct {}; diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py new file mode 100644 index 00000000000..c321d8022e1 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/TestUniquePtrDbgInfoContent.py @@ -0,0 +1,33 @@ +""" +Test std::unique_ptr functionality with a decl from debug info as content. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestUniquePtrDbgInfoContent(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (int)s->a", substrs=['(int) $0 = 3']) + self.expect("expr (int)(s->a = 5)", substrs=['(int) $1 = 5']) + self.expect("expr (int)s->a", substrs=['(int) $2 = 5']) + self.expect("expr (bool)s", substrs=['(bool) $3 = true']) + self.expect("expr s.reset()") + self.expect("expr (bool)s", substrs=['(bool) $4 = false']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/main.cpp new file mode 100644 index 00000000000..73664f1c83a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr-dbg-info-content/main.cpp @@ -0,0 +1,11 @@ +#include <memory> + +struct Foo { + int a; +}; + +int main(int argc, char **argv) { + std::shared_ptr<Foo> s(new Foo); + s->a = 3; + return s->a; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/TestUniquePtr.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/TestUniquePtr.py new file mode 100644 index 00000000000..295ec512327 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/TestUniquePtr.py @@ -0,0 +1,33 @@ +""" +Test basic std::unique_ptr functionality. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestUniquePtr(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (int)*s", substrs=['(int) $0 = 3']) + self.expect("expr (int)(*s = 5)", substrs=['(int) $1 = 5']) + self.expect("expr (int)*s", substrs=['(int) $2 = 5']) + self.expect("expr (bool)s", substrs=['(bool) $3 = true']) + self.expect("expr s.reset()") + self.expect("expr (bool)s", substrs=['(bool) $4 = false']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/main.cpp new file mode 100644 index 00000000000..cb81754087f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/unique_ptr/main.cpp @@ -0,0 +1,7 @@ +#include <memory> + +int main(int argc, char **argv) { + std::shared_ptr<int> s(new int); + *s = 3; + return *s; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/TestBasicVector.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/TestBasicVector.py new file mode 100644 index 00000000000..deaf8f0cb75 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/TestBasicVector.py @@ -0,0 +1,57 @@ +""" +Test basic std::vector functionality. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestBasicVector(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3']) + self.expect("expr (int)a.front()", substrs=['(int) $1 = 3']) + self.expect("expr (int)a[1]", substrs=['(int) $2 = 1']) + self.expect("expr (int)a.back()", substrs=['(int) $3 = 2']) + + self.expect("expr std::sort(a.begin(), a.end())") + self.expect("expr (int)a.front()", substrs=['(int) $4 = 1']) + self.expect("expr (int)a[1]", substrs=['(int) $5 = 2']) + self.expect("expr (int)a.back()", substrs=['(int) $6 = 3']) + + self.expect("expr std::reverse(a.begin(), a.end())") + self.expect("expr (int)a.front()", substrs=['(int) $7 = 3']) + self.expect("expr (int)a[1]", substrs=['(int) $8 = 2']) + self.expect("expr (int)a.back()", substrs=['(int) $9 = 1']) + + self.expect("expr (int)(*a.begin())", substrs=['(int) $10 = 3']) + self.expect("expr (int)(*a.rbegin())", substrs=['(int) $11 = 1']) + + self.expect("expr a.pop_back()") + self.expect("expr (int)a.back()", substrs=['(int) $12 = 2']) + self.expect("expr (size_t)a.size()", substrs=['(size_t) $13 = 2']) + + self.expect("expr (int)a.at(0)", substrs=['(int) $14 = 3']) + + self.expect("expr a.push_back(4)") + self.expect("expr (int)a.back()", substrs=['(int) $15 = 4']) + self.expect("expr (size_t)a.size()", substrs=['(size_t) $16 = 3']) + + self.expect("expr a.emplace_back(5)") + self.expect("expr (int)a.back()", substrs=['(int) $17 = 5']) + self.expect("expr (size_t)a.size()", substrs=['(size_t) $18 = 4']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/main.cpp new file mode 100644 index 00000000000..edf130d4748 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-basic/main.cpp @@ -0,0 +1,6 @@ +#include <vector> + +int main(int argc, char **argv) { + std::vector<int> a = {3, 1, 2}; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/TestBoolVector.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/TestBoolVector.py new file mode 100644 index 00000000000..0ab52695faf --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/TestBoolVector.py @@ -0,0 +1,34 @@ +""" +Test basic std::vector<bool> functionality. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestBoolVector(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 4']) + self.expect("expr (bool)a.front()", substrs=['(bool) $1 = false']) + self.expect("expr (bool)a[1]", substrs=['(bool) $2 = true']) + self.expect("expr (bool)a.back()", substrs=['(bool) $3 = true']) + + self.expect("expr (bool)(*a.begin())", substrs=['(bool) $4 = false']) + self.expect("expr (bool)(*a.rbegin())", substrs=['(bool) $5 = true']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/main.cpp new file mode 100644 index 00000000000..9554401cf50 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-bool/main.cpp @@ -0,0 +1,6 @@ +#include <vector> + +int main(int argc, char **argv) { + std::vector<bool> a = {0, 1, 0, 1}; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py new file mode 100644 index 00000000000..c89265f2cd3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/TestDbgInfoContentVector.py @@ -0,0 +1,47 @@ +""" +Test basic std::vector functionality but with a declaration from +the debug info (the Foo struct) as content. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestDbgInfoContentVector(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 3']) + self.expect("expr (int)a.front().a", substrs=['(int) $1 = 3']) + self.expect("expr (int)a[1].a", substrs=['(int) $2 = 1']) + self.expect("expr (int)a.back().a", substrs=['(int) $3 = 2']) + + self.expect("expr std::reverse(a.begin(), a.end())") + self.expect("expr (int)a.front().a", substrs=['(int) $4 = 2']) + + self.expect("expr (int)(a.begin()->a)", substrs=['(int) $5 = 2']) + self.expect("expr (int)(a.rbegin()->a)", substrs=['(int) $6 = 3']) + + self.expect("expr a.pop_back()") + self.expect("expr (int)a.back().a", substrs=['(int) $7 = 1']) + self.expect("expr (size_t)a.size()", substrs=['(size_t) $8 = 2']) + + self.expect("expr (int)a.at(0).a", substrs=['(int) $9 = 2']) + + self.expect("expr a.push_back({4})") + self.expect("expr (int)a.back().a", substrs=['(int) $10 = 4']) + self.expect("expr (size_t)a.size()", substrs=['(size_t) $11 = 3']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/main.cpp new file mode 100644 index 00000000000..24c3fec75d2 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-dbg-info-content/main.cpp @@ -0,0 +1,10 @@ +#include <vector> + +struct Foo { + int a; +}; + +int main(int argc, char **argv) { + std::vector<Foo> a = {{3}, {1}, {2}}; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/TestVectorOfVectors.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/TestVectorOfVectors.py new file mode 100644 index 00000000000..2b82e1a039a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/TestVectorOfVectors.py @@ -0,0 +1,30 @@ +""" +Test std::vector functionality when it's contents are vectors. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestVectorOfVectors(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (size_t)a.size()", substrs=['(size_t) $0 = 2']) + self.expect("expr (int)a.front().front()", substrs=['(int) $1 = 1']) + self.expect("expr (int)a[1][1]", substrs=['(int) $2 = 2']) + self.expect("expr (int)a.back().at(0)", substrs=['(int) $3 = 3']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/main.cpp new file mode 100644 index 00000000000..b5ada909e43 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/vector-of-vectors/main.cpp @@ -0,0 +1,6 @@ +#include <vector> + +int main(int argc, char **argv) { + std::vector<std::vector<int> > a = {{1, 2, 3}, {3, 2, 1}}; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py new file mode 100644 index 00000000000..0acd54e803c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/TestDbgInfoContentWeakPtr.py @@ -0,0 +1,33 @@ +""" +Test std::weak_ptr functionality with a decl from debug info as content. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestDbgInfoContentWeakPtr(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (int)w.lock()->a", substrs=['(int) $0 = 3']) + self.expect("expr (int)(w.lock()->a = 5)", substrs=['(int) $1 = 5']) + self.expect("expr (int)w.lock()->a", substrs=['(int) $2 = 5']) + self.expect("expr w.use_count()", substrs=['(long) $3 = 1']) + self.expect("expr w.reset()") + self.expect("expr w.use_count()", substrs=['(long) $4 = 0']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/main.cpp new file mode 100644 index 00000000000..d2c5a6258a5 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr-dbg-info-content/main.cpp @@ -0,0 +1,12 @@ +#include <memory> + +struct Foo { + int a; +}; + +int main(int argc, char **argv) { + std::shared_ptr<Foo> s(new Foo); + s->a = 3; + std::weak_ptr<Foo> w = s; + return s->a; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/Makefile new file mode 100644 index 00000000000..01718d86aa7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../../make +USE_LIBCPP := 1 +CXXFLAGS += $(MANDATORY_CXXMODULE_BUILD_CFLAGS) +CXX_SOURCES := main.cpp +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/TestWeakPtr.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/TestWeakPtr.py new file mode 100644 index 00000000000..6b8b9ceb7aa --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/TestWeakPtr.py @@ -0,0 +1,33 @@ +""" +Test basic std::weak_ptr functionality. +""" + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestSharedPtr(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # FIXME: This should work on more setups, so remove these + # skipIf's in the future. + @add_test_categories(["libc++"]) + @skipIf(compiler=no_match("clang")) + @skipIf(oslist=no_match(["linux"])) + @skipIf(debug_info=no_match(["dwarf"])) + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + self.runCmd("settings set target.import-std-module true") + + self.expect("expr (int)*w.lock()", substrs=['(int) $0 = 3']) + self.expect("expr (int)(*w.lock() = 5)", substrs=['(int) $1 = 5']) + self.expect("expr (int)*w.lock()", substrs=['(int) $2 = 5']) + self.expect("expr w.use_count()", substrs=['(long) $3 = 1']) + self.expect("expr w.reset()") + self.expect("expr w.use_count()", substrs=['(long) $4 = 0']) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/main.cpp new file mode 100644 index 00000000000..13479eb9496 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import-std-module/weak_ptr/main.cpp @@ -0,0 +1,8 @@ +#include <memory> + +int main(int argc, char **argv) { + std::shared_ptr<int> s(new int); + *s = 3; + std::weak_ptr<int> w = s; + return *s; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import_builtin_fileid/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/import_builtin_fileid/Makefile new file mode 100644 index 00000000000..4464e2ee9f5 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import_builtin_fileid/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules +LDFLAGS += -framework Cocoa diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import_builtin_fileid/TestImportBuiltinFileID.py b/lldb/packages/Python/lldbsuite/test/commands/expression/import_builtin_fileid/TestImportBuiltinFileID.py new file mode 100644 index 00000000000..08b6a8c90f5 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import_builtin_fileid/TestImportBuiltinFileID.py @@ -0,0 +1,27 @@ +""" +They may be cases where an expression will import SourceLocation and if the +SourceLocation ends up with a FileID that is a built-in we need to copy that +buffer over correctly. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestImportBuiltinFileID(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + @skipIfDarwinEmbedded + @add_test_categories(["gmodules"]) + def test_import_builtin_fileid(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.m", False)) + + self.expect("expr int (*DBG_CGImageGetRenderingIntent)(void *) = ((int (*)(void *))CGImageGetRenderingIntent); DBG_CGImageGetRenderingIntent((void *)0x00000000000000);", + substrs=['$0 = 0']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/import_builtin_fileid/main.m b/lldb/packages/Python/lldbsuite/test/commands/expression/import_builtin_fileid/main.m new file mode 100644 index 00000000000..ef74940b0ac --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/import_builtin_fileid/main.m @@ -0,0 +1,6 @@ +#import <Cocoa/Cocoa.h> + +int main(int argc, const char * argv[]) { + + return 0; // break here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/inline-namespace/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/inline-namespace/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/inline-namespace/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/inline-namespace/TestInlineNamespace.py b/lldb/packages/Python/lldbsuite/test/commands/expression/inline-namespace/TestInlineNamespace.py new file mode 100644 index 00000000000..b17115be292 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/inline-namespace/TestInlineNamespace.py @@ -0,0 +1,26 @@ +""" +Test that we correctly handle inline namespaces. +""" + +import lldb + +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestInlineNamespace(TestBase): + mydir = TestBase.compute_mydir(__file__) + + def test(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, + "// Set break point at this line.", lldb.SBFileSpec("main.cpp")) + + # The 'A::B::f' function must be found via 'A::f' as 'B' is an inline + # namespace. + self.expect("expr A::f()", substrs=['$0 = 3']) + # But we should still find the function when we pretend the inline + # namespace is not inline. + self.expect("expr A::B::f()", substrs=['$1 = 3']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/inline-namespace/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/inline-namespace/main.cpp new file mode 100644 index 00000000000..c10b361a0cd --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/inline-namespace/main.cpp @@ -0,0 +1,10 @@ +namespace A { + inline namespace B { + int f() { return 3; } + }; +} + +int main(int argc, char **argv) { + // Set break point at this line. + return A::f(); +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter-phi-nodes/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter-phi-nodes/Makefile new file mode 100644 index 00000000000..bf2c0b2c108 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter-phi-nodes/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make
+
+CXX_SOURCES := main.cpp
+
+include $(LEVEL)/Makefile.rules
diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py new file mode 100644 index 00000000000..20a9477b1f7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter-phi-nodes/TestIRInterpreterPHINodes.py @@ -0,0 +1,41 @@ +""" +Test PHI nodes work in the IR interpreter. +""" + + +import lldb +from lldbsuite.test.lldbtest import * +import lldbsuite.test.lldbutil as lldbutil + + +class IRInterpreterPHINodesTestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + + def test_phi_node_support(self): + """Test support for PHI nodes in the IR interpreter.""" + + self.build() + exe = self.getBuildArtifact("a.out") + self.runCmd('file ' + exe, CURRENT_EXECUTABLE_SET) + + # Break on the first assignment to i + line = line_number('main.cpp', 'i = 5') + lldbutil.run_break_set_by_file_and_line( + self, 'main.cpp', line, num_expected_locations=1, loc_exact=True) + + self.runCmd('run', RUN_SUCCEEDED) + + # The stop reason of the thread should be breakpoint + self.expect('thread list', STOPPED_DUE_TO_BREAKPOINT, + substrs=['stopped', 'stop reason = breakpoint']) + + self.runCmd('s') + + # The logical 'or' causes a PHI node to be generated. Execute without JIT + # to test that the interpreter can handle this + self.expect('expr -j 0 -- i == 3 || i == 5', substrs=['true']) + + self.runCmd('s') + self.expect('expr -j 0 -- i == 3 || i == 5', substrs=['false']) + self.runCmd('s') + self.expect('expr -j 0 -- i == 3 || i == 5', substrs=['true']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter-phi-nodes/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter-phi-nodes/main.cpp new file mode 100644 index 00000000000..8e181aeba3b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter-phi-nodes/main.cpp @@ -0,0 +1,16 @@ +//===-- main.cpp ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int main() +{ + int i; + i = 5; + i = 2; + i = 3; + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/Makefile new file mode 100644 index 00000000000..c4169a9b101 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../make + +default: a.out + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/TestIRInterpreter.py b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/TestIRInterpreter.py new file mode 100644 index 00000000000..509e3fbd6d0 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/TestIRInterpreter.py @@ -0,0 +1,94 @@ +""" +Test the IR interpreter +""" + +from __future__ import print_function + +import unittest2 + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class IRInterpreterTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + NO_DEBUG_INFO_TESTCASE = True + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number('main.c', + '// Set breakpoint here') + + # Disable confirmation prompt to avoid infinite wait + self.runCmd("settings set auto-confirm true") + self.addTearDownHook( + lambda: self.runCmd("settings clear auto-confirm")) + + def build_and_run(self): + """Test the IR interpreter""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.c", self.line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + @add_test_categories(['pyapi']) + # getpid() is POSIX, among other problems, see bug + @expectedFailureAll( + oslist=['windows'], + bugnumber="http://llvm.org/pr21765") + @expectedFailureNetBSD + @expectedFailureAll( + oslist=['linux'], + archs=['arm'], + bugnumber="llvm.org/pr27868") + def test_ir_interpreter(self): + self.build_and_run() + + options = lldb.SBExpressionOptions() + options.SetLanguage(lldb.eLanguageTypeC_plus_plus) + + set_up_expressions = ["int $i = 9", "int $j = 3", "int $k = 5"] + + expressions = ["$i + $j", + "$i - $j", + "$i * $j", + "$i / $j", + "$i % $k", + "$i << $j", + "$i & $j", + "$i | $j", + "$i ^ $j"] + + for expression in set_up_expressions: + self.frame().EvaluateExpression(expression, options) + + for expression in expressions: + interp_expression = expression + jit_expression = "(int)getpid(); " + expression + + interp_result = self.frame().EvaluateExpression( + interp_expression, options).GetValueAsSigned() + jit_result = self.frame().EvaluateExpression( + jit_expression, options).GetValueAsSigned() + + self.assertEqual( + interp_result, + jit_result, + "While evaluating " + + expression) + + def test_type_conversions(self): + target = self.dbg.GetDummyTarget() + short_val = target.EvaluateExpression("(short)-1") + self.assertEqual(short_val.GetValueAsSigned(), -1) + long_val = target.EvaluateExpression("(long) "+ short_val.GetName()) + self.assertEqual(long_val.GetValueAsSigned(), -1) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/main.c new file mode 100644 index 00000000000..31204b21d97 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/ir-interpreter/main.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main() +{ + printf("This is a dummy\n"); // Set breakpoint here + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/Test11588.py b/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/Test11588.py new file mode 100644 index 00000000000..2c20b63cfd9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/Test11588.py @@ -0,0 +1,67 @@ +""" +Test the solution to issue 11581. +valobj.AddressOf() returns None when an address is +expected in a SyntheticChildrenProvider +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class Issue11581TestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24778") + def test_11581_commands(self): + # This is the function to remove the custom commands in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type synthetic clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + """valobj.AddressOf() should return correct values.""" + self.build() + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + 'Set breakpoint here.', + lldb.SBFileSpec("main.cpp", False)) + self.runCmd("command script import --allow-reload s11588.py") + self.runCmd( + "type synthetic add --python-class s11588.Issue11581SyntheticProvider StgClosure") + + self.expect("expr --show-types -- *((StgClosure*)(r14-1))", + substrs=["(StgClosure) $", + "(StgClosure *) &$", "0x", + "addr = ", + "load_address = "]) + + # register r14 is an x86_64 extension let's skip this part of the test + # if we are on a different architecture + if self.getArchitecture() == 'x86_64': + target = self.dbg.GetSelectedTarget() + process = target.GetProcess() + frame = process.GetSelectedThread().GetSelectedFrame() + pointer = frame.FindVariable("r14") + addr = pointer.GetValueAsUnsigned(0) + self.assertTrue(addr != 0, "could not read pointer to StgClosure") + addr = addr - 1 + self.runCmd("register write r14 %d" % addr) + self.expect( + "register read r14", substrs=[ + "0x", hex(addr)[ + 2:].rstrip("L")]) # Remove trailing 'L' if it exists + self.expect("expr --show-types -- *(StgClosure*)$r14", + substrs=["(StgClosure) $", + "(StgClosure *) &$", "0x", + "addr = ", + "load_address = ", + hex(addr)[2:].rstrip("L"), + str(addr)]) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/main.cpp new file mode 100644 index 00000000000..4f9ea3abf18 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/main.cpp @@ -0,0 +1,54 @@ +// +// 11588.cpp +// + +#include <iostream> + +class StgInfoTable {}; + +class StgHeader +{ +private: + StgInfoTable* info; +public: + StgHeader() + { + info = new StgInfoTable(); + } + ~StgHeader() + { + delete info; + } +}; + +class StgClosure +{ +private: + StgHeader header; + StgClosure* payload[1]; +public: + StgClosure(bool make_payload = true) + { + if (make_payload) + payload[0] = new StgClosure(false); + else + payload[0] = NULL; + } + ~StgClosure() + { + if (payload[0]) + delete payload[0]; + } +}; + +typedef unsigned long long int ptr_type; + +int main() +{ + StgClosure* r14_ = new StgClosure(); + r14_ = (StgClosure*)(((ptr_type)r14_ | 0x01)); // set the LSB to 1 for tagging + ptr_type r14 = (ptr_type)r14_; + int x = 0; + x = 3; + return (x-1); // Set breakpoint here. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/s11588.py b/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/s11588.py new file mode 100644 index 00000000000..51c20423ed3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/issue_11588/s11588.py @@ -0,0 +1,28 @@ +class Issue11581SyntheticProvider(object): + + def __init__(self, valobj, dict): + self.valobj = valobj + self.addrOf = valobj.AddressOf() + self.addr = valobj.GetAddress() + self.load_address = valobj.GetLoadAddress() + + def num_children(self): + return 3 + + def get_child_at_index(self, index): + if index == 0: + return self.addrOf + if index == 1: + return self.valobj.CreateValueFromExpression( + "addr", str(self.addr)) + if index == 2: + return self.valobj.CreateValueFromExpression( + "load_address", str(self.load_address)) + + def get_child_index(self, name): + if name == "addrOf": + return 0 + if name == "addr": + return 1 + if name == "load_address": + return 2 diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/macros/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/macros/Makefile new file mode 100644 index 00000000000..1ecd744be14 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/macros/Makefile @@ -0,0 +1,8 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +DEBUG_INFO_FLAG = -g3 + + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/macros/TestMacros.py b/lldb/packages/Python/lldbsuite/test/commands/expression/macros/TestMacros.py new file mode 100644 index 00000000000..817f6cb3944 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/macros/TestMacros.py @@ -0,0 +1,131 @@ +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TestMacros(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll( + compiler="clang", + bugnumber="clang does not emit .debug_macro[.dwo] sections.") + @expectedFailureAll( + debug_info="dwo", + bugnumber="GCC produces multiple .debug_macro.dwo sections and the spec is unclear as to what it means") + @expectedFailureAll( + hostoslist=["windows"], + compiler="gcc", + triple='.*-android') + def test_expr_with_macros(self): + self.build() + + # Get main source file + src_file = "main.cpp" + hdr_file = "macro1.h" + src_file_spec = lldb.SBFileSpec(src_file) + self.assertTrue(src_file_spec.IsValid(), "Main source file") + + (target, process, thread, bp1) = lldbutil.run_to_source_breakpoint( + self, "Break here", src_file_spec) + + # Get frame for current thread + frame = thread.GetSelectedFrame() + + result = frame.EvaluateExpression("MACRO_1") + self.assertTrue( + result.IsValid() and result.GetValue() == "100", + "MACRO_1 = 100") + + result = frame.EvaluateExpression("MACRO_2") + self.assertTrue( + result.IsValid() and result.GetValue() == "200", + "MACRO_2 = 200") + + result = frame.EvaluateExpression("ONE") + self.assertTrue( + result.IsValid() and result.GetValue() == "1", + "ONE = 1") + + result = frame.EvaluateExpression("TWO") + self.assertTrue( + result.IsValid() and result.GetValue() == "2", + "TWO = 2") + + result = frame.EvaluateExpression("THREE") + self.assertTrue( + result.IsValid() and result.GetValue() == "3", + "THREE = 3") + + result = frame.EvaluateExpression("FOUR") + self.assertTrue( + result.IsValid() and result.GetValue() == "4", + "FOUR = 4") + + result = frame.EvaluateExpression("HUNDRED") + self.assertTrue( + result.IsValid() and result.GetValue() == "100", + "HUNDRED = 100") + + result = frame.EvaluateExpression("THOUSAND") + self.assertTrue( + result.IsValid() and result.GetValue() == "1000", + "THOUSAND = 1000") + + result = frame.EvaluateExpression("MILLION") + self.assertTrue(result.IsValid() and result.GetValue() + == "1000000", "MILLION = 1000000") + + result = frame.EvaluateExpression("MAX(ONE, TWO)") + self.assertTrue( + result.IsValid() and result.GetValue() == "2", + "MAX(ONE, TWO) = 2") + + result = frame.EvaluateExpression("MAX(THREE, TWO)") + self.assertTrue( + result.IsValid() and result.GetValue() == "3", + "MAX(THREE, TWO) = 3") + + # Get the thread of the process + thread.StepOver() + + # Get frame for current thread + frame = thread.GetSelectedFrame() + + result = frame.EvaluateExpression("MACRO_2") + self.assertTrue( + result.GetError().Fail(), + "Printing MACRO_2 fails in the mail file") + + result = frame.EvaluateExpression("FOUR") + self.assertTrue( + result.GetError().Fail(), + "Printing FOUR fails in the main file") + + thread.StepInto() + + # Get frame for current thread + frame = thread.GetSelectedFrame() + + result = frame.EvaluateExpression("ONE") + self.assertTrue( + result.IsValid() and result.GetValue() == "1", + "ONE = 1") + + result = frame.EvaluateExpression("MAX(ONE, TWO)") + self.assertTrue( + result.IsValid() and result.GetValue() == "2", + "MAX(ONE, TWO) = 2") + + # This time, MACRO_1 and MACRO_2 are not visible. + result = frame.EvaluateExpression("MACRO_1") + self.assertTrue(result.GetError().Fail(), + "Printing MACRO_1 fails in the header file") + + result = frame.EvaluateExpression("MACRO_2") + self.assertTrue(result.GetError().Fail(), + "Printing MACRO_2 fails in the header file") diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/macros/macro1.h b/lldb/packages/Python/lldbsuite/test/commands/expression/macros/macro1.h new file mode 100644 index 00000000000..e026bc018ac --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/macros/macro1.h @@ -0,0 +1,17 @@ + +#include "macro2.h" + +#define ONE 1 +#define TWO 2 +#define THREE 3 +#define FOUR 4 + +class Simple +{ +public: + int + Method() + { + return ONE + TWO; + }; +}; diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/macros/macro2.h b/lldb/packages/Python/lldbsuite/test/commands/expression/macros/macro2.h new file mode 100644 index 00000000000..cec6efbba99 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/macros/macro2.h @@ -0,0 +1,8 @@ +#define HUNDRED 100 +#define THOUSAND 1000 +#define MILLION 1000000 + +#define MAX(a, b)\ +((a) > (b) ?\ + (a):\ + (b)) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/macros/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/macros/main.cpp new file mode 100644 index 00000000000..f2c2c101fa1 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/macros/main.cpp @@ -0,0 +1,15 @@ +#include "macro1.h" + +#define MACRO_1 100 +#define MACRO_2 200 + +int +main () +{ + int a = ONE + TWO; // Break here + + #undef MACRO_2 + #undef FOUR + + return Simple().Method(); +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/multiline-completion/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/multiline-completion/Makefile new file mode 100644 index 00000000000..f5a47fcc46c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/multiline-completion/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +C_SOURCES := main.c +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/multiline-completion/TestMultilineCompletion.py b/lldb/packages/Python/lldbsuite/test/commands/expression/multiline-completion/TestMultilineCompletion.py new file mode 100644 index 00000000000..7447e158641 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/multiline-completion/TestMultilineCompletion.py @@ -0,0 +1,30 @@ +""" +Test completion for multiline expressions. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test.lldbpexpect import PExpectTest + +class MultilineCompletionTest(PExpectTest): + + mydir = TestBase.compute_mydir(__file__) + + def test_basic_completion(self): + """Test that we can complete a simple multiline expression""" + self.build() + + self.launch(executable=self.getBuildArtifact("a.out")) + self.expect("b main", substrs=["Breakpoint 1", "address ="]) + self.expect("run", substrs=["stop reason ="]) + + self.child.sendline("expr") + self.child.expect_exact("terminate with an empty line to evaluate") + self.child.send("to_\t") + self.child.expect_exact("to_complete") + + self.child.send("\n\n") + self.expect_prompt() + + self.quit() diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/multiline-completion/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/multiline-completion/main.c new file mode 100644 index 00000000000..03350dd8299 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/multiline-completion/main.c @@ -0,0 +1,5 @@ +int main(int argc, char **argv) { + lldb_enable_attach(); + int to_complete = 0; + return to_complete; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_cpp_and_c/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_cpp_and_c/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_cpp_and_c/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_cpp_and_c/TestNamespaceLocalVarSameNameCppAndC.py b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_cpp_and_c/TestNamespaceLocalVarSameNameCppAndC.py new file mode 100644 index 00000000000..ab2ddd07480 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_cpp_and_c/TestNamespaceLocalVarSameNameCppAndC.py @@ -0,0 +1,24 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestNamespaceLocalVarSameNameCppAndC(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + @add_test_categories(["gmodules"]) + def test_namespace_local_var_same_name_cpp_and_c(self): + self.build() + + (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + self.expect("expr error", + substrs=['(int) $0 = 1']) + + lldbutil.continue_to_breakpoint(self.process, bkpt) + + self.expect("expr error", + substrs=['(int) $1 = 1']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_cpp_and_c/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_cpp_and_c/main.cpp new file mode 100644 index 00000000000..5e8237ed190 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_cpp_and_c/main.cpp @@ -0,0 +1,21 @@ +namespace error { +int x; +} + +struct A { + void foo() { + int error = 1; + + return; // break here + } +}; + +int main() { + int error = 1; + + A a; + + a.foo(); + + return 0; // break here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/Makefile new file mode 100644 index 00000000000..67553218d80 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make +OBJCXX_SOURCES := main.mm util.mm +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/TestNamespaceLocalVarSameNameObjC.py b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/TestNamespaceLocalVarSameNameObjC.py new file mode 100644 index 00000000000..eb894cc37e4 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/TestNamespaceLocalVarSameNameObjC.py @@ -0,0 +1,24 @@ +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestNamespaceLocalVarSameNameObjC(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipUnlessDarwin + @add_test_categories(["gmodules"]) + def test_namespace_local_var_same_name_obj_c(self): + self.build() + + (self.target, self.process, _, bkpt) = lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("util.mm", False)) + + self.expect("expr error", + substrs=['(NSError *) $0 =']) + + lldbutil.continue_to_breakpoint(self.process, bkpt) + + self.expect("expr error", + substrs=['(NSError *) $1 =']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/main.mm b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/main.mm new file mode 100644 index 00000000000..70e9598eefb --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/main.mm @@ -0,0 +1,16 @@ +#import <Foundation/Foundation.h> +@interface Util : NSObject ++ (void)debugPrintErrorStatic; +- (void)debugPrintError; +@end + +int main(int argc, const char * argv[]) { + [Util debugPrintErrorStatic]; + + Util *u = [[Util alloc] init]; + + [u debugPrintError]; + + return 0; +} + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/util.mm b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/util.mm new file mode 100644 index 00000000000..11c9c141df0 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/namespace_local_var_same_name_obj_c/util.mm @@ -0,0 +1,22 @@ +#import <Foundation/Foundation.h> + +namespace error { +int blah; +} + +@interface Util : NSObject ++ (void)debugPrintErrorStatic; +- (void)debugPrintError; +@end + +@implementation Util ++ (void)debugPrintErrorStatic { + NSError* error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:nil]; + NSLog(@"xxx, error = %@", error); // break here +} + +- (void)debugPrintError { + NSError* error = [NSError errorWithDomain:NSURLErrorDomain code:-1 userInfo:nil]; + NSLog(@"xxx, error = %@", error); // break here +} +@end diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/.categories b/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/.categories new file mode 100644 index 00000000000..897e40a99dd --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/.categories @@ -0,0 +1 @@ +expression diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/Makefile new file mode 100644 index 00000000000..a10791d5890 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +C_SOURCES := locking.c +ENABLE_THREADS := YES + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/TestExprDoesntBlock.py b/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/TestExprDoesntBlock.py new file mode 100644 index 00000000000..5b5042b63e4 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/TestExprDoesntBlock.py @@ -0,0 +1,60 @@ +""" +Test that expr will time out and allow other threads to run if it blocks. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprDoesntDeadlockTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @expectedFailureAll(oslist=['freebsd'], bugnumber='llvm.org/pr17946') + @expectedFailureAll( + oslist=["windows"], + bugnumber="Windows doesn't have pthreads, test needs to be ported") + @add_test_categories(["basic_process"]) + def test_with_run_command(self): + """Test that expr will time out and allow other threads to run if it blocks.""" + self.build() + exe = self.getBuildArtifact("a.out") + + # Create a target by the debugger. + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Now create a breakpoint at source line before call_me_to_get_lock + # gets called. + + main_file_spec = lldb.SBFileSpec("locking.c") + breakpoint = target.BreakpointCreateBySourceRegex( + 'Break here', main_file_spec) + if self.TraceOn(): + print("breakpoint:", breakpoint) + self.assertTrue(breakpoint and + breakpoint.GetNumLocations() == 1, + VALID_BREAKPOINT) + + # Now launch the process, and do not stop at entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process, PROCESS_IS_VALID) + + # Frame #0 should be on self.line1 and the break condition should hold. + from lldbsuite.test.lldbutil import get_stopped_thread + thread = get_stopped_thread(process, lldb.eStopReasonBreakpoint) + self.assertTrue( + thread.IsValid(), + "There should be a thread stopped due to breakpoint condition") + + frame0 = thread.GetFrameAtIndex(0) + + var = frame0.EvaluateExpression("call_me_to_get_lock()") + self.assertTrue(var.IsValid()) + self.assertTrue(var.GetValueAsSigned(0) == 567) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/locking.c b/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/locking.c new file mode 100644 index 00000000000..fae9979611d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/no-deadlock/locking.c @@ -0,0 +1,80 @@ +#include <pthread.h> +#include <stdlib.h> +#include <unistd.h> +#include <stdio.h> + +pthread_mutex_t contended_mutex = PTHREAD_MUTEX_INITIALIZER; + +pthread_mutex_t control_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t control_condition; + +pthread_mutex_t thread_started_mutex = PTHREAD_MUTEX_INITIALIZER; +pthread_cond_t thread_started_condition; + +// This function runs in a thread. The locking dance is to make sure that +// by the time the main thread reaches the pthread_join below, this thread +// has for sure acquired the contended_mutex. So then the call_me_to_get_lock +// function will block trying to get the mutex, and only succeed once it +// signals this thread, then lets it run to wake up from the cond_wait and +// release the mutex. + +void * +lock_acquirer_1 (void *input) +{ + pthread_mutex_lock (&contended_mutex); + + // Grab this mutex, that will ensure that the main thread + // is in its cond_wait for it (since that's when it drops the mutex. + + pthread_mutex_lock (&thread_started_mutex); + pthread_mutex_unlock(&thread_started_mutex); + + // Now signal the main thread that it can continue, we have the contended lock + // so the call to call_me_to_get_lock won't make any progress till this + // thread gets a chance to run. + + pthread_mutex_lock (&control_mutex); + + pthread_cond_signal (&thread_started_condition); + + pthread_cond_wait (&control_condition, &control_mutex); + + pthread_mutex_unlock (&contended_mutex); + return NULL; +} + +int +call_me_to_get_lock () +{ + pthread_cond_signal (&control_condition); + pthread_mutex_lock (&contended_mutex); + return 567; +} + +int main () +{ + pthread_t thread_1; + + pthread_cond_init (&control_condition, NULL); + pthread_cond_init (&thread_started_condition, NULL); + + pthread_mutex_lock (&thread_started_mutex); + + pthread_create (&thread_1, NULL, lock_acquirer_1, NULL); + + pthread_cond_wait (&thread_started_condition, &thread_started_mutex); + + pthread_mutex_lock (&control_mutex); + pthread_mutex_unlock (&control_mutex); + + // Break here. At this point the other thread will have the contended_mutex, + // and be sitting in its cond_wait for the control condition. So there is + // no way that our by-hand calling of call_me_to_get_lock will proceed + // without running the first thread at least somewhat. + + call_me_to_get_lock(); + pthread_join (thread_1, NULL); + + return 0; + +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/options/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/options/Makefile new file mode 100644 index 00000000000..81ae6f6f16e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/options/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp foo.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/options/TestExprOptions.py b/lldb/packages/Python/lldbsuite/test/commands/expression/options/TestExprOptions.py new file mode 100644 index 00000000000..8af0ea1ba0c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/options/TestExprOptions.py @@ -0,0 +1,91 @@ +""" +Test expression command options. + +Test cases: + +o test_expr_options: + Test expression command options. +""" + +from __future__ import print_function + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * + + +class ExprOptionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + self.line = line_number('main.cpp', '// breakpoint_in_main') + self.exe = self.getBuildArtifact("a.out") + + def test_expr_options(self): + """These expression command options should work as expected.""" + self.build() + + # Set debugger into synchronous mode + self.dbg.SetAsync(False) + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, '// breakpoint_in_main', self.main_source_spec) + + frame = thread.GetFrameAtIndex(0) + options = lldb.SBExpressionOptions() + + # test --language on C++ expression using the SB API's + + # Make sure we can evaluate a C++11 expression. + val = frame.EvaluateExpression('foo != nullptr') + self.assertTrue(val.IsValid()) + self.assertTrue(val.GetError().Success()) + self.DebugSBValue(val) + + # Make sure it still works if language is set to C++11: + options.SetLanguage(lldb.eLanguageTypeC_plus_plus_11) + val = frame.EvaluateExpression('foo != nullptr', options) + self.assertTrue(val.IsValid()) + self.assertTrue(val.GetError().Success()) + self.DebugSBValue(val) + + # Make sure it fails if language is set to C: + options.SetLanguage(lldb.eLanguageTypeC) + val = frame.EvaluateExpression('foo != nullptr', options) + self.assertTrue(val.IsValid()) + self.assertFalse(val.GetError().Success()) + + @skipIfDarwin + def test_expr_options_lang(self): + """These expression language options should work as expected.""" + self.build() + + # Set debugger into synchronous mode + self.dbg.SetAsync(False) + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, '// breakpoint_in_main', self.main_source_spec) + + frame = thread.GetFrameAtIndex(0) + options = lldb.SBExpressionOptions() + + # Make sure we can retrieve `id` variable if language is set to C++11: + options.SetLanguage(lldb.eLanguageTypeC_plus_plus_11) + val = frame.EvaluateExpression('id == 0', options) + self.assertTrue(val.IsValid()) + self.assertTrue(val.GetError().Success()) + self.DebugSBValue(val) + + # Make sure we can't retrieve `id` variable if language is set to ObjC: + options.SetLanguage(lldb.eLanguageTypeObjC) + val = frame.EvaluateExpression('id == 0', options) + self.assertTrue(val.IsValid()) + self.assertFalse(val.GetError().Success()) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/options/foo.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/options/foo.cpp new file mode 100644 index 00000000000..8a5a6a2b541 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/options/foo.cpp @@ -0,0 +1,11 @@ +namespace ns { + int func(void) + { + return 0; + } +} + +extern "C" int foo(void) +{ + return ns::func(); +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/options/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/options/main.cpp new file mode 100644 index 00000000000..0d30c79bd22 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/options/main.cpp @@ -0,0 +1,17 @@ +extern "C" int foo(void); +static int static_value = 0; +static int id = 1234; + +int +bar() +{ + static_value++; + id++; + return static_value + id; +} + +int main (int argc, char const *argv[]) +{ + bar(); // breakpoint_in_main + return foo(); +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persist_objc_pointeetype/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/persist_objc_pointeetype/Makefile new file mode 100644 index 00000000000..8066198300f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persist_objc_pointeetype/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules +LDFLAGS += -framework Foundation -framework CloudKit + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persist_objc_pointeetype/TestPersistObjCPointeeType.py b/lldb/packages/Python/lldbsuite/test/commands/expression/persist_objc_pointeetype/TestPersistObjCPointeeType.py new file mode 100644 index 00000000000..b6471d0f897 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persist_objc_pointeetype/TestPersistObjCPointeeType.py @@ -0,0 +1,51 @@ +""" +Test that we can p *objcObject +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class PersistObjCPointeeType(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.cpp. + self.line = line_number('main.m', '// break here') + + @skipUnlessDarwin + @skipIf(archs=["i386", "i686"]) + @skipIf(debug_info="gmodules", archs=['arm64', 'armv7', 'armv7k']) # compile error with gmodules for iOS + def test_with(self): + """Test that we can p *objcObject""" + self.build() + + def cleanup(): + pass + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.m", self.line, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + self.expect("p *self", substrs=['_sc_name = nil', + '_sc_name2 = nil', + '_sc_name3 = nil', + '_sc_name4 = nil', + '_sc_name5 = nil', + '_sc_name6 = nil', + '_sc_name7 = nil', + '_sc_name8 = nil']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persist_objc_pointeetype/main.m b/lldb/packages/Python/lldbsuite/test/commands/expression/persist_objc_pointeetype/main.m new file mode 100644 index 00000000000..a2b6b703d6c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persist_objc_pointeetype/main.m @@ -0,0 +1,80 @@ +/* +clang -g ExtendSuperclass.m -o ExtendSuperclass -framework Foundation -framework ProtectedCloudStorage -F/System/Library/PrivateFrameworks/ -framework CloudKit && ./ExtendSuperclass +*/ +#include <assert.h> +#import <Foundation/Foundation.h> +#import <CloudKit/CloudKit.h> + +#define SuperClass CKDatabase + +@interface SubClass : SuperClass +@end + +// class extension +@interface SuperClass () +@property (nonatomic, strong) NSString *_sc_name; +@property (nonatomic, strong) NSString *_sc_name2; +@property (nonatomic, strong) NSString *_sc_name3; +@property (nonatomic, strong) NSString *_sc_name4; +@property (nonatomic, strong) NSString *_sc_name5; +@property (nonatomic, strong) NSString *_sc_name6; +@property (nonatomic, strong) NSString *_sc_name7; +@property (nonatomic, strong) NSString *_sc_name8; +@end + +@implementation SuperClass (MySuperClass) +- (id)initThatDoesNotAssert +{ + return [super init]; +} +@end + +@implementation SubClass +- (id)initThatDoesNotAssert +{ + assert(_sc_name == nil); + assert(_sc_name2 == nil); + assert(_sc_name3 == nil); + assert(_sc_name4 == nil); + assert(_sc_name5 == nil); + assert(_sc_name6 == nil); + assert(_sc_name7 == nil); + assert(_sc_name8 == nil); // break here + + if ((self = [super _initWithContainer:(CKContainer*)@"foo" scope:0xff])) { + assert(_sc_name == nil); + assert(_sc_name2 == nil); + assert(_sc_name3 == nil); + assert(_sc_name4 == nil); + assert(_sc_name5 == nil); + assert(_sc_name6 == nil); + assert(_sc_name7 == nil); + assert(_sc_name8 == nil); + + _sc_name = @"empty"; + } + return self; +} +@synthesize _sc_name; +@synthesize _sc_name2; +@synthesize _sc_name3; +@synthesize _sc_name4; +@synthesize _sc_name5; +@synthesize _sc_name6; +@synthesize _sc_name7; +@synthesize _sc_name8; +- (void)foo:(NSString*)bar { self._sc_name = bar; } +- (NSString*)description { return [NSString stringWithFormat:@"%p: %@", self, self._sc_name]; } +@end + +int main() +{ + SubClass *sc = [[SubClass alloc] initThatDoesNotAssert]; + NSLog(@"%@", sc); + [sc foo:@"bar"]; + NSLog(@"%@", sc); + sc._sc_name = @"bar2"; + NSLog(@"%@", sc); + NSLog(@"%@", sc._sc_name); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_ptr_update/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_ptr_update/Makefile new file mode 100644 index 00000000000..db5f575866d --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_ptr_update/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules + + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_ptr_update/TestPersistentPtrUpdate.py b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_ptr_update/TestPersistentPtrUpdate.py new file mode 100644 index 00000000000..7b963b5bfcd --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_ptr_update/TestPersistentPtrUpdate.py @@ -0,0 +1,41 @@ +""" +Test that we can have persistent pointer variables +""" + +from __future__ import print_function + + +import lldb +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class PersistentPtrUpdateTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def test(self): + """Test that we can have persistent pointer variables""" + self.build() + + def cleanup(): + pass + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + self.runCmd('break set -p here') + + self.runCmd("run", RUN_SUCCEEDED) + + self.runCmd("expr void* $foo = 0") + + self.runCmd("continue") + + self.expect("expr $foo", substrs=['$foo', '0x0']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_ptr_update/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_ptr_update/main.c new file mode 100644 index 00000000000..73346969ecc --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_ptr_update/main.c @@ -0,0 +1,11 @@ +void* foo(void *p) +{ + return p; // break here +} + +int main() { + while (1) { + foo(0); + } + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/Makefile new file mode 100644 index 00000000000..0d70f259501 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/TestNestedPersistentTypes.py b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/TestNestedPersistentTypes.py new file mode 100644 index 00000000000..bde649b0e07 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/TestNestedPersistentTypes.py @@ -0,0 +1,42 @@ +""" +Test that nested persistent types work. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class NestedPersistentTypesTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_persistent_types(self): + """Test that nested persistent types work.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + self.runCmd("breakpoint set --name main") + + self.runCmd("run", RUN_SUCCEEDED) + + self.runCmd("expression struct $foo { int a; int b; };") + + self.runCmd( + "expression struct $bar { struct $foo start; struct $foo end; };") + + self.runCmd("expression struct $bar $my_bar = {{ 2, 3 }, { 4, 5 }};") + + self.expect("expression $my_bar", + substrs=['a = 2', 'b = 3', 'a = 4', 'b = 5']) + + self.expect("expression $my_bar.start.b", + substrs=['(int)', '3']) + + self.expect("expression $my_bar.end.b", + substrs=['(int)', '5']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/TestPersistentTypes.py b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/TestPersistentTypes.py new file mode 100644 index 00000000000..91681b480eb --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/TestPersistentTypes.py @@ -0,0 +1,93 @@ +""" +Test that lldb persistent types works correctly. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class PersistenttypesTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_persistent_types(self): + """Test that lldb persistent types works correctly.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + self.runCmd("breakpoint set --name main") + + self.runCmd("run", RUN_SUCCEEDED) + + self.runCmd("expression struct $foo { int a; int b; };") + + self.expect( + "expression struct $foo $my_foo; $my_foo.a = 2; $my_foo.b = 3;", + startstr="(int) $0 = 3") + + self.expect("expression $my_foo", + substrs=['a = 2', 'b = 3']) + + self.runCmd("expression typedef int $bar") + + self.expect("expression $bar i = 5; i", + startstr="($bar) $1 = 5") + + self.runCmd( + "expression struct $foobar { char a; char b; char c; char d; };") + self.runCmd("next") + + self.expect( + "memory read foo -t $foobar", + substrs=[ + '($foobar) 0x', + ' = ', + "a = 'H'", + "b = 'e'", + "c = 'l'", + "d = 'l'"]) # persistent types are OK to use for memory read + + self.expect( + "memory read foo -t $foobar -x c", + substrs=[ + '($foobar) 0x', + ' = ', + "a = 'H'", + "b = 'e'", + "c = 'l'", + "d = 'l'"]) # persistent types are OK to use for memory read + + self.expect( + "memory read foo -t foobar", + substrs=[ + '($foobar) 0x', + ' = ', + "a = 'H'", + "b = 'e'", + "c = 'l'", + "d = 'l'"], + matching=False, + error=True) # the type name is $foobar, make sure we settle for nothing less + + self.expect("expression struct { int a; int b; } x = { 2, 3 }; x", + substrs=['a = 2', 'b = 3']) + + self.expect( + "expression struct { int x; int y; int z; } object; object.y = 1; object.z = 3; object.x = 2; object", + substrs=[ + 'x = 2', + 'y = 1', + 'z = 3']) + + self.expect( + "expression struct A { int x; int y; }; struct { struct A a; int z; } object; object.a.y = 1; object.z = 3; object.a.x = 2; object", + substrs=[ + 'x = 2', + 'y = 1', + 'z = 3']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/main.c new file mode 100644 index 00000000000..9425c8b1cec --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_types/main.c @@ -0,0 +1,13 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int main (int argc, char const *argv[]) +{ + const char* foo = "Hello world"; + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_variables/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_variables/Makefile new file mode 100644 index 00000000000..0d70f259501 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_variables/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_variables/TestPersistentVariables.py b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_variables/TestPersistentVariables.py new file mode 100644 index 00000000000..57370f121b4 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_variables/TestPersistentVariables.py @@ -0,0 +1,53 @@ +""" +Test that lldb persistent variables works correctly. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.lldbtest import * + + +class PersistentVariablesTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_persistent_variables(self): + """Test that lldb persistent variables works correctly.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + self.runCmd("breakpoint set --source-pattern-regexp break") + + self.runCmd("run", RUN_SUCCEEDED) + + self.runCmd("expression int $i = i") + + self.expect("expression $i == i", + startstr="(bool) $0 = true") + + self.expect("expression $i + 1", + startstr="(int) $1 = 6") + + self.expect("expression $i + 3", + startstr="(int) $2 = 8") + + self.expect("expression $2 + $1", + startstr="(int) $3 = 14") + + self.expect("expression $3", + startstr="(int) $3 = 14") + + self.expect("expression $2", + startstr="(int) $2 = 8") + + self.expect("expression (int)-2", + startstr="(int) $4 = -2") + + self.expect("expression $4 > (int)31", + startstr="(bool) $5 = false") + + self.expect("expression (long)$4", + startstr="(long) $6 = -2") diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_variables/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_variables/main.c new file mode 100644 index 00000000000..771bf4ad342 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/persistent_variables/main.c @@ -0,0 +1,13 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int main (int argc, char const *argv[]) +{ + int i = 5; + return 0; // Set breakpoint here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/po_verbosity/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/po_verbosity/Makefile new file mode 100644 index 00000000000..b6592745356 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/po_verbosity/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m + +include $(LEVEL)/Makefile.rules +LDFLAGS += -framework Foundation diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/po_verbosity/TestPoVerbosity.py b/lldb/packages/Python/lldbsuite/test/commands/expression/po_verbosity/TestPoVerbosity.py new file mode 100644 index 00000000000..4530342ea52 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/po_verbosity/TestPoVerbosity.py @@ -0,0 +1,63 @@ +""" +Test that the po command acts correctly. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class PoVerbosityTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.cpp. + self.line = line_number('main.m', + '// Stop here') + + @skipUnlessDarwin + def test(self): + """Test that the po command acts correctly.""" + self.build() + + # This is the function to remove the custom formats in order to have a + # clean slate for the next test case. + def cleanup(): + self.runCmd('type summary clear', check=False) + self.runCmd('type synthetic clear', check=False) + + # Execute the cleanup function during test case tear down. + self.addTearDownHook(cleanup) + + """Test expr + formatters for good interoperability.""" + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.m", self.line, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + self.expect("expr -O -v -- foo", + substrs=['(id) $', ' = 0x', '1 = 2', '2 = 3;']) + self.expect("expr -O -vfull -- foo", + substrs=['(id) $', ' = 0x', '1 = 2', '2 = 3;']) + self.expect("expr -O -- foo", matching=False, + substrs=['(id) $']) + + self.expect("expr -O -- 22", matching=False, + substrs=['(int) $']) + self.expect("expr -O -- 22", + substrs=['22']) + + self.expect("expr -O -vfull -- 22", + substrs=['(int) $', ' = 22']) + + self.expect("expr -O -v -- 22", + substrs=['(int) $', ' = 22']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/po_verbosity/main.m b/lldb/packages/Python/lldbsuite/test/commands/expression/po_verbosity/main.m new file mode 100644 index 00000000000..9c79f850bf2 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/po_verbosity/main.m @@ -0,0 +1,9 @@ +#import <Foundation/Foundation.h> + +int main() +{ + [NSString initialize]; + id foo = @{@1 : @2, @2 : @3}; + int x = 34; + return 0; // Stop here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/pr35310/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/pr35310/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/pr35310/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/pr35310/TestExprsBug35310.py b/lldb/packages/Python/lldbsuite/test/commands/expression/pr35310/TestExprsBug35310.py new file mode 100644 index 00000000000..6d019c7415f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/pr35310/TestExprsBug35310.py @@ -0,0 +1,39 @@ +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class ExprBug35310(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + def test_issue35310(self): + """Test invoking functions with non-standard linkage names. + + The GNU abi_tag extension used by libstdc++ is a common source + of these, but they could originate from other reasons as well. + """ + self.build() + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) + + value = frame.EvaluateExpression("a.test_abi_tag()") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(0), 1) + + value = frame.EvaluateExpression("a.test_asm_name()") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(0), 2) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/pr35310/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/pr35310/main.cpp new file mode 100644 index 00000000000..a8e8a5c737a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/pr35310/main.cpp @@ -0,0 +1,19 @@ +#include <stdio.h> + +class A { +public: + int __attribute__((abi_tag("cxx11"))) test_abi_tag() { + return 1; + } + int test_asm_name() asm("A_test_asm") { + return 2; + } +}; + +int main(int argc, char **argv) { + A a; + // Break here + a.test_abi_tag(); + a.test_asm_name(); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/radar_8638051/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_8638051/Makefile new file mode 100644 index 00000000000..0d70f259501 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_8638051/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/radar_8638051/Test8638051.py b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_8638051/Test8638051.py new file mode 100644 index 00000000000..e7a5f597b70 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_8638051/Test8638051.py @@ -0,0 +1,38 @@ +""" +Test the robustness of lldb expression parser. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.lldbtest import * + + +class Radar8638051TestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def test_expr_commands(self): + """The following expression commands should not crash.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + self.runCmd("breakpoint set -n c") + + self.runCmd("run", RUN_SUCCEEDED) + + self.expect("expression val", + startstr="(int) $0 = 1") + # (int) $0 = 1 + + self.expect("expression *(&val)", + startstr="(int) $1 = 1") + # (int) $1 = 1 + + # rdar://problem/8638051 + # lldb expression command: Could this crash be avoided + self.expect("expression &val", + startstr="(int *) $2 = ") + # (int *) $2 = 0x.... diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/radar_8638051/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_8638051/main.c new file mode 100644 index 00000000000..dc528a458b3 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_8638051/main.c @@ -0,0 +1,53 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// This simple program is to demonstrate the capability of the lldb command +// "breakpoint command add" to add a set of commands to a breakpoint to be +// executed when the breakpoint is hit. +// +// In particular, we want to break within c(), but only if the immediate caller +// is a(). + +int a(int); +int b(int); +int c(int); + +int a(int val) +{ + if (val <= 1) + return b(val); + else if (val >= 3) + return c(val); // Find the line number where c's parent frame is a here. + + return val; +} + +int b(int val) +{ + return c(val); +} + +int c(int val) +{ + return val + 3; +} + +int main (int argc, char const *argv[]) +{ + int A1 = a(1); // a(1) -> b(1) -> c(1) + printf("a(1) returns %d\n", A1); + + int B2 = b(2); // b(2) -> c(2) + printf("b(2) returns %d\n", B2); + + int A3 = a(3); // a(3) -> c(3) + printf("a(3) returns %d\n", A3); + + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9531204/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9531204/Makefile new file mode 100644 index 00000000000..0d70f259501 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9531204/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9531204/TestPrintfAfterUp.py b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9531204/TestPrintfAfterUp.py new file mode 100644 index 00000000000..4ff28bdfe86 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9531204/TestPrintfAfterUp.py @@ -0,0 +1,43 @@ +""" +The evaluating printf(...) after break stop and then up a stack frame. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class Radar9531204TestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + # rdar://problem/9531204 + @expectedFailureNetBSD + def test_expr_commands(self): + """The evaluating printf(...) after break stop and then up a stack frame.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_symbol( + self, 'foo', sym_exact=True, num_expected_locations=1) + + self.runCmd("run", RUN_SUCCEEDED) + + self.runCmd("frame variable") + + # This works fine. + self.runCmd('expression (int)printf("value is: %d.\\n", value);') + + # rdar://problem/9531204 + # "Error dematerializing struct" error when evaluating expressions "up" on the stack + self.runCmd('up') # frame select -r 1 + + self.runCmd("frame variable") + + # This does not currently. + self.runCmd('expression (int)printf("argc is: %d.\\n", argc)') diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9531204/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9531204/main.c new file mode 100644 index 00000000000..43200d31745 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9531204/main.c @@ -0,0 +1,24 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +// breakpoint set -n foo +// +// +int foo (int value) +{ + printf ("I got the value: %d.\n", value); + return 0; +} + +int main (int argc, char **argv) +{ + foo (argc); + printf ("Hello there: %d.\n", argc); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9673664/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9673664/Makefile new file mode 100644 index 00000000000..0d70f259501 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9673664/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9673664/TestExprHelpExamples.py b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9673664/TestExprHelpExamples.py new file mode 100644 index 00000000000..5406fb0e987 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9673664/TestExprHelpExamples.py @@ -0,0 +1,45 @@ +""" +Test example snippets from the lldb 'help expression' output. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class Radar9673644TestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break inside main(). + self.main_source = "main.c" + self.line = line_number(self.main_source, '// Set breakpoint here.') + + def test_expr_commands(self): + """The following expression commands should just work.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, + self.main_source, + self.line, + num_expected_locations=1, + loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # rdar://problem/9673664 lldb expression evaluation problem + + self.expect('expr char str[] = "foo"; str[0]', + substrs=["'f'"]) + # runCmd: expr char c[] = "foo"; c[0] + # output: (char) $0 = 'f' diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9673664/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9673664/main.c new file mode 100644 index 00000000000..c765cf2a83a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/radar_9673664/main.c @@ -0,0 +1,15 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +#include <stdio.h> + +int main (int argc, char const *argv[]) +{ + printf("Hello, world.\n"); // Set breakpoint here. + + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/rdar42038760/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar42038760/Makefile new file mode 100644 index 00000000000..f5a47fcc46c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar42038760/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +C_SOURCES := main.c +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/rdar42038760/TestScalarURem.py b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar42038760/TestScalarURem.py new file mode 100644 index 00000000000..03424658f3e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar42038760/TestScalarURem.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), None) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/rdar42038760/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar42038760/main.c new file mode 100644 index 00000000000..98a957faf8b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar42038760/main.c @@ -0,0 +1,19 @@ +// Make sure we IR-interpret the expression correctly. + +typedef unsigned int uint32_t; +struct S0 { + signed f2; +}; +static g_463 = 0x1561983AL; +void func_1(void) +{ + struct S0 l_19; + l_19.f2 = 419; + uint32_t l_4037 = 4294967295UL; + l_19.f2 = g_463; //%self.expect("expr ((l_4037 % (-(g_463))) | l_19.f2)", substrs=['(unsigned int) $0 = 358717883']) +} +int main() +{ + func_1(); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/rdar44436068/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar44436068/Makefile new file mode 100644 index 00000000000..f5a47fcc46c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar44436068/Makefile @@ -0,0 +1,3 @@ +LEVEL = ../../make +C_SOURCES := main.c +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/rdar44436068/Test128BitsInteger.py b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar44436068/Test128BitsInteger.py new file mode 100644 index 00000000000..433c275fb58 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar44436068/Test128BitsInteger.py @@ -0,0 +1,6 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), + decorators.skipIf(archs=["armv7k"])) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/rdar44436068/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar44436068/main.c new file mode 100644 index 00000000000..156dbf04a1b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/rdar44436068/main.c @@ -0,0 +1,8 @@ +int main(void) +{ + __int128_t n = 1; + n = n + n; + return n; //%self.expect("p n", substrs=['(__int128_t) $0 = 2']) + //%self.expect("p n + 6", substrs=['(__int128) $1 = 8']) + //%self.expect("p n + n", substrs=['(__int128) $2 = 4']) +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/save_jit_objects/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/save_jit_objects/Makefile new file mode 100644 index 00000000000..0d70f259501 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/save_jit_objects/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +C_SOURCES := main.c + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/save_jit_objects/TestSaveJITObjects.py b/lldb/packages/Python/lldbsuite/test/commands/expression/save_jit_objects/TestSaveJITObjects.py new file mode 100644 index 00000000000..896e599f59c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/save_jit_objects/TestSaveJITObjects.py @@ -0,0 +1,53 @@ +""" +Test that LLDB can emit JIT objects when the appropriate setting is enabled +""" + +from __future__ import print_function + +import os +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class SaveJITObjectsTestCase(TestBase): + mydir = TestBase.compute_mydir(__file__) + + def enumerateJITFiles(self): + return [f for f in os.listdir(self.getBuildDir()) if f.startswith("jit")] + + def countJITFiles(self): + return len(self.enumerateJITFiles()) + + def cleanJITFiles(self): + for j in self.enumerateJITFiles(): + os.remove(j) + return + + @expectedFailureAll(oslist=["windows"]) + @expectedFailureNetBSD + def test_save_jit_objects(self): + self.build() + os.chdir(self.getBuildDir()) + src_file = "main.c" + src_file_spec = lldb.SBFileSpec(src_file) + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "break", src_file_spec) + + frame = thread.frames[0] + + self.cleanJITFiles() + frame.EvaluateExpression("(void*)malloc(0x1)") + self.assertTrue(self.countJITFiles() == 0, + "No files emitted with save-jit-objects=false") + + self.runCmd("settings set target.save-jit-objects true") + frame.EvaluateExpression("(void*)malloc(0x1)") + jit_files_count = self.countJITFiles() + self.cleanJITFiles() + self.assertTrue(jit_files_count != 0, + "At least one file emitted with save-jit-objects=true") + + process.Kill() + os.chdir(self.getSourceDir()) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/save_jit_objects/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/save_jit_objects/main.c new file mode 100644 index 00000000000..c9775b6e989 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/save_jit_objects/main.c @@ -0,0 +1,13 @@ +//===-- main.c --------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +int main (int argc, char const *argv[]) +{ + const char* foo = "Hello world"; // break here + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/scoped_enums/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/scoped_enums/Makefile new file mode 100644 index 00000000000..83b24da17b4 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/scoped_enums/Makefile @@ -0,0 +1,6 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp +CXXFLAGS += -std=c++11 + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/scoped_enums/TestScopedEnumType.py b/lldb/packages/Python/lldbsuite/test/commands/expression/scoped_enums/TestScopedEnumType.py new file mode 100644 index 00000000000..e7bc79d8e7c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/scoped_enums/TestScopedEnumType.py @@ -0,0 +1,45 @@ +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ScopedEnumType(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @skipIf(dwarf_version=['<', '4']) + def test(self): + self.build() + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Set break point at this line.', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) + + self.expect("expr f == Foo::FooBar", + substrs=['(bool) $0 = true']) + + value = frame.EvaluateExpression("f == Foo::FooBar") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsUnsigned(), 1) + + value = frame.EvaluateExpression("b == BarBar") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsUnsigned(), 1) + + ## b is not a Foo + value = frame.EvaluateExpression("b == Foo::FooBar") + self.assertTrue(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + ## integral is not implicitly convertible to a scoped enum + value = frame.EvaluateExpression("1 == Foo::FooBar") + self.assertTrue(value.IsValid()) + self.assertFalse(value.GetError().Success()) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/scoped_enums/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/scoped_enums/main.cpp new file mode 100644 index 00000000000..b0d67d23dc5 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/scoped_enums/main.cpp @@ -0,0 +1,16 @@ +enum class Foo { + FooBar = 42 +}; + +enum Bar { + BarBar = 3, + BarBarBar = 42 +}; + +int main(int argc, const char **argv) { + Foo f = Foo::FooBar; + Bar b = BarBar; + bool b1 = f == Foo::FooBar; + bool b2 = b == BarBar; + return 0; // Set break point at this line. +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/test/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/test/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/test/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/test/TestExprs.py b/lldb/packages/Python/lldbsuite/test/commands/expression/test/TestExprs.py new file mode 100644 index 00000000000..4fe228d40d4 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/test/TestExprs.py @@ -0,0 +1,253 @@ +""" +Test many basic expression commands and SBFrame.EvaluateExpression() API. + +Test cases: + +o test_many_expr_commands: + Test many basic expression commands. +o test_evaluate_expression_python: + Use Python APIs (SBFrame.EvaluateExpression()) to evaluate expressions. +o test_expr_commands_can_handle_quotes: + Throw some expression commands with quotes at lldb. +""" + +from __future__ import print_function + + +import unittest2 + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class BasicExprCommandsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number( + 'main.cpp', + '// Please test many expressions while stopped at this line:') + + # Disable confirmation prompt to avoid infinite wait + self.runCmd("settings set auto-confirm true") + self.addTearDownHook( + lambda: self.runCmd("settings clear auto-confirm")) + + def build_and_run(self): + """These basic expression commands should work as expected.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + @unittest2.expectedFailure( + "llvm.org/pr17135 <rdar://problem/14874559> APFloat::toString does not identify the correct (i.e. least) precision.") + def test_floating_point_expr_commands(self): + self.build_and_run() + + self.expect("expression 2.234f", + patterns=["\(float\) \$.* = 2\.234"]) + # (float) $2 = 2.234 + + def test_many_expr_commands(self): + self.build_and_run() + + self.expect("expression 2", + patterns=["\(int\) \$.* = 2"]) + # (int) $0 = 1 + + self.expect("expression 2ull", + patterns=["\(unsigned long long\) \$.* = 2"]) + # (unsigned long long) $1 = 2 + + self.expect("expression 0.5f", + patterns=["\(float\) \$.* = 0\.5"]) + # (float) $2 = 0.5 + + self.expect("expression 2.234", + patterns=["\(double\) \$.* = 2\.234"]) + # (double) $3 = 2.234 + + self.expect("expression 2+3", + patterns=["\(int\) \$.* = 5"]) + # (int) $4 = 5 + + self.expect("expression argc", + patterns=["\(int\) \$.* = 1"]) + # (int) $5 = 1 + + self.expect("expression argc + 22", + patterns=["\(int\) \$.* = 23"]) + # (int) $6 = 23 + + self.expect("expression argv", + patterns=["\(const char \*\*\) \$.* = 0x"]) + # (const char *) $7 = ... + + self.expect("expression argv[0]", + substrs=["(const char *)", + "a.out"]) + # (const char *) $8 = 0x... "/Volumes/data/lldb/svn/trunk/test/expression_command/test/a.out" + + @add_test_categories(['pyapi']) + @expectedFlakeyNetBSD + def test_evaluate_expression_python(self): + """Test SBFrame.EvaluateExpression() API for evaluating an expression.""" + self.build() + + exe = self.getBuildArtifact("a.out") + + target = self.dbg.CreateTarget(exe) + self.assertTrue(target, VALID_TARGET) + + # Create the breakpoint. + filespec = lldb.SBFileSpec("main.cpp", False) + breakpoint = target.BreakpointCreateByLocation(filespec, self.line) + self.assertTrue(breakpoint, VALID_BREAKPOINT) + + # Verify the breakpoint just created. + self.expect(str(breakpoint), BREAKPOINT_CREATED, exe=False, + substrs=['main.cpp', + str(self.line)]) + + # Launch the process, and do not stop at the entry point. + # Pass 'X Y Z' as the args, which makes argc == 4. + process = target.LaunchSimple( + ['X', 'Y', 'Z'], None, self.get_process_working_directory()) + + if not process: + self.fail("SBTarget.LaunchProcess() failed") + + if process.GetState() != lldb.eStateStopped: + self.fail("Process should be in the 'stopped' state, " + "instead the actual state is: '%s'" % + lldbutil.state_type_to_str(process.GetState())) + + thread = lldbutil.get_one_thread_stopped_at_breakpoint( + process, breakpoint) + self.assertIsNotNone( + thread, "Expected one thread to be stopped at the breakpoint") + + # The filename of frame #0 should be 'main.cpp' and function is main. + self.expect(lldbutil.get_filenames(thread)[0], + "Break correctly at main.cpp", exe=False, + startstr="main.cpp") + self.expect(lldbutil.get_function_names(thread)[0], + "Break correctly at main()", exe=False, + startstr="main") + + # We should be stopped on the breakpoint with a hit count of 1. + self.assertTrue(breakpoint.GetHitCount() == 1, BREAKPOINT_HIT_ONCE) + + # + # Use Python API to evaluate expressions while stopped in a stack frame. + # + frame = thread.GetFrameAtIndex(0) + + val = frame.EvaluateExpression("2.234") + self.expect(val.GetValue(), "2.345 evaluated correctly", exe=False, + startstr="2.234") + self.expect(val.GetTypeName(), "2.345 evaluated correctly", exe=False, + startstr="double") + self.DebugSBValue(val) + + val = frame.EvaluateExpression("argc") + self.expect(val.GetValue(), "Argc evaluated correctly", exe=False, + startstr="4") + self.DebugSBValue(val) + + val = frame.EvaluateExpression("*argv[1]") + self.expect(val.GetValue(), "Argv[1] evaluated correctly", exe=False, + startstr="'X'") + self.DebugSBValue(val) + + val = frame.EvaluateExpression("*argv[2]") + self.expect(val.GetValue(), "Argv[2] evaluated correctly", exe=False, + startstr="'Y'") + self.DebugSBValue(val) + + val = frame.EvaluateExpression("*argv[3]") + self.expect(val.GetValue(), "Argv[3] evaluated correctly", exe=False, + startstr="'Z'") + self.DebugSBValue(val) + + callee_break = target.BreakpointCreateByName( + "a_function_to_call", None) + self.assertTrue(callee_break.GetNumLocations() > 0) + + # Make sure ignoring breakpoints works from the command line: + self.expect("expression -i true -- a_function_to_call()", + substrs=['(int) $', ' 1']) + self.assertTrue(callee_break.GetHitCount() == 1) + + # Now try ignoring breakpoints using the SB API's: + options = lldb.SBExpressionOptions() + options.SetIgnoreBreakpoints(True) + value = frame.EvaluateExpression('a_function_to_call()', options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetValueAsSigned(0) == 2) + self.assertTrue(callee_break.GetHitCount() == 2) + + # rdar://problem/8686536 + # CommandInterpreter::HandleCommand is stripping \'s from input for + # WantsRawCommand commands + @expectedFailureNetBSD + def test_expr_commands_can_handle_quotes(self): + """Throw some expression commands with quotes at lldb.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + # runCmd: expression 'a' + # output: (char) $0 = 'a' + self.expect("expression 'a'", + substrs=['(char) $', + "'a'"]) + + # runCmd: expression (int) printf ("\n\n\tHello there!\n") + # output: (int) $1 = 16 + self.expect(r'''expression (int) printf ("\n\n\tHello there!\n")''', + substrs=['(int) $', + '16']) + + # runCmd: expression (int) printf("\t\x68\n") + # output: (int) $2 = 3 + self.expect(r'''expression (int) printf("\t\x68\n")''', + substrs=['(int) $', + '3']) + + # runCmd: expression (int) printf("\"\n") + # output: (int) $3 = 2 + self.expect(r'''expression (int) printf("\"\n")''', + substrs=['(int) $', + '2']) + + # runCmd: expression (int) printf("'\n") + # output: (int) $4 = 2 + self.expect(r'''expression (int) printf("'\n")''', + substrs=['(int) $', + '2']) + + # runCmd: command alias print_hi expression (int) printf ("\n\tHi!\n") + # output: + self.runCmd( + r'''command alias print_hi expression (int) printf ("\n\tHi!\n")''') + # This fails currently. + self.expect('print_hi', + substrs=['(int) $', + '6']) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/test/TestExprs2.py b/lldb/packages/Python/lldbsuite/test/commands/expression/test/TestExprs2.py new file mode 100644 index 00000000000..1a733bebffe --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/test/TestExprs2.py @@ -0,0 +1,74 @@ +""" +Test some more expression commands. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommands2TestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number( + 'main.cpp', + '// Please test many expressions while stopped at this line:') + + def test_more_expr_commands(self): + """Test some more expression commands.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + # Does static casting work? + self.expect("expression (int*)argv", + startstr="(int *) $0 = 0x") + # (int *) $0 = 0x00007fff5fbff258 + + # Do return values containing the contents of expression locals work? + self.expect("expression int i = 5; i", + startstr="(int) $1 = 5") + # (int) $2 = 5 + self.expect("expression $1 + 1", + startstr="(int) $2 = 6") + # (int) $3 = 6 + + # Do return values containing the results of static expressions work? + self.expect("expression 20 + 3", + startstr="(int) $3 = 23") + # (int) $4 = 5 + self.expect("expression $3 + 1", + startstr="(int) $4 = 24") + # (int) $5 = 6 + + @skipIfLinux + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr24489") + def test_expr_symbols(self): + """Test symbols.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + # Do anonymous symbols work? + self.expect("expression ((char**)environ)[0]", + startstr="(char *) $0 = 0x") + # (char *) $1 = 0x00007fff5fbff298 "Apple_PubSub_Socket_Render=/tmp/launch-7AEsUD/Render" diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/test/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/test/main.cpp new file mode 100644 index 00000000000..22208a87cb4 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/test/main.cpp @@ -0,0 +1,44 @@ +#include <stdio.h> + +static int static_value = 0; + +int +a_function_to_call() +{ + static_value++; + return static_value; +} + +int main (int argc, char const *argv[]) +{ + printf ("Hello world!\n"); + puts ("hello"); + // Please test many expressions while stopped at this line: +#if 0 + expression 'a' // make sure character constant makes it down (this is broken: <rdar://problem/8686536>) + expression 2 // Test int + expression 2ull // Test unsigned long long + expression 2.234f // Test float constants + expression 2.234 // Test double constants + expression 2+3 + expression argc + expression argc + 22 + expression argv + expression argv[0] + expression argv[1] + expression argv[-1] + expression puts("bonjour") // Test constant strings... + expression printf("\t\x68\n") // Test constant strings that contain the \xXX (TAB, 'h', '\n' should be printed) (this is broken: <rdar://problem/8686536>) + expression printf("\"\n") // Test constant strings that contains an escaped double quote char (this is broken: <rdar://problem/8686536>) + expression printf("\'\n") // Test constant strings that contains an escaped single quote char (this is broken: <rdar://problem/8686536>) + expression printf ("one: %i\n", 1) + expression printf ("1.234 as float: %f\n", 1.234f) + expression printf ("1.234 as double: %g\n", 1.234) + expression printf ("one: %i, two: %llu\n", 1, 2ull) + expression printf ("two: %llu, one: %i\n", 2ull, 1) + expression random() % 255l +#endif + + a_function_to_call(); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/timeout/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/timeout/Makefile new file mode 100644 index 00000000000..c9cff412c1b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/timeout/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := wait-a-while.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/timeout/TestCallWithTimeout.py b/lldb/packages/Python/lldbsuite/test/commands/expression/timeout/TestCallWithTimeout.py new file mode 100644 index 00000000000..7862477001e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/timeout/TestCallWithTimeout.py @@ -0,0 +1,80 @@ +""" +Test calling a function that waits a while, and make sure the timeout option to expr works. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprCommandWithTimeoutsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.main_source = "wait-a-while.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + @expectedFlakeyFreeBSD("llvm.org/pr19605") + @expectedFailureAll( + oslist=[ + "windows"], + bugnumber="llvm.org/pr21765") + def test(self): + """Test calling std::String member function.""" + self.build() + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, 'stop here in main.', self.main_source_spec) + + # First set the timeout too short, and make sure we fail. + options = lldb.SBExpressionOptions() + options.SetTimeoutInMicroSeconds(10) + options.SetUnwindOnError(True) + + frame = thread.GetFrameAtIndex(0) + + value = frame.EvaluateExpression("wait_a_while(1000000)", options) + self.assertTrue(value.IsValid()) + self.assertFalse(value.GetError().Success()) + + # Now do the same thing with the command line command, and make sure it + # works too. + interp = self.dbg.GetCommandInterpreter() + + result = lldb.SBCommandReturnObject() + return_value = interp.HandleCommand( + "expr -t 100 -u true -- wait_a_while(1000000)", result) + self.assertTrue(return_value == lldb.eReturnStatusFailed) + + # Okay, now do it again with long enough time outs: + + options.SetTimeoutInMicroSeconds(1000000) + value = frame.EvaluateExpression("wait_a_while (1000)", options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + + # Now do the same thingwith the command line command, and make sure it + # works too. + interp = self.dbg.GetCommandInterpreter() + + result = lldb.SBCommandReturnObject() + return_value = interp.HandleCommand( + "expr -t 1000000 -u true -- wait_a_while(1000)", result) + self.assertTrue(return_value == lldb.eReturnStatusSuccessFinishResult) + + # Finally set the one thread timeout and make sure that doesn't change + # things much: + + options.SetTimeoutInMicroSeconds(1000000) + options.SetOneThreadTimeoutInMicroSeconds(500000) + value = frame.EvaluateExpression("wait_a_while (1000)", options) + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/timeout/wait-a-while.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/timeout/wait-a-while.cpp new file mode 100644 index 00000000000..ac37c5d243b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/timeout/wait-a-while.cpp @@ -0,0 +1,35 @@ +#include <stdio.h> +#include <stdint.h> + +#include <chrono> +#include <thread> + + +int +wait_a_while (int microseconds) +{ + int num_times = 0; + auto end_time = std::chrono::system_clock::now() + std::chrono::microseconds(microseconds); + + while (1) + { + num_times++; + auto wait_time = end_time - std::chrono::system_clock::now(); + + std::this_thread::sleep_for(wait_time); + if (std::chrono::system_clock::now() > end_time) + break; + } + return num_times; +} + +int +main (int argc, char **argv) +{ + printf ("stop here in main.\n"); + int num_times = wait_a_while (argc * 1000); + printf ("Done, took %d times.\n", num_times); + + return 0; + +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/Makefile new file mode 100644 index 00000000000..9e35242c72f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/Makefile @@ -0,0 +1,13 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp test.cpp + +include $(LEVEL)/Makefile.rules + +a.out: dummy + +dummy: + $(MAKE) VPATH=$(VPATH) -I $(SRCDIR) -f $(SRCDIR)/dummy.mk + +clean:: + $(MAKE) VPATH=$(VPATH) -I $(SRCDIR) -f $(SRCDIR)/dummy.mk clean diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/TestTopLevelExprs.py b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/TestTopLevelExprs.py new file mode 100644 index 00000000000..e6a632b7f23 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/TestTopLevelExprs.py @@ -0,0 +1,94 @@ +""" +Test top-level expressions. +""" + +from __future__ import print_function + + +import unittest2 + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class TopLevelExpressionsTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.c. + self.line = line_number('main.cpp', + '// Set breakpoint here') + self.dummy_line = line_number('dummy.cpp', + '// Set breakpoint here') + + # Disable confirmation prompt to avoid infinite wait + self.runCmd("settings set auto-confirm true") + self.addTearDownHook( + lambda: self.runCmd("settings clear auto-confirm")) + + def build_and_run(self): + """Test top-level expressions.""" + self.build() + + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.cpp", self.line, num_expected_locations=1, loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + def run_dummy(self): + self.runCmd("file " + self.getBuildArtifact("dummy"), + CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, + "dummy.cpp", + self.dummy_line, + num_expected_locations=1, + loc_exact=False) + + self.runCmd("run", RUN_SUCCEEDED) + + @add_test_categories(['pyapi']) + @skipIf(debug_info="gmodules") # not relevant + @skipIf(oslist=["windows"]) # Error in record layout on Windows + def test_top_level_expressions(self): + self.build_and_run() + + resultFromCode = self.frame().EvaluateExpression("doTest()").GetValueAsUnsigned() + + self.runCmd("kill") + + self.run_dummy() + + codeFile = open('test.cpp', 'r') + + expressions = [] + current_expression = "" + + for line in codeFile: + if line.startswith("// --"): + expressions.append(current_expression) + current_expression = "" + else: + current_expression += line + + options = lldb.SBExpressionOptions() + options.SetLanguage(lldb.eLanguageTypeC_plus_plus) + options.SetTopLevel(True) + + for expression in expressions: + self.frame().EvaluateExpression(expression, options) + + resultFromTopLevel = self.frame().EvaluateExpression("doTest()") + + self.assertTrue(resultFromTopLevel.IsValid()) + self.assertEqual( + resultFromCode, + resultFromTopLevel.GetValueAsUnsigned()) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/dummy.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/dummy.cpp new file mode 100644 index 00000000000..fa49bd4bda7 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/dummy.cpp @@ -0,0 +1,15 @@ +#include <stdio.h> + +// These are needed to make sure that the linker does not strip the parts of the +// C++ abi library that are necessary to execute the expressions in the +// debugger. It would be great if we did not need to do this, but the fact that +// LLDB cannot conjure up the abi library on demand is not relevant for testing +// top level expressions. +struct DummyA {}; +struct DummyB : public virtual DummyA {}; + +int main() { + DummyB b; + printf("This is a dummy\n"); // Set breakpoint here + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/dummy.mk b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/dummy.mk new file mode 100644 index 00000000000..af97678b2cf --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/dummy.mk @@ -0,0 +1,6 @@ +LEVEL = ../../make + +CXX_SOURCES := dummy.cpp +EXE := dummy + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/main.cpp new file mode 100644 index 00000000000..f9b2dd4c6d9 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/main.cpp @@ -0,0 +1,9 @@ +#include <stdio.h> + +extern int doTest(); + +int main() +{ + printf("%d\n", doTest()); // Set breakpoint here + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/test.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/test.cpp new file mode 100644 index 00000000000..5a978743596 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/top-level/test.cpp @@ -0,0 +1,107 @@ +class MyClass +{ +public: + int memberResult() + { + return 1; + } + static int staticResult() + { + return 1; + } + int externResult(); +}; + +// -- + +int MyClass::externResult() +{ + return 1; +} + +// -- + +MyClass m; + +// -- + +enum MyEnum { + myEnumOne = 1, + myEnumTwo, + myEnumThree +}; + +// -- + +class AnotherClass +{ +public: + __attribute__ ((always_inline)) int complicatedFunction() + { + struct { + int i; + } s = { 15 }; + + int numbers[4] = { 2, 3, 4, 5 }; + + for (signed char number: numbers) + { + s.i -= number; + } + + return s.i; + } +}; + +// -- + +class DiamondA +{ +private: + struct { + int m_i; + }; +public: + DiamondA(int i) : m_i(i) { } + int accessor() { return m_i; } +}; + +// -- + +class DiamondB : public virtual DiamondA +{ +public: + DiamondB(int i) : DiamondA(i) { } +}; + +// -- + +class DiamondC : public virtual DiamondA +{ +public: + DiamondC(int i) : DiamondA(i) { } +}; + +// -- + +class DiamondD : public DiamondB, public DiamondC +{ +public: + DiamondD(int i) : DiamondA(i), DiamondB(i), DiamondC(i) { } +}; + +// -- + +int doTest() +{ + int accumulator = m.memberResult(); + accumulator += MyClass::staticResult(); + accumulator += m.externResult(); + accumulator += MyEnum::myEnumThree; + accumulator += myEnumOne; + accumulator += AnotherClass().complicatedFunction(); + accumulator += DiamondD(3).accessor(); + return accumulator; +} + +// -- diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/Makefile new file mode 100644 index 00000000000..5974461e256 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/Makefile @@ -0,0 +1,7 @@ +LEVEL = ../../make + +OBJC_SOURCES := main.m foo.m + +include $(LEVEL)/Makefile.rules + +LDFLAGS += -framework Foundation
\ No newline at end of file diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/TestObjCTypeQueryFromOtherCompileUnit.py b/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/TestObjCTypeQueryFromOtherCompileUnit.py new file mode 100644 index 00000000000..bac8e5453e4 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/TestObjCTypeQueryFromOtherCompileUnit.py @@ -0,0 +1,41 @@ +""" +Regression test for <rdar://problem/8981098>: + +The expression parser's type search only looks in the current compilation unit for types. +""" + +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ObjCTypeQueryTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + # Find the line number to break for main.m. + self.line = line_number( + 'main.m', "// Set breakpoint here, then do 'expr (NSArray*)array_token'.") + + @skipUnlessDarwin + def test(self): + """The expression parser's type search should be wider than the current compilation unit.""" + self.build() + self.runCmd("file " + self.getBuildArtifact("a.out"), CURRENT_EXECUTABLE_SET) + + lldbutil.run_break_set_by_file_and_line( + self, "main.m", self.line, num_expected_locations=1, loc_exact=True) + + self.runCmd("run", RUN_SUCCEEDED) + + # Now do a NSArry type query from the 'main.m' compile uint. + self.expect("expression (NSArray*)array_token", + substrs=['(NSArray *) $0 = 0x']) + # (NSArray *) $0 = 0x00007fff70118398 diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/foo.m b/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/foo.m new file mode 100644 index 00000000000..1609ebd838f --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/foo.m @@ -0,0 +1,28 @@ +#import <Foundation/Foundation.h> + +NSMutableArray * +GetArray () +{ + static NSMutableArray *the_array = NULL; + if (the_array == NULL) + the_array = [[NSMutableArray alloc] init]; + return the_array; +} + +int +AddElement (char *value) +{ + NSString *element = [NSString stringWithUTF8String: value]; + int cur_elem = [GetArray() count]; + [GetArray() addObject: element]; + return cur_elem; +} + +const char * +GetElement (int idx) +{ + if (idx >= [GetArray() count]) + return NULL; + else + return [[GetArray() objectAtIndex: idx] UTF8String]; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/main.m b/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/main.m new file mode 100644 index 00000000000..3f5738314e6 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/two-files/main.m @@ -0,0 +1,22 @@ +#import <Foundation/Foundation.h> +#include <stdio.h> + +extern int AddElement (char *value); +extern char *GetElement (int idx); +extern void *GetArray(); + +int +main () +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + + int idx = AddElement ("some string"); + void *array_token = GetArray(); + + char *string = GetElement (0); // Set breakpoint here, then do 'expr (NSArray*)array_token'. + if (string) + printf ("This: %s.\n", string); + + [pool release]; + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/unicode-in-variable/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/unicode-in-variable/Makefile new file mode 100644 index 00000000000..3759b5f9255 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/unicode-in-variable/Makefile @@ -0,0 +1,4 @@ +LEVEL = ../../make +CXX_SOURCES := main.cpp +CXX_FLAGS_EXTRA := -finput-charset=UTF-8 -fextended-identifiers +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/unicode-in-variable/TestUnicodeInVariable.py b/lldb/packages/Python/lldbsuite/test/commands/expression/unicode-in-variable/TestUnicodeInVariable.py new file mode 100644 index 00000000000..03424658f3e --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/unicode-in-variable/TestUnicodeInVariable.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals(), None) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/unicode-in-variable/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/unicode-in-variable/main.cpp new file mode 100644 index 00000000000..82e38b1ef4c --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/unicode-in-variable/main.cpp @@ -0,0 +1,17 @@ +// Make sure we correctly handle unicode in variable names. + +struct A { + // We need a member variable in the context that could shadow our local + // variable. If our optimization code fails to handle this, then we won't + // correctly inject our local variable so that it won't get shadowed. + int foob\u00E1r = 2; + int foo() { + int foob\u00E1r = 3; + return foob\u00E1r; //%self.expect("expr foobár", substrs=['(int)', ' = 3']) + } +}; + +int main() { + A a; + return a.foo(); +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/unwind_expression/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/unwind_expression/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/unwind_expression/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/unwind_expression/TestUnwindExpression.py b/lldb/packages/Python/lldbsuite/test/commands/expression/unwind_expression/TestUnwindExpression.py new file mode 100644 index 00000000000..d42ee3de404 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/unwind_expression/TestUnwindExpression.py @@ -0,0 +1,101 @@ +""" +Test stopping at a breakpoint in an expression, and unwinding from there. +""" + +from __future__ import print_function + + +import unittest2 + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class UnwindFromExpressionTest(TestBase): + + mydir = TestBase.compute_mydir(__file__) + main_spec = lldb.SBFileSpec("main.cpp", False) + + def build_and_run_to_bkpt(self): + self.build() + + (target, process, self.thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "// Set a breakpoint here to get started", self.main_spec) + + # Next set a breakpoint in this function, set up Expression options to stop on + # breakpoint hits, and call the function. + self.fun_bkpt = self.target().BreakpointCreateBySourceRegex( + "// Stop inside the function here.", self.main_spec) + self.assertTrue(self.fun_bkpt, VALID_BREAKPOINT) + + + @no_debug_info_test + @expectedFailureAll(bugnumber="llvm.org/pr33164") + def test_conditional_bktp(self): + """ + Test conditional breakpoint handling in the IgnoreBreakpoints = False case + """ + self.build_and_run_to_bkpt() + + self.fun_bkpt.SetCondition("0") # Should not get hit + options = lldb.SBExpressionOptions() + options.SetIgnoreBreakpoints(False) + options.SetUnwindOnError(False) + + main_frame = self.thread.GetFrameAtIndex(0) + val = main_frame.EvaluateExpression("second_function(47)", options) + self.assertTrue( + val.GetError().Success(), + "We did complete the execution.") + self.assertEquals(47, val.GetValueAsSigned()) + + + @add_test_categories(['pyapi']) + @expectedFlakeyNetBSD + def test_unwind_expression(self): + """Test unwinding from an expression.""" + self.build_and_run_to_bkpt() + + # Run test with varying one thread timeouts to also test the halting + # logic in the IgnoreBreakpoints = False case + self.do_unwind_test(self.thread, self.fun_bkpt, 1000) + self.do_unwind_test(self.thread, self.fun_bkpt, 100000) + + def do_unwind_test(self, thread, bkpt, timeout): + # + # Use Python API to evaluate expressions while stopped in a stack frame. + # + main_frame = thread.GetFrameAtIndex(0) + + options = lldb.SBExpressionOptions() + options.SetIgnoreBreakpoints(False) + options.SetUnwindOnError(False) + options.SetOneThreadTimeoutInMicroSeconds(timeout) + + val = main_frame.EvaluateExpression("a_function_to_call()", options) + + self.assertTrue( + val.GetError().Fail(), + "We did not complete the execution.") + error_str = val.GetError().GetCString() + self.assertTrue( + "Execution was interrupted, reason: breakpoint" in error_str, + "And the reason was right.") + + thread = lldbutil.get_one_thread_stopped_at_breakpoint( + self.process(), bkpt) + self.assertTrue( + thread.IsValid(), + "We are indeed stopped at our breakpoint") + + # Now unwind the expression, and make sure we got back to where we + # started. + error = thread.UnwindInnermostExpression() + self.assertTrue(error.Success(), "We succeeded in unwinding") + + cur_frame = thread.GetFrameAtIndex(0) + self.assertTrue( + cur_frame.IsEqual(main_frame), + "We got back to the main frame.") diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/unwind_expression/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/unwind_expression/main.cpp new file mode 100644 index 00000000000..56b06f31ecc --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/unwind_expression/main.cpp @@ -0,0 +1,22 @@ +static int static_value = 0; + +int +a_function_to_call() +{ + static_value++; // Stop inside the function here. + return static_value; +} + +int second_function(int x){ + for(int i=0; i<10; ++i) { + a_function_to_call(); + } + return x; +} + +int main (int argc, char const *argv[]) +{ + a_function_to_call(); // Set a breakpoint here to get started + second_function(1); + return 0; +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/vector_of_enums/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/vector_of_enums/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/vector_of_enums/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/vector_of_enums/TestVectorOfEnums.py b/lldb/packages/Python/lldbsuite/test/commands/expression/vector_of_enums/TestVectorOfEnums.py new file mode 100644 index 00000000000..2da95460e24 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/vector_of_enums/TestVectorOfEnums.py @@ -0,0 +1,29 @@ +""" +Test Expression Parser regression test to ensure that we handle enums +correctly, in this case specifically std::vector of enums. +""" + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestVectorOfEnums(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + @add_test_categories(["libc++"]) + def test_vector_of_enums(self): + self.build() + + lldbutil.run_to_source_breakpoint(self, '// break here', + lldb.SBFileSpec("main.cpp", False)) + + self.expect("expr v", substrs=[ + 'size=3', + '[0] = a', + '[1] = b', + '[2] = c', + '}' + ]) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/vector_of_enums/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/vector_of_enums/main.cpp new file mode 100644 index 00000000000..10d3ae569a5 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/vector_of_enums/main.cpp @@ -0,0 +1,14 @@ +#include <vector> + +enum E { +a, +b, +c, +d +} ; + +int main() { + std::vector<E> v = {E::a, E::b, E::c}; + + return v.size(); // break here +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/Makefile new file mode 100644 index 00000000000..ea434d42714 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/Makefile @@ -0,0 +1,26 @@ +LEVEL = ../../make +CFLAGS_EXTRAS += -std=c99 +LD_FLAGS := -dynamiclib +include $(LEVEL)/Makefile.rules + +all: a.out dylib missing + +dylib: dylib.o + $(CC) $(LD_FLAGS) -o libdylib.dylib dylib.o + +missing: dylib2.o + mkdir hidden + $(CC) $(LD_FLAGS) -o hidden/libdylib.dylib dylib2.o + +a.out: main.o dylib missing + $(CC) $(CFLAGS) -L. -ldylib main.o + +dylib.o: dylib.h $(SRCDIR)/dylib.c + $(CC) -DHAS_THEM $(CFLAGS) -c $(SRCDIR)/dylib.c + +dylib2.o: dylib.h $(SRCDIR)/dylib.c + $(CC) $(CFLAGS) -c $(SRCDIR)/dylib.c -o dylib2.o + +main.o: dylib.h $(SRCDIR)/main.c + $(CC) $(CFLAGS) -c $(SRCDIR)/main.c -fmodules -fmodules-cache-path=$(CLANG_MODULE_CACHE_DIR) + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/TestWeakSymbols.py b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/TestWeakSymbols.py new file mode 100644 index 00000000000..2999cba7d99 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/TestWeakSymbols.py @@ -0,0 +1,81 @@ +""" +Test that we can compile expressions referring to +absent weak symbols from a dylib. +""" + +from __future__ import print_function + + +import os +import lldb +from lldbsuite.test import decorators +import lldbsuite.test.lldbutil as lldbutil +from lldbsuite.test.lldbtest import * + + +class TestWeakSymbolsInExpressions(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + NO_DEBUG_INFO_TESTCASE = True + + @decorators.skipUnlessDarwin + def test_weak_symbol_in_expr(self): + """Tests that we can refer to weak symbols in expressions.""" + self.build() + self.main_source_file = lldb.SBFileSpec("main.c") + self.do_test() + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + def run_weak_var_check (self, weak_varname, present): + # The expression will modify present_weak_int to signify which branch + # was taken. Set it to so we don't get confused by a previous run. + value = self.target.FindFirstGlobalVariable("present_weak_int") + value.SetValueFromCString("0") + if present: + correct_value = 10 + else: + correct_value = 20 + + # Note, I'm adding the "; 10" at the end of the expression to work around + # the bug that expressions with no result currently return False for Success()... + expr = "if (&" + weak_varname + " != NULL) { present_weak_int = 10; } else { present_weak_int = 20;}; 10" + result = self.frame.EvaluateExpression(expr) + self.assertTrue(result.GetError().Success(), "absent_weak_int expr failed: %s"%(result.GetError().GetCString())) + self.assertEqual(value.GetValueAsSigned(), correct_value, "Didn't change present_weak_int correctly.") + + def do_test(self): + hidden_dir = os.path.join(self.getBuildDir(), "hidden") + + launch_info = lldb.SBLaunchInfo(None) + launch_info.SetWorkingDirectory(self.getBuildDir()) + # We have to point to the hidden directory to pick up the + # version of the dylib without the weak symbols: + env_expr = self.platformContext.shlib_environment_var + "=" + hidden_dir + launch_info.SetEnvironmentEntries([env_expr], True) + + (self.target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + "Set a breakpoint here", self.main_source_file, + launch_info = launch_info) + # First we have to import the Dylib module so we get the type info + # for the weak symbol. We need to add the source dir to the module + # search paths, and then run @import to introduce it into the expression + # context: + self.dbg.HandleCommand("settings set target.clang-module-search-paths " + self.getSourceDir()) + + self.frame = thread.frames[0] + self.assertTrue(self.frame.IsValid(), "Got a good frame") + options = lldb.SBExpressionOptions() + options.SetLanguage(lldb.eLanguageTypeObjC) + result = self.frame.EvaluateExpression("@import Dylib", options) + + # Now run an expression that references an absent weak symbol: + self.run_weak_var_check("absent_weak_int", False) + self.run_weak_var_check("absent_weak_function", False) + + # Make sure we can do the same thing with present weak symbols + self.run_weak_var_check("present_weak_int", True) + self.run_weak_var_check("present_weak_function", True) diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/dylib.c b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/dylib.c new file mode 100644 index 00000000000..dc513e5c5fb --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/dylib.c @@ -0,0 +1,14 @@ +#include "dylib.h" + +int present_weak_int = 10; +int present_weak_function() +{ + return present_weak_int; +} + +#if defined HAS_THEM +int absent_weak_int = 10; +int absent_weak_function() { + return absent_weak_int; +} +#endif diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/dylib.h b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/dylib.h new file mode 100644 index 00000000000..f668ec0a784 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/dylib.h @@ -0,0 +1,8 @@ +extern int absent_weak_int __attribute__((weak_import)); + +extern int present_weak_int __attribute__((weak_import)); + +extern int absent_weak_function() __attribute__((weak_import)); + +extern int present_weak_function() __attribute__((weak_import)); + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/main.c b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/main.c new file mode 100644 index 00000000000..5ea257bae5b --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/main.c @@ -0,0 +1,23 @@ +#include "dylib.h" +#include <stdio.h> + +int +doSomething() +{ + // Set a breakpoint here. + if (&absent_weak_int != NULL) + printf("In absent_weak_int: %d\n", absent_weak_int); + if (absent_weak_function != NULL) + printf("In absent_weak_func: %p\n", absent_weak_function); + if (&present_weak_int != NULL) + printf("In present_weak_int: %d\n", present_weak_int); + if (present_weak_function != NULL) + printf("In present_weak_func: %p\n", present_weak_function); + +} + +int +main() +{ + return doSomething(); +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/module.modulemap b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/module.modulemap new file mode 100644 index 00000000000..6f7671400bc --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/weak_symbols/module.modulemap @@ -0,0 +1,3 @@ +module Dylib { + header "dylib.h" +} diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/xvalue/Makefile b/lldb/packages/Python/lldbsuite/test/commands/expression/xvalue/Makefile new file mode 100644 index 00000000000..8a7102e347a --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/xvalue/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/xvalue/TestXValuePrinting.py b/lldb/packages/Python/lldbsuite/test/commands/expression/xvalue/TestXValuePrinting.py new file mode 100644 index 00000000000..3aac6488660 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/xvalue/TestXValuePrinting.py @@ -0,0 +1,37 @@ +from __future__ import print_function + + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class ExprXValuePrintingTestCase(TestBase): + + mydir = TestBase.compute_mydir(__file__) + + def setUp(self): + # Call super's setUp(). + TestBase.setUp(self) + + self.main_source = "main.cpp" + self.main_source_spec = lldb.SBFileSpec(self.main_source) + + def do_test(self, dictionary=None): + """Printing an xvalue should work.""" + self.build(dictionary=dictionary) + + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint(self, + '// Break here', self.main_source_spec) + frame = thread.GetFrameAtIndex(0) + + value = frame.EvaluateExpression("foo().data") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(), 1234) + + @expectedFailureAll(oslist=["windows"], bugnumber="llvm.org/pr21765") + def test(self): + self.do_test() + diff --git a/lldb/packages/Python/lldbsuite/test/commands/expression/xvalue/main.cpp b/lldb/packages/Python/lldbsuite/test/commands/expression/xvalue/main.cpp new file mode 100644 index 00000000000..556c63f2b44 --- /dev/null +++ b/lldb/packages/Python/lldbsuite/test/commands/expression/xvalue/main.cpp @@ -0,0 +1,12 @@ +struct Tmp +{ + int data = 1234; +}; + +Tmp foo() { return Tmp(); } + +int main(int argc, char const *argv[]) +{ + int something = foo().data; + return 0; // Break here +} |