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++).getRawValue ();
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 .getRawValue ();
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 .getRawValue ();
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 *
@@ -897,6 +940,14 @@ TemplateArgumentList::CreateCopy(ASTContext &Context,
897940 return new (Mem) TemplateArgumentList (Args);
898941}
899942
943+ unsigned TemplateArgumentList::ComputeODRHash (ArrayRef<TemplateArgument> Args) {
944+ ODRHash Hasher;
945+ for (TemplateArgument TA : Args)
946+ Hasher.AddTemplateArgument (TA);
947+
948+ return Hasher.CalculateHash ();
949+ }
950+
900951FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create (
901952 ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
902953 TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs,
@@ -1262,8 +1313,9 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
12621313 DeclarationName (), nullptr , nullptr );
12631314}
12641315
1265- void VarTemplateDecl::LoadLazySpecializations () const {
1266- loadLazySpecializationsImpl ();
1316+ void VarTemplateDecl::LoadLazySpecializations (
1317+ bool OnlyPartial/* =false*/ ) const {
1318+ loadLazySpecializationsImpl (OnlyPartial);
12671319}
12681320
12691321llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
@@ -1274,7 +1326,7 @@ VarTemplateDecl::getSpecializations() const {
12741326
12751327llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
12761328VarTemplateDecl::getPartialSpecializations () const {
1277- LoadLazySpecializations ();
1329+ LoadLazySpecializations (/* PartialOnly = */ true );
12781330 return getCommonPtr ()->PartialSpecializations ;
12791331}
12801332
@@ -1288,12 +1340,14 @@ VarTemplateDecl::newCommon(ASTContext &C) const {
12881340VarTemplateSpecializationDecl *
12891341VarTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
12901342 void *&InsertPos) {
1291- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
1343+ auto *Common = getCommonPtr ();
1344+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
12921345}
12931346
12941347void VarTemplateDecl::AddSpecialization (VarTemplateSpecializationDecl *D,
12951348 void *InsertPos) {
1296- addSpecializationImpl<VarTemplateDecl>(getSpecializations (), D, InsertPos);
1349+ auto *Common = getCommonPtr ();
1350+ addSpecializationImpl<VarTemplateDecl>(Common->Specializations , D, InsertPos);
12971351}
12981352
12991353VarTemplatePartialSpecializationDecl *
0 commit comments