clang 20.0.0git
TemplateArgumentHasher.cpp
Go to the documentation of this file.
1//===- TemplateArgumentHasher.cpp - Hash Template Arguments -----*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "clang/AST/APValue.h"
11#include "clang/AST/Decl.h"
12#include "clang/AST/DeclCXX.h"
17#include "llvm/ADT/FoldingSet.h"
18
19using namespace clang;
20
21namespace {
22
23class 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 llvm::FoldingSetNodeID ID;
36
37public:
38 TemplateArgumentHasher() = default;
39
40 void AddTemplateArgument(TemplateArgument TA);
41
42 void AddInteger(unsigned V) { ID.AddInteger(V); }
43
44 unsigned getValue() {
45 if (BailedOut)
46 return BailedOutValue;
47
48 return ID.computeStableHash();
49 }
50
51 void setBailedOut() { BailedOut = true; }
52
53 void AddType(const Type *T);
54 void AddQualType(QualType T);
55 void AddDecl(const Decl *D);
56 void AddStructuralValue(const APValue &);
57 void AddTemplateName(TemplateName Name);
58 void AddDeclarationName(DeclarationName Name);
59 void AddIdentifierInfo(const IdentifierInfo *II);
60};
61
62void TemplateArgumentHasher::AddTemplateArgument(TemplateArgument TA) {
63 const auto Kind = TA.getKind();
64 AddInteger(Kind);
65
66 switch (Kind) {
68 llvm_unreachable("Expected valid TemplateArgument");
70 AddQualType(TA.getAsType());
71 break;
73 AddDecl(TA.getAsDecl());
74 break;
76 ID.AddPointer(nullptr);
77 break;
79 // There are integrals (e.g.: _BitInt(128)) that cannot be represented as
80 // any builtin integral type, so we use the hash of APSInt instead.
81 TA.getAsIntegral().Profile(ID);
82 break;
83 }
85 AddQualType(TA.getStructuralValueType());
86 AddStructuralValue(TA.getAsStructuralValue());
87 break;
90 AddTemplateName(TA.getAsTemplateOrTemplatePattern());
91 break;
93 // If we meet expression in template argument, it implies
94 // that the template is still dependent. It is meaningless
95 // to get a stable hash for the template. Bail out simply.
96 BailedOut = true;
97 break;
99 AddInteger(TA.pack_size());
100 for (auto SubTA : TA.pack_elements()) {
101 AddTemplateArgument(SubTA);
102 }
103 break;
104 }
105}
106
107void TemplateArgumentHasher::AddStructuralValue(const APValue &Value) {
108 auto Kind = Value.getKind();
109 AddInteger(Kind);
110
111 // 'APValue::Profile' uses pointer values to make hash for LValue and
112 // MemberPointer, but they differ from one compiler invocation to another.
113 // It may be difficult to handle such cases. Bail out simply.
114
115 if (Kind == APValue::LValue || Kind == APValue::MemberPointer) {
116 BailedOut = true;
117 return;
118 }
119
120 Value.Profile(ID);
121}
122
123void TemplateArgumentHasher::AddTemplateName(TemplateName Name) {
124 switch (Name.getKind()) {
126 AddDecl(Name.getAsTemplateDecl());
127 break;
129 QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName();
130 AddTemplateName(QTN->getUnderlyingTemplate());
131 break;
132 }
138 BailedOut = true;
139 break;
141 UsingShadowDecl *USD = Name.getAsUsingShadowDecl();
142 if (USD)
143 AddDecl(USD->getTargetDecl());
144 else
145 BailedOut = true;
146 break;
147 }
149 AddTemplateName(Name.getAsDeducedTemplateName()->getUnderlying());
150 break;
151 }
152}
153
154void TemplateArgumentHasher::AddIdentifierInfo(const IdentifierInfo *II) {
155 assert(II && "Expecting non-null pointer.");
156 ID.AddString(II->getName());
157}
158
159void TemplateArgumentHasher::AddDeclarationName(DeclarationName Name) {
160 if (Name.isEmpty())
161 return;
162
163 switch (Name.getNameKind()) {
165 AddIdentifierInfo(Name.getAsIdentifierInfo());
166 break;
170 BailedOut = true;
171 break;
174 AddQualType(Name.getCXXNameType());
175 break;
177 AddInteger(Name.getCXXOverloadedOperator());
178 break;
180 AddIdentifierInfo(Name.getCXXLiteralIdentifier());
181 break;
183 AddQualType(Name.getCXXNameType());
184 break;
186 break;
188 if (auto *Template = Name.getCXXDeductionGuideTemplate())
189 AddDecl(Template);
190 }
191 }
192}
193
194void TemplateArgumentHasher::AddDecl(const Decl *D) {
195 const NamedDecl *ND = dyn_cast<NamedDecl>(D);
196 if (!ND) {
197 BailedOut = true;
198 return;
199 }
200
201 AddDeclarationName(ND->getDeclName());
202}
203
204void TemplateArgumentHasher::AddQualType(QualType T) {
205 if (T.isNull()) {
206 BailedOut = true;
207 return;
208 }
209 SplitQualType split = T.split();
210 AddInteger(split.Quals.getAsOpaqueValue());
211 AddType(split.Ty);
212}
213
214// Process a Type pointer. Add* methods call back into TemplateArgumentHasher
215// while Visit* methods process the relevant parts of the Type.
216// Any unhandled type will make the hash computation bail out.
217class TypeVisitorHelper : public TypeVisitor<TypeVisitorHelper> {
218 typedef TypeVisitor<TypeVisitorHelper> Inherited;
219 llvm::FoldingSetNodeID &ID;
220 TemplateArgumentHasher &Hash;
221
222public:
223 TypeVisitorHelper(llvm::FoldingSetNodeID &ID, TemplateArgumentHasher &Hash)
224 : ID(ID), Hash(Hash) {}
225
226 void AddDecl(const Decl *D) {
227 if (D)
228 Hash.AddDecl(D);
229 else
230 Hash.AddInteger(0);
231 }
232
233 void AddQualType(QualType T) { Hash.AddQualType(T); }
234
235 void AddType(const Type *T) {
236 if (T)
237 Hash.AddType(T);
238 else
239 Hash.AddInteger(0);
240 }
241
242 void VisitQualifiers(Qualifiers Quals) {
243 Hash.AddInteger(Quals.getAsOpaqueValue());
244 }
245
246 void Visit(const Type *T) { Inherited::Visit(T); }
247
248 // Unhandled types. Bail out simply.
249 void VisitType(const Type *T) { Hash.setBailedOut(); }
250
251 void VisitAdjustedType(const AdjustedType *T) {
252 AddQualType(T->getOriginalType());
253 }
254
255 void VisitDecayedType(const DecayedType *T) {
256 // getDecayedType and getPointeeType are derived from getAdjustedType
257 // and don't need to be separately processed.
258 VisitAdjustedType(T);
259 }
260
261 void VisitArrayType(const ArrayType *T) {
262 AddQualType(T->getElementType());
263 Hash.AddInteger(llvm::to_underlying(T->getSizeModifier()));
264 VisitQualifiers(T->getIndexTypeQualifiers());
265 }
266 void VisitConstantArrayType(const ConstantArrayType *T) {
267 T->getSize().Profile(ID);
268 VisitArrayType(T);
269 }
270
271 void VisitAttributedType(const AttributedType *T) {
272 Hash.AddInteger(T->getAttrKind());
273 AddQualType(T->getModifiedType());
274 }
275
276 void VisitBuiltinType(const BuiltinType *T) { Hash.AddInteger(T->getKind()); }
277
278 void VisitComplexType(const ComplexType *T) {
279 AddQualType(T->getElementType());
280 }
281
282 void VisitDecltypeType(const DecltypeType *T) {
283 AddQualType(T->getUnderlyingType());
284 }
285
286 void VisitDeducedType(const DeducedType *T) {
287 AddQualType(T->getDeducedType());
288 }
289
290 void VisitAutoType(const AutoType *T) { VisitDeducedType(T); }
291
292 void VisitDeducedTemplateSpecializationType(
294 Hash.AddTemplateName(T->getTemplateName());
295 VisitDeducedType(T);
296 }
297
298 void VisitFunctionType(const FunctionType *T) {
299 AddQualType(T->getReturnType());
300 T->getExtInfo().Profile(ID);
301 Hash.AddInteger(T->isConst());
302 Hash.AddInteger(T->isVolatile());
303 Hash.AddInteger(T->isRestrict());
304 }
305
306 void VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
307 VisitFunctionType(T);
308 }
309
310 void VisitFunctionProtoType(const FunctionProtoType *T) {
311 Hash.AddInteger(T->getNumParams());
312 for (auto ParamType : T->getParamTypes())
313 AddQualType(ParamType);
314
315 VisitFunctionType(T);
316 }
317
318 void VisitMemberPointerType(const MemberPointerType *T) {
319 AddQualType(T->getPointeeType());
320 AddType(T->getClass());
321 }
322
323 void VisitPackExpansionType(const PackExpansionType *T) {
324 AddQualType(T->getPattern());
325 }
326
327 void VisitParenType(const ParenType *T) { AddQualType(T->getInnerType()); }
328
329 void VisitPointerType(const PointerType *T) {
330 AddQualType(T->getPointeeType());
331 }
332
333 void VisitReferenceType(const ReferenceType *T) {
334 AddQualType(T->getPointeeTypeAsWritten());
335 }
336
337 void VisitLValueReferenceType(const LValueReferenceType *T) {
338 VisitReferenceType(T);
339 }
340
341 void VisitRValueReferenceType(const RValueReferenceType *T) {
342 VisitReferenceType(T);
343 }
344
345 void
346 VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
347 AddDecl(T->getAssociatedDecl());
348 Hash.AddTemplateArgument(T->getArgumentPack());
349 }
350
351 void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
352 AddDecl(T->getAssociatedDecl());
353 AddQualType(T->getReplacementType());
354 }
355
356 void VisitTagType(const TagType *T) { AddDecl(T->getDecl()); }
357
358 void VisitRecordType(const RecordType *T) { VisitTagType(T); }
359 void VisitEnumType(const EnumType *T) { VisitTagType(T); }
360
361 void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
362 Hash.AddInteger(T->template_arguments().size());
363 for (const auto &TA : T->template_arguments()) {
364 Hash.AddTemplateArgument(TA);
365 }
366 Hash.AddTemplateName(T->getTemplateName());
367 }
368
369 void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
370 Hash.AddInteger(T->getDepth());
371 Hash.AddInteger(T->getIndex());
372 Hash.AddInteger(T->isParameterPack());
373 }
374
375 void VisitTypedefType(const TypedefType *T) { AddDecl(T->getDecl()); }
376
377 void VisitElaboratedType(const ElaboratedType *T) {
378 AddQualType(T->getNamedType());
379 }
380
381 void VisitUnaryTransformType(const UnaryTransformType *T) {
382 AddQualType(T->getUnderlyingType());
383 AddQualType(T->getBaseType());
384 }
385
386 void VisitVectorType(const VectorType *T) {
387 AddQualType(T->getElementType());
388 Hash.AddInteger(T->getNumElements());
389 Hash.AddInteger(llvm::to_underlying(T->getVectorKind()));
390 }
391
392 void VisitExtVectorType(const ExtVectorType *T) { VisitVectorType(T); }
393};
394
395void TemplateArgumentHasher::AddType(const Type *T) {
396 assert(T && "Expecting non-null pointer.");
397 TypeVisitorHelper(ID, *this).Visit(T);
398}
399
400} // namespace
401
404 TemplateArgumentHasher Hasher;
405 Hasher.AddInteger(Args.size());
406 for (TemplateArgument Arg : Args)
407 Hasher.AddTemplateArgument(Arg);
408 return Hasher.getValue();
409}
#define V(N, I)
Definition: ASTContext.h:3443
const Decl * D
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the C++ template declaration subclasses.
Defines the clang::IdentifierInfo, clang::IdentifierTable, and clang::Selector interfaces.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
Represents a type which was implicitly adjusted by the semantic engine for arbitrary reasons.
Definition: Type.h:3357
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3577
An attributed type is a type to which a type attribute has been applied.
Definition: Type.h:6127
Represents a C++11 auto or C++14 decltype(auto) type, possibly constrained by a type-constraint.
Definition: Type.h:6556
This class is used for builtin types like 'int'.
Definition: Type.h:3034
Complex values, per C99 6.2.5p11.
Definition: Type.h:3145
Represents the canonical version of C arrays with a specified constant size.
Definition: Type.h:3615
Represents a pointer type decayed from an array or function type.
Definition: Type.h:3391
Decl - This represents one declaration (or definition), e.g.
Definition: DeclBase.h:86
The name of a declaration.
Represents the type decltype(expr) (C++11).
Definition: Type.h:5874
Represents a C++17 deduced template specialization type.
Definition: Type.h:6604
Common base class for placeholders for types that get replaced by placeholder type deduction: C++11 a...
Definition: Type.h:6522
Represents a type that was referred to using an elaborated type keyword, e.g., struct S,...
Definition: Type.h:6943
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of enums.
Definition: Type.h:6098
ExtVectorType - Extended vector type.
Definition: Type.h:4126
Represents a K&R-style 'int foo()' function, which has no information available about its arguments.
Definition: Type.h:4681
Represents a prototype with parameter type info, e.g.
Definition: Type.h:5102
unsigned getNumParams() const
Definition: Type.h:5355
void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Ctx)
Definition: Type.cpp:3867
ArrayRef< QualType > getParamTypes() const
Definition: Type.h:5362
void Profile(llvm::FoldingSetNodeID &ID) const
Definition: Type.h:4551
FunctionType - C99 6.7.5.3 - Function Declarators.
Definition: Type.h:4321
ExtInfo getExtInfo() const
Definition: Type.h:4655
bool isConst() const
Definition: Type.h:4661
bool isRestrict() const
Definition: Type.h:4663
QualType getReturnType() const
Definition: Type.h:4643
bool isVolatile() const
Definition: Type.h:4662
One of these records is kept for each identifier that is lexed.
StringRef getName() const
Return the actual identifier string.
An lvalue reference type, per C++11 [dcl.ref].
Definition: Type.h:3483
A pointer to member type per C++ 8.3.3 - Pointers to members.
Definition: Type.h:3519
This represents a decl that may have a name.
Definition: Decl.h:253
DeclarationName getDeclName() const
Get the actual, stored name of the declaration, which may be a special name.
Definition: Decl.h:319
Represents a pack expansion of types.
Definition: Type.h:7141
Sugar for parentheses used when specifying types.
Definition: Type.h:3172
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3198
A (possibly-)qualified type.
Definition: Type.h:929
Represents a template name as written in source code.
Definition: TemplateName.h:491
TemplateName getUnderlyingTemplate() const
Return the underlying template name.
Definition: TemplateName.h:526
The collection of all-type qualifiers we support.
Definition: Type.h:324
uint64_t getAsOpaqueValue() const
Definition: Type.h:448
An rvalue reference type, per C++11 [dcl.ref].
Definition: Type.h:3501
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:6072
Base for LValueReferenceType and RValueReferenceType.
Definition: Type.h:3439
Represents the result of substituting a set of types for a template type parameter pack.
Definition: Type.h:6464
Represents the result of substituting a type for a template type parameter.
Definition: Type.h:6383
Represents a template argument.
Definition: TemplateBase.h:61
QualType getStructuralValueType() const
Get the type of a StructuralValue.
Definition: TemplateBase.h:399
QualType getAsType() const
Retrieve the type for a type template argument.
Definition: TemplateBase.h:319
llvm::APSInt getAsIntegral() const
Retrieve the template argument as an integral value.
Definition: TemplateBase.h:363
unsigned pack_size() const
The number of template arguments in the given template argument pack.
Definition: TemplateBase.h:438
ValueDecl * getAsDecl() const
Retrieve the declaration for a declaration non-type template argument.
Definition: TemplateBase.h:326
ArrayRef< TemplateArgument > pack_elements() const
Iterator range referencing all of the elements of a template argument pack.
Definition: TemplateBase.h:432
@ Declaration
The template argument is a declaration that was provided for a pointer, reference,...
Definition: TemplateBase.h:74
@ Template
The template argument is a template name that was provided for a template template parameter.
Definition: TemplateBase.h:93
@ StructuralValue
The template argument is a non-type template argument that can't be represented by the special-case D...
Definition: TemplateBase.h:89
@ Pack
The template argument is actually a parameter pack.
Definition: TemplateBase.h:107
@ TemplateExpansion
The template argument is a pack expansion of a template name that was provided for a template templat...
Definition: TemplateBase.h:97
@ NullPtr
The template argument is a null pointer or null pointer to member that was provided for a non-type te...
Definition: TemplateBase.h:78
@ Type
The template argument is a type.
Definition: TemplateBase.h:70
@ Null
Represents an empty template argument, e.g., one that has not been deduced.
Definition: TemplateBase.h:67
@ Integral
The template argument is an integral value stored in an llvm::APSInt that was provided for an integra...
Definition: TemplateBase.h:82
@ Expression
The template argument is an expression, and we've not resolved it to one of the other forms yet,...
Definition: TemplateBase.h:103
ArgKind getKind() const
Return the kind of stored template argument.
Definition: TemplateBase.h:295
TemplateName getAsTemplateOrTemplatePattern() const
Retrieve the template argument as a template name; if the argument is a pack expansion,...
Definition: TemplateBase.h:350
const APValue & getAsStructuralValue() const
Get the value of a StructuralValue.
Definition: TemplateBase.h:396
Represents a C++ template name within the type system.
Definition: TemplateName.h:220
@ UsingTemplate
A template name that refers to a template declaration found through a specific using shadow declarati...
Definition: TemplateName.h:265
@ OverloadedTemplate
A set of overloaded template declarations.
Definition: TemplateName.h:240
@ Template
A single template declaration.
Definition: TemplateName.h:237
@ DependentTemplate
A dependent template name that has not been resolved to a template (or set of templates).
Definition: TemplateName.h:252
@ SubstTemplateTemplateParm
A template template parameter that has been substituted for some other template name.
Definition: TemplateName.h:256
@ SubstTemplateTemplateParmPack
A template template parameter pack that has been substituted for a template template argument pack,...
Definition: TemplateName.h:261
@ DeducedTemplate
A template name that refers to another TemplateName with deduced default arguments.
Definition: TemplateName.h:269
@ QualifiedTemplate
A qualified template name, where the qualification is kept to describe the source code as written.
Definition: TemplateName.h:248
@ AssumedTemplate
An unqualified-id that has been assumed to name a function template that will be found by ADL.
Definition: TemplateName.h:244
Represents a type template specialization; the template must be a class template, a type alias templa...
Definition: Type.h:6661
An operation on a type.
Definition: TypeVisitor.h:64
RetTy Visit(const Type *T)
Performs the operation associated with this visitor object.
Definition: TypeVisitor.h:68
RetTy VisitType(const Type *)
Method called if ImpClass doesn't provide specific handler for some type class.
Definition: TypeVisitor.h:87
The base class of the type hierarchy.
Definition: Type.h:1828
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:738
A unary type transform, which is a type constructed from another.
Definition: Type.h:5989
Represents a shadow declaration implicitly introduced into a scope by a (resolved) using-declaration ...
Definition: DeclCXX.h:3338
NamedDecl * getTargetDecl() const
Gets the underlying declaration which has been brought into the local scope.
Definition: DeclCXX.h:3402
Kind getKind() const
Definition: Value.h:137
Represents a GCC generic vector type.
Definition: Type.h:4034
unsigned StableHashForTemplateArguments(llvm::ArrayRef< TemplateArgument > Args)
Calculate a stable hash value for template arguments.
The JSON file list parser is used to communicate input to InstallAPI.
const FunctionProtoType * T
A std::pair-like structure for storing a qualified type split into its local qualifiers and its local...
Definition: Type.h:862
const Type * Ty
The locally-unqualified type.
Definition: Type.h:864
Qualifiers Quals
The local qualifiers.
Definition: Type.h:867