Index: packages/Python/lldbsuite/test/expression_command/lambda/Makefile =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/expression_command/lambda/Makefile @@ -0,0 +1,5 @@ +LEVEL = ../../make + +CXX_SOURCES := main.cpp + +include $(LEVEL)/Makefile.rules Index: packages/Python/lldbsuite/test/expression_command/lambda/TestLambda.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/expression_command/lambda/TestLambda.py @@ -0,0 +1,73 @@ +from __future__ import print_function + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class LambdaTestCase(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.exe = os.path.join(os.getcwd(), "a.out") + + def test_expression_inside_lambda(self): + self.build() + + target = self.dbg.CreateTarget(self.exe) + self.assertTrue(target) + + breakpoint = target.BreakpointCreateBySourceRegex( + '// Break here 1', self.main_source_spec) + self.assertTrue(breakpoint) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process) + + threads = lldbutil.get_threads_stopped_at_breakpoint( + process, breakpoint) + self.assertEqual(len(threads), 1) + + frame = threads[0].GetFrameAtIndex(0) + + value = frame.EvaluateExpression("a + b") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(0), 579) + + @expectedFailureAll(compiler="gcc") + def test_expression_call_lambda(self): + self.build() + + target = self.dbg.CreateTarget(self.exe) + self.assertTrue(target) + + breakpoint = target.BreakpointCreateBySourceRegex( + '// Break here 2', self.main_source_spec) + self.assertTrue(breakpoint) + + # Launch the process, and do not stop at the entry point. + process = target.LaunchSimple( + None, None, self.get_process_working_directory()) + self.assertTrue(process) + + threads = lldbutil.get_threads_stopped_at_breakpoint( + process, breakpoint) + self.assertEqual(len(threads), 1) + + frame = threads[0].GetFrameAtIndex(0) + + value = frame.EvaluateExpression("l(321, 654)") + self.assertTrue(value.IsValid()) + self.assertTrue(value.GetError().Success()) + self.assertEqual(value.GetValueAsSigned(0), 975) + Index: packages/Python/lldbsuite/test/expression_command/lambda/main.cpp =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/expression_command/lambda/main.cpp @@ -0,0 +1,6 @@ +int main() { + auto l = [](int a, int b) { + return a + b; // Break here 1 + }; + return l(123, 456); // Break here 2 +} Index: source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -3777,7 +3777,37 @@ const DWARFDIE &die, DWARFDIE *decl_ctx_die_copy) { SymbolFileDWARF *dwarf = die.GetDWARF(); + bool is_type = false; + switch (die.Tag()) { + case DW_TAG_base_type: + case DW_TAG_class_type: + case DW_TAG_const_type: + case DW_TAG_pointer_type: + case DW_TAG_reference_type: + case DW_TAG_restrict_type: + case DW_TAG_rvalue_reference_type: + case DW_TAG_structure_type: + case DW_TAG_typedef: + case DW_TAG_union_type: + case DW_TAG_unspecified_type: + case DW_TAG_volatile_type: + is_type = true; + break; + default: + break; + } + DWARFDIE decl_ctx_die = dwarf->GetDeclContextDIEContainingDIE(die); + if (is_type) { + // The clang AST importer can't handle types declared inside a BlockDecl. + // Move these declarartions into the parent context of the block. This will + // make the behavior from gcc (what emits type information inside lexical + // blocks) consistent with the way clang emits debug info for types defined + // inside a function (class, namespace or compile unit level). + while (decl_ctx_die.Tag() == DW_TAG_lexical_block) { + decl_ctx_die = dwarf->GetDeclContextDIEContainingDIE(decl_ctx_die); + } + } if (decl_ctx_die_copy) *decl_ctx_die_copy = decl_ctx_die;