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"
@@ -351,17 +353,44 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
351
353
return Common;
352
354
}
353
355
354
- void RedeclarableTemplateDecl::loadLazySpecializationsImpl () const {
356
+ void RedeclarableTemplateDecl::loadLazySpecializationsImpl (
357
+ bool OnlyPartial /* =false*/ ) const {
355
358
// Grab the most recent declaration to ensure we've loaded any lazy
356
359
// redeclarations of this template.
357
360
CommonBase *CommonBasePtr = getMostRecentDecl ()->getCommonPtr ();
358
- if (CommonBasePtr->LazySpecializations ) {
359
- ASTContext &Context = getASTContext ();
360
- GlobalDeclID *Specs = CommonBasePtr->LazySpecializations ;
361
- CommonBasePtr->LazySpecializations = nullptr ;
362
- unsigned SpecSize = (*Specs++).getRawValue ();
363
- for (unsigned I = 0 ; I != SpecSize; ++I)
364
- (void )Context.getExternalSource ()->GetExternalDecl (Specs[I]);
361
+ if (auto *Specs = CommonBasePtr->LazySpecializations ) {
362
+ if (!OnlyPartial)
363
+ CommonBasePtr->LazySpecializations = nullptr ;
364
+ unsigned N = Specs[0 ].DeclID .getRawValue ();
365
+ for (unsigned I = 0 ; I != N; ++I) {
366
+ // Skip over already loaded specializations.
367
+ if (!Specs[I + 1 ].ODRHash )
368
+ continue ;
369
+ if (!OnlyPartial || Specs[I + 1 ].IsPartial )
370
+ (void )loadLazySpecializationImpl (Specs[I + 1 ]);
371
+ }
372
+ }
373
+ }
374
+
375
+ Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl (
376
+ LazySpecializationInfo &LazySpecInfo) const {
377
+ GlobalDeclID ID = LazySpecInfo.DeclID ;
378
+ assert (ID.isValid () && " Loading already loaded specialization!" );
379
+ // Note that we loaded the specialization.
380
+ LazySpecInfo.DeclID = GlobalDeclID ();
381
+ LazySpecInfo.ODRHash = LazySpecInfo.IsPartial = 0 ;
382
+ return getASTContext ().getExternalSource ()->GetExternalDecl (ID);
383
+ }
384
+
385
+ void RedeclarableTemplateDecl::loadLazySpecializationsImpl (
386
+ ArrayRef<TemplateArgument> Args, TemplateParameterList *TPL) const {
387
+ CommonBase *CommonBasePtr = getMostRecentDecl ()->getCommonPtr ();
388
+ if (auto *Specs = CommonBasePtr->LazySpecializations ) {
389
+ unsigned Hash = TemplateArgumentList::ComputeODRHash (Args);
390
+ unsigned N = Specs[0 ].DeclID .getRawValue ();
391
+ for (unsigned I = 0 ; I != N; ++I)
392
+ if (Specs[I + 1 ].ODRHash && Specs[I + 1 ].ODRHash == Hash)
393
+ (void )loadLazySpecializationImpl (Specs[I + 1 ]);
365
394
}
366
395
}
367
396
@@ -372,6 +401,8 @@ RedeclarableTemplateDecl::findSpecializationImpl(
372
401
ProfileArguments&&... ProfileArgs) {
373
402
using SETraits = SpecEntryTraits<EntryType>;
374
403
404
+ loadLazySpecializationsImpl (std::forward<ProfileArguments>(ProfileArgs)...);
405
+
375
406
llvm::FoldingSetNodeID ID;
376
407
EntryType::Profile (ID, std::forward<ProfileArguments>(ProfileArgs)...,
377
408
getASTContext ());
@@ -387,10 +418,14 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
387
418
388
419
if (InsertPos) {
389
420
#ifndef NDEBUG
421
+ auto Args = SETraits::getTemplateArgs (Entry);
422
+ // Due to hash collisions, it can happen that we load another template
423
+ // specialization with the same hash. This is fine, as long as the next
424
+ // call to findSpecializationImpl does not find a matching Decl for the
425
+ // template arguments.
426
+ loadLazySpecializationsImpl (Args);
390
427
void *CorrectInsertPos;
391
- assert (!findSpecializationImpl (Specializations,
392
- CorrectInsertPos,
393
- SETraits::getTemplateArgs (Entry)) &&
428
+ assert (!findSpecializationImpl (Specializations, CorrectInsertPos, Args) &&
394
429
InsertPos == CorrectInsertPos &&
395
430
" given incorrect InsertPos for specialization" );
396
431
#endif
@@ -448,12 +483,14 @@ FunctionTemplateDecl::getSpecializations() const {
448
483
FunctionDecl *
449
484
FunctionTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
450
485
void *&InsertPos) {
451
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
486
+ auto *Common = getCommonPtr ();
487
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
452
488
}
453
489
454
490
void FunctionTemplateDecl::addSpecialization (
455
491
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
456
- addSpecializationImpl<FunctionTemplateDecl>(getSpecializations (), Info,
492
+ auto *Common = getCommonPtr ();
493
+ addSpecializationImpl<FunctionTemplateDecl>(Common->Specializations , Info,
457
494
InsertPos);
458
495
}
459
496
@@ -513,8 +550,9 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
513
550
DeclarationName (), nullptr , nullptr );
514
551
}
515
552
516
- void ClassTemplateDecl::LoadLazySpecializations () const {
517
- loadLazySpecializationsImpl ();
553
+ void ClassTemplateDecl::LoadLazySpecializations (
554
+ bool OnlyPartial /* =false*/ ) const {
555
+ loadLazySpecializationsImpl (OnlyPartial);
518
556
}
519
557
520
558
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
@@ -525,7 +563,7 @@ ClassTemplateDecl::getSpecializations() const {
525
563
526
564
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
527
565
ClassTemplateDecl::getPartialSpecializations () const {
528
- LoadLazySpecializations ();
566
+ LoadLazySpecializations (/* PartialOnly = */ true );
529
567
return getCommonPtr ()->PartialSpecializations ;
530
568
}
531
569
@@ -539,12 +577,15 @@ ClassTemplateDecl::newCommon(ASTContext &C) const {
539
577
ClassTemplateSpecializationDecl *
540
578
ClassTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
541
579
void *&InsertPos) {
542
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
580
+ auto *Common = getCommonPtr ();
581
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
543
582
}
544
583
545
584
void ClassTemplateDecl::AddSpecialization (ClassTemplateSpecializationDecl *D,
546
585
void *InsertPos) {
547
- addSpecializationImpl<ClassTemplateDecl>(getSpecializations (), D, InsertPos);
586
+ auto *Common = getCommonPtr ();
587
+ addSpecializationImpl<ClassTemplateDecl>(Common->Specializations , D,
588
+ InsertPos);
548
589
}
549
590
550
591
ClassTemplatePartialSpecializationDecl *
@@ -897,6 +938,14 @@ TemplateArgumentList::CreateCopy(ASTContext &Context,
897
938
return new (Mem) TemplateArgumentList (Args);
898
939
}
899
940
941
+ unsigned TemplateArgumentList::ComputeODRHash (ArrayRef<TemplateArgument> Args) {
942
+ ODRHash Hasher;
943
+ for (TemplateArgument TA : Args)
944
+ Hasher.AddTemplateArgument (TA);
945
+
946
+ return Hasher.CalculateHash ();
947
+ }
948
+
900
949
FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create (
901
950
ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
902
951
TemplateSpecializationKind TSK, TemplateArgumentList *TemplateArgs,
@@ -1262,8 +1311,9 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
1262
1311
DeclarationName (), nullptr , nullptr );
1263
1312
}
1264
1313
1265
- void VarTemplateDecl::LoadLazySpecializations () const {
1266
- loadLazySpecializationsImpl ();
1314
+ void VarTemplateDecl::LoadLazySpecializations (
1315
+ bool OnlyPartial /* =false*/ ) const {
1316
+ loadLazySpecializationsImpl (OnlyPartial);
1267
1317
}
1268
1318
1269
1319
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
@@ -1274,7 +1324,7 @@ VarTemplateDecl::getSpecializations() const {
1274
1324
1275
1325
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
1276
1326
VarTemplateDecl::getPartialSpecializations () const {
1277
- LoadLazySpecializations ();
1327
+ LoadLazySpecializations (/* PartialOnly = */ true );
1278
1328
return getCommonPtr ()->PartialSpecializations ;
1279
1329
}
1280
1330
@@ -1288,12 +1338,14 @@ VarTemplateDecl::newCommon(ASTContext &C) const {
1288
1338
VarTemplateSpecializationDecl *
1289
1339
VarTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
1290
1340
void *&InsertPos) {
1291
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
1341
+ auto *Common = getCommonPtr ();
1342
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
1292
1343
}
1293
1344
1294
1345
void VarTemplateDecl::AddSpecialization (VarTemplateSpecializationDecl *D,
1295
1346
void *InsertPos) {
1296
- addSpecializationImpl<VarTemplateDecl>(getSpecializations (), D, InsertPos);
1347
+ auto *Common = getCommonPtr ();
1348
+ addSpecializationImpl<VarTemplateDecl>(Common->Specializations , D, InsertPos);
1297
1349
}
1298
1350
1299
1351
VarTemplatePartialSpecializationDecl *
0 commit comments