From: Douglas Gregor Date: Wed, 1 Feb 2012 21:00:38 +0000 (+0000) Subject: Make sure that imported definitions get completed before we add X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ac32ff9812e7d6bc31573b5499bfd005fc8b8f39;p=clang Make sure that imported definitions get completed before we add anything into the corresponding DeclContext. Co-hacked with Sean; fixes . git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@149535 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/AST/ASTImporter.h b/include/clang/AST/ASTImporter.h index b583fbf906..7157efe5b3 100644 --- a/include/clang/AST/ASTImporter.h +++ b/include/clang/AST/ASTImporter.h @@ -255,6 +255,12 @@ namespace clang { /// \brief Return the set of declarations that we know are not equivalent. NonEquivalentDeclSet &getNonEquivalentDecls() { return NonEquivalentDecls; } + + /// \brief Called for ObjCInterfaceDecl, ObjCProtocolDecl, and TagDecl. + /// Mark the Decl as complete, filling it in as much as possible. + /// + /// \param D A declaration in the "to" context. + virtual void CompleteDecl(Decl* D); /// \brief Note that we have imported the "from" declaration by mapping it /// to the (potentially-newly-created) "to" declaration. diff --git a/lib/AST/ASTImporter.cpp b/lib/AST/ASTImporter.cpp index 4ac9f76586..556f97d858 100644 --- a/lib/AST/ASTImporter.cpp +++ b/lib/AST/ASTImporter.cpp @@ -86,7 +86,7 @@ namespace clang { void ImportDeclarationNameLoc(const DeclarationNameInfo &From, DeclarationNameInfo& To); void ImportDeclContext(DeclContext *FromDC, bool ForceImport = false); - + /// \brief What we should import from the definition. enum ImportDefinitionKind { /// \brief Import the default subset of the definition, which might be @@ -100,14 +100,19 @@ namespace clang { IDK_Basic }; + bool shouldForceImportDeclContext(ImportDefinitionKind IDK) { + return IDK == IDK_Everything || + (IDK == IDK_Default && !Importer.isMinimalImport()); + } + bool ImportDefinition(RecordDecl *From, RecordDecl *To, ImportDefinitionKind Kind = IDK_Default); bool ImportDefinition(EnumDecl *From, EnumDecl *To, - bool ForceImport = false); + ImportDefinitionKind Kind = IDK_Default); bool ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, - bool ForceImport = false); + ImportDefinitionKind Kind = IDK_Default); bool ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To, - bool ForceImport = false); + ImportDefinitionKind Kind = IDK_Default); TemplateParameterList *ImportTemplateParameterList( TemplateParameterList *Params); TemplateArgument ImportTemplateArgument(const TemplateArgument &From); @@ -1793,7 +1798,7 @@ ASTNodeImporter::ImportDeclarationNameLoc(const DeclarationNameInfo &From, llvm_unreachable("Unknown name kind."); } -void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { +void ASTNodeImporter::ImportDeclContext(DeclContext *FromDC, bool ForceImport) { if (Importer.isMinimalImport() && !ForceImport) { Importer.ImportContext(FromDC); return; @@ -1892,8 +1897,7 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, ToCXX->setBases(Bases.data(), Bases.size()); } - if (Kind == IDK_Everything || - (Kind == IDK_Default && !Importer.isMinimalImport())) + if (shouldForceImportDeclContext(Kind)) ImportDeclContext(From, /*ForceImport=*/true); To->completeDefinition(); @@ -1901,9 +1905,12 @@ bool ASTNodeImporter::ImportDefinition(RecordDecl *From, RecordDecl *To, } bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, - bool ForceImport) { - if (To->getDefinition() || To->isBeingDefined()) + ImportDefinitionKind Kind) { + if (To->getDefinition() || To->isBeingDefined()) { + if (Kind == IDK_Everything) + ImportDeclContext(From, /*ForceImport=*/true); return false; + } To->startDefinition(); @@ -1914,8 +1921,9 @@ bool ASTNodeImporter::ImportDefinition(EnumDecl *From, EnumDecl *To, QualType ToPromotionType = Importer.Import(From->getPromotionType()); if (ToPromotionType.isNull()) return true; - - ImportDeclContext(From, ForceImport); + + if (shouldForceImportDeclContext(Kind)) + ImportDeclContext(From, /*ForceImport=*/true); // FIXME: we might need to merge the number of positive or negative bits // if the enumerator lists don't match. @@ -3125,9 +3133,10 @@ Decl *ASTNodeImporter::VisitObjCCategoryDecl(ObjCCategoryDecl *D) { bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From, ObjCProtocolDecl *To, - bool ForceImport) { + ImportDefinitionKind Kind) { if (To->getDefinition()) { - ImportDeclContext(From); + if (shouldForceImportDeclContext(Kind)) + ImportDeclContext(From); return false; } @@ -3155,8 +3164,10 @@ bool ASTNodeImporter::ImportDefinition(ObjCProtocolDecl *From, To->setProtocolList(Protocols.data(), Protocols.size(), ProtocolLocs.data(), Importer.getToContext()); - // Import all of the members of this protocol. - ImportDeclContext(From); + if (shouldForceImportDeclContext(Kind)) { + // Import all of the members of this protocol. + ImportDeclContext(From, /*ForceImport=*/true); + } return false; } @@ -3211,7 +3222,7 @@ Decl *ASTNodeImporter::VisitObjCProtocolDecl(ObjCProtocolDecl *D) { bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, ObjCInterfaceDecl *To, - bool ForceImport) { + ImportDefinitionKind Kind) { if (To->getDefinition()) { // Check consistency of superclass. ObjCInterfaceDecl *FromSuper = From->getSuperClass(); @@ -3242,7 +3253,8 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, diag::note_odr_objc_missing_superclass); } - ImportDeclContext(From); + if (shouldForceImportDeclContext(Kind)) + ImportDeclContext(From); return false; } @@ -3298,9 +3310,10 @@ bool ASTNodeImporter::ImportDefinition(ObjCInterfaceDecl *From, To->setImplementation(Impl); } - // Import all of the members of this class. - ImportDeclContext(From); - + if (shouldForceImportDeclContext(Kind)) { + // Import all of the members of this class. + ImportDeclContext(From, /*ForceImport=*/true); + } return false; } @@ -4190,15 +4203,51 @@ DeclContext *ASTImporter::ImportContext(DeclContext *FromDC) { return FromDC; DeclContext *ToDC = cast_or_null(Import(cast(FromDC))); - if (RecordDecl *ToRecord = dyn_cast_or_null(ToDC)) { - // When we're using a record declaration as a context, we need it to have - // a definition. - ASTNodeImporter Importer(*this); - + if (!ToDC) + return 0; + + // When we're using a record/enum/Objective-C class/protocol as a context, we + // need it to have a definition. + if (RecordDecl *ToRecord = dyn_cast(ToDC)) { RecordDecl *FromRecord = cast(FromDC); - if (FromRecord->isCompleteDefinition()) - Importer.ImportDefinition(FromRecord, ToRecord, - ASTNodeImporter::IDK_Basic); + if (ToRecord->isCompleteDefinition()) { + // Do nothing. + } else if (FromRecord->isCompleteDefinition()) { + ASTNodeImporter(*this).ImportDefinition(FromRecord, ToRecord, + ASTNodeImporter::IDK_Basic); + } else { + CompleteDecl(ToRecord); + } + } else if (EnumDecl *ToEnum = dyn_cast(ToDC)) { + EnumDecl *FromEnum = cast(FromDC); + if (ToEnum->isCompleteDefinition()) { + // Do nothing. + } else if (FromEnum->isCompleteDefinition()) { + ASTNodeImporter(*this).ImportDefinition(FromEnum, ToEnum, + ASTNodeImporter::IDK_Basic); + } else { + CompleteDecl(ToEnum); + } + } else if (ObjCInterfaceDecl *ToClass = dyn_cast(ToDC)) { + ObjCInterfaceDecl *FromClass = cast(FromDC); + if (ToClass->getDefinition()) { + // Do nothing. + } else if (ObjCInterfaceDecl *FromDef = FromClass->getDefinition()) { + ASTNodeImporter(*this).ImportDefinition(FromDef, ToClass, + ASTNodeImporter::IDK_Basic); + } else { + CompleteDecl(ToClass); + } + } else if (ObjCProtocolDecl *ToProto = dyn_cast(ToDC)) { + ObjCProtocolDecl *FromProto = cast(FromDC); + if (ToProto->getDefinition()) { + // Do nothing. + } else if (ObjCProtocolDecl *FromDef = FromProto->getDefinition()) { + ASTNodeImporter(*this).ImportDefinition(FromDef, ToProto, + ASTNodeImporter::IDK_Basic); + } else { + CompleteDecl(ToProto); + } } return ToDC; @@ -4450,7 +4499,7 @@ void ASTImporter::ImportDefinition(Decl *From) { if (EnumDecl *ToEnum = dyn_cast(To)) { if (!ToEnum->getDefinition()) { Importer.ImportDefinition(cast(FromDC), ToEnum, - /*ForceImport=*/true); + ASTNodeImporter::IDK_Everything); return; } } @@ -4458,7 +4507,7 @@ void ASTImporter::ImportDefinition(Decl *From) { if (ObjCInterfaceDecl *ToIFace = dyn_cast(To)) { if (!ToIFace->getDefinition()) { Importer.ImportDefinition(cast(FromDC), ToIFace, - /*ForceImport=*/true); + ASTNodeImporter::IDK_Everything); return; } } @@ -4466,7 +4515,7 @@ void ASTImporter::ImportDefinition(Decl *From) { if (ObjCProtocolDecl *ToProto = dyn_cast(To)) { if (!ToProto->getDefinition()) { Importer.ImportDefinition(cast(FromDC), ToProto, - /*ForceImport=*/true); + ASTNodeImporter::IDK_Everything); return; } } @@ -4565,6 +4614,26 @@ DiagnosticBuilder ASTImporter::FromDiag(SourceLocation Loc, unsigned DiagID) { return FromContext.getDiagnostics().Report(Loc, DiagID); } +void ASTImporter::CompleteDecl (Decl *D) { + if (ObjCInterfaceDecl *ID = dyn_cast(D)) { + if (!ID->getDefinition()) + ID->startDefinition(); + } + else if (ObjCProtocolDecl *PD = dyn_cast(D)) { + if (!PD->getDefinition()) + PD->startDefinition(); + } + else if (TagDecl *TD = dyn_cast(D)) { + if (!TD->getDefinition() && !TD->isBeingDefined()) { + TD->startDefinition(); + TD->setCompleteDefinition(true); + } + } + else { + assert (0 && "CompleteDecl called on a Decl that can't be completed"); + } +} + Decl *ASTImporter::Imported(Decl *From, Decl *To) { ImportedDecls[From] = To; return To;