diff options
Diffstat (limited to 'clang/lib/Serialization/ASTWriterDecl.cpp')
| -rw-r--r-- | clang/lib/Serialization/ASTWriterDecl.cpp | 129 |
1 files changed, 94 insertions, 35 deletions
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp index ad357e30d575..75c1d9a6d438 100644 --- a/clang/lib/Serialization/ASTWriterDecl.cpp +++ b/clang/lib/Serialization/ASTWriterDecl.cpp @@ -177,11 +177,12 @@ namespace clang { Record.AddSourceLocation(typeParams->getRAngleLoc()); } - /// Add to the record the first declaration from each module file that - /// provides a declaration of D. The intent is to provide a sufficient - /// set such that reloading this set will load all current redeclarations. - void AddFirstDeclFromEachModule(const Decl *D, bool IncludeLocal) { - llvm::MapVector<ModuleFile*, const Decl*> Firsts; + /// Collect the first declaration from each module file that provides a + /// declaration of D. + void CollectFirstDeclFromEachModule( + const Decl *D, bool IncludeLocal, + llvm::MapVector<ModuleFile *, const Decl *> &Firsts) { + // FIXME: We can skip entries that we know are implied by others. for (const Decl *R = D->getMostRecentDecl(); R; R = R->getPreviousDecl()) { if (R->isFromASTFile()) @@ -189,10 +190,41 @@ namespace clang { else if (IncludeLocal) Firsts[nullptr] = R; } + } + + /// Add to the record the first declaration from each module file that + /// provides a declaration of D. The intent is to provide a sufficient + /// set such that reloading this set will load all current redeclarations. + void AddFirstDeclFromEachModule(const Decl *D, bool IncludeLocal) { + llvm::MapVector<ModuleFile *, const Decl *> Firsts; + CollectFirstDeclFromEachModule(D, IncludeLocal, Firsts); + for (const auto &F : Firsts) Record.AddDeclRef(F.second); } + /// Add to the record the first template specialization from each module + /// file that provides a declaration of D. We store the DeclId and an + /// ODRHash of the template arguments of D which should provide enough + /// information to load D only if the template instantiator needs it. + void AddFirstSpecializationDeclFromEachModule( + const Decl *D, llvm::SmallVectorImpl<const Decl *> &SpecsInMap, + llvm::SmallVectorImpl<const Decl *> &PartialSpecsInMap) { + assert((isa<ClassTemplateSpecializationDecl>(D) || + isa<VarTemplateSpecializationDecl>(D) || isa<FunctionDecl>(D)) && + "Must not be called with other decls"); + llvm::MapVector<ModuleFile *, const Decl *> Firsts; + CollectFirstDeclFromEachModule(D, /*IncludeLocal*/ true, Firsts); + + for (const auto &F : Firsts) { + if (isa<ClassTemplatePartialSpecializationDecl, + VarTemplatePartialSpecializationDecl>(F.second)) + PartialSpecsInMap.push_back(F.second); + else + SpecsInMap.push_back(F.second); + } + } + /// Get the specialization decl from an entry in the specialization list. template <typename EntryType> typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType * @@ -205,8 +237,9 @@ namespace clang { decltype(T::PartialSpecializations) &getPartialSpecializations(T *Common) { return Common->PartialSpecializations; } - ArrayRef<Decl> getPartialSpecializations(FunctionTemplateDecl::Common *) { - return {}; + MutableArrayRef<FunctionTemplateSpecializationInfo> + getPartialSpecializations(FunctionTemplateDecl::Common *) { + return std::nullopt; } template<typename DeclTy> @@ -217,37 +250,37 @@ namespace clang { // our chained AST reader, we can just write out the DeclIDs. Otherwise, // we need to resolve them to actual declarations. if (Writer.Chain != Record.getASTContext().getExternalSource() && - Common->LazySpecializations) { + Writer.Chain && Writer.Chain->haveUnloadedSpecializations(D)) { D->LoadLazySpecializations(); - assert(!Common->LazySpecializations); + assert(!Writer.Chain->haveUnloadedSpecializations(D)); } - ArrayRef<GlobalDeclID> LazySpecializations; - if (auto *LS = Common->LazySpecializations) - LazySpecializations = llvm::ArrayRef(LS + 1, LS[0].getRawValue()); - - // Add a slot to the record for the number of specializations. - unsigned I = Record.size(); - Record.push_back(0); - - // AddFirstDeclFromEachModule might trigger deserialization, invalidating - // *Specializations iterators. - llvm::SmallVector<const Decl*, 16> Specs; + // AddFirstSpecializationDeclFromEachModule might trigger deserialization, + // invalidating *Specializations iterators. + llvm::SmallVector<const Decl *, 16> AllSpecs; for (auto &Entry : Common->Specializations) - Specs.push_back(getSpecializationDecl(Entry)); + AllSpecs.push_back(getSpecializationDecl(Entry)); for (auto &Entry : getPartialSpecializations(Common)) - Specs.push_back(getSpecializationDecl(Entry)); + AllSpecs.push_back(getSpecializationDecl(Entry)); - for (auto *D : Specs) { + llvm::SmallVector<const Decl *, 16> Specs; + llvm::SmallVector<const Decl *, 16> PartialSpecs; + for (auto *D : AllSpecs) { assert(D->isCanonicalDecl() && "non-canonical decl in set"); - AddFirstDeclFromEachModule(D, /*IncludeLocal*/true); + AddFirstSpecializationDeclFromEachModule(D, Specs, PartialSpecs); + } + + Record.AddOffset(Writer.WriteSpecializationInfoLookupTable( + D, Specs, /*IsPartial=*/false)); + + // Function Template Decl doesn't have partial decls. + if (isa<FunctionTemplateDecl>(D)) { + assert(PartialSpecs.empty()); + return; } - Record.append( - DeclIDIterator<GlobalDeclID, DeclID>(LazySpecializations.begin()), - DeclIDIterator<GlobalDeclID, DeclID>(LazySpecializations.end())); - // Update the size entry we added earlier. - Record[I] = Record.size() - I - 1; + Record.AddOffset(Writer.WriteSpecializationInfoLookupTable( + D, PartialSpecs, /*IsPartial=*/true)); } /// Ensure that this template specialization is associated with the specified @@ -268,8 +301,13 @@ namespace clang { if (Writer.getFirstLocalDecl(Specialization) != Specialization) return; - Writer.DeclUpdates[Template].push_back(ASTWriter::DeclUpdate( - UPD_CXX_ADDED_TEMPLATE_SPECIALIZATION, Specialization)); + if (isa<ClassTemplatePartialSpecializationDecl, + VarTemplatePartialSpecializationDecl>(Specialization)) + Writer.PartialSpecializationsUpdates[cast<NamedDecl>(Template)] + .push_back(cast<NamedDecl>(Specialization)); + else + Writer.SpecializationsUpdates[cast<NamedDecl>(Template)].push_back( + cast<NamedDecl>(Specialization)); } }; } @@ -760,6 +798,17 @@ void ASTDeclWriter::VisitFunctionDecl(FunctionDecl *D) { } } + if (D->getFriendObjectKind()) { + // For a function defined inline within a class template, we have to force + // the canonical definition to be the one inside the canonical definition of + // the template. Remember this relation to deserialize them together. + if (auto *RD = dyn_cast<CXXRecordDecl>(D->getLexicalParent())) + if (RD->isDependentContext() && RD->isThisDeclarationADefinition()) { + Writer.RelatedDeclsMap[Writer.GetDeclRef(RD)].push_back( + Writer.GetDeclRef(D)); + } + } + Record.push_back(D->param_size()); for (auto *P : D->parameters()) Record.AddDeclRef(P); @@ -1525,7 +1574,7 @@ void ASTDeclWriter::VisitCXXRecordDecl(CXXRecordDecl *D) { // For lambdas inside canonical FunctionDecl remember the mapping. if (auto FD = llvm::dyn_cast_or_null<FunctionDecl>(D->getDeclContext()); FD && FD->isCanonicalDecl()) { - Writer.FunctionToLambdasMap[Writer.GetDeclRef(FD)].push_back( + Writer.RelatedDeclsMap[Writer.GetDeclRef(FD)].push_back( Writer.GetDeclRef(D)); } } else { @@ -1656,7 +1705,7 @@ void ASTDeclWriter::VisitFriendDecl(FriendDecl *D) { // so as to simplify memory allocation during deserialization. Record.push_back(D->NumTPLists); VisitDecl(D); - bool hasFriendDecl = D->Friend.is<NamedDecl*>(); + bool hasFriendDecl = isa<NamedDecl *>(D->Friend); Record.push_back(hasFriendDecl); if (hasFriendDecl) Record.AddDeclRef(D->getFriendDecl()); @@ -1757,7 +1806,7 @@ void ASTDeclWriter::VisitClassTemplateSpecializationDecl( if (Decl *InstFromD = InstFrom.dyn_cast<ClassTemplateDecl *>()) { Record.AddDeclRef(InstFromD); } else { - Record.AddDeclRef(InstFrom.get<ClassTemplatePartialSpecializationDecl *>()); + Record.AddDeclRef(cast<ClassTemplatePartialSpecializationDecl *>(InstFrom)); Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); } @@ -1835,7 +1884,7 @@ void ASTDeclWriter::VisitVarTemplateSpecializationDecl( if (Decl *InstFromD = InstFrom.dyn_cast<VarTemplateDecl *>()) { Record.AddDeclRef(InstFromD); } else { - Record.AddDeclRef(InstFrom.get<VarTemplatePartialSpecializationDecl *>()); + Record.AddDeclRef(cast<VarTemplatePartialSpecializationDecl *>(InstFrom)); Record.AddTemplateArgumentList(&D->getTemplateInstantiationArgs()); } @@ -2774,6 +2823,16 @@ void ASTWriter::WriteDeclAbbrevs() { Abv->Add(BitCodeAbbrevOp(serialization::DECL_CONTEXT_VISIBLE)); Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); DeclContextVisibleLookupAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(serialization::DECL_SPECIALIZATIONS)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + DeclSpecializationsAbbrev = Stream.EmitAbbrev(std::move(Abv)); + + Abv = std::make_shared<BitCodeAbbrev>(); + Abv->Add(BitCodeAbbrevOp(serialization::DECL_PARTIAL_SPECIALIZATIONS)); + Abv->Add(BitCodeAbbrevOp(BitCodeAbbrevOp::Blob)); + DeclPartialSpecializationsAbbrev = Stream.EmitAbbrev(std::move(Abv)); } /// isRequiredDecl - Check if this is a "required" Decl, which must be seen by |
