summaryrefslogtreecommitdiff
path: root/clang/lib/Serialization/ASTWriterDecl.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Serialization/ASTWriterDecl.cpp')
-rw-r--r--clang/lib/Serialization/ASTWriterDecl.cpp129
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