Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/TestWithModuleDebugging.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/TestWithModuleDebugging.py +++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/TestWithModuleDebugging.py @@ -69,3 +69,26 @@ 42, memberValue.GetValueAsSigned(), "Member value incorrect") + + testValue = frame.EvaluateExpression("bar") + self.assertTrue( + testValue.GetError().Success(), + "Test expression value invalid: %s" % + (testValue.GetError().GetCString())) + self.assertTrue( + testValue.GetTypeName() == "Foo::Bar", + "Test expression type incorrect") + + memberValue = testValue.GetChildMemberWithName("i") + self.assertTrue( + memberValue.GetError().Success(), + "Member value missing or invalid: %s" % + (testValue.GetError().GetCString())) + self.assertTrue( + memberValue.GetTypeName() == "int", + "Member type incorrect") + self.assertEqual( + 123, + memberValue.GetValueAsSigned(), + "Member value incorrect") + Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/main.cpp =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/main.cpp +++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/main.cpp @@ -1,5 +1,8 @@ +class Foo::Bar { int i = 123; }; + int main(int argc, const char * argv[]) { IntContainer test(42); + Foo::Bar bar; return 0; // break here } Index: lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/pch.h =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/pch.h +++ lldb/trunk/packages/Python/lldbsuite/test/lang/cpp/gmodules/pch.h @@ -10,3 +10,8 @@ }; typedef GenericContainer IntContainer; + +struct Foo { + class Bar; + Bar *bar; +}; Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -205,6 +205,33 @@ return type_sp; } +static void CompleteExternalTagDeclType(ClangASTImporter &ast_importer, + clang::DeclContext *decl_ctx, + DWARFDIE die, + const char *type_name_cstr) { + auto *tag_decl_ctx = clang::dyn_cast(decl_ctx); + if (!tag_decl_ctx) + return; + + // If this type was not imported from an external AST, there's + // nothing to do. + CompilerType type = ClangASTContext::GetTypeForDecl(tag_decl_ctx); + if (!type || !ast_importer.CanImport(type)) + return; + + auto qual_type = ClangUtil::GetQualType(type); + if (!ast_importer.RequireCompleteType(qual_type)) { + die.GetDWARF()->GetObjectFile()->GetModule()->ReportError( + "Unable to complete the Decl context for DIE '%s' at offset " + "0x%8.8x.\nPlease file a bug report.", + type_name_cstr ?: "", die.GetOffset()); + // We need to make the type look complete otherwise, we + // might crash in Clang when adding children. + if (ClangASTContext::StartTagDeclarationDefinition(type)) + ClangASTContext::CompleteTagDeclarationDefinition(type); + } +} + TypeSP DWARFASTParserClang::ParseTypeFromDWARF(const SymbolContext &sc, const DWARFDIE &die, Log *log, bool *type_is_new_ptr) { @@ -795,6 +822,16 @@ if (!clang_type) { clang::DeclContext *decl_ctx = GetClangDeclContextContainingDIE(die, nullptr); + + // If your decl context is a record that was imported from + // another AST context (in the gmodules case), we need to + // make sure the type backing the Decl is complete before + // adding children to it. This is not an issue in the + // non-gmodules case because the debug info will always contain + // a full definition of parent types in that case. + CompleteExternalTagDeclType(GetClangASTImporter(), decl_ctx, die, + type_name_cstr); + if (accessibility == eAccessNone && decl_ctx) { // Check the decl context that contains this class/struct/union. // If it is a class we must give it an accessibility.