diff options
5 files changed, 117 insertions, 1 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 3e08f25..009722b8 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2150,6 +2150,7 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, SymbolFileDWARF *dwarf = die.GetDWARF(); ClangASTImporter::LayoutInfo layout_info; + std::vector<DWARFDIE> contained_type_dies; if (die.HasChildren()) { const bool type_is_objc_object_or_interface = @@ -2175,7 +2176,8 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, DelayedPropertyList delayed_properties; ParseChildMembers(die, clang_type, bases, member_function_dies, - delayed_properties, default_accessibility, layout_info); + contained_type_dies, delayed_properties, + default_accessibility, layout_info); // Now parse any methods if there were any... for (const DWARFDIE &die : member_function_dies) @@ -2231,6 +2233,12 @@ bool DWARFASTParserClang::CompleteRecordType(const DWARFDIE &die, if (record_decl) GetClangASTImporter().SetRecordLayout(record_decl, layout_info); } + // Now parse all contained types inside of the class. We make forward + // declarations to all classes, but we need the CXXRecordDecl to have decls + // for all contained types because we don't get asked for them via the + // external AST support. + for (const DWARFDIE &die : contained_type_dies) + dwarf->ResolveType(die); return (bool)clang_type; } @@ -3110,6 +3118,7 @@ bool DWARFASTParserClang::ParseChildMembers( const DWARFDIE &parent_die, CompilerType &class_clang_type, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, std::vector<DWARFDIE> &member_function_dies, + std::vector<DWARFDIE> &contained_type_dies, DelayedPropertyList &delayed_properties, const AccessType default_accessibility, ClangASTImporter::LayoutInfo &layout_info) { @@ -3159,6 +3168,8 @@ bool DWARFASTParserClang::ParseChildMembers( break; default: + if (llvm::dwarf::isType(tag)) + contained_type_dies.push_back(die); break; } } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index 3e28e54d..8d4af20 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -175,6 +175,7 @@ protected: lldb_private::CompilerType &class_compiler_type, std::vector<std::unique_ptr<clang::CXXBaseSpecifier>> &base_classes, std::vector<lldb_private::plugin::dwarf::DWARFDIE> &member_function_dies, + std::vector<lldb_private::plugin::dwarf::DWARFDIE> &contained_type_dies, DelayedPropertyList &delayed_properties, const lldb::AccessType default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info); diff --git a/lldb/test/API/commands/expression/nested/Makefile b/lldb/test/API/commands/expression/nested/Makefile new file mode 100644 index 0000000..99998b2 --- /dev/null +++ b/lldb/test/API/commands/expression/nested/Makefile @@ -0,0 +1,3 @@ +CXX_SOURCES := main.cpp + +include Makefile.rules diff --git a/lldb/test/API/commands/expression/nested/TestNestedExpressions.py b/lldb/test/API/commands/expression/nested/TestNestedExpressions.py new file mode 100644 index 0000000..7f194e9 --- /dev/null +++ b/lldb/test/API/commands/expression/nested/TestNestedExpressions.py @@ -0,0 +1,70 @@ +""" +Test calling an expression with errors that a FixIt can fix. +""" + +import lldb +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + + +class NestedExpressions(TestBase): + + def test_enum_in_nested_structs(self): + """ + Test expressions that references an enumeration in nested structs. + """ + self.build() + exe_path = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe_path) + self.assertTrue(target, "Target: %s is not valid." % (exe_path)) + self.expect_expr("A::B::C::EnumType::Eleven", + result_type="A::B::C::EnumType", + result_value="Eleven") + + def test_struct_in_nested_structs(self): + """ + Test expressions that references a struct in nested structs. + """ + self.build() + exe_path = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe_path) + self.assertTrue(target, "Target: %s is not valid." % (exe_path)) + self.expect_expr("sizeof(A::B::C)", result_value="1") + self.expect_expr("sizeof(A::B)", result_value="2") + + def test_static_in_nested_structs(self): + """ + Test expressions that references a static variable in nested structs. + """ + self.build() + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Stop here to evaluate expressions", lldb.SBFileSpec("main.cpp") + ) + self.expect_expr("A::B::C::enum_static", + result_type="A::B::C::EnumType", + result_value="Eleven") + + def test_enum_in_nested_namespaces(self): + """ + Test expressions that references an enumeration in nested namespaces. + """ + self.build() + exe_path = self.getBuildArtifact("a.out") + target = self.dbg.CreateTarget(exe_path) + self.assertTrue(target, "Target: %s is not valid." % (exe_path)) + self.expect_expr("a::b::c::Color::Blue", + result_type="a::b::c::Color", + result_value="Blue") + + def test_static_in_nested_namespaces(self): + """ + Test expressions that references an enumeration in nested namespaces. + """ + self.build() + (target, process, thread, bkpt) = lldbutil.run_to_source_breakpoint( + self, "Stop here to evaluate expressions", lldb.SBFileSpec("main.cpp") + ) + self.expect_expr("a::b::c::d", + result_type="int", + result_value="12") diff --git a/lldb/test/API/commands/expression/nested/main.cpp b/lldb/test/API/commands/expression/nested/main.cpp new file mode 100644 index 0000000..620535f --- /dev/null +++ b/lldb/test/API/commands/expression/nested/main.cpp @@ -0,0 +1,31 @@ +namespace a { +namespace b { +namespace c { +static int d = 12; +enum Color { Red, Green, Blue }; +} // namespace c +} // namespace b +} // namespace a + +struct A { + int _a = 'a'; + struct B { + short _b = 'b'; + struct C { + char _c = 'c'; + enum EnumType : int { Eleven = 11 }; + static EnumType enum_static; + }; + }; +}; + +A::B::C::EnumType A::B::C::enum_static = A::B::C::Eleven; + +int foo() { + a::b::c::Color color = a::b::c::Blue; + return A::B::C::enum_static == a::b::c::d && ((int)color == 0); +} + +int main() { + return foo(); // Stop here to evaluate expressions +} |