2020#include " clang/AST/TemplateBase.h"
2121#include " clang/AST/TemplateName.h"
2222#include " clang/AST/Type.h"
23+ #include " clang/AST/ODRHash.h"
24+ #include " clang/AST/ExprCXX.h"
2325#include " clang/AST/TypeLoc.h"
2426#include " clang/Basic/Builtins.h"
2527#include " clang/Basic/LLVM.h"
@@ -331,17 +333,46 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
331333 return Common;
332334}
333335
334- void RedeclarableTemplateDecl::loadLazySpecializationsImpl () const {
336+ void RedeclarableTemplateDecl::loadLazySpecializationsImpl (
337+ bool OnlyPartial/* =false*/ ) const {
335338 // Grab the most recent declaration to ensure we've loaded any lazy
336339 // redeclarations of this template.
337340 CommonBase *CommonBasePtr = getMostRecentDecl ()->getCommonPtr ();
338- if (CommonBasePtr->LazySpecializations ) {
339- ASTContext &Context = getASTContext ();
340- GlobalDeclID *Specs = CommonBasePtr->LazySpecializations ;
341- CommonBasePtr->LazySpecializations = nullptr ;
342- unsigned SpecSize = (*Specs++).get ();
343- for (unsigned I = 0 ; I != SpecSize; ++I)
344- (void )Context.getExternalSource ()->GetExternalDecl (Specs[I]);
341+ if (auto *Specs = CommonBasePtr->LazySpecializations ) {
342+ if (!OnlyPartial)
343+ CommonBasePtr->LazySpecializations = nullptr ;
344+ unsigned N = Specs[0 ].DeclID .get ();
345+ for (unsigned I = 0 ; I != N; ++I) {
346+ // Skip over already loaded specializations.
347+ if (!Specs[I+1 ].ODRHash )
348+ continue ;
349+ if (!OnlyPartial || Specs[I+1 ].IsPartial )
350+ (void )loadLazySpecializationImpl (Specs[I+1 ]);
351+ }
352+ }
353+ }
354+
355+ Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl (
356+ LazySpecializationInfo &LazySpecInfo) const {
357+ GlobalDeclID ID = LazySpecInfo.DeclID ;
358+ assert (ID.isValid () && " Loading already loaded specialization!" );
359+ // Note that we loaded the specialization.
360+ LazySpecInfo.DeclID = GlobalDeclID ();
361+ LazySpecInfo.ODRHash = LazySpecInfo.IsPartial = 0 ;
362+ return getASTContext ().getExternalSource ()->GetExternalDecl (ID);
363+ }
364+
365+ void
366+ RedeclarableTemplateDecl::loadLazySpecializationsImpl (ArrayRef<TemplateArgument>
367+ Args,
368+ TemplateParameterList *TPL) const {
369+ CommonBase *CommonBasePtr = getMostRecentDecl ()->getCommonPtr ();
370+ if (auto *Specs = CommonBasePtr->LazySpecializations ) {
371+ unsigned Hash = TemplateArgumentList::ComputeODRHash (Args);
372+ unsigned N = Specs[0 ].DeclID .get ();
373+ for (uint32_t I = 0 ; I != N; ++I)
374+ if (Specs[I+1 ].ODRHash && Specs[I+1 ].ODRHash == Hash)
375+ (void )loadLazySpecializationImpl (Specs[I+1 ]);
345376 }
346377}
347378
@@ -352,6 +383,8 @@ RedeclarableTemplateDecl::findSpecializationImpl(
352383 ProfileArguments&&... ProfileArgs) {
353384 using SETraits = SpecEntryTraits<EntryType>;
354385
386+ loadLazySpecializationsImpl (std::forward<ProfileArguments>(ProfileArgs)...);
387+
355388 llvm::FoldingSetNodeID ID;
356389 EntryType::Profile (ID, std::forward<ProfileArguments>(ProfileArgs)...,
357390 getASTContext ());
@@ -367,10 +400,14 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
367400
368401 if (InsertPos) {
369402#ifndef NDEBUG
403+ auto Args = SETraits::getTemplateArgs (Entry);
404+ // Due to hash collisions, it can happen that we load another template
405+ // specialization with the same hash. This is fine, as long as the next
406+ // call to findSpecializationImpl does not find a matching Decl for the
407+ // template arguments.
408+ loadLazySpecializationsImpl (Args);
370409 void *CorrectInsertPos;
371- assert (!findSpecializationImpl (Specializations,
372- CorrectInsertPos,
373- SETraits::getTemplateArgs (Entry)) &&
410+ assert (!findSpecializationImpl (Specializations, CorrectInsertPos, Args) &&
374411 InsertPos == CorrectInsertPos &&
375412 " given incorrect InsertPos for specialization" );
376413#endif
@@ -444,12 +481,14 @@ FunctionTemplateDecl::getSpecializations() const {
444481FunctionDecl *
445482FunctionTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
446483 void *&InsertPos) {
447- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
484+ auto *Common = getCommonPtr ();
485+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
448486}
449487
450488void FunctionTemplateDecl::addSpecialization (
451489 FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
452- addSpecializationImpl<FunctionTemplateDecl>(getSpecializations (), Info,
490+ auto *Common = getCommonPtr ();
491+ addSpecializationImpl<FunctionTemplateDecl>(Common->Specializations , Info,
453492 InsertPos);
454493}
455494
@@ -509,8 +548,9 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
509548 DeclarationName (), nullptr , nullptr );
510549}
511550
512- void ClassTemplateDecl::LoadLazySpecializations () const {
513- loadLazySpecializationsImpl ();
551+ void ClassTemplateDecl::LoadLazySpecializations (
552+ bool OnlyPartial/* =false*/ ) const {
553+ loadLazySpecializationsImpl (OnlyPartial);
514554}
515555
516556llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
@@ -521,7 +561,7 @@ ClassTemplateDecl::getSpecializations() const {
521561
522562llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
523563ClassTemplateDecl::getPartialSpecializations () const {
524- LoadLazySpecializations ();
564+ LoadLazySpecializations (/* PartialOnly = */ true );
525565 return getCommonPtr ()->PartialSpecializations ;
526566}
527567
@@ -535,12 +575,15 @@ ClassTemplateDecl::newCommon(ASTContext &C) const {
535575ClassTemplateSpecializationDecl *
536576ClassTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
537577 void *&InsertPos) {
538- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
578+ auto *Common = getCommonPtr ();
579+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
539580}
540581
541582void ClassTemplateDecl::AddSpecialization (ClassTemplateSpecializationDecl *D,
542583 void *InsertPos) {
543- addSpecializationImpl<ClassTemplateDecl>(getSpecializations (), D, InsertPos);
584+ auto *Common = getCommonPtr ();
585+ addSpecializationImpl<ClassTemplateDecl>(Common->Specializations , D,
586+ InsertPos);
544587}
545588
546589ClassTemplatePartialSpecializationDecl *
@@ -882,6 +925,14 @@ TemplateArgumentList::CreateCopy(ASTContext &Context,
882925 return new (Mem) TemplateArgumentList (Args);
883926}
884927
928+ unsigned TemplateArgumentList::ComputeODRHash (ArrayRef<TemplateArgument> Args) {
929+ ODRHash Hasher;
930+ for (TemplateArgument TA : Args)
931+ Hasher.AddTemplateArgument (TA);
932+
933+ return Hasher.CalculateHash ();
934+ }
935+
885936FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create (
886937 ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
887938 TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs,
@@ -1223,8 +1274,9 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
12231274 DeclarationName (), nullptr , nullptr );
12241275}
12251276
1226- void VarTemplateDecl::LoadLazySpecializations () const {
1227- loadLazySpecializationsImpl ();
1277+ void VarTemplateDecl::LoadLazySpecializations (
1278+ bool OnlyPartial/* =false*/ ) const {
1279+ loadLazySpecializationsImpl (OnlyPartial);
12281280}
12291281
12301282llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
@@ -1235,7 +1287,7 @@ VarTemplateDecl::getSpecializations() const {
12351287
12361288llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
12371289VarTemplateDecl::getPartialSpecializations () const {
1238- LoadLazySpecializations ();
1290+ LoadLazySpecializations (/* PartialOnly = */ true );
12391291 return getCommonPtr ()->PartialSpecializations ;
12401292}
12411293
@@ -1249,12 +1301,14 @@ VarTemplateDecl::newCommon(ASTContext &C) const {
12491301VarTemplateSpecializationDecl *
12501302VarTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
12511303 void *&InsertPos) {
1252- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
1304+ auto *Common = getCommonPtr ();
1305+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
12531306}
12541307
12551308void VarTemplateDecl::AddSpecialization (VarTemplateSpecializationDecl *D,
12561309 void *InsertPos) {
1257- addSpecializationImpl<VarTemplateDecl>(getSpecializations (), D, InsertPos);
1310+ auto *Common = getCommonPtr ();
1311+ addSpecializationImpl<VarTemplateDecl>(Common->Specializations , D, InsertPos);
12581312}
12591313
12601314VarTemplatePartialSpecializationDecl *
0 commit comments