rupprecht created this revision. rupprecht added reviewers: labath, teemperor. Herald added a reviewer: shafik. rupprecht requested review of this revision. Herald added a project: LLDB. Herald added a subscriber: lldb-commits.
This reverts commit 3bf96b0329be554c67282b0d7d8da6a864b9e38f <https://reviews.llvm.org/rG3bf96b0329be554c67282b0d7d8da6a864b9e38f>. It causes crashes as reported in PR52257 and a few other places. A reproducer is bundled with this commit to verify any fix forward. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D113449 Files: lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp lldb/test/API/lang/cpp/reference-to-outer-type/Makefile lldb/test/API/lang/cpp/reference-to-outer-type/TestCppReferenceToOuterClass.py lldb/test/API/lang/cpp/reference-to-outer-type/main.cpp lldb/test/Shell/SymbolFile/DWARF/PR52257.cpp
Index: lldb/test/Shell/SymbolFile/DWARF/PR52257.cpp =================================================================== --- /dev/null +++ lldb/test/Shell/SymbolFile/DWARF/PR52257.cpp @@ -0,0 +1,21 @@ +// Verify that LLDB doesn't crash. See llvm.org/PR52257. + +// RUN: %clangxx_host -g -c %s -o %t.o +// RUN: %lldb -b -o "print b" %t.o | FileCheck %s + +// CHECK: (lldb) print b +// CHECK: (B) $0 = { +// CHECK: tag_set_ = nullptr +// CHECK: } + +template <typename> struct pair {}; +struct A { + using iterator = pair<char *>; + pair<char *> a_[]; +}; +struct B { + using iterator = A::iterator; + iterator begin(); + A *tag_set_; +}; +B b; Index: lldb/test/API/lang/cpp/reference-to-outer-type/main.cpp =================================================================== --- lldb/test/API/lang/cpp/reference-to-outer-type/main.cpp +++ /dev/null @@ -1,23 +0,0 @@ -struct Outer { - typedef int HookToOuter; - // When importing this type, we have to import all of it before adding it - // via the FieldDecl to 'Outer'. If we don't do this, then Clang will - // while adding 'NestedClassMember' ask for the full type of 'NestedClass' - // which then will start pulling in the 'RefToOuter' member. That member - // will import the typedef above and add it to 'Outer'. And adding a - // Decl to a DeclContext that is currently already in the process of adding - // another Decl will cause an inconsistent lookup. - struct NestedClass { - HookToOuter RefToOuter; - int SomeMember; - } NestedClassMember; -}; - -// We query the members of base classes of a type by doing a lookup via Clang. -// As this tests is trying to find a borked lookup, we need a base class here -// to make our 'GetChildMemberWithName' use the Clang lookup. -struct In : Outer {}; - -In test_var; - -int main() { return test_var.NestedClassMember.SomeMember; } Index: lldb/test/API/lang/cpp/reference-to-outer-type/TestCppReferenceToOuterClass.py =================================================================== --- lldb/test/API/lang/cpp/reference-to-outer-type/TestCppReferenceToOuterClass.py +++ /dev/null @@ -1,16 +0,0 @@ -import lldb -from lldbsuite.test.decorators import * -from lldbsuite.test.lldbtest import * -from lldbsuite.test import lldbutil - -class TestCase(TestBase): - - mydir = TestBase.compute_mydir(__file__) - - def test(self): - self.build() - self.dbg.CreateTarget(self.getBuildArtifact("a.out")) - test_var = self.expect_expr("test_var", result_type="In") - nested_member = test_var.GetChildMemberWithName('NestedClassMember') - self.assertEqual("Outer::NestedClass", - nested_member.GetType().GetName()) Index: lldb/test/API/lang/cpp/reference-to-outer-type/Makefile =================================================================== --- lldb/test/API/lang/cpp/reference-to-outer-type/Makefile +++ /dev/null @@ -1,3 +0,0 @@ -CXX_SOURCES := main.cpp - -include Makefile.rules Index: lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -479,7 +479,10 @@ decl->getDeclKindName(), ast_dump); } - CopyDecl(decl); + Decl *copied_decl = CopyDecl(decl); + + if (!copied_decl) + continue; // FIXME: We should add the copied decl to the 'decls' list. This would // add the copied Decl into the DeclContext and make sure that we @@ -489,6 +492,12 @@ // lookup issues later on. // We can't just add them for now as the ASTImporter already added the // decl into the DeclContext and this would add it twice. + + if (FieldDecl *copied_field = dyn_cast<FieldDecl>(copied_decl)) { + QualType copied_field_type = copied_field->getType(); + + m_ast_importer_sp->RequireCompleteType(copied_field_type); + } } else { SkippedDecls = true; } Index: lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp =================================================================== --- lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp +++ lldb/source/Plugins/ExpressionParser/Clang/ClangASTImporter.cpp @@ -888,37 +888,6 @@ LLDB_LOG(log, "[ClangASTImporter] Complete definition not found"); } - // Disable the minimal import for fields that have record types. There is - // no point in minimally importing the record behind their type as Clang - // will anyway request their definition when the FieldDecl is added to the - // RecordDecl (as Clang will query the FieldDecl's type for things such - // as a deleted constexpr destructor). - // By importing the type ahead of time we avoid some corner cases where - // the FieldDecl's record is importing in the middle of Clang's - // `DeclContext::addDecl` logic. - if (clang::FieldDecl *fd = dyn_cast<FieldDecl>(From)) { - // This is only necessary because we do the 'minimal import'. Remove this - // once LLDB stopped using that mode. - assert(isMinimalImport() && "Only necessary for minimal import"); - QualType field_type = fd->getType(); - if (field_type->isRecordType()) { - // First get the underlying record and minimally import it. - clang::TagDecl *record_decl = field_type->getAsTagDecl(); - llvm::Expected<Decl *> imported = Import(record_decl); - if (!imported) - return imported.takeError(); - // Check how/if the import got redirected to a different AST. Now - // import the definition of what was actually imported. If there is no - // origin then that means the record was imported by just picking a - // compatible type in the target AST (in which case there is no more - // importing to do). - if (clang::Decl *origin = m_master.GetDeclOrigin(*imported).decl) { - if (llvm::Error def_err = ImportDefinition(record_decl)) - return std::move(def_err); - } - } - } - return ASTImporter::ImportImpl(From); }
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits