Index: include/clang/AST/ASTImporter.h =================================================================== --- include/clang/AST/ASTImporter.h +++ include/clang/AST/ASTImporter.h @@ -314,13 +314,13 @@ /// \param D A declaration in the "to" context. virtual void CompleteDecl(Decl* D); - /// Note that we have imported the "from" declaration by mapping it - /// to the (potentially-newly-created) "to" declaration. - /// /// Subclasses can override this function to observe all of the \c From -> /// \c To declaration mappings as they are imported. - virtual Decl *Imported(Decl *From, Decl *To); - + virtual Decl *Imported(Decl *From, Decl *To) { return To; } + + /// Store and assign the imported declaration to its counterpart. + Decl *MapImported(Decl *From, Decl *To); + /// Called by StructuralEquivalenceContext. If a RecordDecl is /// being compared to another RecordDecl as part of import, completing the /// other RecordDecl may trigger importation of the first RecordDecl. This Index: include/clang/AST/DeclBase.h =================================================================== --- include/clang/AST/DeclBase.h +++ include/clang/AST/DeclBase.h @@ -309,7 +309,7 @@ protected: friend class ASTDeclReader; friend class ASTDeclWriter; - friend class ASTImporter; + friend class ASTNodeImporter; friend class ASTReader; friend class CXXClassMemberWrapper; friend class LinkageComputer; Index: lib/AST/ASTImporter.cpp =================================================================== --- lib/AST/ASTImporter.cpp +++ lib/AST/ASTImporter.cpp @@ -95,6 +95,58 @@ public StmtVisitor { ASTImporter &Importer; + // Wrapper for an overload set. + template struct CallOverloadedCreateFun { + template + auto operator()(Args &&... args) + -> decltype(ToDeclT::Create(std::forward(args)...)) { + return ToDeclT::Create(std::forward(args)...); + } + }; + + // Always use this function to create a Decl during import. There are + // certain tasks which must be done after the Decl was created, e.g. we + // must immediately register that as an imported Decl. + // Returns a pair consisting of a pointer to the new or the already imported + // Decl and a bool value set to true if the `FromD` had been imported + // before. + template + std::pair CreateDecl(FromDeclT *FromD, Args &&... args) { + // There may be several overloads of ToDeclT::Create. We must make sure + // to call the one which would be chosen by the arguments, thus we use a + // wrapper for the overload set. + CallOverloadedCreateFun OC; + return CreateDecl(OC, FromD, std::forward(args)...); + } + // Use this overload directly only if a special create function must be + // used, e.g. CXXRecordDecl::CreateLambda . + template + auto CreateDecl(CreateFunT CreateFun, FromDeclT *FromD, Args &&... args) + -> std::pair(args)...)), bool> { + using ToDeclT = typename std::remove_pointer(args)...))>::type; + ToDeclT *AlreadyImported = + cast_or_null(Importer.GetAlreadyImportedOrNull(FromD)); + if (AlreadyImported) { + return std::make_pair(AlreadyImported, /*AlreadyImported=*/true); + } + ToDeclT *ToD = CreateFun(std::forward(args)...); + InitializeImportedDecl(FromD, ToD); + return std::make_pair(ToD, /*AlreadyImported=*/false); + } + + void InitializeImportedDecl(Decl *FromD, Decl *ToD) { + Importer.MapImported(FromD, ToD); + ToD->IdentifierNamespace = FromD->IdentifierNamespace; + if (FromD->hasAttrs()) + for (const Attr *FromAttr : FromD->getAttrs()) + ToD->addAttr(Importer.Import(FromAttr)); + if (FromD->isUsed()) + ToD->setIsUsed(); + if (FromD->isImplicit()) + ToD->setImplicit(); + } + public: explicit ASTNodeImporter(ASTImporter &Importer) : Importer(Importer) {} @@ -1572,9 +1624,14 @@ // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); - EmptyDecl *ToD = EmptyDecl::Create(Importer.getToContext(), DC, Loc); + bool AlreadyImported; + EmptyDecl *ToD; + std::tie(ToD, AlreadyImported) = + CreateDecl(D, Importer.getToContext(), DC, Loc); + if (AlreadyImported) + return ToD; + ToD->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToD); LexicalDC->addDeclInternal(ToD); return ToD; } @@ -1583,7 +1640,7 @@ TranslationUnitDecl *ToD = Importer.getToContext().getTranslationUnitDecl(); - Importer.Imported(D, ToD); + Importer.MapImported(D, ToD); return ToD; } @@ -1597,19 +1654,19 @@ if (!DC) return nullptr; - AccessSpecDecl *accessSpecDecl - = AccessSpecDecl::Create(Importer.getToContext(), D->getAccess(), - DC, Loc, ColonLoc); - - if (!accessSpecDecl) - return nullptr; + bool AlreadyImported; + AccessSpecDecl *ToD; + std::tie(ToD, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), D->getAccess(), DC, Loc, ColonLoc); + if (AlreadyImported) + return ToD; // Lexical DeclContext and Semantic DeclContext // is always the same for the accessSpec. - accessSpecDecl->setLexicalDeclContext(DC); - DC->addDeclInternal(accessSpecDecl); + ToD->setLexicalDeclContext(DC); + DC->addDeclInternal(ToD); - return accessSpecDecl; + return ToD; } Decl *ASTNodeImporter::VisitStaticAssertDecl(StaticAssertDecl *D) { @@ -1631,13 +1688,16 @@ if (!ToMsg && FromMsg) return nullptr; - StaticAssertDecl *ToD = StaticAssertDecl::Create( - Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, - Importer.Import(D->getRParenLoc()), D->isFailed()); + bool AlreadyImported; + StaticAssertDecl *ToD; + std::tie(ToD, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, + Importer.Import(D->getRParenLoc()), D->isFailed()); + if (AlreadyImported) + return ToD; ToD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToD); - Importer.Imported(D, ToD); return ToD; } @@ -1688,11 +1748,13 @@ // Create the "to" namespace, if needed. NamespaceDecl *ToNamespace = MergeWithNamespace; if (!ToNamespace) { - ToNamespace = NamespaceDecl::Create(Importer.getToContext(), DC, - D->isInline(), - Importer.Import(D->getLocStart()), - Loc, Name.getAsIdentifierInfo(), - /*PrevDecl=*/nullptr); + bool AlreadyImported; + std::tie(ToNamespace, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, D->isInline(), + Importer.Import(D->getLocStart()), Loc, Name.getAsIdentifierInfo(), + /*PrevDecl=*/nullptr); + if (AlreadyImported) + return ToNamespace; ToNamespace->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToNamespace); @@ -1705,7 +1767,7 @@ cast(DC)->setAnonymousNamespace(ToNamespace); } } - Importer.Imported(D, ToNamespace); + Importer.MapImported(D, ToNamespace); ImportDeclContext(D); @@ -1738,13 +1800,16 @@ if (D->getQualifierLoc() && !ToQLoc) return nullptr; - NamespaceAliasDecl *ToD = NamespaceAliasDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getNamespaceLoc()), - Importer.Import(D->getAliasLoc()), ToII, ToQLoc, - Importer.Import(D->getTargetNameLoc()), TargetDecl); + bool AlreadyImported; + NamespaceAliasDecl *ToD; + std::tie(ToD, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getNamespaceLoc()), + Importer.Import(D->getAliasLoc()), ToII, ToQLoc, + Importer.Import(D->getTargetNameLoc()), TargetDecl); + if (AlreadyImported) + return ToD; ToD->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToD); LexicalDC->addDeclInternal(ToD); return ToD; @@ -1775,7 +1840,7 @@ if (auto *FoundTypedef = dyn_cast(FoundDecl)) { if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(), FoundTypedef->getUnderlyingType())) - return Importer.Imported(D, FoundTypedef); + return Importer.MapImported(D, FoundTypedef); } ConflictingDecls.push_back(FoundDecl); @@ -1795,27 +1860,25 @@ if (T.isNull()) return nullptr; - // Some nodes (like anonymous tags referred by typedefs) are allowed to - // import their enclosing typedef directly. Check if this is the case. - if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D)) - return AlreadyImported; - // Create the new typedef node. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); SourceLocation StartL = Importer.Import(D->getLocStart()); + + bool AlreadyImported; TypedefNameDecl *ToTypedef; if (IsAlias) - ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC, StartL, Loc, - Name.getAsIdentifierInfo(), TInfo); + std::tie(ToTypedef, AlreadyImported) = + CreateDecl(D, Importer.getToContext(), DC, StartL, Loc, + Name.getAsIdentifierInfo(), TInfo); else - ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC, - StartL, Loc, - Name.getAsIdentifierInfo(), - TInfo); + std::tie(ToTypedef, AlreadyImported) = + CreateDecl(D, Importer.getToContext(), DC, StartL, Loc, + Name.getAsIdentifierInfo(), TInfo); + if (AlreadyImported) + return ToTypedef; ToTypedef->setAccess(D->getAccess()); ToTypedef->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToTypedef); // Templated declarations should not appear in DeclContext. TypeAliasDecl *FromAlias = IsAlias ? cast(D) : nullptr; @@ -1856,7 +1919,7 @@ if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; if (auto *FoundAlias = dyn_cast(FoundDecl)) - return Importer.Imported(D, FoundAlias); + return Importer.MapImported(D, FoundAlias); ConflictingDecls.push_back(FoundDecl); } @@ -1879,14 +1942,17 @@ if (!TemplDecl) return nullptr; - TypeAliasTemplateDecl *ToAlias = TypeAliasTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, Params, TemplDecl); + bool AlreadyImported; + TypeAliasTemplateDecl *ToAlias; + std::tie(ToAlias, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Loc, Name, Params, TemplDecl); + if (AlreadyImported) + return ToAlias; TemplDecl->setDescribedAliasTemplate(ToAlias); ToAlias->setAccess(D->getAccess()); ToAlias->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToAlias); LexicalDC->addDeclInternal(ToAlias); return ToAlias; } @@ -1904,15 +1970,18 @@ assert(LexicalDC->isFunctionOrMethod()); - LabelDecl *ToLabel = D->isGnuLocal() - ? LabelDecl::Create(Importer.getToContext(), - DC, Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo(), - Importer.Import(D->getLocStart())) - : LabelDecl::Create(Importer.getToContext(), - DC, Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo()); - Importer.Imported(D, ToLabel); + bool AlreadyImported; + LabelDecl *ToLabel; + std::tie(ToLabel, AlreadyImported) = + D->isGnuLocal() ? CreateDecl(D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo(), + Importer.Import(D->getLocStart())) + : CreateDecl(D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo()); + if (AlreadyImported) + return ToLabel; auto *Label = cast_or_null(Importer.Import(D->getStmt())); if (!Label) @@ -1961,7 +2030,7 @@ if (auto *FoundEnum = dyn_cast(Found)) { if (IsStructuralMatch(D, FoundEnum)) - return Importer.Imported(D, FoundEnum); + return Importer.MapImported(D, FoundEnum); } ConflictingDecls.push_back(FoundDecl); @@ -1973,18 +2042,21 @@ ConflictingDecls.size()); } } - + // Create the enum declaration. - EnumDecl *D2 = EnumDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocStart()), - Loc, Name.getAsIdentifierInfo(), nullptr, - D->isScoped(), D->isScopedUsingClassTag(), - D->isFixed()); + bool AlreadyImported; + EnumDecl *D2; + std::tie(D2, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getLocStart()), Loc, + Name.getAsIdentifierInfo(), nullptr, D->isScoped(), + D->isScopedUsingClassTag(), D->isFixed()); + if (AlreadyImported) + return D2; + // Import the qualifier, if any. D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, D2); LexicalDC->addDeclInternal(D2); // Import the integer type. @@ -2016,7 +2088,7 @@ if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of this record. @@ -2096,7 +2168,7 @@ // unit only had a forward declaration anyway; call it the same // function. // FIXME: For C++, we should also merge methods here. - return Importer.Imported(D, FoundDef); + return Importer.MapImported(D, FoundDef); } } else if (!D->isCompleteDefinition()) { // We have a forward declaration of this type, so adopt that forward @@ -2137,15 +2209,17 @@ RecordDecl *D2 = AdoptDecl; SourceLocation StartLoc = Importer.Import(D->getLocStart()); if (!D2) { + bool AlreadyImported; CXXRecordDecl *D2CXX = nullptr; if (auto *DCXX = dyn_cast(D)) { if (DCXX->isLambda()) { TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo()); - D2CXX = CXXRecordDecl::CreateLambda(Importer.getToContext(), - DC, TInfo, Loc, - DCXX->isDependentLambda(), - DCXX->isGenericLambda(), - DCXX->getLambdaCaptureDefault()); + std::tie(D2CXX, AlreadyImported) = CreateDecl( + CXXRecordDecl::CreateLambda, D, Importer.getToContext(), DC, TInfo, + Loc, DCXX->isDependentLambda(), DCXX->isGenericLambda(), + DCXX->getLambdaCaptureDefault()); + if (AlreadyImported) + return D2CXX; Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl()); if (DCXX->getLambdaContextDecl() && !CDecl) return nullptr; @@ -2155,25 +2229,27 @@ // Sema::ActOnStartCXXMemberDeclarations CXXRecordDecl *const PrevDecl = nullptr; const bool DelayTypeCreation = true; - D2CXX = CXXRecordDecl::Create( - Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, + std::tie(D2CXX, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation); + if (AlreadyImported) + return D2CXX; Importer.getToContext().getTypeDeclType( D2CXX, dyn_cast(DC)); } else { - D2CXX = CXXRecordDecl::Create(Importer.getToContext(), - D->getTagKind(), - DC, StartLoc, Loc, - Name.getAsIdentifierInfo()); + std::tie(D2CXX, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), cast_or_null(PrevDecl)); + if (AlreadyImported) + return D2CXX; } + D2 = D2CXX; D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); if (!DCXX->getDescribedClassTemplate() || DCXX->isImplicit()) LexicalDC->addDeclInternal(D2); - Importer.Imported(D, D2); - if (ClassTemplateDecl *FromDescribed = DCXX->getDescribedClassTemplate()) { auto *ToDescribed = cast_or_null( @@ -2195,22 +2271,21 @@ Importer.Import(MemberInfo->getPointOfInstantiation())); } } else { - D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(), - DC, StartLoc, Loc, Name.getAsIdentifierInfo()); + std::tie(D2, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), PrevDecl); + if (AlreadyImported) + return D2; D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); } - + D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); if (D->isAnonymousStructOrUnion()) D2->setAnonymousStructOrUnion(true); - if (PrevDecl) { - // FIXME: do this for all Redeclarables, not just RecordDecls. - D2->setPreviousDecl(PrevDecl); - } } - - Importer.Imported(D, D2); + + Importer.MapImported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2, IDK_Default)) return nullptr; @@ -2246,7 +2321,7 @@ if (auto *FoundEnumConstant = dyn_cast(FoundDecl)) { if (IsStructuralMatch(D, FoundEnumConstant)) - return Importer.Imported(D, FoundEnumConstant); + return Importer.MapImported(D, FoundEnumConstant); } ConflictingDecls.push_back(FoundDecl); @@ -2265,13 +2340,16 @@ if (D->getInitExpr() && !Init) return nullptr; - EnumConstantDecl *ToEnumerator - = EnumConstantDecl::Create(Importer.getToContext(), cast(DC), Loc, - Name.getAsIdentifierInfo(), T, - Init, D->getInitVal()); + bool AlreadyImported; + EnumConstantDecl *ToEnumerator; + std::tie(ToEnumerator, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), cast(DC), Loc, + Name.getAsIdentifierInfo(), T, Init, D->getInitVal()); + if (AlreadyImported) + return ToEnumerator; + ToEnumerator->setAccess(D->getAccess()); ToEnumerator->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToEnumerator); LexicalDC->addDeclInternal(ToEnumerator); return ToEnumerator; } @@ -2422,7 +2500,7 @@ FoundFunction->getType())) { if (D->doesThisDeclarationHaveABody() && FoundFunction->hasBody()) - return Importer.Imported(D, FoundFunction); + return Importer.MapImported(D, FoundFunction); FoundByLookup = FoundFunction; break; } @@ -2499,16 +2577,15 @@ // Create the imported function. FunctionDecl *ToFunction = nullptr; + bool AlreadyImported; SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart()); if (auto *FromConstructor = dyn_cast(D)) { - ToFunction = CXXConstructorDecl::Create(Importer.getToContext(), - cast(DC), - InnerLocStart, - NameInfo, T, TInfo, - FromConstructor->isExplicit(), - D->isInlineSpecified(), - D->isImplicit(), - D->isConstexpr()); + std::tie(ToFunction, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), cast(DC), InnerLocStart, + NameInfo, T, TInfo, FromConstructor->isExplicit(), + D->isInlineSpecified(), D->isImplicit(), D->isConstexpr()); + if (AlreadyImported) + return ToFunction; if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) { SmallVector CtorInitializers; for (auto *I : FromConstructor->inits()) { @@ -2525,38 +2602,30 @@ ToCtor->setNumCtorInitializers(NumInitializers); } } else if (isa(D)) { - ToFunction = CXXDestructorDecl::Create(Importer.getToContext(), - cast(DC), - InnerLocStart, - NameInfo, T, TInfo, - D->isInlineSpecified(), - D->isImplicit()); - } else if (auto *FromConversion = dyn_cast(D)) { - ToFunction = CXXConversionDecl::Create(Importer.getToContext(), - cast(DC), - InnerLocStart, - NameInfo, T, TInfo, - D->isInlineSpecified(), - FromConversion->isExplicit(), - D->isConstexpr(), - Importer.Import(D->getLocEnd())); + std::tie(ToFunction, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), cast(DC), InnerLocStart, + NameInfo, T, TInfo, D->isInlineSpecified(), D->isImplicit()); + } else if (CXXConversionDecl *FromConversion = + dyn_cast(D)) { + std::tie(ToFunction, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), cast(DC), InnerLocStart, + NameInfo, T, TInfo, D->isInlineSpecified(), + FromConversion->isExplicit(), D->isConstexpr(), + Importer.Import(D->getLocEnd())); } else if (auto *Method = dyn_cast(D)) { - ToFunction = CXXMethodDecl::Create(Importer.getToContext(), - cast(DC), - InnerLocStart, - NameInfo, T, TInfo, - Method->getStorageClass(), - Method->isInlineSpecified(), - D->isConstexpr(), - Importer.Import(D->getLocEnd())); + std::tie(ToFunction, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), cast(DC), InnerLocStart, + NameInfo, T, TInfo, Method->getStorageClass(), + Method->isInlineSpecified(), D->isConstexpr(), + Importer.Import(D->getLocEnd())); } else { - ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, - InnerLocStart, - NameInfo, T, TInfo, D->getStorageClass(), - D->isInlineSpecified(), - D->hasWrittenPrototype(), - D->isConstexpr()); + std::tie(ToFunction, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, InnerLocStart, NameInfo, T, TInfo, + D->getStorageClass(), D->isInlineSpecified(), D->hasWrittenPrototype(), + D->isConstexpr()); } + if (AlreadyImported) + return ToFunction; // Import the qualifier, if any. ToFunction->setQualifierInfo(Importer.Import(D->getQualifierLoc())); @@ -2565,7 +2634,6 @@ ToFunction->setVirtualAsWritten(D->isVirtualAsWritten()); ToFunction->setTrivial(D->isTrivial()); ToFunction->setPure(D->isPure()); - Importer.Imported(D, ToFunction); // Set the parameters. for (auto *Param : Parameters) { @@ -2696,7 +2764,7 @@ if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType())) { - Importer.Imported(D, FoundField); + Importer.MapImported(D, FoundField); return FoundField; } @@ -2718,11 +2786,15 @@ if (!BitWidth && D->getBitWidth()) return nullptr; - FieldDecl *ToField = FieldDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, BitWidth, D->isMutable(), - D->getInClassInitStyle()); + bool AlreadyImported; + FieldDecl *ToField; + std::tie(ToField, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()), + Loc, Name.getAsIdentifierInfo(), T, TInfo, BitWidth, D->isMutable(), + D->getInClassInitStyle()); + if (AlreadyImported) + return ToField; + ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); if (Expr *FromInitializer = D->getInClassInitializer()) { @@ -2733,7 +2805,6 @@ return nullptr; } ToField->setImplicit(D->isImplicit()); - Importer.Imported(D, ToField); LexicalDC->addDeclInternal(ToField); return ToField; } @@ -2761,7 +2832,7 @@ if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType(), !Name.isEmpty())) { - Importer.Imported(D, FoundField); + Importer.MapImported(D, FoundField); return FoundField; } @@ -2793,16 +2864,21 @@ NamedChain[i++] = cast(D); } - IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create( - Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, - {NamedChain, D->getChainingSize()}); + llvm::MutableArrayRef CH = {NamedChain, D->getChainingSize()}; + bool AlreadyImported; + IndirectFieldDecl *ToIndirectField; + std::tie(ToIndirectField, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, CH); + if (AlreadyImported) { + // FIXME here we leak `NamedChain` which is allocated before + return ToIndirectField; + } for (const auto *A : D->attrs()) ToIndirectField->addAttr(Importer.Import(A)); ToIndirectField->setAccess(D->getAccess()); ToIndirectField->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToIndirectField); LexicalDC->addDeclInternal(ToIndirectField); return ToIndirectField; } @@ -2827,13 +2903,13 @@ if (D->getFriendDecl() && ImportedFriend->getFriendDecl()) { if (Context.IsStructurallyEquivalent(D->getFriendDecl(), ImportedFriend->getFriendDecl())) - return Importer.Imported(D, ImportedFriend); + return Importer.MapImported(D, ImportedFriend); } else if (D->getFriendType() && ImportedFriend->getFriendType()) { if (Importer.IsStructurallyEquivalent( D->getFriendType()->getType(), ImportedFriend->getFriendType()->getType(), true)) - return Importer.Imported(D, ImportedFriend); + return Importer.MapImported(D, ImportedFriend); } ImportedFriend = ImportedFriend->getNextFriend(); } @@ -2861,12 +2937,13 @@ ToTPLists[I] = List; } - FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocation()), - ToFU, Importer.Import(D->getFriendLoc()), - ToTPLists); - - Importer.Imported(D, FrD); + bool AlreadyImported; + FriendDecl *FrD; + std::tie(FrD, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getLocation()), ToFU, + Importer.Import(D->getFriendLoc()), ToTPLists); + if (AlreadyImported) + return FrD; FrD->setAccess(D->getAccess()); FrD->setLexicalDeclContext(LexicalDC); @@ -2892,7 +2969,7 @@ if (auto *FoundIvar = dyn_cast(FoundDecl)) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundIvar->getType())) { - Importer.Imported(D, FoundIvar); + Importer.MapImported(D, FoundIvar); return FoundIvar; } @@ -2914,14 +2991,16 @@ if (!BitWidth && D->getBitWidth()) return nullptr; - ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), - cast(DC), - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, D->getAccessControl(), - BitWidth, D->getSynthesize()); + bool AlreadyImported; + ObjCIvarDecl *ToIvar; + std::tie(ToIvar, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), cast(DC), + Importer.Import(D->getInnerLocStart()), Loc, Name.getAsIdentifierInfo(), + T, TInfo, D->getAccessControl(), BitWidth, D->getSynthesize()); + if (AlreadyImported) + return ToIvar; + ToIvar->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToIvar); LexicalDC->addDeclInternal(ToIvar); return ToIvar; } @@ -2994,7 +3073,7 @@ if (MergeWithVar) { // An equivalent variable with external linkage has been found. Link // the two declarations, then merge them. - Importer.Imported(D, MergeWithVar); + Importer.MapImported(D, MergeWithVar); if (VarDecl *DDef = D->getDefinition()) { if (VarDecl *ExistingDef = MergeWithVar->getDefinition()) { @@ -3032,15 +3111,17 @@ // Create the imported variable. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - VarDecl *ToVar = VarDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, - D->getStorageClass()); + bool AlreadyImported; + VarDecl *ToVar; + std::tie(ToVar, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()), + Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass()); + if (AlreadyImported) + return ToVar; + ToVar->setQualifierInfo(Importer.Import(D->getQualifierLoc())); ToVar->setAccess(D->getAccess()); ToVar->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToVar); // Templated declarations should never appear in the enclosing DeclContext. if (!D->getDescribedVarTemplate()) @@ -3079,10 +3160,12 @@ return nullptr; // Create the imported parameter. - auto *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), T, - D->getParameterKind()); - return Importer.Imported(D, ToParm); + bool AlreadyImported; + ImplicitParamDecl *ToParm; + std::tie(ToParm, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, + D->getParameterKind()); + return ToParm; } Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { @@ -3105,11 +3188,14 @@ // Create the imported parameter. TypeSourceInfo *TInfo = Importer.Import(D->getTypeSourceInfo()); - ParmVarDecl *ToParm = ParmVarDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, D->getStorageClass(), - /*DefaultArg*/ nullptr); + bool AlreadyImported; + ParmVarDecl *ToParm; + std::tie(ToParm, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getInnerLocStart()), + Loc, Name.getAsIdentifierInfo(), T, TInfo, D->getStorageClass(), + /*DefaultArg*/ nullptr); + if (AlreadyImported) + return ToParm; // Set the default argument. ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); @@ -3142,7 +3228,7 @@ if (D->isUsed()) ToParm->setIsUsed(); - return Importer.Imported(D, ToParm); + return ToParm; } Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { @@ -3214,7 +3300,7 @@ } // FIXME: Any other bits we need to merge? - return Importer.Imported(D, FoundMethod); + return Importer.MapImported(D, FoundMethod); } } @@ -3225,11 +3311,15 @@ TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo()); - ObjCMethodDecl *ToMethod = ObjCMethodDecl::Create( - Importer.getToContext(), Loc, Importer.Import(D->getLocEnd()), + bool AlreadyImported; + ObjCMethodDecl *ToMethod; + std::tie(ToMethod, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), Loc, Importer.Import(D->getLocEnd()), Name.getObjCSelector(), ResultTy, ReturnTInfo, DC, D->isInstanceMethod(), D->isVariadic(), D->isPropertyAccessor(), D->isImplicit(), D->isDefined(), D->getImplementationControl(), D->hasRelatedResultType()); + if (AlreadyImported) + return ToMethod; // FIXME: When we decide to merge method definitions, we'll need to // deal with implicit parameters. @@ -3258,7 +3348,6 @@ ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs); ToMethod->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToMethod); LexicalDC->addDeclInternal(ToMethod); return ToMethod; } @@ -3278,16 +3367,16 @@ if (!BoundInfo) return nullptr; - ObjCTypeParamDecl *Result = ObjCTypeParamDecl::Create( - Importer.getToContext(), DC, - D->getVariance(), - Importer.Import(D->getVarianceLoc()), - D->getIndex(), - Importer.Import(D->getLocation()), - Name.getAsIdentifierInfo(), - Importer.Import(D->getColonLoc()), - BoundInfo); - Importer.Imported(D, Result); + bool AlreadyImported; + ObjCTypeParamDecl *Result; + std::tie(Result, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, D->getVariance(), + Importer.Import(D->getVarianceLoc()), D->getIndex(), + Importer.Import(D->getLocation()), Name.getAsIdentifierInfo(), + Importer.Import(D->getColonLoc()), BoundInfo); + if (AlreadyImported) + return Result; + Result->setLexicalDeclContext(LexicalDC); return Result; } @@ -3313,18 +3402,19 @@ = ToInterface->FindCategoryDeclaration(Name.getAsIdentifierInfo()); ObjCCategoryDecl *ToCategory = MergeWithCategory; if (!ToCategory) { - ToCategory = ObjCCategoryDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getAtStartLoc()), - Loc, - Importer.Import(D->getCategoryNameLoc()), - Name.getAsIdentifierInfo(), - ToInterface, - /*TypeParamList=*/nullptr, - Importer.Import(D->getIvarLBraceLoc()), - Importer.Import(D->getIvarRBraceLoc())); + + bool AlreadyImported; + std::tie(ToCategory, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()), + Loc, Importer.Import(D->getCategoryNameLoc()), + Name.getAsIdentifierInfo(), ToInterface, + /*TypeParamList=*/nullptr, Importer.Import(D->getIvarLBraceLoc()), + Importer.Import(D->getIvarRBraceLoc())); + if (AlreadyImported) + return ToCategory; + ToCategory->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToCategory); - Importer.Imported(D, ToCategory); // Import the type parameter list after calling Imported, to avoid // loops when bringing in their DeclContext. ToCategory->setTypeParamList(ImportObjCTypeParamList( @@ -3351,7 +3441,7 @@ ToCategory->setProtocolList(Protocols.data(), Protocols.size(), ProtocolLocs.data(), Importer.getToContext()); } else { - Importer.Imported(D, ToCategory); + Importer.MapImported(D, ToCategory); } // Import all of the members of this category. @@ -3420,7 +3510,7 @@ if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of a protocol. @@ -3446,15 +3536,18 @@ ObjCProtocolDecl *ToProto = MergeWithProtocol; if (!ToProto) { - ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, - Name.getAsIdentifierInfo(), Loc, - Importer.Import(D->getAtStartLoc()), - /*PrevDecl=*/nullptr); + bool AlreadyImported; + std::tie(ToProto, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Name.getAsIdentifierInfo(), Loc, + Importer.Import(D->getAtStartLoc()), + /*PrevDecl=*/nullptr); + if (AlreadyImported) + return ToProto; ToProto->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProto); } - - Importer.Imported(D, ToProto); + + Importer.MapImported(D, ToProto); if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto)) return nullptr; @@ -3470,14 +3563,14 @@ SourceLocation LangLoc = Importer.Import(D->getLocation()); bool HasBraces = D->hasBraces(); - - LinkageSpecDecl *ToLinkageSpec = - LinkageSpecDecl::Create(Importer.getToContext(), - DC, - ExternLoc, - LangLoc, - D->getLanguage(), - HasBraces); + + bool AlreadyImported; + LinkageSpecDecl *ToLinkageSpec; + std::tie(ToLinkageSpec, AlreadyImported) = + CreateDecl(D, Importer.getToContext(), DC, ExternLoc, + LangLoc, D->getLanguage(), HasBraces); + if (AlreadyImported) + return ToLinkageSpec; if (HasBraces) { SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc()); @@ -3487,8 +3580,6 @@ ToLinkageSpec->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToLinkageSpec); - Importer.Imported(D, ToLinkageSpec); - return ToLinkageSpec; } @@ -3506,13 +3597,16 @@ Importer.Import(D->getNameInfo().getLoc())); ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); - UsingDecl *ToUsing = UsingDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getUsingLoc()), - Importer.Import(D->getQualifierLoc()), - NameInfo, D->hasTypename()); + bool AlreadyImported; + UsingDecl *ToUsing; + std::tie(ToUsing, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, D->hasTypename()); + if (AlreadyImported) + return ToUsing; + ToUsing->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsing); - Importer.Imported(D, ToUsing); if (NamedDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingDecl(D)) { @@ -3555,12 +3649,15 @@ if (!ToTarget) return nullptr; - UsingShadowDecl *ToShadow = UsingShadowDecl::Create( - Importer.getToContext(), DC, Loc, ToUsing, ToTarget); + bool AlreadyImported; + UsingShadowDecl *ToShadow; + std::tie(ToShadow, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Loc, ToUsing, ToTarget); + if (AlreadyImported) + return ToShadow; ToShadow->setLexicalDeclContext(LexicalDC); ToShadow->setAccess(D->getAccess()); - Importer.Imported(D, ToShadow); if (UsingShadowDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) { @@ -3598,14 +3695,18 @@ if (!ToNominated) return nullptr; - UsingDirectiveDecl *ToUsingDir = UsingDirectiveDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), - Importer.Import(D->getNamespaceKeyLocation()), - Importer.Import(D->getQualifierLoc()), - Importer.Import(D->getIdentLocation()), ToNominated, ToComAncestor); + bool AlreadyImported; + UsingDirectiveDecl *ToUsingDir; + std::tie(ToUsingDir, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getNamespaceKeyLocation()), + Importer.Import(D->getQualifierLoc()), + Importer.Import(D->getIdentLocation()), ToNominated, ToComAncestor); + if (AlreadyImported) + return ToUsingDir; + ToUsingDir->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingDir); - Importer.Imported(D, ToUsingDir); return ToUsingDir; } @@ -3624,12 +3725,15 @@ DeclarationNameInfo NameInfo(Name, Importer.Import(D->getNameInfo().getLoc())); ImportDeclarationNameLoc(D->getNameInfo(), NameInfo); - UnresolvedUsingValueDecl *ToUsingValue = UnresolvedUsingValueDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), - Importer.Import(D->getQualifierLoc()), NameInfo, - Importer.Import(D->getEllipsisLoc())); + bool AlreadyImported; + UnresolvedUsingValueDecl *ToUsingValue; + std::tie(ToUsingValue, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, + Importer.Import(D->getEllipsisLoc())); + if (AlreadyImported) + return ToUsingValue; - Importer.Imported(D, ToUsingValue); ToUsingValue->setAccess(D->getAccess()); ToUsingValue->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingValue); @@ -3648,13 +3752,16 @@ if (ToD) return ToD; - UnresolvedUsingTypenameDecl *ToUsing = UnresolvedUsingTypenameDecl::Create( - Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), - Importer.Import(D->getTypenameLoc()), - Importer.Import(D->getQualifierLoc()), Loc, Name, - Importer.Import(D->getEllipsisLoc())); + bool AlreadyImported; + UnresolvedUsingTypenameDecl *ToUsing; + std::tie(ToUsing, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getUsingLoc()), + Importer.Import(D->getTypenameLoc()), + Importer.Import(D->getQualifierLoc()), Loc, Name, + Importer.Import(D->getEllipsisLoc())); + if (AlreadyImported) + return ToUsing; - Importer.Imported(D, ToUsing); ToUsing->setAccess(D->getAccess()); ToUsing->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsing); @@ -3786,7 +3893,7 @@ if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of an @interface. @@ -3814,16 +3921,18 @@ // Create an interface declaration, if one does not already exist. ObjCInterfaceDecl *ToIface = MergeWithIface; if (!ToIface) { - ToIface = ObjCInterfaceDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getAtStartLoc()), - Name.getAsIdentifierInfo(), - /*TypeParamList=*/nullptr, - /*PrevDecl=*/nullptr, Loc, - D->isImplicitInterfaceDecl()); + bool AlreadyImported; + std::tie(ToIface, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getAtStartLoc()), + Name.getAsIdentifierInfo(), + /*TypeParamList=*/nullptr, + /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl()); + if (AlreadyImported) + return ToIface; ToIface->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToIface); } - Importer.Imported(D, ToIface); + Importer.MapImported(D, ToIface); // Import the type parameter list after calling Imported, to avoid // loops when bringing in their DeclContext. ToIface->setTypeParamList(ImportObjCTypeParamList( @@ -3848,13 +3957,14 @@ return nullptr; SourceLocation CategoryNameLoc = Importer.Import(D->getCategoryNameLoc()); - ToImpl = ObjCCategoryImplDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getIdentifier()), - Category->getClassInterface(), - Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc()), - CategoryNameLoc); - + bool AlreadyImported; + std::tie(ToImpl, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getIdentifier()), + Category->getClassInterface(), Importer.Import(D->getLocation()), + Importer.Import(D->getAtStartLoc()), CategoryNameLoc); + if (AlreadyImported) + return ToImpl; + DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); @@ -3868,7 +3978,7 @@ Category->setImplementation(ToImpl); } - Importer.Imported(D, ToImpl); + Importer.MapImported(D, ToImpl); ImportDeclContext(D); return ToImpl; } @@ -3893,15 +4003,17 @@ if (!Impl) { // We haven't imported an implementation yet. Create a new @implementation // now. - Impl = ObjCImplementationDecl::Create(Importer.getToContext(), - Importer.ImportContext(D->getDeclContext()), - Iface, Super, - Importer.Import(D->getLocation()), - Importer.Import(D->getAtStartLoc()), - Importer.Import(D->getSuperClassLoc()), - Importer.Import(D->getIvarLBraceLoc()), - Importer.Import(D->getIvarRBraceLoc())); - + bool AlreadyImported; + std::tie(Impl, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), Importer.ImportContext(D->getDeclContext()), + Iface, Super, Importer.Import(D->getLocation()), + Importer.Import(D->getAtStartLoc()), + Importer.Import(D->getSuperClassLoc()), + Importer.Import(D->getIvarLBraceLoc()), + Importer.Import(D->getIvarRBraceLoc())); + if (AlreadyImported) + return Impl; + if (D->getDeclContext() != D->getLexicalDeclContext()) { DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); @@ -3909,12 +4021,12 @@ return nullptr; Impl->setLexicalDeclContext(LexicalDC); } - + // Associate the implementation with the class it implements. Iface->setImplementation(Impl); - Importer.Imported(D, Iface->getImplementation()); + Importer.MapImported(D, Iface->getImplementation()); } else { - Importer.Imported(D, Iface->getImplementation()); + Importer.MapImported(D, Iface->getImplementation()); // Verify that the existing @implementation has the same superclass. if ((Super && !Impl->getSuperClass()) || @@ -3980,7 +4092,7 @@ // FIXME: Check property attributes, getters, setters, etc.? // Consider these properties to be equivalent. - Importer.Imported(D, FoundProp); + Importer.MapImported(D, FoundProp); return FoundProp; } } @@ -3991,15 +4103,15 @@ return nullptr; // Create the new property. - ObjCPropertyDecl *ToProperty - = ObjCPropertyDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), - Importer.Import(D->getAtLoc()), - Importer.Import(D->getLParenLoc()), - Importer.Import(D->getType()), - TSI, - D->getPropertyImplementation()); - Importer.Imported(D, ToProperty); + bool AlreadyImported; + ObjCPropertyDecl *ToProperty; + std::tie(ToProperty, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), + Importer.Import(D->getAtLoc()), Importer.Import(D->getLParenLoc()), + Importer.Import(D->getType()), TSI, D->getPropertyImplementation()); + if (AlreadyImported) + return ToProperty; + ToProperty->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProperty); @@ -4053,16 +4165,17 @@ ObjCPropertyImplDecl *ToImpl = InImpl->FindPropertyImplDecl(Property->getIdentifier(), Property->getQueryKind()); - if (!ToImpl) { - ToImpl = ObjCPropertyImplDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocStart()), - Importer.Import(D->getLocation()), - Property, - D->getPropertyImplementation(), - Ivar, - Importer.Import(D->getPropertyIvarDeclLoc())); + if (!ToImpl) { + bool AlreadyImported; + std::tie(ToImpl, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Importer.Import(D->getLocStart()), + Importer.Import(D->getLocation()), Property, + D->getPropertyImplementation(), Ivar, + Importer.Import(D->getPropertyIvarDeclLoc())); + if (AlreadyImported) + return ToImpl; + ToImpl->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToImpl); LexicalDC->addDeclInternal(ToImpl); } else { // Check that we have the same kind of property implementation (@synthesize @@ -4095,7 +4208,7 @@ } // Merge the existing implementation with the new implementation. - Importer.Imported(D, ToImpl); + Importer.MapImported(D, ToImpl); } return ToImpl; @@ -4107,15 +4220,15 @@ // is created. // FIXME: Import default argument. - return TemplateTypeParmDecl::Create(Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - Importer.Import(D->getLocStart()), - Importer.Import(D->getLocation()), - D->getDepth(), - D->getIndex(), - Importer.Import(D->getIdentifier()), - D->wasDeclaredWithTypename(), - D->isParameterPack()); + bool AlreadyImported; + TemplateTypeParmDecl *ToD; + std::tie(ToD, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + Importer.Import(D->getLocStart()), Importer.Import(D->getLocation()), + D->getDepth(), D->getIndex(), Importer.Import(D->getIdentifier()), + D->wasDeclaredWithTypename(), D->isParameterPack()); + return ToD; } Decl * @@ -4139,13 +4252,16 @@ return nullptr; // FIXME: Import default argument. - - return NonTypeTemplateParmDecl::Create(Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - Importer.Import(D->getInnerLocStart()), - Loc, D->getDepth(), D->getPosition(), - Name.getAsIdentifierInfo(), - T, D->isParameterPack(), TInfo); + + bool AlreadyImported; + NonTypeTemplateParmDecl *ToD; + std::tie(ToD, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + Importer.Import(D->getInnerLocStart()), Loc, D->getDepth(), + D->getPosition(), Name.getAsIdentifierInfo(), T, D->isParameterPack(), + TInfo); + return ToD; } Decl * @@ -4157,7 +4273,7 @@ // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); - + // Import template parameters. TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); @@ -4165,13 +4281,15 @@ return nullptr; // FIXME: Import default argument. - - return TemplateTemplateParmDecl::Create(Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - Loc, D->getDepth(), D->getPosition(), - D->isParameterPack(), - Name.getAsIdentifierInfo(), - TemplateParams); + + bool AlreadyImported; + TemplateTemplateParmDecl *ToD; + std::tie(ToD, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), Loc, D->getDepth(), + D->getPosition(), D->isParameterPack(), Name.getAsIdentifierInfo(), + TemplateParams); + return ToD; } // Returns the definition for a (forward) declaration of a ClassTemplateDecl, if @@ -4197,7 +4315,7 @@ if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of this class template. @@ -4236,9 +4354,9 @@ if (IsStructuralMatch(D, FoundTemplate)) { // The class templates structurally match; call it the same template. - Importer.Imported(D->getTemplatedDecl(), - FoundTemplate->getTemplatedDecl()); - return Importer.Imported(D, FoundTemplate); + Importer.MapImported(D->getTemplatedDecl(), + FoundTemplate->getTemplatedDecl()); + return Importer.MapImported(D, FoundTemplate); } } @@ -4263,29 +4381,25 @@ if (!ToTemplated) return nullptr; - // Resolve possible cyclic import. - if (Decl *AlreadyImported = Importer.GetAlreadyImportedOrNull(D)) - return AlreadyImported; - // Create the class template declaration itself. TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); if (!TemplateParams) return nullptr; - ClassTemplateDecl *D2 = ClassTemplateDecl::Create(Importer.getToContext(), DC, - Loc, Name, TemplateParams, - ToTemplated); + bool AlreadyImported; + ClassTemplateDecl *D2; + std::tie(D2, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Loc, Name, TemplateParams, ToTemplated); + if (AlreadyImported) + return D2; + ToTemplated->setDescribedClassTemplate(D2); D2->setAccess(D->getAccess()); D2->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(D2); - // Note the relationship between the class templates. - Importer.Imported(D, D2); - Importer.Imported(FromTemplated, ToTemplated); - if (FromTemplated->isCompleteDefinition() && !ToTemplated->isCompleteDefinition()) { // FIXME: Import definition! @@ -4305,7 +4419,7 @@ if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } auto *ClassTemplate = @@ -4341,6 +4455,8 @@ void *InsertPos = nullptr; ClassTemplateSpecializationDecl *D2 = ClassTemplate->findSpecialization(TemplateArgs, InsertPos); + Optional AlreadyImported; // Using optional to make sure that all paths + // initialize it. if (D2) { // We already have a class template specialization with these template // arguments. @@ -4352,7 +4468,7 @@ // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // function. - return Importer.Imported(D, FoundDef); + return Importer.MapImported(D, FoundDef); } } } else { @@ -4376,20 +4492,22 @@ if (!ToTPList && PartialSpec->getTemplateParameters()) return nullptr; - D2 = ClassTemplatePartialSpecializationDecl::Create( - Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc, - ToTPList, ClassTemplate, - llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), - ToTAInfo, CanonInjType, nullptr); + std::tie(D2, AlreadyImported) = + CreateDecl( + D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc, + ToTPList, ClassTemplate, + llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), + ToTAInfo, CanonInjType, nullptr); } else { - D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(), - D->getTagKind(), DC, - StartLoc, IdLoc, - ClassTemplate, - TemplateArgs, - /*PrevDecl=*/nullptr); + std::tie(D2, AlreadyImported) = + CreateDecl( + D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, IdLoc, + ClassTemplate, TemplateArgs, /*PrevDecl=*/nullptr); } + assert(AlreadyImported.hasValue()); + if (*AlreadyImported) + return D2; D2->setSpecializationKind(D->getSpecializationKind()); @@ -4399,8 +4517,6 @@ // Import the qualifier, if any. D2->setQualifierInfo(Importer.Import(D->getQualifierLoc())); - Importer.Imported(D, D2); - if (auto *TSI = D->getTypeAsWritten()) { TypeSourceInfo *TInfo = Importer.Import(TSI); if (!TInfo) @@ -4426,7 +4542,6 @@ LexicalDC->addDeclInternal(D2); } } - Importer.Imported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2)) return nullptr; @@ -4445,7 +4560,7 @@ if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of this variable template. @@ -4472,9 +4587,9 @@ if (auto *FoundTemplate = dyn_cast(Found)) { if (IsStructuralMatch(D, FoundTemplate)) { // The variable templates structurally match; call it the same template. - Importer.Imported(D->getTemplatedDecl(), - FoundTemplate->getTemplatedDecl()); - return Importer.Imported(D, FoundTemplate); + Importer.MapImported(D->getTemplatedDecl(), + FoundTemplate->getTemplatedDecl()); + return Importer.MapImported(D, FoundTemplate); } } @@ -4508,18 +4623,19 @@ if (!TemplateParams) return nullptr; - VarTemplateDecl *ToVarTD = VarTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, TemplateParams, ToTemplated); + bool AlreadyImported; + VarTemplateDecl *ToVarTD; + std::tie(ToVarTD, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Loc, Name, TemplateParams, ToTemplated); + if (AlreadyImported) + return ToVarTD; + ToTemplated->setDescribedVarTemplate(ToVarTD); ToVarTD->setAccess(D->getAccess()); ToVarTD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToVarTD); - // Note the relationship between the variable templates. - Importer.Imported(D, ToVarTD); - Importer.Imported(DTemplated, ToTemplated); - if (DTemplated->isThisDeclarationADefinition() && !ToTemplated->isThisDeclarationADefinition()) { // FIXME: Import definition! @@ -4539,7 +4655,7 @@ if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } auto *VarTemplate = cast_or_null( @@ -4585,7 +4701,7 @@ // The record types structurally match, or the "from" translation // unit only had a forward declaration anyway; call it the same // variable. - return Importer.Imported(D, FoundDef); + return Importer.MapImported(D, FoundDef); } } } else { @@ -4617,9 +4733,13 @@ if (!ToTPList) return nullptr; - auto *ToPartial = PartVarSpecDecl::Create( - Importer.getToContext(), DC, StartLoc, IdLoc, ToTPList, VarTemplate, - T, TInfo, D->getStorageClass(), TemplateArgs, ArgInfos); + bool AlreadyImported; + PartVarSpecDecl *ToPartial; + std::tie(ToPartial, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, StartLoc, IdLoc, ToTPList, + VarTemplate, T, TInfo, D->getStorageClass(), TemplateArgs, ArgInfos); + if (AlreadyImported) + return ToPartial; auto *FromInst = FromPartial->getInstantiatedFromMember(); auto *ToInst = cast_or_null(Importer.Import(FromInst)); @@ -4632,9 +4752,12 @@ D2 = ToPartial; } else { // Full specialization - D2 = VarTemplateSpecializationDecl::Create( - Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo, - D->getStorageClass(), TemplateArgs); + bool AlreadyImported; + std::tie(D2, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, + TInfo, D->getStorageClass(), TemplateArgs); + if (AlreadyImported) + return D2; } SourceLocation POI = D->getPointOfInstantiation(); @@ -4660,8 +4783,6 @@ D2->setAccess(D->getAccess()); } - Importer.Imported(D, D2); - // NOTE: isThisDeclarationADefinition() can return DeclarationOnly even if // declaration has initializer. Should this be fixed in the AST?.. Anyway, // we have to check the declaration for initializer - otherwise, it won't be @@ -4699,7 +4820,7 @@ if (FoundFunction->hasExternalFormalLinkage() && D->hasExternalFormalLinkage()) { if (IsStructuralMatch(D, FoundFunction)) { - Importer.Imported(D, FoundFunction); + Importer.MapImported(D, FoundFunction); // FIXME: Actually try to merge the body and other attributes. return FoundFunction; } @@ -4718,13 +4839,16 @@ if (!TemplatedFD) return nullptr; - FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD); + bool AlreadyImported; + FunctionTemplateDecl *ToFunc; + std::tie(ToFunc, AlreadyImported) = CreateDecl( + D, Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD); + if (AlreadyImported) + return ToFunc; TemplatedFD->setDescribedFunctionTemplate(ToFunc); ToFunc->setAccess(D->getAccess()); ToFunc->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToFunc); LexicalDC->addDeclInternal(ToFunc); return ToFunc; @@ -6809,22 +6933,20 @@ ASTNodeImporter Importer(*this); - // Check whether we've already imported this declaration. - llvm::DenseMap::iterator Pos = ImportedDecls.find(FromD); - if (Pos != ImportedDecls.end()) { - Decl *ToD = Pos->second; - Importer.ImportDefinitionIfNeeded(FromD, ToD); + // Check whether we've already imported this declaration. + Decl *ToD = GetAlreadyImportedOrNull(FromD); + if (ToD) { return ToD; } - - // Import the type - Decl *ToD = Importer.Visit(FromD); + + // Import the type. + ToD = Importer.Visit(FromD); if (!ToD) return nullptr; - // Record the imported declaration. - ImportedDecls[FromD] = ToD; - ToD->IdentifierNamespace = FromD->IdentifierNamespace; + // Notify subclasses. + Imported(FromD, ToD); + return ToD; } @@ -7423,17 +7545,12 @@ } } -Decl *ASTImporter::Imported(Decl *From, Decl *To) { - if (From->hasAttrs()) { - for (const auto *FromAttr : From->getAttrs()) - To->addAttr(Import(FromAttr)); - } - if (From->isUsed()) { - To->setIsUsed(); - } - if (From->isImplicit()) { - To->setImplicit(); - } +Decl *ASTImporter::MapImported(Decl *From, Decl *To) { + llvm::DenseMap::iterator Pos = ImportedDecls.find(From); + assert((Pos == ImportedDecls.end() || Pos->second == To) && + "Try to import an already imported Decl"); + if (Pos != ImportedDecls.end()) + return Pos->second; ImportedDecls[From] = To; return To; } Index: lib/AST/ExternalASTMerger.cpp =================================================================== --- lib/AST/ExternalASTMerger.cpp +++ lib/AST/ExternalASTMerger.cpp @@ -154,7 +154,7 @@ ToContainer->setMustBuildLookupTable(); assert(Parent.CanComplete(ToContainer)); } - return ASTImporter::Imported(From, To); + return To; } ASTImporter &GetReverse() { return Reverse; } }; @@ -229,7 +229,7 @@ SourceTag->getASTContext().getExternalSource()->CompleteType(SourceTag); if (!SourceTag->getDefinition()) return false; - Forward.Imported(SourceTag, Tag); + Forward.MapImported(SourceTag, Tag); Forward.ImportDefinition(SourceTag); Tag->setCompleteDefinition(SourceTag->isCompleteDefinition()); return true; @@ -248,7 +248,7 @@ SourceInterface); if (!SourceInterface->getDefinition()) return false; - Forward.Imported(SourceInterface, Interface); + Forward.MapImported(SourceInterface, Interface); Forward.ImportDefinition(SourceInterface); return true; }); @@ -304,7 +304,7 @@ void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin, ASTImporter &Importer) { Origins[ToDC] = Origin; - Importer.ASTImporter::Imported(cast(Origin.DC), const_cast(cast(ToDC))); + Importer.ASTImporter::MapImported(cast(Origin.DC), const_cast(cast(ToDC))); } ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target,