Author: martong Date: Thu Jul 12 02:42:05 2018 New Revision: 336896 URL: http://llvm.org/viewvc/llvm-project?rev=336896&view=rev Log: [ASTImporter] Refactor Decl creation
Summary: Generalize the creation of Decl nodes during Import. With this patch we do the same things after and before a new AST node is created (::Create) The import logic should be really simple, we create the node, then we mark that as imported, then we recursively import the parts for that node and then set them on that node. However, the AST is actually a graph, so we have to handle circles. If we mark something as imported (`MapImported()`) then we return with the corresponding `To` decl whenever we want to import that node again, this way circles are handled. In order to make this algorithm work we must ensure things, which are handled in the generic CreateDecl<> template: * There are no `Import()` calls in between any node creation (::Create) and the `MapImported()` call. * Before actually creating an AST node (::Create), we must check if the Node had been imported already, if yes then return with that one. One very important case for this is connected to templates: we may start an import both from the templated decl of a template and from the template itself. Now, the virtual `Imported` function is called in `ASTImporter::Impor(Decl *)`, but only once, when the `Decl` is imported. One point of this refactor is to separate responsibilities. The original `Imported()` had 3 responsibilities: - notify subclasses when an import happened - register the decl into `ImportedDecls` - initialise the Decl (set attributes, etc) Now all of these are in separate functions: - `Imported` - `MapImported` - `InitializeImportedDecl` I tried to check all the clients, I executed tests for `ExternalASTMerger.cpp` and some unittests for lldb. Reviewers: a.sidorin, balazske, xazax.hun, r.stahl Subscribers: rnkovacs, dkrupp, cfe-commits Differential Revision: https://reviews.llvm.org/D47632 Modified: cfe/trunk/include/clang/AST/ASTImporter.h cfe/trunk/include/clang/AST/ASTStructuralEquivalence.h cfe/trunk/include/clang/AST/DeclBase.h cfe/trunk/lib/AST/ASTImporter.cpp cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp cfe/trunk/lib/AST/ExternalASTMerger.cpp cfe/trunk/lib/Sema/SemaType.cpp cfe/trunk/unittests/AST/ASTImporterTest.cpp cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp Modified: cfe/trunk/include/clang/AST/ASTImporter.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTImporter.h?rev=336896&r1=336895&r2=336896&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTImporter.h (original) +++ cfe/trunk/include/clang/AST/ASTImporter.h Thu Jul 12 02:42:05 2018 @@ -314,13 +314,13 @@ class Attr; /// \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 Modified: cfe/trunk/include/clang/AST/ASTStructuralEquivalence.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/ASTStructuralEquivalence.h?rev=336896&r1=336895&r2=336896&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/ASTStructuralEquivalence.h (original) +++ cfe/trunk/include/clang/AST/ASTStructuralEquivalence.h Thu Jul 12 02:42:05 2018 @@ -30,6 +30,14 @@ class QualType; class RecordDecl; class SourceLocation; +/// \brief Whether to perform a normal or minimal equivalence check. +/// In case of `Minimal`, we do not perform a recursive check of decls with +/// external storage. +enum class StructuralEquivalenceKind { + Default, + Minimal, +}; + struct StructuralEquivalenceContext { /// AST contexts for which we are checking structural equivalence. ASTContext &FromCtx, &ToCtx; @@ -47,6 +55,8 @@ struct StructuralEquivalenceContext { /// (which we have already complained about). llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls; + StructuralEquivalenceKind EqKind; + /// Whether we're being strict about the spelling of types when /// unifying two types. bool StrictTypeSpelling; @@ -63,10 +73,11 @@ struct StructuralEquivalenceContext { StructuralEquivalenceContext( ASTContext &FromCtx, ASTContext &ToCtx, llvm::DenseSet<std::pair<Decl *, Decl *>> &NonEquivalentDecls, + StructuralEquivalenceKind EqKind, bool StrictTypeSpelling = false, bool Complain = true, bool ErrorOnTagTypeMismatch = false) : FromCtx(FromCtx), ToCtx(ToCtx), NonEquivalentDecls(NonEquivalentDecls), - StrictTypeSpelling(StrictTypeSpelling), + EqKind(EqKind), StrictTypeSpelling(StrictTypeSpelling), ErrorOnTagTypeMismatch(ErrorOnTagTypeMismatch), Complain(Complain) {} DiagnosticBuilder Diag1(SourceLocation Loc, unsigned DiagID); Modified: cfe/trunk/include/clang/AST/DeclBase.h URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/AST/DeclBase.h?rev=336896&r1=336895&r2=336896&view=diff ============================================================================== --- cfe/trunk/include/clang/AST/DeclBase.h (original) +++ cfe/trunk/include/clang/AST/DeclBase.h Thu Jul 12 02:42:05 2018 @@ -309,7 +309,7 @@ private: protected: friend class ASTDeclReader; friend class ASTDeclWriter; - friend class ASTImporter; + friend class ASTNodeImporter; friend class ASTReader; friend class CXXClassMemberWrapper; friend class LinkageComputer; Modified: cfe/trunk/lib/AST/ASTImporter.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTImporter.cpp?rev=336896&r1=336895&r2=336896&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTImporter.cpp (original) +++ cfe/trunk/lib/AST/ASTImporter.cpp Thu Jul 12 02:42:05 2018 @@ -90,11 +90,83 @@ namespace clang { return getCanonicalForwardRedeclChain<FunctionDecl>(FD); } + void updateFlags(const Decl *From, Decl *To) { + // Check if some flags or attrs are new in 'From' and copy into 'To'. + // FIXME: Other flags or attrs? + if (From->isUsed(false) && !To->isUsed(false)) + To->setIsUsed(); + } + class ASTNodeImporter : public TypeVisitor<ASTNodeImporter, QualType>, public DeclVisitor<ASTNodeImporter, Decl *>, public StmtVisitor<ASTNodeImporter, Stmt *> { ASTImporter &Importer; + // Wrapper for an overload set. + template <typename ToDeclT> struct CallOverloadedCreateFun { + template <typename... Args> + auto operator()(Args &&... args) + -> decltype(ToDeclT::Create(std::forward<Args>(args)...)) { + return ToDeclT::Create(std::forward<Args>(args)...); + } + }; + + // Always use these functions 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. The parameter `ToD` + // will be set to the newly created Decl or if had been imported before + // then to the already imported Decl. Returns a bool value set to true if + // the `FromD` had been imported before. + template <typename ToDeclT, typename FromDeclT, typename... Args> + LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, 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<ToDeclT> OC; + return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, + std::forward<Args>(args)...); + } + // Use this overload if a special Type is needed to be created. E.g if we + // want to create a `TypeAliasDecl` and assign that to a `TypedefNameDecl` + // then: + // TypedefNameDecl *ToTypedef; + // GetImportedOrCreateDecl<TypeAliasDecl>(ToTypedef, FromD, ...); + template <typename NewDeclT, typename ToDeclT, typename FromDeclT, + typename... Args> + LLVM_NODISCARD bool GetImportedOrCreateDecl(ToDeclT *&ToD, FromDeclT *FromD, + Args &&... args) { + CallOverloadedCreateFun<NewDeclT> OC; + return GetImportedOrCreateSpecialDecl(ToD, OC, FromD, + std::forward<Args>(args)...); + } + // Use this version if a special create function must be + // used, e.g. CXXRecordDecl::CreateLambda . + template <typename ToDeclT, typename CreateFunT, typename FromDeclT, + typename... Args> + LLVM_NODISCARD bool + GetImportedOrCreateSpecialDecl(ToDeclT *&ToD, CreateFunT CreateFun, + FromDeclT *FromD, Args &&... args) { + ToD = cast_or_null<ToDeclT>(Importer.GetAlreadyImportedOrNull(FromD)); + if (ToD) + return true; // Already imported. + ToD = CreateFun(std::forward<Args>(args)...); + InitializeImportedDecl(FromD, ToD); + return false; // A new Decl is created. + } + + 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) {} @@ -1485,6 +1557,12 @@ bool ASTNodeImporter::ImportTemplateArgu return false; } +static StructuralEquivalenceKind +getStructuralEquivalenceKind(const ASTImporter &Importer) { + return Importer.isMinimalImport() ? StructuralEquivalenceKind::Minimal + : StructuralEquivalenceKind::Default; +} + bool ASTNodeImporter::IsStructuralMatch(RecordDecl *FromRecord, RecordDecl *ToRecord, bool Complain) { // Eliminate a potential failure point where we attempt to re-import @@ -1499,6 +1577,7 @@ bool ASTNodeImporter::IsStructuralMatch( StructuralEquivalenceContext Ctx(Importer.getFromContext(), ToRecord->getASTContext(), Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer), false, Complain); return Ctx.IsStructurallyEquivalent(FromRecord, ToRecord); } @@ -1507,14 +1586,15 @@ bool ASTNodeImporter::IsStructuralMatch( bool Complain) { StructuralEquivalenceContext Ctx( Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), false, Complain); + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, Complain); return Ctx.IsStructurallyEquivalent(FromVar, ToVar); } bool ASTNodeImporter::IsStructuralMatch(EnumDecl *FromEnum, EnumDecl *ToEnum) { - StructuralEquivalenceContext Ctx(Importer.getFromContext(), - Importer.getToContext(), - Importer.getNonEquivalentDecls()); + StructuralEquivalenceContext Ctx( + Importer.getFromContext(), Importer.getToContext(), + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer)); return Ctx.IsStructurallyEquivalent(FromEnum, ToEnum); } @@ -1522,14 +1602,16 @@ bool ASTNodeImporter::IsStructuralMatch( FunctionTemplateDecl *To) { StructuralEquivalenceContext Ctx( Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), false, false); + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, false); return Ctx.IsStructurallyEquivalent(From, To); } bool ASTNodeImporter::IsStructuralMatch(FunctionDecl *From, FunctionDecl *To) { StructuralEquivalenceContext Ctx( Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), false, false); + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, false); return Ctx.IsStructurallyEquivalent(From, To); } @@ -1547,7 +1629,8 @@ bool ASTNodeImporter::IsStructuralMatch( ClassTemplateDecl *To) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls()); + Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer)); return Ctx.IsStructurallyEquivalent(From, To); } @@ -1555,7 +1638,8 @@ bool ASTNodeImporter::IsStructuralMatch( VarTemplateDecl *To) { StructuralEquivalenceContext Ctx(Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls()); + Importer.getNonEquivalentDecls(), + getStructuralEquivalenceKind(Importer)); return Ctx.IsStructurallyEquivalent(From, To); } @@ -1581,9 +1665,11 @@ Decl *ASTNodeImporter::VisitEmptyDecl(Em // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); - EmptyDecl *ToD = EmptyDecl::Create(Importer.getToContext(), DC, Loc); + EmptyDecl *ToD; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, Loc)) + return ToD; + ToD->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToD); LexicalDC->addDeclInternal(ToD); return ToD; } @@ -1592,7 +1678,7 @@ Decl *ASTNodeImporter::VisitTranslationU TranslationUnitDecl *ToD = Importer.getToContext().getTranslationUnitDecl(); - Importer.Imported(D, ToD); + Importer.MapImported(D, ToD); return ToD; } @@ -1606,19 +1692,17 @@ Decl *ASTNodeImporter::VisitAccessSpecDe if (!DC) return nullptr; - AccessSpecDecl *accessSpecDecl - = AccessSpecDecl::Create(Importer.getToContext(), D->getAccess(), - DC, Loc, ColonLoc); - - if (!accessSpecDecl) - return nullptr; + AccessSpecDecl *ToD; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), D->getAccess(), + DC, Loc, ColonLoc)) + 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) { @@ -1640,13 +1724,14 @@ Decl *ASTNodeImporter::VisitStaticAssert if (!ToMsg && FromMsg) return nullptr; - StaticAssertDecl *ToD = StaticAssertDecl::Create( - Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, - Importer.Import(D->getRParenLoc()), D->isFailed()); + StaticAssertDecl *ToD; + if (GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), DC, Loc, AssertExpr, ToMsg, + Importer.Import(D->getRParenLoc()), D->isFailed())) + return ToD; ToD->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToD); - Importer.Imported(D, ToD); return ToD; } @@ -1697,11 +1782,11 @@ Decl *ASTNodeImporter::VisitNamespaceDec // 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); + if (GetImportedOrCreateDecl( + ToNamespace, D, Importer.getToContext(), DC, D->isInline(), + Importer.Import(D->getLocStart()), Loc, Name.getAsIdentifierInfo(), + /*PrevDecl=*/nullptr)) + return ToNamespace; ToNamespace->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToNamespace); @@ -1714,7 +1799,7 @@ Decl *ASTNodeImporter::VisitNamespaceDec cast<NamespaceDecl>(DC)->setAnonymousNamespace(ToNamespace); } } - Importer.Imported(D, ToNamespace); + Importer.MapImported(D, ToNamespace); ImportDeclContext(D); @@ -1747,13 +1832,15 @@ Decl *ASTNodeImporter::VisitNamespaceAli 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); + NamespaceAliasDecl *ToD; + if (GetImportedOrCreateDecl(ToD, D, Importer.getToContext(), DC, + Importer.Import(D->getNamespaceLoc()), + Importer.Import(D->getAliasLoc()), ToII, ToQLoc, + Importer.Import(D->getTargetNameLoc()), + TargetDecl)) + return ToD; ToD->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToD); LexicalDC->addDeclInternal(ToD); return ToD; @@ -1784,7 +1871,7 @@ Decl *ASTNodeImporter::VisitTypedefNameD if (auto *FoundTypedef = dyn_cast<TypedefNameDecl>(FoundDecl)) { if (Importer.IsStructurallyEquivalent(D->getUnderlyingType(), FoundTypedef->getUnderlyingType())) - return Importer.Imported(D, FoundTypedef); + return Importer.MapImported(D, FoundTypedef); } ConflictingDecls.push_back(FoundDecl); @@ -1804,27 +1891,23 @@ Decl *ASTNodeImporter::VisitTypedefNameD 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()); + TypedefNameDecl *ToTypedef; - if (IsAlias) - ToTypedef = TypeAliasDecl::Create(Importer.getToContext(), DC, StartL, Loc, - Name.getAsIdentifierInfo(), TInfo); - else - ToTypedef = TypedefDecl::Create(Importer.getToContext(), DC, - StartL, Loc, - Name.getAsIdentifierInfo(), - TInfo); + if (IsAlias) { + if (GetImportedOrCreateDecl<TypeAliasDecl>( + ToTypedef, D, Importer.getToContext(), DC, StartL, Loc, + Name.getAsIdentifierInfo(), TInfo)) + return ToTypedef; + } else if (GetImportedOrCreateDecl<TypedefDecl>( + ToTypedef, D, Importer.getToContext(), DC, StartL, Loc, + Name.getAsIdentifierInfo(), TInfo)) + return ToTypedef; ToTypedef->setAccess(D->getAccess()); ToTypedef->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToTypedef); // Templated declarations should not appear in DeclContext. TypeAliasDecl *FromAlias = IsAlias ? cast<TypeAliasDecl>(D) : nullptr; @@ -1865,7 +1948,7 @@ Decl *ASTNodeImporter::VisitTypeAliasTem if (!FoundDecl->isInIdentifierNamespace(IDNS)) continue; if (auto *FoundAlias = dyn_cast<TypeAliasTemplateDecl>(FoundDecl)) - return Importer.Imported(D, FoundAlias); + return Importer.MapImported(D, FoundAlias); ConflictingDecls.push_back(FoundDecl); } @@ -1888,14 +1971,15 @@ Decl *ASTNodeImporter::VisitTypeAliasTem if (!TemplDecl) return nullptr; - TypeAliasTemplateDecl *ToAlias = TypeAliasTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, Params, TemplDecl); + TypeAliasTemplateDecl *ToAlias; + if (GetImportedOrCreateDecl(ToAlias, D, Importer.getToContext(), DC, Loc, + Name, Params, TemplDecl)) + return ToAlias; TemplDecl->setDescribedAliasTemplate(ToAlias); ToAlias->setAccess(D->getAccess()); ToAlias->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToAlias); LexicalDC->addDeclInternal(ToAlias); return ToAlias; } @@ -1913,15 +1997,16 @@ Decl *ASTNodeImporter::VisitLabelDecl(La 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); + LabelDecl *ToLabel; + if (D->isGnuLocal() + ? GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo(), + Importer.Import(D->getLocStart())) + : GetImportedOrCreateDecl(ToLabel, D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), + Name.getAsIdentifierInfo())) + return ToLabel; auto *Label = cast_or_null<LabelStmt>(Importer.Import(D->getStmt())); if (!Label) @@ -1970,7 +2055,7 @@ Decl *ASTNodeImporter::VisitEnumDecl(Enu if (auto *FoundEnum = dyn_cast<EnumDecl>(Found)) { if (IsStructuralMatch(D, FoundEnum)) - return Importer.Imported(D, FoundEnum); + return Importer.MapImported(D, FoundEnum); } ConflictingDecls.push_back(FoundDecl); @@ -1982,18 +2067,19 @@ Decl *ASTNodeImporter::VisitEnumDecl(Enu 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()); + EnumDecl *D2; + if (GetImportedOrCreateDecl( + D2, D, Importer.getToContext(), DC, Importer.Import(D->getLocStart()), + Loc, Name.getAsIdentifierInfo(), nullptr, D->isScoped(), + D->isScopedUsingClassTag(), D->isFixed())) + 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. @@ -2025,7 +2111,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(R if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of this record. @@ -2096,7 +2182,7 @@ Decl *ASTNodeImporter::VisitRecordDecl(R // 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 @@ -2141,11 +2227,11 @@ Decl *ASTNodeImporter::VisitRecordDecl(R if (auto *DCXX = dyn_cast<CXXRecordDecl>(D)) { if (DCXX->isLambda()) { TypeSourceInfo *TInfo = Importer.Import(DCXX->getLambdaTypeInfo()); - D2CXX = CXXRecordDecl::CreateLambda(Importer.getToContext(), - DC, TInfo, Loc, - DCXX->isDependentLambda(), - DCXX->isGenericLambda(), - DCXX->getLambdaCaptureDefault()); + if (GetImportedOrCreateSpecialDecl( + D2CXX, CXXRecordDecl::CreateLambda, D, Importer.getToContext(), + DC, TInfo, Loc, DCXX->isDependentLambda(), + DCXX->isGenericLambda(), DCXX->getLambdaCaptureDefault())) + return D2CXX; Decl *CDecl = Importer.Import(DCXX->getLambdaContextDecl()); if (DCXX->getLambdaContextDecl() && !CDecl) return nullptr; @@ -2155,25 +2241,27 @@ Decl *ASTNodeImporter::VisitRecordDecl(R // Sema::ActOnStartCXXMemberDeclarations CXXRecordDecl *const PrevDecl = nullptr; const bool DelayTypeCreation = true; - D2CXX = CXXRecordDecl::Create( - Importer.getToContext(), D->getTagKind(), DC, StartLoc, Loc, - Name.getAsIdentifierInfo(), PrevDecl, DelayTypeCreation); + if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), + D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), PrevDecl, + DelayTypeCreation)) + return D2CXX; Importer.getToContext().getTypeDeclType( D2CXX, dyn_cast<CXXRecordDecl>(DC)); } else { - D2CXX = CXXRecordDecl::Create(Importer.getToContext(), - D->getTagKind(), - DC, StartLoc, Loc, - Name.getAsIdentifierInfo()); + if (GetImportedOrCreateDecl(D2CXX, D, Importer.getToContext(), + D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), + cast_or_null<CXXRecordDecl>(PrevDecl))) + 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<ClassTemplateDecl>( @@ -2218,22 +2306,20 @@ Decl *ASTNodeImporter::VisitRecordDecl(R Importer.Import(MemberInfo->getPointOfInstantiation())); } } else { - D2 = RecordDecl::Create(Importer.getToContext(), D->getTagKind(), - DC, StartLoc, Loc, Name.getAsIdentifierInfo()); + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), + D->getTagKind(), DC, StartLoc, Loc, + Name.getAsIdentifierInfo(), PrevDecl)) + 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; @@ -2269,7 +2355,7 @@ Decl *ASTNodeImporter::VisitEnumConstant if (auto *FoundEnumConstant = dyn_cast<EnumConstantDecl>(FoundDecl)) { if (IsStructuralMatch(D, FoundEnumConstant)) - return Importer.Imported(D, FoundEnumConstant); + return Importer.MapImported(D, FoundEnumConstant); } ConflictingDecls.push_back(FoundDecl); @@ -2288,13 +2374,14 @@ Decl *ASTNodeImporter::VisitEnumConstant if (D->getInitExpr() && !Init) return nullptr; - EnumConstantDecl *ToEnumerator - = EnumConstantDecl::Create(Importer.getToContext(), cast<EnumDecl>(DC), Loc, - Name.getAsIdentifierInfo(), T, - Init, D->getInitVal()); + EnumConstantDecl *ToEnumerator; + if (GetImportedOrCreateDecl( + ToEnumerator, D, Importer.getToContext(), cast<EnumDecl>(DC), Loc, + Name.getAsIdentifierInfo(), T, Init, D->getInitVal())) + return ToEnumerator; + ToEnumerator->setAccess(D->getAccess()); ToEnumerator->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToEnumerator); LexicalDC->addDeclInternal(ToEnumerator); return ToEnumerator; } @@ -2445,7 +2532,7 @@ Decl *ASTNodeImporter::VisitFunctionDecl const FunctionDecl *Definition = nullptr; if (D->doesThisDeclarationHaveABody() && FoundFunction->hasBody(Definition)) { - return Importer.Imported( + return Importer.MapImported( D, const_cast<FunctionDecl *>(Definition)); } FoundByLookup = FoundFunction; @@ -2526,14 +2613,11 @@ Decl *ASTNodeImporter::VisitFunctionDecl FunctionDecl *ToFunction = nullptr; SourceLocation InnerLocStart = Importer.Import(D->getInnerLocStart()); if (auto *FromConstructor = dyn_cast<CXXConstructorDecl>(D)) { - ToFunction = CXXConstructorDecl::Create(Importer.getToContext(), - cast<CXXRecordDecl>(DC), - InnerLocStart, - NameInfo, T, TInfo, - FromConstructor->isExplicit(), - D->isInlineSpecified(), - D->isImplicit(), - D->isConstexpr()); + if (GetImportedOrCreateDecl<CXXConstructorDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + InnerLocStart, NameInfo, T, TInfo, FromConstructor->isExplicit(), + D->isInlineSpecified(), D->isImplicit(), D->isConstexpr())) + return ToFunction; if (unsigned NumInitializers = FromConstructor->getNumCtorInitializers()) { SmallVector<CXXCtorInitializer *, 4> CtorInitializers; for (auto *I : FromConstructor->inits()) { @@ -2550,37 +2634,30 @@ Decl *ASTNodeImporter::VisitFunctionDecl ToCtor->setNumCtorInitializers(NumInitializers); } } else if (isa<CXXDestructorDecl>(D)) { - ToFunction = CXXDestructorDecl::Create(Importer.getToContext(), - cast<CXXRecordDecl>(DC), - InnerLocStart, - NameInfo, T, TInfo, - D->isInlineSpecified(), - D->isImplicit()); - } else if (auto *FromConversion = dyn_cast<CXXConversionDecl>(D)) { - ToFunction = CXXConversionDecl::Create(Importer.getToContext(), - cast<CXXRecordDecl>(DC), - InnerLocStart, - NameInfo, T, TInfo, - D->isInlineSpecified(), - FromConversion->isExplicit(), - D->isConstexpr(), - SourceLocation()); + if (GetImportedOrCreateDecl<CXXDestructorDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), + D->isImplicit())) + return ToFunction; + } else if (CXXConversionDecl *FromConversion = + dyn_cast<CXXConversionDecl>(D)) { + if (GetImportedOrCreateDecl<CXXConversionDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + InnerLocStart, NameInfo, T, TInfo, D->isInlineSpecified(), + FromConversion->isExplicit(), D->isConstexpr(), SourceLocation())) + return ToFunction; } else if (auto *Method = dyn_cast<CXXMethodDecl>(D)) { - ToFunction = CXXMethodDecl::Create(Importer.getToContext(), - cast<CXXRecordDecl>(DC), - InnerLocStart, - NameInfo, T, TInfo, - Method->getStorageClass(), - Method->isInlineSpecified(), - D->isConstexpr(), - SourceLocation()); + if (GetImportedOrCreateDecl<CXXMethodDecl>( + ToFunction, D, Importer.getToContext(), cast<CXXRecordDecl>(DC), + InnerLocStart, NameInfo, T, TInfo, Method->getStorageClass(), + Method->isInlineSpecified(), D->isConstexpr(), SourceLocation())) + return ToFunction; } else { - ToFunction = FunctionDecl::Create(Importer.getToContext(), DC, - InnerLocStart, - NameInfo, T, TInfo, D->getStorageClass(), - D->isInlineSpecified(), - D->hasWrittenPrototype(), - D->isConstexpr()); + if (GetImportedOrCreateDecl(ToFunction, D, Importer.getToContext(), DC, + InnerLocStart, NameInfo, T, TInfo, + D->getStorageClass(), D->isInlineSpecified(), + D->hasWrittenPrototype(), D->isConstexpr())) + return ToFunction; } // Import the qualifier, if any. @@ -2591,7 +2668,6 @@ Decl *ASTNodeImporter::VisitFunctionDecl ToFunction->setTrivial(D->isTrivial()); ToFunction->setPure(D->isPure()); ToFunction->setRangeEnd(Importer.Import(D->getLocEnd())); - Importer.Imported(D, ToFunction); // Set the parameters. for (auto *Param : Parameters) { @@ -2722,7 +2798,7 @@ Decl *ASTNodeImporter::VisitFieldDecl(Fi if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType())) { - Importer.Imported(D, FoundField); + Importer.MapImported(D, FoundField); return FoundField; } @@ -2744,11 +2820,13 @@ Decl *ASTNodeImporter::VisitFieldDecl(Fi 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()); + FieldDecl *ToField; + if (GetImportedOrCreateDecl(ToField, D, Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, BitWidth, + D->isMutable(), D->getInClassInitStyle())) + return ToField; + ToField->setAccess(D->getAccess()); ToField->setLexicalDeclContext(LexicalDC); if (Expr *FromInitializer = D->getInClassInitializer()) { @@ -2759,7 +2837,6 @@ Decl *ASTNodeImporter::VisitFieldDecl(Fi return nullptr; } ToField->setImplicit(D->isImplicit()); - Importer.Imported(D, ToField); LexicalDC->addDeclInternal(ToField); return ToField; } @@ -2787,7 +2864,7 @@ Decl *ASTNodeImporter::VisitIndirectFiel if (Importer.IsStructurallyEquivalent(D->getType(), FoundField->getType(), !Name.isEmpty())) { - Importer.Imported(D, FoundField); + Importer.MapImported(D, FoundField); return FoundField; } @@ -2819,16 +2896,18 @@ Decl *ASTNodeImporter::VisitIndirectFiel NamedChain[i++] = cast<NamedDecl>(D); } - IndirectFieldDecl *ToIndirectField = IndirectFieldDecl::Create( - Importer.getToContext(), DC, Loc, Name.getAsIdentifierInfo(), T, - {NamedChain, D->getChainingSize()}); + llvm::MutableArrayRef<NamedDecl *> CH = {NamedChain, D->getChainingSize()}; + IndirectFieldDecl *ToIndirectField; + if (GetImportedOrCreateDecl(ToIndirectField, D, Importer.getToContext(), DC, + Loc, Name.getAsIdentifierInfo(), T, CH)) + // 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; } @@ -2847,19 +2926,20 @@ Decl *ASTNodeImporter::VisitFriendDecl(F FriendDecl *ImportedFriend = RD->getFirstFriend(); StructuralEquivalenceContext Context( Importer.getFromContext(), Importer.getToContext(), - Importer.getNonEquivalentDecls(), false, false); + Importer.getNonEquivalentDecls(), getStructuralEquivalenceKind(Importer), + false, false); while (ImportedFriend) { 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(); } @@ -2887,12 +2967,11 @@ Decl *ASTNodeImporter::VisitFriendDecl(F ToTPLists[I] = List; } - FriendDecl *FrD = FriendDecl::Create(Importer.getToContext(), DC, - Importer.Import(D->getLocation()), - ToFU, Importer.Import(D->getFriendLoc()), - ToTPLists); - - Importer.Imported(D, FrD); + FriendDecl *FrD; + if (GetImportedOrCreateDecl(FrD, D, Importer.getToContext(), DC, + Importer.Import(D->getLocation()), ToFU, + Importer.Import(D->getFriendLoc()), ToTPLists)) + return FrD; FrD->setAccess(D->getAccess()); FrD->setLexicalDeclContext(LexicalDC); @@ -2918,7 +2997,7 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl if (auto *FoundIvar = dyn_cast<ObjCIvarDecl>(FoundDecl)) { if (Importer.IsStructurallyEquivalent(D->getType(), FoundIvar->getType())) { - Importer.Imported(D, FoundIvar); + Importer.MapImported(D, FoundIvar); return FoundIvar; } @@ -2940,14 +3019,15 @@ Decl *ASTNodeImporter::VisitObjCIvarDecl if (!BitWidth && D->getBitWidth()) return nullptr; - ObjCIvarDecl *ToIvar = ObjCIvarDecl::Create(Importer.getToContext(), - cast<ObjCContainerDecl>(DC), - Importer.Import(D->getInnerLocStart()), - Loc, Name.getAsIdentifierInfo(), - T, TInfo, D->getAccessControl(), - BitWidth, D->getSynthesize()); + ObjCIvarDecl *ToIvar; + if (GetImportedOrCreateDecl( + ToIvar, D, Importer.getToContext(), cast<ObjCContainerDecl>(DC), + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, D->getAccessControl(), BitWidth, + D->getSynthesize())) + return ToIvar; + ToIvar->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToIvar); LexicalDC->addDeclInternal(ToIvar); return ToIvar; } @@ -3018,10 +3098,11 @@ Decl *ASTNodeImporter::VisitVarDecl(VarD } if (MergeWithVar) { - // An equivalent variable with external linkage has been found. Link + // An equivalent variable with external linkage has been found. Link // the two declarations, then merge them. - Importer.Imported(D, MergeWithVar); - + Importer.MapImported(D, MergeWithVar); + updateFlags(D, MergeWithVar); + if (VarDecl *DDef = D->getDefinition()) { if (VarDecl *ExistingDef = MergeWithVar->getDefinition()) { Importer.ToDiag(ExistingDef->getLocation(), @@ -3058,24 +3139,21 @@ Decl *ASTNodeImporter::VisitVarDecl(VarD // 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()); + VarDecl *ToVar; + if (GetImportedOrCreateDecl(ToVar, D, Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, + D->getStorageClass())) + 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()) LexicalDC->addDeclInternal(ToVar); - if (!D->isFileVarDecl() && - D->isUsed()) - ToVar->setIsUsed(); - // Merge the initializer. if (ImportDefinition(D, ToVar)) return nullptr; @@ -3105,10 +3183,12 @@ Decl *ASTNodeImporter::VisitImplicitPara return nullptr; // Create the imported parameter. - auto *ToParm = ImplicitParamDecl::Create(Importer.getToContext(), DC, Loc, - Name.getAsIdentifierInfo(), T, - D->getParameterKind()); - return Importer.Imported(D, ToParm); + ImplicitParamDecl *ToParm = nullptr; + if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo(), T, + D->getParameterKind())) + return ToParm; + return ToParm; } Decl *ASTNodeImporter::VisitParmVarDecl(ParmVarDecl *D) { @@ -3131,11 +3211,13 @@ Decl *ASTNodeImporter::VisitParmVarDecl( // 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); + ParmVarDecl *ToParm; + if (GetImportedOrCreateDecl(ToParm, D, Importer.getToContext(), DC, + Importer.Import(D->getInnerLocStart()), Loc, + Name.getAsIdentifierInfo(), T, TInfo, + D->getStorageClass(), + /*DefaultArg*/ nullptr)) + return ToParm; // Set the default argument. ToParm->setHasInheritedDefaultArg(D->hasInheritedDefaultArg()); @@ -3165,10 +3247,7 @@ Decl *ASTNodeImporter::VisitParmVarDecl( D->getFunctionScopeIndex()); } - if (D->isUsed()) - ToParm->setIsUsed(); - - return Importer.Imported(D, ToParm); + return ToParm; } Decl *ASTNodeImporter::VisitObjCMethodDecl(ObjCMethodDecl *D) { @@ -3240,7 +3319,7 @@ Decl *ASTNodeImporter::VisitObjCMethodDe } // FIXME: Any other bits we need to merge? - return Importer.Imported(D, FoundMethod); + return Importer.MapImported(D, FoundMethod); } } @@ -3251,11 +3330,14 @@ Decl *ASTNodeImporter::VisitObjCMethodDe TypeSourceInfo *ReturnTInfo = Importer.Import(D->getReturnTypeSourceInfo()); - ObjCMethodDecl *ToMethod = ObjCMethodDecl::Create( - 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()); + ObjCMethodDecl *ToMethod; + if (GetImportedOrCreateDecl( + ToMethod, 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())) + return ToMethod; // FIXME: When we decide to merge method definitions, we'll need to // deal with implicit parameters. @@ -3284,7 +3366,6 @@ Decl *ASTNodeImporter::VisitObjCMethodDe ToMethod->setMethodParams(Importer.getToContext(), ToParams, SelLocs); ToMethod->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToMethod); LexicalDC->addDeclInternal(ToMethod); return ToMethod; } @@ -3304,16 +3385,14 @@ Decl *ASTNodeImporter::VisitObjCTypePara 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); + ObjCTypeParamDecl *Result; + if (GetImportedOrCreateDecl( + Result, D, Importer.getToContext(), DC, D->getVariance(), + Importer.Import(D->getVarianceLoc()), D->getIndex(), + Importer.Import(D->getLocation()), Name.getAsIdentifierInfo(), + Importer.Import(D->getColonLoc()), BoundInfo)) + return Result; + Result->setLexicalDeclContext(LexicalDC); return Result; } @@ -3339,18 +3418,18 @@ Decl *ASTNodeImporter::VisitObjCCategory = 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())); + + if (GetImportedOrCreateDecl(ToCategory, 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()))) + 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( @@ -3377,7 +3456,7 @@ Decl *ASTNodeImporter::VisitObjCCategory 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. @@ -3446,7 +3525,7 @@ Decl *ASTNodeImporter::VisitObjCProtocol if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of a protocol. @@ -3472,15 +3551,16 @@ Decl *ASTNodeImporter::VisitObjCProtocol ObjCProtocolDecl *ToProto = MergeWithProtocol; if (!ToProto) { - ToProto = ObjCProtocolDecl::Create(Importer.getToContext(), DC, - Name.getAsIdentifierInfo(), Loc, - Importer.Import(D->getAtStartLoc()), - /*PrevDecl=*/nullptr); + if (GetImportedOrCreateDecl(ToProto, D, Importer.getToContext(), DC, + Name.getAsIdentifierInfo(), Loc, + Importer.Import(D->getAtStartLoc()), + /*PrevDecl=*/nullptr)) + return ToProto; ToProto->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProto); } - - Importer.Imported(D, ToProto); + + Importer.MapImported(D, ToProto); if (D->isThisDeclarationADefinition() && ImportDefinition(D, ToProto)) return nullptr; @@ -3496,14 +3576,11 @@ Decl *ASTNodeImporter::VisitLinkageSpecD SourceLocation LangLoc = Importer.Import(D->getLocation()); bool HasBraces = D->hasBraces(); - - LinkageSpecDecl *ToLinkageSpec = - LinkageSpecDecl::Create(Importer.getToContext(), - DC, - ExternLoc, - LangLoc, - D->getLanguage(), - HasBraces); + + LinkageSpecDecl *ToLinkageSpec; + if (GetImportedOrCreateDecl(ToLinkageSpec, D, Importer.getToContext(), DC, + ExternLoc, LangLoc, D->getLanguage(), HasBraces)) + return ToLinkageSpec; if (HasBraces) { SourceLocation RBraceLoc = Importer.Import(D->getRBraceLoc()); @@ -3513,8 +3590,6 @@ Decl *ASTNodeImporter::VisitLinkageSpecD ToLinkageSpec->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToLinkageSpec); - Importer.Imported(D, ToLinkageSpec); - return ToLinkageSpec; } @@ -3532,13 +3607,15 @@ Decl *ASTNodeImporter::VisitUsingDecl(Us 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()); + UsingDecl *ToUsing; + if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, + D->hasTypename())) + return ToUsing; + ToUsing->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsing); - Importer.Imported(D, ToUsing); if (NamedDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingDecl(D)) { @@ -3581,12 +3658,13 @@ Decl *ASTNodeImporter::VisitUsingShadowD if (!ToTarget) return nullptr; - UsingShadowDecl *ToShadow = UsingShadowDecl::Create( - Importer.getToContext(), DC, Loc, ToUsing, ToTarget); + UsingShadowDecl *ToShadow; + if (GetImportedOrCreateDecl(ToShadow, D, Importer.getToContext(), DC, Loc, + ToUsing, ToTarget)) + return ToShadow; ToShadow->setLexicalDeclContext(LexicalDC); ToShadow->setAccess(D->getAccess()); - Importer.Imported(D, ToShadow); if (UsingShadowDecl *FromPattern = Importer.getFromContext().getInstantiatedFromUsingShadowDecl(D)) { @@ -3624,14 +3702,17 @@ Decl *ASTNodeImporter::VisitUsingDirecti 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); + UsingDirectiveDecl *ToUsingDir; + if (GetImportedOrCreateDecl(ToUsingDir, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getNamespaceKeyLocation()), + Importer.Import(D->getQualifierLoc()), + Importer.Import(D->getIdentLocation()), + ToNominated, ToComAncestor)) + return ToUsingDir; + ToUsingDir->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingDir); - Importer.Imported(D, ToUsingDir); return ToUsingDir; } @@ -3650,12 +3731,13 @@ Decl *ASTNodeImporter::VisitUnresolvedUs 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())); + UnresolvedUsingValueDecl *ToUsingValue; + if (GetImportedOrCreateDecl(ToUsingValue, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getQualifierLoc()), NameInfo, + Importer.Import(D->getEllipsisLoc()))) + return ToUsingValue; - Importer.Imported(D, ToUsingValue); ToUsingValue->setAccess(D->getAccess()); ToUsingValue->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsingValue); @@ -3674,13 +3756,14 @@ Decl *ASTNodeImporter::VisitUnresolvedUs 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())); + UnresolvedUsingTypenameDecl *ToUsing; + if (GetImportedOrCreateDecl(ToUsing, D, Importer.getToContext(), DC, + Importer.Import(D->getUsingLoc()), + Importer.Import(D->getTypenameLoc()), + Importer.Import(D->getQualifierLoc()), Loc, Name, + Importer.Import(D->getEllipsisLoc()))) + return ToUsing; - Importer.Imported(D, ToUsing); ToUsing->setAccess(D->getAccess()); ToUsing->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToUsing); @@ -3812,7 +3895,7 @@ Decl *ASTNodeImporter::VisitObjCInterfac if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of an @interface. @@ -3840,16 +3923,16 @@ Decl *ASTNodeImporter::VisitObjCInterfac // 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()); + if (GetImportedOrCreateDecl( + ToIface, D, Importer.getToContext(), DC, + Importer.Import(D->getAtStartLoc()), Name.getAsIdentifierInfo(), + /*TypeParamList=*/nullptr, + /*PrevDecl=*/nullptr, Loc, D->isImplicitInterfaceDecl())) + 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( @@ -3874,13 +3957,13 @@ Decl *ASTNodeImporter::VisitObjCCategory 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); - + if (GetImportedOrCreateDecl( + ToImpl, D, Importer.getToContext(), DC, + Importer.Import(D->getIdentifier()), Category->getClassInterface(), + Importer.Import(D->getLocation()), + Importer.Import(D->getAtStartLoc()), CategoryNameLoc)) + return ToImpl; + DeclContext *LexicalDC = DC; if (D->getDeclContext() != D->getLexicalDeclContext()) { LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); @@ -3894,7 +3977,7 @@ Decl *ASTNodeImporter::VisitObjCCategory Category->setImplementation(ToImpl); } - Importer.Imported(D, ToImpl); + Importer.MapImported(D, ToImpl); ImportDeclContext(D); return ToImpl; } @@ -3919,15 +4002,15 @@ Decl *ASTNodeImporter::VisitObjCImplemen 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())); - + if (GetImportedOrCreateDecl(Impl, 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()))) + return Impl; + if (D->getDeclContext() != D->getLexicalDeclContext()) { DeclContext *LexicalDC = Importer.ImportContext(D->getLexicalDeclContext()); @@ -3935,12 +4018,12 @@ Decl *ASTNodeImporter::VisitObjCImplemen 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()) || @@ -4006,7 +4089,7 @@ Decl *ASTNodeImporter::VisitObjCProperty // FIXME: Check property attributes, getters, setters, etc.? // Consider these properties to be equivalent. - Importer.Imported(D, FoundProp); + Importer.MapImported(D, FoundProp); return FoundProp; } } @@ -4017,15 +4100,14 @@ Decl *ASTNodeImporter::VisitObjCProperty 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); + ObjCPropertyDecl *ToProperty; + if (GetImportedOrCreateDecl( + ToProperty, D, Importer.getToContext(), DC, Loc, + Name.getAsIdentifierInfo(), Importer.Import(D->getAtLoc()), + Importer.Import(D->getLParenLoc()), Importer.Import(D->getType()), + TSI, D->getPropertyImplementation())) + return ToProperty; + ToProperty->setLexicalDeclContext(LexicalDC); LexicalDC->addDeclInternal(ToProperty); @@ -4079,16 +4161,15 @@ Decl *ASTNodeImporter::VisitObjCProperty 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) { + if (GetImportedOrCreateDecl(ToImpl, D, Importer.getToContext(), DC, + Importer.Import(D->getLocStart()), + Importer.Import(D->getLocation()), Property, + D->getPropertyImplementation(), Ivar, + Importer.Import(D->getPropertyIvarDeclLoc()))) + return ToImpl; + ToImpl->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToImpl); LexicalDC->addDeclInternal(ToImpl); } else { // Check that we have the same kind of property implementation (@synthesize @@ -4121,7 +4202,7 @@ Decl *ASTNodeImporter::VisitObjCProperty } // Merge the existing implementation with the new implementation. - Importer.Imported(D, ToImpl); + Importer.MapImported(D, ToImpl); } return ToImpl; @@ -4133,15 +4214,14 @@ Decl *ASTNodeImporter::VisitTemplateType // 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()); + TemplateTypeParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, 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 * @@ -4165,13 +4245,15 @@ ASTNodeImporter::VisitNonTypeTemplatePar 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); + + NonTypeTemplateParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, D, Importer.getToContext(), + Importer.getToContext().getTranslationUnitDecl(), + Importer.Import(D->getInnerLocStart()), Loc, D->getDepth(), + D->getPosition(), Name.getAsIdentifierInfo(), T, D->isParameterPack(), + TInfo); + return ToD; } Decl * @@ -4183,7 +4265,7 @@ ASTNodeImporter::VisitTemplateTemplatePa // Import the location of this declaration. SourceLocation Loc = Importer.Import(D->getLocation()); - + // Import template parameters. TemplateParameterList *TemplateParams = ImportTemplateParameterList(D->getTemplateParameters()); @@ -4191,13 +4273,14 @@ ASTNodeImporter::VisitTemplateTemplatePa return nullptr; // FIXME: Import default argument. - - return TemplateTemplateParmDecl::Create(Importer.getToContext(), - Importer.getToContext().getTranslationUnitDecl(), - Loc, D->getDepth(), D->getPosition(), - D->isParameterPack(), - Name.getAsIdentifierInfo(), - TemplateParams); + + TemplateTemplateParmDecl *ToD = nullptr; + (void)GetImportedOrCreateDecl( + ToD, 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 @@ -4223,7 +4306,7 @@ Decl *ASTNodeImporter::VisitClassTemplat if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of this class template. @@ -4262,9 +4345,9 @@ Decl *ASTNodeImporter::VisitClassTemplat 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); } } @@ -4289,29 +4372,23 @@ Decl *ASTNodeImporter::VisitClassTemplat 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); + ClassTemplateDecl *D2; + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, Loc, Name, + TemplateParams, ToTemplated)) + 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! @@ -4331,7 +4408,7 @@ Decl *ASTNodeImporter::VisitClassTemplat if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } auto *ClassTemplate = @@ -4378,7 +4455,7 @@ Decl *ASTNodeImporter::VisitClassTemplat // 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 { @@ -4402,19 +4479,18 @@ Decl *ASTNodeImporter::VisitClassTemplat 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); + if (GetImportedOrCreateDecl<ClassTemplatePartialSpecializationDecl>( + D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, + IdLoc, ToTPList, ClassTemplate, + llvm::makeArrayRef(TemplateArgs.data(), TemplateArgs.size()), + ToTAInfo, CanonInjType, nullptr)) + return D2; } else { - D2 = ClassTemplateSpecializationDecl::Create(Importer.getToContext(), - D->getTagKind(), DC, - StartLoc, IdLoc, - ClassTemplate, - TemplateArgs, - /*PrevDecl=*/nullptr); + if (GetImportedOrCreateDecl( + D2, D, Importer.getToContext(), D->getTagKind(), DC, StartLoc, + IdLoc, ClassTemplate, TemplateArgs, /*PrevDecl=*/nullptr)) + return D2; } D2->setSpecializationKind(D->getSpecializationKind()); @@ -4425,8 +4501,6 @@ Decl *ASTNodeImporter::VisitClassTemplat // 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) @@ -4452,7 +4526,6 @@ Decl *ASTNodeImporter::VisitClassTemplat LexicalDC->addDeclInternal(D2); } } - Importer.Imported(D, D2); if (D->isCompleteDefinition() && ImportDefinition(D, D2)) return nullptr; @@ -4471,7 +4544,7 @@ Decl *ASTNodeImporter::VisitVarTemplateD if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } // Import the major distinguishing characteristics of this variable template. @@ -4498,9 +4571,9 @@ Decl *ASTNodeImporter::VisitVarTemplateD if (auto *FoundTemplate = dyn_cast<VarTemplateDecl>(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); } } @@ -4534,18 +4607,17 @@ Decl *ASTNodeImporter::VisitVarTemplateD if (!TemplateParams) return nullptr; - VarTemplateDecl *ToVarTD = VarTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, TemplateParams, ToTemplated); + VarTemplateDecl *ToVarTD; + if (GetImportedOrCreateDecl(ToVarTD, D, Importer.getToContext(), DC, Loc, + Name, TemplateParams, ToTemplated)) + 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! @@ -4565,7 +4637,7 @@ Decl *ASTNodeImporter::VisitVarTemplateS if (!ImportedDef) return nullptr; - return Importer.Imported(D, ImportedDef); + return Importer.MapImported(D, ImportedDef); } auto *VarTemplate = cast_or_null<VarTemplateDecl>( @@ -4611,7 +4683,7 @@ Decl *ASTNodeImporter::VisitVarTemplateS // 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 { @@ -4643,9 +4715,12 @@ Decl *ASTNodeImporter::VisitVarTemplateS if (!ToTPList) return nullptr; - auto *ToPartial = PartVarSpecDecl::Create( - Importer.getToContext(), DC, StartLoc, IdLoc, ToTPList, VarTemplate, - T, TInfo, D->getStorageClass(), TemplateArgs, ArgInfos); + PartVarSpecDecl *ToPartial; + if (GetImportedOrCreateDecl(ToPartial, D, Importer.getToContext(), DC, + StartLoc, IdLoc, ToTPList, VarTemplate, T, + TInfo, D->getStorageClass(), TemplateArgs, + ArgInfos)) + return ToPartial; auto *FromInst = FromPartial->getInstantiatedFromMember(); auto *ToInst = cast_or_null<PartVarSpecDecl>(Importer.Import(FromInst)); @@ -4658,9 +4733,10 @@ Decl *ASTNodeImporter::VisitVarTemplateS D2 = ToPartial; } else { // Full specialization - D2 = VarTemplateSpecializationDecl::Create( - Importer.getToContext(), DC, StartLoc, IdLoc, VarTemplate, T, TInfo, - D->getStorageClass(), TemplateArgs); + if (GetImportedOrCreateDecl(D2, D, Importer.getToContext(), DC, StartLoc, + IdLoc, VarTemplate, T, TInfo, + D->getStorageClass(), TemplateArgs)) + return D2; } SourceLocation POI = D->getPointOfInstantiation(); @@ -4686,8 +4762,6 @@ Decl *ASTNodeImporter::VisitVarTemplateS 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 @@ -4725,7 +4799,7 @@ Decl *ASTNodeImporter::VisitFunctionTemp 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; } @@ -4744,13 +4818,14 @@ Decl *ASTNodeImporter::VisitFunctionTemp if (!TemplatedFD) return nullptr; - FunctionTemplateDecl *ToFunc = FunctionTemplateDecl::Create( - Importer.getToContext(), DC, Loc, Name, Params, TemplatedFD); + FunctionTemplateDecl *ToFunc; + if (GetImportedOrCreateDecl(ToFunc, D, Importer.getToContext(), DC, Loc, Name, + Params, TemplatedFD)) + return ToFunc; TemplatedFD->setDescribedFunctionTemplate(ToFunc); ToFunc->setAccess(D->getAccess()); ToFunc->setLexicalDeclContext(LexicalDC); - Importer.Imported(D, ToFunc); LexicalDC->addDeclInternal(ToFunc); return ToFunc; @@ -6835,6 +6910,7 @@ Decl *ASTImporter::GetAlreadyImportedOrN llvm::DenseMap<Decl *, Decl *>::iterator Pos = ImportedDecls.find(FromD); if (Pos != ImportedDecls.end()) { Decl *ToD = Pos->second; + // FIXME: move this call to ImportDeclParts(). ASTNodeImporter(*this).ImportDefinitionIfNeeded(FromD, ToD); return ToD; } else { @@ -6848,22 +6924,22 @@ Decl *ASTImporter::Import(Decl *FromD) { ASTNodeImporter Importer(*this); - // Check whether we've already imported this declaration. - llvm::DenseMap<Decl *, Decl *>::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) { + // If FromD has some updated flags after last import, apply it + updateFlags(FromD, 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; } @@ -7471,17 +7547,12 @@ void ASTImporter::CompleteDecl (Decl *D) } } -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<Decl *, Decl *>::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; } @@ -7494,6 +7565,7 @@ bool ASTImporter::IsStructurallyEquivale return true; StructuralEquivalenceContext Ctx(FromContext, ToContext, NonEquivalentDecls, - false, Complain); + getStructuralEquivalenceKind(*this), false, + Complain); return Ctx.IsStructurallyEquivalent(From, To); } Modified: cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp?rev=336896&r1=336895&r2=336896&view=diff ============================================================================== --- cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp (original) +++ cfe/trunk/lib/AST/ASTStructuralEquivalence.cpp Thu Jul 12 02:42:05 2018 @@ -955,6 +955,15 @@ static bool IsStructurallyEquivalent(Str if (!D1 || !D2) return true; + // If any of the records has external storage and we do a minimal check (or + // AST import) we assmue they are equivalent. (If we didn't have this + // assumption then `RecordDecl::LoadFieldsFromExternalStorage` could trigger + // another AST import which in turn would call the structural equivalency + // check again and finally we'd have an improper result.) + if (Context.EqKind == StructuralEquivalenceKind::Minimal) + if (D1->hasExternalLexicalStorage() || D2->hasExternalLexicalStorage()) + return true; + if (auto *D1CXX = dyn_cast<CXXRecordDecl>(D1)) { if (auto *D2CXX = dyn_cast<CXXRecordDecl>(D2)) { if (D1CXX->hasExternalLexicalStorage() && Modified: cfe/trunk/lib/AST/ExternalASTMerger.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/AST/ExternalASTMerger.cpp?rev=336896&r1=336895&r2=336896&view=diff ============================================================================== --- cfe/trunk/lib/AST/ExternalASTMerger.cpp (original) +++ cfe/trunk/lib/AST/ExternalASTMerger.cpp Thu Jul 12 02:42:05 2018 @@ -154,7 +154,7 @@ public: ToContainer->setMustBuildLookupTable(); assert(Parent.CanComplete(ToContainer)); } - return ASTImporter::Imported(From, To); + return To; } ASTImporter &GetReverse() { return Reverse; } }; @@ -229,7 +229,7 @@ void ExternalASTMerger::CompleteType(Tag 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 @@ void ExternalASTMerger::CompleteType(Obj 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::ForceRecordOrigi void ExternalASTMerger::RecordOriginImpl(const DeclContext *ToDC, DCOrigin Origin, ASTImporter &Importer) { Origins[ToDC] = Origin; - Importer.ASTImporter::Imported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC))); + Importer.ASTImporter::MapImported(cast<Decl>(Origin.DC), const_cast<Decl*>(cast<Decl>(ToDC))); } ExternalASTMerger::ExternalASTMerger(const ImporterTarget &Target, Modified: cfe/trunk/lib/Sema/SemaType.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Sema/SemaType.cpp?rev=336896&r1=336895&r2=336896&view=diff ============================================================================== --- cfe/trunk/lib/Sema/SemaType.cpp (original) +++ cfe/trunk/lib/Sema/SemaType.cpp Thu Jul 12 02:42:05 2018 @@ -7537,6 +7537,7 @@ bool Sema::hasStructuralCompatLayout(Dec // and isolate from other C++ specific checks. StructuralEquivalenceContext Ctx( D->getASTContext(), Suggested->getASTContext(), NonEquivalentDecls, + StructuralEquivalenceKind::Default, false /*StrictTypeSpelling*/, true /*Complain*/, true /*ErrorOnTagTypeMismatch*/); return Ctx.IsStructurallyEquivalent(D, Suggested); Modified: cfe/trunk/unittests/AST/ASTImporterTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/ASTImporterTest.cpp?rev=336896&r1=336895&r2=336896&view=diff ============================================================================== --- cfe/trunk/unittests/AST/ASTImporterTest.cpp (original) +++ cfe/trunk/unittests/AST/ASTImporterTest.cpp Thu Jul 12 02:42:05 2018 @@ -284,12 +284,15 @@ class ASTImporterTestBase : public Param // Buffer for the To context, must live in the test scope. std::string ToCode; + // Represents a "From" translation unit and holds an importer object which we + // use to import from this translation unit. struct TU { // Buffer for the context, must live in the test scope. std::string Code; std::string FileName; std::unique_ptr<ASTUnit> Unit; TranslationUnitDecl *TUDecl = nullptr; + std::unique_ptr<ASTImporter> Importer; TU(StringRef Code, StringRef FileName, ArgVector Args) : Code(Code), FileName(FileName), Unit(tooling::buildASTFromCodeWithArgs(this->Code, Args, @@ -297,6 +300,16 @@ class ASTImporterTestBase : public Param TUDecl(Unit->getASTContext().getTranslationUnitDecl()) { Unit->enableSourceFileDiagnostics(); } + + Decl *import(ASTUnit *ToAST, Decl *FromDecl) { + assert(ToAST); + if (!Importer) { + Importer.reset(new ASTImporter( + ToAST->getASTContext(), ToAST->getFileManager(), + Unit->getASTContext(), Unit->getFileManager(), false)); + } + return Importer->Import(FromDecl); + } }; // We may have several From contexts and related translation units. In each @@ -329,14 +342,10 @@ public: ToAST = tooling::buildASTFromCodeWithArgs(ToCode, ToArgs, OutputFileName); ToAST->enableSourceFileDiagnostics(); - ASTContext &FromCtx = FromTU.Unit->getASTContext(), - &ToCtx = ToAST->getASTContext(); + ASTContext &FromCtx = FromTU.Unit->getASTContext(); createVirtualFileIfNeeded(ToAST.get(), InputFileName, FromTU.Code); - ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx, - FromTU.Unit->getFileManager(), false); - IdentifierInfo *ImportedII = &FromCtx.Idents.get(Identifier); assert(ImportedII && "Declaration with the given identifier " "should be specified in test!"); @@ -347,7 +356,8 @@ public: assert(FoundDecls.size() == 1); - Decl *Imported = Importer.Import(FoundDecls.front()); + Decl *Imported = FromTU.import(ToAST.get(), FoundDecls.front()); + assert(Imported); return std::make_tuple(*FoundDecls.begin(), Imported); } @@ -401,11 +411,7 @@ public: assert(It != FromTUs.end()); createVirtualFileIfNeeded(ToAST.get(), It->FileName, It->Code); - ASTContext &FromCtx = From->getASTContext(), - &ToCtx = ToAST->getASTContext(); - ASTImporter Importer(ToCtx, ToAST->getFileManager(), FromCtx, - FromCtx.getSourceManager().getFileManager(), false); - return Importer.Import(From); + return It->import(ToAST.get(), From); } ~ASTImporterTestBase() { @@ -1089,8 +1095,7 @@ TEST_P(ASTImporterTestBase, ImportOfTemp EXPECT_EQ(ToTemplated1, ToTemplated); } -TEST_P(ASTImporterTestBase, - DISABLED_ImportOfTemplatedDeclOfFunctionTemplateDecl) { +TEST_P(ASTImporterTestBase, ImportOfTemplatedDeclOfFunctionTemplateDecl) { Decl *FromTU = getTuDecl("template<class X> void f(){}", Lang_CXX); auto From = FirstDeclMatcher<FunctionTemplateDecl>().match( FromTU, functionTemplateDecl()); @@ -1166,7 +1171,7 @@ TEST_P(ASTImporterTestBase, ImportCorrec ASSERT_EQ(ToTemplated1, ToTemplated); } -TEST_P(ASTImporterTestBase, DISABLED_ImportFunctionWithBackReferringParameter) { +TEST_P(ASTImporterTestBase, ImportFunctionWithBackReferringParameter) { Decl *From, *To; std::tie(From, To) = getImportedDecl( R"( @@ -1711,6 +1716,49 @@ TEST_P(ASTImporterTestBase, ObjectsWithU EXPECT_NE(To0->getCanonicalDecl(), To1->getCanonicalDecl()); } +TEST_P(ASTImporterTestBase, ImportDoesUpdateUsedFlag) { + auto Pattern = varDecl(hasName("x")); + VarDecl *Imported1; + { + Decl *FromTU = getTuDecl("extern int x;", Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); + Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX)); + } + VarDecl *Imported2; + { + Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input1.cc"); + auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); + Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX)); + } + EXPECT_EQ(Imported1->getCanonicalDecl(), Imported2->getCanonicalDecl()); + EXPECT_FALSE(Imported2->isUsed(false)); + { + Decl *FromTU = + getTuDecl("extern int x; int f() { return x; }", Lang_CXX, "input2.cc"); + auto *FromD = + FirstDeclMatcher<FunctionDecl>().match(FromTU, functionDecl()); + Import(FromD, Lang_CXX); + } + EXPECT_TRUE(Imported2->isUsed(false)); +} + +TEST_P(ASTImporterTestBase, ReimportWithUsedFlag) { + auto Pattern = varDecl(hasName("x")); + + Decl *FromTU = getTuDecl("int x;", Lang_CXX, "input0.cc"); + auto *FromD = FirstDeclMatcher<VarDecl>().match(FromTU, Pattern); + + auto *Imported1 = cast<VarDecl>(Import(FromD, Lang_CXX)); + + ASSERT_FALSE(Imported1->isUsed(false)); + + FromD->setIsUsed(); + auto *Imported2 = cast<VarDecl>(Import(FromD, Lang_CXX)); + + EXPECT_EQ(Imported1, Imported2); + EXPECT_TRUE(Imported2->isUsed(false)); +} + struct ImportFunctions : ASTImporterTestBase {}; TEST_P(ImportFunctions, @@ -2043,14 +2091,10 @@ TEST_P(ImportFriendFunctions, EXPECT_EQ(ToFD->getPreviousDecl(), ImportedD); } -// This test is disabled, because ATM we create a redundant FunctionDecl. We -// start the import with the definition of `f` then we continue with the import -// of the type of `f` which involves `X`. During the import of `X` we start -// again the import of the definition of `f` and then finally we create the -// node. But then in the first frame of `VisitFunctionDecl` we create a node -// again since we do not check if such a node exists yet or not. This is being -// fixed in a separate patch: https://reviews.llvm.org/D47632 -// FIXME enable this test once the above patch is approved. +// Disabled temporarily, because the new structural equivalence check +// (https://reviews.llvm.org/D48628) breaks it. +// PreviousDecl is not set because there is no structural match. +// FIXME Enable! TEST_P(ImportFriendFunctions, DISABLED_ImportFriendFunctionRedeclChainDefWithClass) { auto Pattern = functionDecl(hasName("f")); @@ -2080,16 +2124,12 @@ TEST_P(ImportFriendFunctions, (*ImportedD->param_begin())->getOriginalType()); } -// This test is disabled, because ATM we create a redundant FunctionDecl. We -// start the import with the definition of `f` then we continue with the import -// of the type of `f` which involves `X`. During the import of `X` we start -// again the import of the definition of `f` and then finally we create the -// node. But then in the first frame of `VisitFunctionDecl` we create a node -// again since we do not check if such a node exists yet or not. This is being -// fixed in a separate patch: https://reviews.llvm.org/D47632 -// FIXME enable this test once the above patch is approved. +// Disabled temporarily, because the new structural equivalence check +// (https://reviews.llvm.org/D48628) breaks it. +// PreviousDecl is not set because there is no structural match. +// FIXME Enable! TEST_P(ImportFriendFunctions, - DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) { + DISABLED_ImportFriendFunctionRedeclChainDefWithClass_ImportTheProto) { auto Pattern = functionDecl(hasName("f")); Decl *FromTU = getTuDecl( Modified: cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp?rev=336896&r1=336895&r2=336896&view=diff ============================================================================== --- cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp (original) +++ cfe/trunk/unittests/AST/StructuralEquivalenceTest.cpp Thu Jul 12 02:42:05 2018 @@ -64,8 +64,9 @@ struct StructuralEquivalenceTest : ::tes bool testStructuralMatch(NamedDecl *D0, NamedDecl *D1) { llvm::DenseSet<std::pair<Decl *, Decl *>> NonEquivalentDecls; - StructuralEquivalenceContext Ctx(D0->getASTContext(), D1->getASTContext(), - NonEquivalentDecls, false, false); + StructuralEquivalenceContext Ctx( + D0->getASTContext(), D1->getASTContext(), NonEquivalentDecls, + StructuralEquivalenceKind::Default, false, false); return Ctx.IsStructurallyEquivalent(D0, D1); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits