aboutsummaryrefslogtreecommitdiff
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.cpp74
1 files changed, 62 insertions, 12 deletions
diff --git a/clang/lib/Serialization/ASTWriterDecl.cpp b/clang/lib/Serialization/ASTWriterDecl.cpp
index f224075..2cbf8e7 100644
--- a/clang/lib/Serialization/ASTWriterDecl.cpp
+++ b/clang/lib/Serialization/ASTWriterDecl.cpp
@@ -175,11 +175,11 @@ 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())
@@ -187,10 +187,49 @@ 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,
+ bool IncludeLocal) {
+ 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, Firsts);
+
+ for (const auto &F : Firsts) {
+ Record.AddDeclRef(F.second);
+ ArrayRef<TemplateArgument> Args;
+ if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
+ Args = CTSD->getTemplateArgs().asArray();
+ else if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D))
+ Args = VTSD->getTemplateArgs().asArray();
+ else if (auto *FD = dyn_cast<FunctionDecl>(D))
+ Args = FD->getTemplateSpecializationArgs()->asArray();
+ assert(Args.size());
+ Record.push_back(TemplateArgumentList::ComputeODRHash(Args));
+ bool IsPartialSpecialization
+ = isa<ClassTemplatePartialSpecializationDecl>(D) ||
+ isa<VarTemplatePartialSpecializationDecl>(D);
+ Record.push_back(IsPartialSpecialization);
+ }
+ }
+
/// Get the specialization decl from an entry in the specialization list.
template <typename EntryType>
typename RedeclarableTemplateDecl::SpecEntryTraits<EntryType>::DeclType *
@@ -203,7 +242,8 @@ namespace clang {
decltype(T::PartialSpecializations) &getPartialSpecializations(T *Common) {
return Common->PartialSpecializations;
}
- ArrayRef<Decl> getPartialSpecializations(FunctionTemplateDecl::Common *) {
+ MutableArrayRef<FunctionTemplateSpecializationInfo>
+ getPartialSpecializations(FunctionTemplateDecl::Common *) {
return std::nullopt;
}
@@ -220,9 +260,11 @@ namespace clang {
assert(!Common->LazySpecializations);
}
- ArrayRef<DeclID> LazySpecializations;
+ using LazySpecializationInfo
+ = RedeclarableTemplateDecl::LazySpecializationInfo;
+ ArrayRef<LazySpecializationInfo> LazySpecializations;
if (auto *LS = Common->LazySpecializations)
- LazySpecializations = llvm::ArrayRef(LS + 1, LS[0]);
+ LazySpecializations = llvm::ArrayRef(LS + 1, LS[0].DeclID);
// Add a slot to the record for the number of specializations.
unsigned I = Record.size();
@@ -238,12 +280,20 @@ namespace clang {
for (auto *D : Specs) {
assert(D->isCanonicalDecl() && "non-canonical decl in set");
- AddFirstDeclFromEachModule(D, /*IncludeLocal*/true);
+ AddFirstSpecializationDeclFromEachModule(D, /*IncludeLocal*/true);
+ }
+ for (auto &SpecInfo : LazySpecializations) {
+ Record.push_back(SpecInfo.DeclID);
+ Record.push_back(SpecInfo.ODRHash);
+ Record.push_back(SpecInfo.IsPartial);
}
- Record.append(LazySpecializations.begin(), LazySpecializations.end());
- // Update the size entry we added earlier.
- Record[I] = Record.size() - I - 1;
+ // Update the size entry we added earlier. We linerized the
+ // LazySpecializationInfo members and we need to adjust the size as we
+ // will read them always together.
+ assert ((Record.size() - I - 1) % 3 == 0
+ && "Must be divisible by LazySpecializationInfo count!");
+ Record[I] = (Record.size() - I - 1) / 3;
}
/// Ensure that this template specialization is associated with the specified