@@ -21,17 +21,6 @@ using namespace clang;
21
21
namespace {
22
22
23
23
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
-
35
24
llvm::FoldingSetNodeID ID;
36
25
37
26
public:
@@ -41,14 +30,7 @@ class TemplateArgumentHasher {
41
30
42
31
void AddInteger (unsigned V) { ID.AddInteger (V); }
43
32
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 (); }
52
34
53
35
void AddType (const Type *T);
54
36
void AddQualType (QualType T);
@@ -92,8 +74,7 @@ void TemplateArgumentHasher::AddTemplateArgument(TemplateArgument TA) {
92
74
case TemplateArgument::Expression:
93
75
// If we meet expression in template argument, it implies
94
76
// 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.
97
78
break ;
98
79
case TemplateArgument::Pack:
99
80
AddInteger (TA.pack_size ());
@@ -110,10 +91,9 @@ void TemplateArgumentHasher::AddStructuralValue(const APValue &Value) {
110
91
111
92
// 'APValue::Profile' uses pointer values to make hash for LValue and
112
93
// 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.
114
95
115
96
if (Kind == APValue::LValue || Kind == APValue::MemberPointer) {
116
- BailedOut = true ;
117
97
return ;
118
98
}
119
99
@@ -135,14 +115,11 @@ void TemplateArgumentHasher::AddTemplateName(TemplateName Name) {
135
115
case TemplateName::DependentTemplate:
136
116
case TemplateName::SubstTemplateTemplateParm:
137
117
case TemplateName::SubstTemplateTemplateParmPack:
138
- BailedOut = true ;
139
118
break ;
140
119
case TemplateName::UsingTemplate: {
141
120
UsingShadowDecl *USD = Name.getAsUsingShadowDecl ();
142
121
if (USD)
143
122
AddDecl (USD->getTargetDecl ());
144
- else
145
- BailedOut = true ;
146
123
break ;
147
124
}
148
125
}
@@ -164,7 +141,6 @@ void TemplateArgumentHasher::AddDeclarationName(DeclarationName Name) {
164
141
case DeclarationName::ObjCZeroArgSelector:
165
142
case DeclarationName::ObjCOneArgSelector:
166
143
case DeclarationName::ObjCMultiArgSelector:
167
- BailedOut = true ;
168
144
break ;
169
145
case DeclarationName::CXXConstructorName:
170
146
case DeclarationName::CXXDestructorName:
@@ -191,16 +167,29 @@ void TemplateArgumentHasher::AddDeclarationName(DeclarationName Name) {
191
167
void TemplateArgumentHasher::AddDecl (const Decl *D) {
192
168
const NamedDecl *ND = dyn_cast<NamedDecl>(D);
193
169
if (!ND) {
194
- BailedOut = true ;
195
170
return ;
196
171
}
197
172
198
173
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);
199
189
}
200
190
201
191
void TemplateArgumentHasher::AddQualType (QualType T) {
202
192
if (T.isNull ()) {
203
- BailedOut = true ;
204
193
return ;
205
194
}
206
195
SplitQualType split = T.split ();
@@ -210,7 +199,6 @@ void TemplateArgumentHasher::AddQualType(QualType T) {
210
199
211
200
// Process a Type pointer. Add* methods call back into TemplateArgumentHasher
212
201
// while Visit* methods process the relevant parts of the Type.
213
- // Any unhandled type will make the hash computation bail out.
214
202
class TypeVisitorHelper : public TypeVisitor <TypeVisitorHelper> {
215
203
typedef TypeVisitor<TypeVisitorHelper> Inherited;
216
204
llvm::FoldingSetNodeID &ID;
@@ -242,9 +230,6 @@ class TypeVisitorHelper : public TypeVisitor<TypeVisitorHelper> {
242
230
243
231
void Visit (const Type *T) { Inherited::Visit (T); }
244
232
245
- // Unhandled types. Bail out simply.
246
- void VisitType (const Type *T) { Hash.setBailedOut (); }
247
-
248
233
void VisitAdjustedType (const AdjustedType *T) {
249
234
AddQualType (T->getOriginalType ());
250
235
}
0 commit comments