20
20
#include " clang/AST/TemplateBase.h"
21
21
#include " clang/AST/TemplateName.h"
22
22
#include " clang/AST/Type.h"
23
+ #include " clang/AST/ODRHash.h"
24
+ #include " clang/AST/ExprCXX.h"
23
25
#include " clang/AST/TypeLoc.h"
24
26
#include " clang/Basic/Builtins.h"
25
27
#include " clang/Basic/LLVM.h"
@@ -331,17 +333,46 @@ RedeclarableTemplateDecl::CommonBase *RedeclarableTemplateDecl::getCommonPtr() c
331
333
return Common;
332
334
}
333
335
334
- void RedeclarableTemplateDecl::loadLazySpecializationsImpl () const {
336
+ void RedeclarableTemplateDecl::loadLazySpecializationsImpl (
337
+ bool OnlyPartial/* =false*/ ) const {
335
338
// Grab the most recent declaration to ensure we've loaded any lazy
336
339
// redeclarations of this template.
337
340
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 ]);
345
376
}
346
377
}
347
378
@@ -352,6 +383,8 @@ RedeclarableTemplateDecl::findSpecializationImpl(
352
383
ProfileArguments&&... ProfileArgs) {
353
384
using SETraits = SpecEntryTraits<EntryType>;
354
385
386
+ loadLazySpecializationsImpl (std::forward<ProfileArguments>(ProfileArgs)...);
387
+
355
388
llvm::FoldingSetNodeID ID;
356
389
EntryType::Profile (ID, std::forward<ProfileArguments>(ProfileArgs)...,
357
390
getASTContext ());
@@ -367,10 +400,14 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
367
400
368
401
if (InsertPos) {
369
402
#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);
370
409
void *CorrectInsertPos;
371
- assert (!findSpecializationImpl (Specializations,
372
- CorrectInsertPos,
373
- SETraits::getTemplateArgs (Entry)) &&
410
+ assert (!findSpecializationImpl (Specializations, CorrectInsertPos, Args) &&
374
411
InsertPos == CorrectInsertPos &&
375
412
" given incorrect InsertPos for specialization" );
376
413
#endif
@@ -444,12 +481,14 @@ FunctionTemplateDecl::getSpecializations() const {
444
481
FunctionDecl *
445
482
FunctionTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
446
483
void *&InsertPos) {
447
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
484
+ auto *Common = getCommonPtr ();
485
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
448
486
}
449
487
450
488
void FunctionTemplateDecl::addSpecialization (
451
489
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
452
- addSpecializationImpl<FunctionTemplateDecl>(getSpecializations (), Info,
490
+ auto *Common = getCommonPtr ();
491
+ addSpecializationImpl<FunctionTemplateDecl>(Common->Specializations , Info,
453
492
InsertPos);
454
493
}
455
494
@@ -509,8 +548,9 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
509
548
DeclarationName (), nullptr , nullptr );
510
549
}
511
550
512
- void ClassTemplateDecl::LoadLazySpecializations () const {
513
- loadLazySpecializationsImpl ();
551
+ void ClassTemplateDecl::LoadLazySpecializations (
552
+ bool OnlyPartial/* =false*/ ) const {
553
+ loadLazySpecializationsImpl (OnlyPartial);
514
554
}
515
555
516
556
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
@@ -521,7 +561,7 @@ ClassTemplateDecl::getSpecializations() const {
521
561
522
562
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
523
563
ClassTemplateDecl::getPartialSpecializations () const {
524
- LoadLazySpecializations ();
564
+ LoadLazySpecializations (/* PartialOnly = */ true );
525
565
return getCommonPtr ()->PartialSpecializations ;
526
566
}
527
567
@@ -535,12 +575,15 @@ ClassTemplateDecl::newCommon(ASTContext &C) const {
535
575
ClassTemplateSpecializationDecl *
536
576
ClassTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
537
577
void *&InsertPos) {
538
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
578
+ auto *Common = getCommonPtr ();
579
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
539
580
}
540
581
541
582
void ClassTemplateDecl::AddSpecialization (ClassTemplateSpecializationDecl *D,
542
583
void *InsertPos) {
543
- addSpecializationImpl<ClassTemplateDecl>(getSpecializations (), D, InsertPos);
584
+ auto *Common = getCommonPtr ();
585
+ addSpecializationImpl<ClassTemplateDecl>(Common->Specializations , D,
586
+ InsertPos);
544
587
}
545
588
546
589
ClassTemplatePartialSpecializationDecl *
@@ -882,6 +925,14 @@ TemplateArgumentList::CreateCopy(ASTContext &Context,
882
925
return new (Mem) TemplateArgumentList (Args);
883
926
}
884
927
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
+
885
936
FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create (
886
937
ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
887
938
TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs,
@@ -1223,8 +1274,9 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
1223
1274
DeclarationName (), nullptr , nullptr );
1224
1275
}
1225
1276
1226
- void VarTemplateDecl::LoadLazySpecializations () const {
1227
- loadLazySpecializationsImpl ();
1277
+ void VarTemplateDecl::LoadLazySpecializations (
1278
+ bool OnlyPartial/* =false*/ ) const {
1279
+ loadLazySpecializationsImpl (OnlyPartial);
1228
1280
}
1229
1281
1230
1282
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
@@ -1235,7 +1287,7 @@ VarTemplateDecl::getSpecializations() const {
1235
1287
1236
1288
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
1237
1289
VarTemplateDecl::getPartialSpecializations () const {
1238
- LoadLazySpecializations ();
1290
+ LoadLazySpecializations (/* PartialOnly = */ true );
1239
1291
return getCommonPtr ()->PartialSpecializations ;
1240
1292
}
1241
1293
@@ -1249,12 +1301,14 @@ VarTemplateDecl::newCommon(ASTContext &C) const {
1249
1301
VarTemplateSpecializationDecl *
1250
1302
VarTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
1251
1303
void *&InsertPos) {
1252
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
1304
+ auto *Common = getCommonPtr ();
1305
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
1253
1306
}
1254
1307
1255
1308
void VarTemplateDecl::AddSpecialization (VarTemplateSpecializationDecl *D,
1256
1309
void *InsertPos) {
1257
- addSpecializationImpl<VarTemplateDecl>(getSpecializations (), D, InsertPos);
1310
+ auto *Common = getCommonPtr ();
1311
+ addSpecializationImpl<VarTemplateDecl>(Common->Specializations , D, InsertPos);
1258
1312
}
1259
1313
1260
1314
VarTemplatePartialSpecializationDecl *
0 commit comments