@@ -21,17 +21,6 @@ using namespace clang;
2121namespace {
2222
2323class 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
3726public:
@@ -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) {
191167void 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
201191void 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.
214202class 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