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,16 +333,43 @@ 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
- uint32_t *Specs = CommonBasePtr->LazySpecializations ;
341
- CommonBasePtr->LazySpecializations = nullptr ;
342
- for (uint32_t I = 0 , N = *Specs++; I != N; ++I)
343
- (void )Context.getExternalSource ()->GetExternalDecl (Specs[I]);
341
+ if (auto *Specs = CommonBasePtr->LazySpecializations ) {
342
+ if (!OnlyPartial)
343
+ CommonBasePtr->LazySpecializations = nullptr ;
344
+ for (uint32_t I = 0 , N = Specs[0 ].DeclID ; I != N; ++I) {
345
+ // Skip over already loaded specializations.
346
+ if (!Specs[I+1 ].ODRHash )
347
+ continue ;
348
+ if (!OnlyPartial || Specs[I+1 ].IsPartial )
349
+ (void )loadLazySpecializationImpl (Specs[I+1 ]);
350
+ }
351
+ }
352
+ }
353
+
354
+ Decl *RedeclarableTemplateDecl::loadLazySpecializationImpl (
355
+ LazySpecializationInfo &LazySpecInfo) const {
356
+ uint32_t ID = LazySpecInfo.DeclID ;
357
+ assert (ID && " Loading already loaded specialization!" );
358
+ // Note that we loaded the specialization.
359
+ LazySpecInfo.DeclID = LazySpecInfo.ODRHash = LazySpecInfo.IsPartial = 0 ;
360
+ return getASTContext ().getExternalSource ()->GetExternalDecl (ID);
361
+ }
362
+
363
+ void
364
+ RedeclarableTemplateDecl::loadLazySpecializationsImpl (ArrayRef<TemplateArgument>
365
+ Args,
366
+ TemplateParameterList *TPL) const {
367
+ CommonBase *CommonBasePtr = getMostRecentDecl ()->getCommonPtr ();
368
+ if (auto *Specs = CommonBasePtr->LazySpecializations ) {
369
+ unsigned Hash = TemplateArgumentList::ComputeODRHash (Args);
370
+ for (uint32_t I = 0 , N = Specs[0 ].DeclID ; I != N; ++I)
371
+ if (Specs[I+1 ].ODRHash && Specs[I+1 ].ODRHash == Hash)
372
+ (void )loadLazySpecializationImpl (Specs[I+1 ]);
344
373
}
345
374
}
346
375
@@ -351,6 +380,8 @@ RedeclarableTemplateDecl::findSpecializationImpl(
351
380
ProfileArguments&&... ProfileArgs) {
352
381
using SETraits = SpecEntryTraits<EntryType>;
353
382
383
+ loadLazySpecializationsImpl (std::forward<ProfileArguments>(ProfileArgs)...);
384
+
354
385
llvm::FoldingSetNodeID ID;
355
386
EntryType::Profile (ID, std::forward<ProfileArguments>(ProfileArgs)...,
356
387
getASTContext ());
@@ -366,10 +397,14 @@ void RedeclarableTemplateDecl::addSpecializationImpl(
366
397
367
398
if (InsertPos) {
368
399
#ifndef NDEBUG
400
+ auto Args = SETraits::getTemplateArgs (Entry);
401
+ // Due to hash collisions, it can happen that we load another template
402
+ // specialization with the same hash. This is fine, as long as the next
403
+ // call to findSpecializationImpl does not find a matching Decl for the
404
+ // template arguments.
405
+ loadLazySpecializationsImpl (Args);
369
406
void *CorrectInsertPos;
370
- assert (!findSpecializationImpl (Specializations,
371
- CorrectInsertPos,
372
- SETraits::getTemplateArgs (Entry)) &&
407
+ assert (!findSpecializationImpl (Specializations, CorrectInsertPos, Args) &&
373
408
InsertPos == CorrectInsertPos &&
374
409
" given incorrect InsertPos for specialization" );
375
410
#endif
@@ -443,12 +478,14 @@ FunctionTemplateDecl::getSpecializations() const {
443
478
FunctionDecl *
444
479
FunctionTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
445
480
void *&InsertPos) {
446
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
481
+ auto *Common = getCommonPtr ();
482
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
447
483
}
448
484
449
485
void FunctionTemplateDecl::addSpecialization (
450
486
FunctionTemplateSpecializationInfo *Info, void *InsertPos) {
451
- addSpecializationImpl<FunctionTemplateDecl>(getSpecializations (), Info,
487
+ auto *Common = getCommonPtr ();
488
+ addSpecializationImpl<FunctionTemplateDecl>(Common->Specializations , Info,
452
489
InsertPos);
453
490
}
454
491
@@ -508,8 +545,9 @@ ClassTemplateDecl *ClassTemplateDecl::CreateDeserialized(ASTContext &C,
508
545
DeclarationName (), nullptr , nullptr );
509
546
}
510
547
511
- void ClassTemplateDecl::LoadLazySpecializations () const {
512
- loadLazySpecializationsImpl ();
548
+ void ClassTemplateDecl::LoadLazySpecializations (
549
+ bool OnlyPartial/* =false*/ ) const {
550
+ loadLazySpecializationsImpl (OnlyPartial);
513
551
}
514
552
515
553
llvm::FoldingSetVector<ClassTemplateSpecializationDecl> &
@@ -520,7 +558,7 @@ ClassTemplateDecl::getSpecializations() const {
520
558
521
559
llvm::FoldingSetVector<ClassTemplatePartialSpecializationDecl> &
522
560
ClassTemplateDecl::getPartialSpecializations () const {
523
- LoadLazySpecializations ();
561
+ LoadLazySpecializations (/* PartialOnly = */ true );
524
562
return getCommonPtr ()->PartialSpecializations ;
525
563
}
526
564
@@ -534,12 +572,15 @@ ClassTemplateDecl::newCommon(ASTContext &C) const {
534
572
ClassTemplateSpecializationDecl *
535
573
ClassTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
536
574
void *&InsertPos) {
537
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
575
+ auto *Common = getCommonPtr ();
576
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
538
577
}
539
578
540
579
void ClassTemplateDecl::AddSpecialization (ClassTemplateSpecializationDecl *D,
541
580
void *InsertPos) {
542
- addSpecializationImpl<ClassTemplateDecl>(getSpecializations (), D, InsertPos);
581
+ auto *Common = getCommonPtr ();
582
+ addSpecializationImpl<ClassTemplateDecl>(Common->Specializations , D,
583
+ InsertPos);
543
584
}
544
585
545
586
ClassTemplatePartialSpecializationDecl *
@@ -883,6 +924,14 @@ TemplateArgumentList::CreateCopy(ASTContext &Context,
883
924
return new (Mem) TemplateArgumentList (Args);
884
925
}
885
926
927
+ unsigned TemplateArgumentList::ComputeODRHash (ArrayRef<TemplateArgument> Args) {
928
+ ODRHash Hasher;
929
+ for (TemplateArgument TA : Args)
930
+ Hasher.AddTemplateArgument (TA);
931
+
932
+ return Hasher.CalculateHash ();
933
+ }
934
+
886
935
FunctionTemplateSpecializationInfo *FunctionTemplateSpecializationInfo::Create (
887
936
ASTContext &C, FunctionDecl *FD, FunctionTemplateDecl *Template,
888
937
TemplateSpecializationKind TSK, const TemplateArgumentList *TemplateArgs,
@@ -1225,8 +1274,9 @@ VarTemplateDecl *VarTemplateDecl::CreateDeserialized(ASTContext &C,
1225
1274
DeclarationName (), nullptr , nullptr );
1226
1275
}
1227
1276
1228
- void VarTemplateDecl::LoadLazySpecializations () const {
1229
- loadLazySpecializationsImpl ();
1277
+ void VarTemplateDecl::LoadLazySpecializations (
1278
+ bool OnlyPartial/* =false*/ ) const {
1279
+ loadLazySpecializationsImpl (OnlyPartial);
1230
1280
}
1231
1281
1232
1282
llvm::FoldingSetVector<VarTemplateSpecializationDecl> &
@@ -1237,7 +1287,7 @@ VarTemplateDecl::getSpecializations() const {
1237
1287
1238
1288
llvm::FoldingSetVector<VarTemplatePartialSpecializationDecl> &
1239
1289
VarTemplateDecl::getPartialSpecializations () const {
1240
- LoadLazySpecializations ();
1290
+ LoadLazySpecializations (/* PartialOnly = */ true );
1241
1291
return getCommonPtr ()->PartialSpecializations ;
1242
1292
}
1243
1293
@@ -1251,12 +1301,14 @@ VarTemplateDecl::newCommon(ASTContext &C) const {
1251
1301
VarTemplateSpecializationDecl *
1252
1302
VarTemplateDecl::findSpecialization (ArrayRef<TemplateArgument> Args,
1253
1303
void *&InsertPos) {
1254
- return findSpecializationImpl (getSpecializations (), InsertPos, Args);
1304
+ auto *Common = getCommonPtr ();
1305
+ return findSpecializationImpl (Common->Specializations , InsertPos, Args);
1255
1306
}
1256
1307
1257
1308
void VarTemplateDecl::AddSpecialization (VarTemplateSpecializationDecl *D,
1258
1309
void *InsertPos) {
1259
- addSpecializationImpl<VarTemplateDecl>(getSpecializations (), D, InsertPos);
1310
+ auto *Common = getCommonPtr ();
1311
+ addSpecializationImpl<VarTemplateDecl>(Common->Specializations , D, InsertPos);
1260
1312
}
1261
1313
1262
1314
VarTemplatePartialSpecializationDecl *
0 commit comments