tberghammer created this revision. tberghammer added a reviewer: clayborg. tberghammer added a subscriber: lldb-commits.
Fix expression evaluation inside lambda functions for gcc gcc emits the artificial struct created for lambda expressions inside a lexical block what is not understood by clang (it emits them at the compile unit level). This CL changes the dwarf parsing code to move types defined inside a lexical block to the first parent what is not a lexical block to avoid this clang limitation. This will make the experience between clang and gcc consistent as clang moves these types out of the lexical blocks before emitting the debug info. https://reviews.llvm.org/D27394 Files: packages/Python/lldbsuite/test/expression_command/lambda/Makefile packages/Python/lldbsuite/test/expression_command/lambda/TestLambda.py packages/Python/lldbsuite/test/expression_command/lambda/main.cpp source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp
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; 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: 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/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
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits