Make AST deserialization for class template specializations lazier, by
not loading the specializations of a class template until some AST
consumer needs them.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@117498 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/DeclTemplate.cpp b/lib/AST/DeclTemplate.cpp
index d96b830..36b92fa 100644
--- a/lib/AST/DeclTemplate.cpp
+++ b/lib/AST/DeclTemplate.cpp
@@ -189,6 +189,29 @@
return New;
}
+void ClassTemplateDecl::LoadLazySpecializations() {
+ Common *CommonPtr = getCommonPtr();
+ if (CommonPtr->LazySpecializations) {
+ ASTContext &Context = getASTContext();
+ uint32_t *Specs = CommonPtr->LazySpecializations;
+ CommonPtr->LazySpecializations = 0;
+ for (uint32_t I = 0, N = *Specs++; I != N; ++I)
+ (void)Context.getExternalSource()->GetExternalDecl(Specs[I]);
+ }
+}
+
+llvm::FoldingSet<ClassTemplateSpecializationDecl> &
+ClassTemplateDecl::getSpecializations() {
+ LoadLazySpecializations();
+ return getCommonPtr()->Specializations;
+}
+
+llvm::FoldingSet<ClassTemplatePartialSpecializationDecl> &
+ClassTemplateDecl::getPartialSpecializations() {
+ LoadLazySpecializations();
+ return getCommonPtr()->PartialSpecializations;
+}
+
RedeclarableTemplateDecl::CommonBase *
ClassTemplateDecl::newCommon(ASTContext &C) {
Common *CommonPtr = new (C) Common;
diff --git a/lib/Serialization/ASTReaderDecl.cpp b/lib/Serialization/ASTReaderDecl.cpp
index 322a671..b815878 100644
--- a/lib/Serialization/ASTReaderDecl.cpp
+++ b/lib/Serialization/ASTReaderDecl.cpp
@@ -1017,18 +1017,33 @@
VisitRedeclarableTemplateDecl(D);
if (D->getPreviousDeclaration() == 0) {
- // This ClassTemplateDecl owns a CommonPtr; read it.
+ // This ClassTemplateDecl owns a CommonPtr; read it to keep track of all of
+ // the specializations.
+ llvm::SmallVector<serialization::DeclID, 2> SpecIDs;
+ SpecIDs.push_back(0);
+
+ // Specializations.
+ unsigned Size = Record[Idx++];
+ SpecIDs[0] += Size;
+ SpecIDs.append(Record.begin() + Idx, Record.begin() + Idx + Size);
+ Idx += Size;
- // FoldingSets are filled in VisitClassTemplateSpecializationDecl.
- unsigned size = Record[Idx++];
- while (size--)
- cast<ClassTemplateSpecializationDecl>(Reader.GetDecl(Record[Idx++]));
+ // Partial specializations.
+ Size = Record[Idx++];
+ SpecIDs[0] += Size;
+ SpecIDs.append(Record.begin() + Idx, Record.begin() + Idx + Size);
+ Idx += Size;
- size = Record[Idx++];
- while (size--)
- cast<ClassTemplatePartialSpecializationDecl>(
- Reader.GetDecl(Record[Idx++]));
-
+ if (SpecIDs[0]) {
+ typedef serialization::DeclID DeclID;
+
+ ClassTemplateDecl::Common *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations
+ = new (*Reader.getContext()) DeclID [SpecIDs.size()];
+ memcpy(CommonPtr->LazySpecializations, SpecIDs.data(),
+ SpecIDs.size() * sizeof(DeclID));
+ }
+
// InjectedClassNameType is computed.
}
}
@@ -1071,15 +1086,15 @@
D->TemplateArgs.init(C, TemplArgs.data(), TemplArgs.size());
D->PointOfInstantiation = ReadSourceLocation(Record, Idx);
D->SpecializationKind = (TemplateSpecializationKind)Record[Idx++];
-
+
if (D->isCanonicalDecl()) { // It's kept in the folding set.
ClassTemplateDecl *CanonPattern
= cast<ClassTemplateDecl>(Reader.GetDecl(Record[Idx++]));
if (ClassTemplatePartialSpecializationDecl *Partial
- = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
- CanonPattern->getPartialSpecializations().InsertNode(Partial);
+ = dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
+ CanonPattern->getCommonPtr()->PartialSpecializations.InsertNode(Partial);
} else {
- CanonPattern->getSpecializations().InsertNode(D);
+ CanonPattern->getCommonPtr()->Specializations.InsertNode(D);
}
}
}