Skip to content

Commit f4e61d3

Browse files
committed
[llvm-project] Fix lazy template loading
Backport upstream PR llvm/llvm-project#133057
1 parent 199c6b1 commit f4e61d3

File tree

3 files changed

+20
-47
lines changed

3 files changed

+20
-47
lines changed

Diff for: interpreter/llvm-project/clang/lib/AST/DeclTemplate.cpp

-6
Original file line numberDiff line numberDiff line change
@@ -350,12 +350,6 @@ bool RedeclarableTemplateDecl::loadLazySpecializationsImpl(
350350
if (!ExternalSource)
351351
return false;
352352

353-
// If TPL is not null, it implies that we're loading specializations for
354-
// partial templates. We need to load all specializations in such cases.
355-
if (TPL)
356-
return ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
357-
/*OnlyPartial=*/false);
358-
359353
return ExternalSource->LoadExternalSpecializations(this->getCanonicalDecl(),
360354
Args);
361355
}

Diff for: interpreter/llvm-project/clang/lib/Serialization/ASTReader.cpp

+2-8
Original file line numberDiff line numberDiff line change
@@ -7723,14 +7723,8 @@ void ASTReader::CompleteRedeclChain(const Decl *D) {
77237723
}
77247724
}
77257725

7726-
if (Template) {
7727-
// For partitial specialization, load all the specializations for safety.
7728-
if (isa<ClassTemplatePartialSpecializationDecl,
7729-
VarTemplatePartialSpecializationDecl>(D))
7730-
Template->loadLazySpecializationsImpl();
7731-
else
7732-
Template->loadLazySpecializationsImpl(Args);
7733-
}
7726+
if (Template)
7727+
Template->loadLazySpecializationsImpl(Args);
77347728
}
77357729

77367730
CXXCtorInitializer **

Diff for: interpreter/llvm-project/clang/lib/Serialization/TemplateArgumentHasher.cpp

