summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Smith <richard-llvm@metafoo.co.uk>2013-06-28 04:37:53 +0000
committerRichard Smith <richard-llvm@metafoo.co.uk>2013-06-28 04:37:53 +0000
commitfeb3e1a1e375edd83d3f55d8bb54350ea8c9f987 (patch)
treefcae0a0a13e3f64a639c653ba7a79c748c552920
parentc3ccdbe2bf049229a932e7530fb14fd20bc0aa34 (diff)
downloadbcm5719-llvm-feb3e1a1e375edd83d3f55d8bb54350ea8c9f987.tar.gz
bcm5719-llvm-feb3e1a1e375edd83d3f55d8bb54350ea8c9f987.zip
Lazily deserialize function template specializations. This fixes a cycle in
module deserialization / merging, and more laziness here is general goodness. llvm-svn: 185132
-rw-r--r--clang/include/clang/AST/DeclTemplate.h18
-rw-r--r--clang/lib/AST/DeclTemplate.cpp17
-rw-r--r--clang/lib/Serialization/ASTReaderDecl.cpp30
-rw-r--r--clang/test/PCH/cxx-templates.cpp5
4 files changed, 55 insertions, 15 deletions
diff --git a/clang/include/clang/AST/DeclTemplate.h b/clang/include/clang/AST/DeclTemplate.h
index 89c0f05a8f6..14ed8a1e621 100644
--- a/clang/include/clang/AST/DeclTemplate.h
+++ b/clang/include/clang/AST/DeclTemplate.h
@@ -743,7 +743,7 @@ protected:
/// \brief Data that is common to all of the declarations of a given
/// function template.
struct Common : CommonBase {
- Common() : InjectedArgs(0) { }
+ Common() : InjectedArgs(), LazySpecializations() { }
/// \brief The function template specializations for this function
/// template, including explicit specializations and instantiations.
@@ -757,6 +757,13 @@ protected:
/// template, and is allocated lazily, since most function templates do not
/// require the use of this information.
TemplateArgument *InjectedArgs;
+
+ /// \brief If non-null, points to an array of specializations known only
+ /// by their external declaration IDs.
+ ///
+ /// The first value in the array is the number of of specializations
+ /// that follow.
+ uint32_t *LazySpecializations;
};
FunctionTemplateDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
@@ -771,12 +778,13 @@ protected:
friend class FunctionDecl;
+ /// \brief Load any lazily-loaded specializations from the external source.
+ void LoadLazySpecializations() const;
+
/// \brief Retrieve the set of function template specializations of this
/// function template.
llvm::FoldingSetVector<FunctionTemplateSpecializationInfo> &
- getSpecializations() const {
- return getCommonPtr()->Specializations;
- }
+ getSpecializations() const;
/// \brief Add a specialization of this function template.
///
@@ -1822,7 +1830,7 @@ protected:
QualType InjectedClassNameType;
/// \brief If non-null, points to an array of specializations (including
- /// partial specializations) known ownly by their external declaration IDs.
+ /// partial specializations) known only by their external declaration IDs.
///
/// The first value in the array is the number of of specializations/
/// partial specializations that follow.
diff --git a/clang/lib/AST/DeclTemplate.cpp b/clang/lib/AST/DeclTemplate.cpp
index d764d2bedb1..ac0d54f5011 100644
--- a/clang/lib/AST/DeclTemplate.cpp
+++ b/clang/lib/AST/DeclTemplate.cpp
@@ -245,6 +245,23 @@ FunctionTemplateDecl::newCommon(ASTContext &C) const {
return CommonPtr;
}
+void FunctionTemplateDecl::LoadLazySpecializations() const {
+ 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::FoldingSetVector<FunctionTemplateSpecializationInfo> &
+FunctionTemplateDecl::getSpecializations() const {
+ LoadLazySpecializations();
+ return getCommonPtr()->Specializations;
+}
+
FunctionDecl *
FunctionTemplateDecl::findSpecialization(const TemplateArgument *Args,
unsigned NumArgs, void *&InsertPos) {
diff --git a/clang/lib/Serialization/ASTReaderDecl.cpp b/clang/lib/Serialization/ASTReaderDecl.cpp
index e93eae81127..84a8b09e4e5 100644
--- a/clang/lib/Serialization/ASTReaderDecl.cpp
+++ b/clang/lib/Serialization/ASTReaderDecl.cpp
@@ -606,11 +606,16 @@ void ASTDeclReader::VisitFunctionDecl(FunctionDecl *FD) {
FunctionTemplateSpecializationInfo::Profile(ID, TemplArgs.data(),
TemplArgs.size(), C);
void *InsertPos = 0;
- CanonTemplate->getSpecializations().FindNodeOrInsertPos(ID, InsertPos);
+ FunctionTemplateDecl::Common *CommonPtr = CanonTemplate->getCommonPtr();
+ CommonPtr->Specializations.FindNodeOrInsertPos(ID, InsertPos);
if (InsertPos)
- CanonTemplate->getSpecializations().InsertNode(FTInfo, InsertPos);
- else
- assert(0 && "Another specialization already inserted!");
+ CommonPtr->Specializations.InsertNode(FTInfo, InsertPos);
+ else {
+ assert(Reader.getContext().getLangOpts().Modules &&
+ "already deserialized this template specialization");
+ // FIXME: This specialization is a redeclaration of one from another
+ // module. Merge it.
+ }
}
break;
}
@@ -1508,12 +1513,17 @@ void ASTDeclReader::VisitFunctionTemplateDecl(FunctionTemplateDecl *D) {
if (ThisDeclID == Redecl.getFirstID()) {
// This FunctionTemplateDecl owns a CommonPtr; read it.
- // Read the function specialization declarations.
- // FunctionTemplateDecl's FunctionTemplateSpecializationInfos are filled
- // when reading the specialized FunctionDecl.
- unsigned NumSpecs = Record[Idx++];
- while (NumSpecs--)
- (void)ReadDecl(Record, Idx);
+ // Read the function specialization declaration IDs. The specializations
+ // themselves will be loaded if they're needed.
+ if (unsigned NumSpecs = Record[Idx++]) {
+ // FIXME: Append specializations!
+ FunctionTemplateDecl::Common *CommonPtr = D->getCommonPtr();
+ CommonPtr->LazySpecializations = new (Reader.getContext())
+ serialization::DeclID[NumSpecs + 1];
+ CommonPtr->LazySpecializations[0] = NumSpecs;
+ for (unsigned I = 0; I != NumSpecs; ++I)
+ CommonPtr->LazySpecializations[I + 1] = ReadDeclID(Record, Idx);
+ }
}
}
diff --git a/clang/test/PCH/cxx-templates.cpp b/clang/test/PCH/cxx-templates.cpp
index 6da5a75cddd..433f73f12a2 100644
--- a/clang/test/PCH/cxx-templates.cpp
+++ b/clang/test/PCH/cxx-templates.cpp
@@ -7,6 +7,11 @@
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t -verify %s -ast-dump -o -
// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize | FileCheck %s
+// Test with modules.
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -fmodules -x c++-header -emit-pch -o %t %S/cxx-templates.h
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -fmodules -include-pch %t -verify %s -ast-dump -o -
+// RUN: %clang_cc1 -std=c++11 -fcxx-exceptions -fexceptions -fmodules -include-pch %t %s -emit-llvm -o - -error-on-deserialized-decl doNotDeserialize | FileCheck %s
+
// expected-no-diagnostics
// CHECK: define weak_odr void @_ZN2S4IiE1mEv
OpenPOWER on IntegriCloud