Index: clang/lib/AST/ASTImporter.cpp =================================================================== --- clang/lib/AST/ASTImporter.cpp +++ clang/lib/AST/ASTImporter.cpp @@ -8166,7 +8166,19 @@ FromRecord, ToRecord, ASTNodeImporter::IDK_Basic)) return std::move(Err); } else { - CompleteDecl(ToRecord); + // If FromRecord is not defined we need to force it to be. + // Simply calling CompleteDecl(...) for a RecordDecl will break some cases + // it will start the definition but we never finish it. + // If a RecordDecl has base classes they won't be imported and we will + // be missing anything that we inherit from those bases. + if (FromRecord->hasExternalLexicalStorage() && + !FromRecord->isCompleteDefinition()) + FromRecord->getASTContext().getExternalSource()->CompleteType( + FromRecord); + + if (Error Err = ASTNodeImporter(*this).ImportDefinition( + FromRecord, ToRecord, ASTNodeImporter::IDK_Basic)) + return std::move(Err); } } else if (auto *ToEnum = dyn_cast(ToDC)) { auto *FromEnum = cast(FromDC); Index: lldb/test/API/commands/expression/import_base_class_when_class_has_derived_member/TestImportBaseClassWhenClassHasDerivedMember.py =================================================================== --- /dev/null +++ lldb/test/API/commands/expression/import_base_class_when_class_has_derived_member/TestImportBaseClassWhenClassHasDerivedMember.py @@ -0,0 +1,4 @@ +from lldbsuite.test import lldbinline +from lldbsuite.test import decorators + +lldbinline.MakeInlineTest(__file__, globals()) Index: lldb/test/API/commands/expression/import_base_class_when_class_has_derived_member/main.cpp =================================================================== --- /dev/null +++ lldb/test/API/commands/expression/import_base_class_when_class_has_derived_member/main.cpp @@ -0,0 +1,36 @@ +struct B { + int dump() const; +}; + +int B::dump() const { return 42; } + +// Derived class D obtains dump() method from base class B +struct D : public B { + // Introduce a TypedefNameDecl + using Iterator = D *; +}; + +struct C { + // This will cause use to invoke VisitTypedefNameDecl(...) when Importing + // the DeclContext of C. + // We will invoke ImportContext(...) which should force the From Decl to + // be defined if it not already defined. We will then Import the definition + // to the To Decl. + // This will force processing of the base class of D which allows us to see + // base class methods such as dump(). + D::Iterator iter; + + bool f(D *DD) { + return true; //%self.expect_expr("DD->dump()", result_type="int", + // result_value="42") + } +}; + +int main() { + C c; + D d; + + c.f(&d); + + return 0; +}