+18-33
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,6 @@ using namespace clang;
2121
namespace {
2222

2323
class TemplateArgumentHasher {
24-
// If we bail out during the process of calculating hash values for
25-
// template arguments for any reason. We're allowed to do it since
26-
// TemplateArgumentHasher are only required to give the same hash value
27-
// for the same template arguments, but not required to give different
28-
// hash value for different template arguments.
29-
//
30-
// So in the worst case, it is still a valid implementation to give all
31-
// inputs the same BailedOutValue as output.
32-
bool BailedOut = false;
33-
static constexpr unsigned BailedOutValue = 0x12345678;
34-
3524
llvm::FoldingSetNodeID ID;
3625

3726
public:
@@ -41,14 +30,7 @@ class TemplateArgumentHasher {
4130

4231
void AddInteger(unsigned V) { ID.AddInteger(V); }
4332

44-
unsigned getValue() {
45-
if (BailedOut)
46-
return BailedOutValue;
47-
48-
return ID.ComputeHash();
49-
}
50-
51-
void setBailedOut() { BailedOut = true; }
33+
unsigned getValue() { return ID.ComputeHash(); }
5234

5335
void AddType(const Type *T);
5436
void AddQualType(QualType T);
@@ -92,8 +74,7 @@ void TemplateArgumentHasher::AddTemplateArgument(TemplateArgument TA) {
9274
case TemplateArgument::Expression:
9375
// If we meet expression in template argument, it implies
9476
// that the template is still dependent. It is meaningless
95-
// to get a stable hash for the template. Bail out simply.
96-
BailedOut = true;
77+
// to get a stable hash for the template.
9778
break;
9879
case TemplateArgument::Pack:
9980
AddInteger(TA.pack_size());
@@ -110,10 +91,9 @@ void TemplateArgumentHasher::AddStructuralValue(const APValue &Value) {
11091

11192
// 'APValue::Profile' uses pointer values to make hash for LValue and
11293
// MemberPointer, but they differ from one compiler invocation to another.
113-
// It may be difficult to handle such cases. Bail out simply.
94+
// It may be difficult to handle such cases.
11495

11596
if (Kind == APValue::LValue || Kind == APValue::MemberPointer) {
116-
BailedOut = true;
11797
return;
11898
}
11999

@@ -135,14 +115,11 @@ void TemplateArgumentHasher::AddTemplateName(TemplateName Name) {
135115
case TemplateName::DependentTemplate:
136116
case TemplateName::SubstTemplateTemplateParm:
137117
case TemplateName::SubstTemplateTemplateParmPack:
138-
BailedOut = true;
139118
break;
140119
case TemplateName::UsingTemplate: {
141120
UsingShadowDecl *USD = Name.getAsUsingShadowDecl();
142121
if (USD)
143122
AddDecl(USD->getTargetDecl());
144-
else
145-
BailedOut = true;
146123
break;
147124
}
148125
}
@@ -164,7 +141,6 @@ void TemplateArgumentHasher::AddDeclarationName(DeclarationName Name) {
164141
case DeclarationName::ObjCZeroArgSelector:
165142
case DeclarationName::ObjCOneArgSelector:
166143
case DeclarationName::ObjCMultiArgSelector:
167-
BailedOut = true;
168144
break;
169145
case DeclarationName::CXXConstructorName:
170146
case DeclarationName::CXXDestructorName:
@@ -191,16 +167,29 @@ void TemplateArgumentHasher::AddDeclarationName(DeclarationName Name) {
191167
void TemplateArgumentHasher::AddDecl(const Decl *D) {
192168
const NamedDecl *ND = dyn_cast<NamedDecl>(D);
193169
if (!ND) {
194-
BailedOut = true;
195170
return;
196171
}
197172

198173
AddDeclarationName(ND->getDeclName());
174+
175+
// If this was a specialization we should take into account its template
176+
// arguments. This helps to reduce collisions coming when visiting template
177+
// specialization types (eg. when processing type template arguments).
178+
ArrayRef<TemplateArgument> Args;
179+
if (auto *CTSD = dyn_cast<ClassTemplateSpecializationDecl>(D))
180+
Args = CTSD->getTemplateArgs().asArray();
181+
else if (auto *VTSD = dyn_cast<VarTemplateSpecializationDecl>(D))
182+
Args = VTSD->getTemplateArgs().asArray();
183+
else if (auto *FD = dyn_cast<FunctionDecl>(D))
184+
if (FD->getTemplateSpecializationArgs())
185+
Args = FD->getTemplateSpecializationArgs()->asArray();
186+
187+
for (auto &TA : Args)
188+
AddTemplateArgument(TA);
199189
}
200190

201191
void TemplateArgumentHasher::AddQualType(QualType T) {
202192
if (T.isNull()) {
203-
BailedOut = true;
204193
return;
205194
}
206195
SplitQualType split = T.split();
@@ -210,7 +199,6 @@ void TemplateArgumentHasher::AddQualType(QualType T) {
210199

211200
// Process a Type pointer. Add* methods call back into TemplateArgumentHasher
212201
// while Visit* methods process the relevant parts of the Type.
213-
// Any unhandled type will make the hash computation bail out.
214202
class TypeVisitorHelper : public TypeVisitor<TypeVisitorHelper> {
215203
typedef TypeVisitor<TypeVisitorHelper> Inherited;
216204
llvm::FoldingSetNodeID &ID;
@@ -242,9 +230,6 @@ class TypeVisitorHelper : public TypeVisitor<TypeVisitorHelper> {
242230

243231
void Visit(const Type *T) { Inherited::Visit(T); }
244232

245-
// Unhandled types. Bail out simply.
246-
void VisitType(const Type *T) { Hash.setBailedOut(); }
247-
248233
void VisitAdjustedType(const AdjustedType *T) {
249234
AddQualType(T->getOriginalType());
250235
}

0 commit comments

Comments
 (0)