16
16
#include " clang/AST/DeclCXX.h"
17
17
#include " clang/AST/DeclarationName.h"
18
18
#include " clang/AST/Expr.h"
19
+ #include " clang/AST/ExprCXX.h"
19
20
#include " clang/AST/ExternalASTSource.h"
21
+ #include " clang/AST/ODRHash.h"
20
22
#include " clang/AST/TemplateBase.h"
21
23
#include " clang/AST/TemplateName.h"
22
24
#include " clang/AST/Type.h"
@@ -340,17 +342,44 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
340
342
return getCommonPtrInternal ();
341
343
}
342
344
343
- void RedeclarableTemplateDecl::loadLazySpecializationsImpl () const {
345
+ void RedeclarableTemplateDecl::loadLazySpecializationsImpl (
346
+ bool OnlyPartial /* =false*/ ) const {
344
347
// Grab the most recent declaration to ensure we've loaded any lazy
345
348
// redeclarations of this template.
346
349
CommonBase *CommonBasePtr = getMostRecentDecl ()->getCommonPtr ();
347
- if (CommonBasePtr->LazySpecializations ) {
348
- ASTContext &Context = getASTContext ();
349
- GlobalDeclID *Specs = CommonBasePtr->LazySpecializations ;
350
- CommonBasePtr->LazySpecializations = nullptr ;
351
- unsigned SpecSize = (*Specs++).getRawValue ();
352
- for (unsigned I = 0 ; I != SpecSize; ++I)
353
- (void )Context.getExternalSource ()->GetExternalDecl (Specs[I]);
350
+ if (auto *Specs = CommonBasePtr->LazySpecializations ) {
351
+ if (!OnlyPartial)
352
+ CommonBasePtr->LazySpecializations = nullptr ;
353
+ unsigned N = Specs[0 ].DeclID .getRawValue ();
354
+ for (unsigned I = 0 ; I != N; ++I) {
355
+ // Skip over already loaded specializations.
356
+ if (!Specs[I + 1 ].ODRHash )
357
+ continue ;
358
+ if (!OnlyPartial || Specs[I + 1 ].IsPartial )
359
+ (void )loadLazySpecializationImpl (Specs[I + 1 ]);
360
+ }
361
+ }
362
+ }
363
+
364
+ Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl (
365
+ LazySpecializationInfo &LazySpecInfo) const {
366
+ GlobalDeclID ID = LazySpecInfo.DeclID ;
367
+ assert (ID.isValid () && " Loading already loaded specialization!" );
368
+ // Note that we loaded the specialization.
369
+ LazySpecInfo.DeclID = GlobalDeclID ();
370
+ LazySpecInfo.ODRHash = LazySpecInfo.IsPartial = 0 ;
371
+ return getASTContext ().getExternalSource ()->GetExternalDecl (ID);
372
+ }
373
+
374
+ void RedeclarableTemplateDecl::loadLazySpecializationsImpl (
375
+ ArrayRef<TemplateArgument> Args, TemplateParameterList *TPL) const {
376
+ CommonBase *CommonBasePtr = getMostRecentDecl ()->getCommonPtr ();
377
+ if (auto *Specs = CommonBasePtr->LazySpecializations ) {
378
+ unsigned Hash = TemplateArgumentList::ComputeODRHash (Args);
379
+ unsigned N = Specs[0 ].DeclID .getRawValue ();
380
+ for (unsigned I = 0 ; I != N; ++I)
381
+ if (Specs[I + 1 ].ODRHash && Specs[I + 1 ].ODRHash == Hash)
382
+ (void )loadLazySpecializationImpl (Specs[I + 1 ]);
354
383
}
355
384
}
356
385
@@ -361,6 +390,8 @@ RedeclarableTemplateDecl::findSpecializationImpl(
361
390
ProfileArguments&&... ProfileArgs) {
362
391
using SETraits = SpecEntryTraits<EntryType>;
363
392
393
+ loadLazySpecializationsImpl (std::forward<ProfileArguments>(ProfileArgs)...);
394
+
364
395
llvm::FoldingSetNodeID ID;
365
396
EntryType::Profile (ID, std::forward<ProfileArguments>(ProfileArgs)...,
366
397
getASTContext ());
@@ -376,10 +407,14 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
376
407
377
408
if (InsertPos) {
378
409
#ifndef NDEBUG
410
+ auto Args = SETraits::getTemplateArgs (Entry);
411
+ // Due to hash collisions, it can happen that we load another template
412
+ // specialization with the same hash. This is fine, as long as the next
413
+ // call to findSpecializationImpl does not find a matching Decl for the
414
+ // template arguments.
415
+ loadLazySpecializationsImpl (Args);
379
416
void *CorrectInsertPos;
380
- assert (!findSpecializationImpl (Specializations,
381
- CorrectInsertPos,
382
- SETraits::getTemplateArgs (Entry)) &&
417
+ assert (!findSpecializationImpl (Specializations, CorrectInsertPos, Args) &&
383
418
InsertPos == CorrectInsertPos &&
384
419
" given incorrect InsertPos for specialization" );
385
420
#endif
@@ -453,12 +488,14 @@ FunctionTemplateDecl::getSpecializations() const {
453
488
FunctionDecl *
454
489
FunctionTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
455
490
void *&InsertPos) {
456
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
491
+ auto *Common = getCommonPtr ();
492
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
457
493
}
458
494
459
495
void FunctionTemplateDecl::addSpecialization (
460
496
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
461
- addSpecializationImpl<FunctionTemplateDecl>(getSpecializations (), Info,
497
+ auto *Common = getCommonPtr ();
498
+ addSpecializationImpl<FunctionTemplateDecl>(Common->Specializations , Info,
462
499
InsertPos);
463
500
}
464
501
@@ -516,8 +553,9 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
516
553
DeclarationName (), nullptr , nullptr );
517
554
}
518
555
519
- void ClassTemplateDecl::LoadLazySpecializations () const {
520
- loadLazySpecializationsImpl ();
556
+ void ClassTemplateDecl::LoadLazySpecializations (
557
+ bool OnlyPartial /* =false*/ ) const {
558
+ loadLazySpecializationsImpl (OnlyPartial);
521
559
}
522
560
523
561
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
@@ -528,7 +566,7 @@ ClassTemplateDecl::getSpecializations() const {
528
566
529
567
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
530
568
ClassTemplateDecl::getPartialSpecializations () const {
531
- LoadLazySpecializations ();
569
+ LoadLazySpecializations (/* PartialOnly = */ true );
532
570
return getCommonPtr ()->PartialSpecializations ;
533
571
}
534
572
@@ -542,12 +580,15 @@ ClassTemplateDecl::newCommon(ASTContext &C) const {
542
580
ClassTemplateSpecializationDecl *
543
581
ClassTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
544
582
void *&InsertPos) {
545
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
583
+ auto *Common = getCommonPtr ();
584
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
546
585
}
547
586
548
587
void ClassTemplateDecl::AddSpecialization (ClassTemplateSpecializationDecl *D,
549
588
void *InsertPos) {
550
- addSpecializationImpl<ClassTemplateDecl>(getSpecializations (), D, InsertPos);
589
+ auto *Common = getCommonPtr ();
590
+ addSpecializationImpl<ClassTemplateDecl>(Common->Specializations , D,
591
+ InsertPos);
551
592
}
552
593
553
594
ClassTemplatePartialSpecializationDecl *
@@ -904,6 +945,14 @@ TemplateArgumentList::CreateCopy(ASTContext &Context,
904
945
return new (Mem) TemplateArgumentList (Args);
905
946
}
906
947
948
+ unsigned TemplateArgumentList::ComputeODRHash (ArrayRef<TemplateArgument> Args) {
949
+ ODRHash Hasher;
950
+ for (TemplateArgument TA : Args)
951
+ Hasher.AddTemplateArgument (TA);
952
+
953
+ return Hasher.CalculateHash ();
954
+ }
955
+
907
956
FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create (
908
957
ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
909
958
TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs,
@@ -1283,8 +1332,9 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
1283
1332
DeclarationName (), nullptr , nullptr );
1284
1333
}
1285
1334
1286
- void VarTemplateDecl::LoadLazySpecializations () const {
1287
- loadLazySpecializationsImpl ();
1335
+ void VarTemplateDecl::LoadLazySpecializations (
1336
+ bool OnlyPartial /* =false*/ ) const {
1337
+ loadLazySpecializationsImpl (OnlyPartial);
1288
1338
}
1289
1339
1290
1340
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
@@ -1295,7 +1345,7 @@ VarTemplateDecl::getSpecializations() const {
1295
1345
1296
1346
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
1297
1347
VarTemplateDecl::getPartialSpecializations () const {
1298
- LoadLazySpecializations ();
1348
+ LoadLazySpecializations (/* PartialOnly = */ true );
1299
1349
return getCommonPtr ()->PartialSpecializations ;
1300
1350
}
1301
1351
@@ -1309,12 +1359,14 @@ VarTemplateDecl::newCommon(ASTContext &C) const {
1309
1359
VarTemplateSpecializationDecl *
1310
1360
VarTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
1311
1361
void *&InsertPos) {
1312
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
1362
+ auto *Common = getCommonPtr ();
1363
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
1313
1364
}
1314
1365
1315
1366
void VarTemplateDecl::AddSpecialization (VarTemplateSpecializationDecl *D,
1316
1367
void *InsertPos) {
1317
- addSpecializationImpl<VarTemplateDecl>(getSpecializations (), D, InsertPos);
1368
+ auto *Common = getCommonPtr ();
1369
+ addSpecializationImpl<VarTemplateDecl>(Common->Specializations , D, InsertPos);
1318
1370
}
1319
1371
1320
1372
VarTemplatePartialSpecializationDecl *
0 commit comments