xref: /llvm-project/clang/lib/Serialization/TemplateArgumentHasher.cpp (revision 20e904950967c125abc1e91f57e5a373987ff016)
1*20e90495SChuanqi Xu //===- TemplateArgumentHasher.cpp - Hash Template Arguments -----*- C++ -*-===//
2*20e90495SChuanqi Xu //
3*20e90495SChuanqi Xu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*20e90495SChuanqi Xu // See https://llvm.org/LICENSE.txt for license information.
5*20e90495SChuanqi Xu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*20e90495SChuanqi Xu //
7*20e90495SChuanqi Xu //===----------------------------------------------------------------------===//
8*20e90495SChuanqi Xu 
9*20e90495SChuanqi Xu #include "TemplateArgumentHasher.h"
10*20e90495SChuanqi Xu #include "clang/AST/APValue.h"
11*20e90495SChuanqi Xu #include "clang/AST/Decl.h"
12*20e90495SChuanqi Xu #include "clang/AST/DeclCXX.h"
13*20e90495SChuanqi Xu #include "clang/AST/DeclTemplate.h"
14*20e90495SChuanqi Xu #include "clang/AST/DeclarationName.h"
15*20e90495SChuanqi Xu #include "clang/AST/TypeVisitor.h"
16*20e90495SChuanqi Xu #include "clang/Basic/IdentifierTable.h"
17*20e90495SChuanqi Xu #include "llvm/ADT/FoldingSet.h"
18*20e90495SChuanqi Xu 
19*20e90495SChuanqi Xu using namespace clang;
20*20e90495SChuanqi Xu 
21*20e90495SChuanqi Xu namespace {
22*20e90495SChuanqi Xu 
23*20e90495SChuanqi Xu class TemplateArgumentHasher {
24*20e90495SChuanqi Xu   // If we bail out during the process of calculating hash values for
25*20e90495SChuanqi Xu   // template arguments for any reason. We're allowed to do it since
26*20e90495SChuanqi Xu   // TemplateArgumentHasher are only required to give the same hash value
27*20e90495SChuanqi Xu   // for the same template arguments, but not required to give different
28*20e90495SChuanqi Xu   // hash value for different template arguments.
29*20e90495SChuanqi Xu   //
30*20e90495SChuanqi Xu   // So in the worst case, it is still a valid implementation to give all
31*20e90495SChuanqi Xu   // inputs the same BailedOutValue as output.
32*20e90495SChuanqi Xu   bool BailedOut = false;
33*20e90495SChuanqi Xu   static constexpr unsigned BailedOutValue = 0x12345678;
34*20e90495SChuanqi Xu 
35*20e90495SChuanqi Xu   llvm::FoldingSetNodeID ID;
36*20e90495SChuanqi Xu 
37*20e90495SChuanqi Xu public:
38*20e90495SChuanqi Xu   TemplateArgumentHasher() = default;
39*20e90495SChuanqi Xu 
40*20e90495SChuanqi Xu   void AddTemplateArgument(TemplateArgument TA);
41*20e90495SChuanqi Xu 
42*20e90495SChuanqi Xu   void AddInteger(unsigned V) { ID.AddInteger(V); }
43*20e90495SChuanqi Xu 
44*20e90495SChuanqi Xu   unsigned getValue() {
45*20e90495SChuanqi Xu     if (BailedOut)
46*20e90495SChuanqi Xu       return BailedOutValue;
47*20e90495SChuanqi Xu 
48*20e90495SChuanqi Xu     return ID.computeStableHash();
49*20e90495SChuanqi Xu   }
50*20e90495SChuanqi Xu 
51*20e90495SChuanqi Xu   void setBailedOut() { BailedOut = true; }
52*20e90495SChuanqi Xu 
53*20e90495SChuanqi Xu   void AddType(const Type *T);
54*20e90495SChuanqi Xu   void AddQualType(QualType T);
55*20e90495SChuanqi Xu   void AddDecl(const Decl *D);
56*20e90495SChuanqi Xu   void AddStructuralValue(const APValue &);
57*20e90495SChuanqi Xu   void AddTemplateName(TemplateName Name);
58*20e90495SChuanqi Xu   void AddDeclarationName(DeclarationName Name);
59*20e90495SChuanqi Xu   void AddIdentifierInfo(const IdentifierInfo *II);
60*20e90495SChuanqi Xu };
61*20e90495SChuanqi Xu 
62*20e90495SChuanqi Xu void TemplateArgumentHasher::AddTemplateArgument(TemplateArgument TA) {
63*20e90495SChuanqi Xu   const auto Kind = TA.getKind();
64*20e90495SChuanqi Xu   AddInteger(Kind);
65*20e90495SChuanqi Xu 
66*20e90495SChuanqi Xu   switch (Kind) {
67*20e90495SChuanqi Xu   case TemplateArgument::Null:
68*20e90495SChuanqi Xu     llvm_unreachable("Expected valid TemplateArgument");
69*20e90495SChuanqi Xu   case TemplateArgument::Type:
70*20e90495SChuanqi Xu     AddQualType(TA.getAsType());
71*20e90495SChuanqi Xu     break;
72*20e90495SChuanqi Xu   case TemplateArgument::Declaration:
73*20e90495SChuanqi Xu     AddDecl(TA.getAsDecl());
74*20e90495SChuanqi Xu     break;
75*20e90495SChuanqi Xu   case TemplateArgument::NullPtr:
76*20e90495SChuanqi Xu     ID.AddPointer(nullptr);
77*20e90495SChuanqi Xu     break;
78*20e90495SChuanqi Xu   case TemplateArgument::Integral: {
79*20e90495SChuanqi Xu     // There are integrals (e.g.: _BitInt(128)) that cannot be represented as
80*20e90495SChuanqi Xu     // any builtin integral type, so we use the hash of APSInt instead.
81*20e90495SChuanqi Xu     TA.getAsIntegral().Profile(ID);
82*20e90495SChuanqi Xu     break;
83*20e90495SChuanqi Xu   }
84*20e90495SChuanqi Xu   case TemplateArgument::StructuralValue:
85*20e90495SChuanqi Xu     AddQualType(TA.getStructuralValueType());
86*20e90495SChuanqi Xu     AddStructuralValue(TA.getAsStructuralValue());
87*20e90495SChuanqi Xu     break;
88*20e90495SChuanqi Xu   case TemplateArgument::Template:
89*20e90495SChuanqi Xu   case TemplateArgument::TemplateExpansion:
90*20e90495SChuanqi Xu     AddTemplateName(TA.getAsTemplateOrTemplatePattern());
91*20e90495SChuanqi Xu     break;
92*20e90495SChuanqi Xu   case TemplateArgument::Expression:
93*20e90495SChuanqi Xu     // If we meet expression in template argument, it implies
94*20e90495SChuanqi Xu     // that the template is still dependent. It is meaningless
95*20e90495SChuanqi Xu     // to get a stable hash for the template. Bail out simply.
96*20e90495SChuanqi Xu     BailedOut = true;
97*20e90495SChuanqi Xu     break;
98*20e90495SChuanqi Xu   case TemplateArgument::Pack:
99*20e90495SChuanqi Xu     AddInteger(TA.pack_size());
100*20e90495SChuanqi Xu     for (auto SubTA : TA.pack_elements()) {
101*20e90495SChuanqi Xu       AddTemplateArgument(SubTA);
102*20e90495SChuanqi Xu     }
103*20e90495SChuanqi Xu     break;
104*20e90495SChuanqi Xu   }
105*20e90495SChuanqi Xu }
106*20e90495SChuanqi Xu 
107*20e90495SChuanqi Xu void TemplateArgumentHasher::AddStructuralValue(const APValue &Value) {
108*20e90495SChuanqi Xu   auto Kind = Value.getKind();
109*20e90495SChuanqi Xu   AddInteger(Kind);
110*20e90495SChuanqi Xu 
111*20e90495SChuanqi Xu   // 'APValue::Profile' uses pointer values to make hash for LValue and
112*20e90495SChuanqi Xu   // MemberPointer, but they differ from one compiler invocation to another.
113*20e90495SChuanqi Xu   // It may be difficult to handle such cases. Bail out simply.
114*20e90495SChuanqi Xu 
115*20e90495SChuanqi Xu   if (Kind == APValue::LValue || Kind == APValue::MemberPointer) {
116*20e90495SChuanqi Xu     BailedOut = true;
117*20e90495SChuanqi Xu     return;
118*20e90495SChuanqi Xu   }
119*20e90495SChuanqi Xu 
120*20e90495SChuanqi Xu   Value.Profile(ID);
121*20e90495SChuanqi Xu }
122*20e90495SChuanqi Xu 
123*20e90495SChuanqi Xu void TemplateArgumentHasher::AddTemplateName(TemplateName Name) {
124*20e90495SChuanqi Xu   switch (Name.getKind()) {
125*20e90495SChuanqi Xu   case TemplateName::Template:
126*20e90495SChuanqi Xu     AddDecl(Name.getAsTemplateDecl());
127*20e90495SChuanqi Xu     break;
128*20e90495SChuanqi Xu   case TemplateName::QualifiedTemplate: {
129*20e90495SChuanqi Xu     QualifiedTemplateName *QTN = Name.getAsQualifiedTemplateName();
130*20e90495SChuanqi Xu     AddTemplateName(QTN->getUnderlyingTemplate());
131*20e90495SChuanqi Xu     break;
132*20e90495SChuanqi Xu   }
133*20e90495SChuanqi Xu   case TemplateName::OverloadedTemplate:
134*20e90495SChuanqi Xu   case TemplateName::AssumedTemplate:
135*20e90495SChuanqi Xu   case TemplateName::DependentTemplate:
136*20e90495SChuanqi Xu   case TemplateName::SubstTemplateTemplateParm:
137*20e90495SChuanqi Xu   case TemplateName::SubstTemplateTemplateParmPack:
138*20e90495SChuanqi Xu     BailedOut = true;
139*20e90495SChuanqi Xu     break;
140*20e90495SChuanqi Xu   case TemplateName::UsingTemplate: {
141*20e90495SChuanqi Xu     UsingShadowDecl *USD = Name.getAsUsingShadowDecl();
142*20e90495SChuanqi Xu     if (USD)
143*20e90495SChuanqi Xu       AddDecl(USD->getTargetDecl());
144*20e90495SChuanqi Xu     else
145*20e90495SChuanqi Xu       BailedOut = true;
146*20e90495SChuanqi Xu     break;
147*20e90495SChuanqi Xu   }
148*20e90495SChuanqi Xu   case TemplateName::DeducedTemplate:
149*20e90495SChuanqi Xu     AddTemplateName(Name.getAsDeducedTemplateName()->getUnderlying());
150*20e90495SChuanqi Xu     break;
151*20e90495SChuanqi Xu   }
152*20e90495SChuanqi Xu }
153*20e90495SChuanqi Xu 
154*20e90495SChuanqi Xu void TemplateArgumentHasher::AddIdentifierInfo(const IdentifierInfo *II) {
155*20e90495SChuanqi Xu   assert(II && "Expecting non-null pointer.");
156*20e90495SChuanqi Xu   ID.AddString(II->getName());
157*20e90495SChuanqi Xu }
158*20e90495SChuanqi Xu 
159*20e90495SChuanqi Xu void TemplateArgumentHasher::AddDeclarationName(DeclarationName Name) {
160*20e90495SChuanqi Xu   if (Name.isEmpty())
161*20e90495SChuanqi Xu     return;
162*20e90495SChuanqi Xu 
163*20e90495SChuanqi Xu   switch (Name.getNameKind()) {
164*20e90495SChuanqi Xu   case DeclarationName::Identifier:
165*20e90495SChuanqi Xu     AddIdentifierInfo(Name.getAsIdentifierInfo());
166*20e90495SChuanqi Xu     break;
167*20e90495SChuanqi Xu   case DeclarationName::ObjCZeroArgSelector:
168*20e90495SChuanqi Xu   case DeclarationName::ObjCOneArgSelector:
169*20e90495SChuanqi Xu   case DeclarationName::ObjCMultiArgSelector:
170*20e90495SChuanqi Xu     BailedOut = true;
171*20e90495SChuanqi Xu     break;
172*20e90495SChuanqi Xu   case DeclarationName::CXXConstructorName:
173*20e90495SChuanqi Xu   case DeclarationName::CXXDestructorName:
174*20e90495SChuanqi Xu     AddQualType(Name.getCXXNameType());
175*20e90495SChuanqi Xu     break;
176*20e90495SChuanqi Xu   case DeclarationName::CXXOperatorName:
177*20e90495SChuanqi Xu     AddInteger(Name.getCXXOverloadedOperator());
178*20e90495SChuanqi Xu     break;
179*20e90495SChuanqi Xu   case DeclarationName::CXXLiteralOperatorName:
180*20e90495SChuanqi Xu     AddIdentifierInfo(Name.getCXXLiteralIdentifier());
181*20e90495SChuanqi Xu     break;
182*20e90495SChuanqi Xu   case DeclarationName::CXXConversionFunctionName:
183*20e90495SChuanqi Xu     AddQualType(Name.getCXXNameType());
184*20e90495SChuanqi Xu     break;
185*20e90495SChuanqi Xu   case DeclarationName::CXXUsingDirective:
186*20e90495SChuanqi Xu     break;
187*20e90495SChuanqi Xu   case DeclarationName::CXXDeductionGuideName: {
188*20e90495SChuanqi Xu     if (auto *Template = Name.getCXXDeductionGuideTemplate())
189*20e90495SChuanqi Xu       AddDecl(Template);
190*20e90495SChuanqi Xu   }
191*20e90495SChuanqi Xu   }
192*20e90495SChuanqi Xu }
193*20e90495SChuanqi Xu 
194*20e90495SChuanqi Xu void TemplateArgumentHasher::AddDecl(const Decl *D) {
195*20e90495SChuanqi Xu   const NamedDecl *ND = dyn_cast<NamedDecl>(D);
196*20e90495SChuanqi Xu   if (!ND) {
197*20e90495SChuanqi Xu     BailedOut = true;
198*20e90495SChuanqi Xu     return;
199*20e90495SChuanqi Xu   }
200*20e90495SChuanqi Xu 
201*20e90495SChuanqi Xu   AddDeclarationName(ND->getDeclName());
202*20e90495SChuanqi Xu }
203*20e90495SChuanqi Xu 
204*20e90495SChuanqi Xu void TemplateArgumentHasher::AddQualType(QualType T) {
205*20e90495SChuanqi Xu   if (T.isNull()) {
206*20e90495SChuanqi Xu     BailedOut = true;
207*20e90495SChuanqi Xu     return;
208*20e90495SChuanqi Xu   }
209*20e90495SChuanqi Xu   SplitQualType split = T.split();
210*20e90495SChuanqi Xu   AddInteger(split.Quals.getAsOpaqueValue());
211*20e90495SChuanqi Xu   AddType(split.Ty);
212*20e90495SChuanqi Xu }
213*20e90495SChuanqi Xu 
214*20e90495SChuanqi Xu // Process a Type pointer.  Add* methods call back into TemplateArgumentHasher
215*20e90495SChuanqi Xu // while Visit* methods process the relevant parts of the Type.
216*20e90495SChuanqi Xu // Any unhandled type will make the hash computation bail out.
217*20e90495SChuanqi Xu class TypeVisitorHelper : public TypeVisitor<TypeVisitorHelper> {
218*20e90495SChuanqi Xu   typedef TypeVisitor<TypeVisitorHelper> Inherited;
219*20e90495SChuanqi Xu   llvm::FoldingSetNodeID &ID;
220*20e90495SChuanqi Xu   TemplateArgumentHasher &Hash;
221*20e90495SChuanqi Xu 
222*20e90495SChuanqi Xu public:
223*20e90495SChuanqi Xu   TypeVisitorHelper(llvm::FoldingSetNodeID &ID, TemplateArgumentHasher &Hash)
224*20e90495SChuanqi Xu       : ID(ID), Hash(Hash) {}
225*20e90495SChuanqi Xu 
226*20e90495SChuanqi Xu   void AddDecl(const Decl *D) {
227*20e90495SChuanqi Xu     if (D)
228*20e90495SChuanqi Xu       Hash.AddDecl(D);
229*20e90495SChuanqi Xu     else
230*20e90495SChuanqi Xu       Hash.AddInteger(0);
231*20e90495SChuanqi Xu   }
232*20e90495SChuanqi Xu 
233*20e90495SChuanqi Xu   void AddQualType(QualType T) { Hash.AddQualType(T); }
234*20e90495SChuanqi Xu 
235*20e90495SChuanqi Xu   void AddType(const Type *T) {
236*20e90495SChuanqi Xu     if (T)
237*20e90495SChuanqi Xu       Hash.AddType(T);
238*20e90495SChuanqi Xu     else
239*20e90495SChuanqi Xu       Hash.AddInteger(0);
240*20e90495SChuanqi Xu   }
241*20e90495SChuanqi Xu 
242*20e90495SChuanqi Xu   void VisitQualifiers(Qualifiers Quals) {
243*20e90495SChuanqi Xu     Hash.AddInteger(Quals.getAsOpaqueValue());
244*20e90495SChuanqi Xu   }
245*20e90495SChuanqi Xu 
246*20e90495SChuanqi Xu   void Visit(const Type *T) { Inherited::Visit(T); }
247*20e90495SChuanqi Xu 
248*20e90495SChuanqi Xu   // Unhandled types. Bail out simply.
249*20e90495SChuanqi Xu   void VisitType(const Type *T) { Hash.setBailedOut(); }
250*20e90495SChuanqi Xu 
251*20e90495SChuanqi Xu   void VisitAdjustedType(const AdjustedType *T) {
252*20e90495SChuanqi Xu     AddQualType(T->getOriginalType());
253*20e90495SChuanqi Xu   }
254*20e90495SChuanqi Xu 
255*20e90495SChuanqi Xu   void VisitDecayedType(const DecayedType *T) {
256*20e90495SChuanqi Xu     // getDecayedType and getPointeeType are derived from getAdjustedType
257*20e90495SChuanqi Xu     // and don't need to be separately processed.
258*20e90495SChuanqi Xu     VisitAdjustedType(T);
259*20e90495SChuanqi Xu   }
260*20e90495SChuanqi Xu 
261*20e90495SChuanqi Xu   void VisitArrayType(const ArrayType *T) {
262*20e90495SChuanqi Xu     AddQualType(T->getElementType());
263*20e90495SChuanqi Xu     Hash.AddInteger(llvm::to_underlying(T->getSizeModifier()));
264*20e90495SChuanqi Xu     VisitQualifiers(T->getIndexTypeQualifiers());
265*20e90495SChuanqi Xu   }
266*20e90495SChuanqi Xu   void VisitConstantArrayType(const ConstantArrayType *T) {
267*20e90495SChuanqi Xu     T->getSize().Profile(ID);
268*20e90495SChuanqi Xu     VisitArrayType(T);
269*20e90495SChuanqi Xu   }
270*20e90495SChuanqi Xu 
271*20e90495SChuanqi Xu   void VisitAttributedType(const AttributedType *T) {
272*20e90495SChuanqi Xu     Hash.AddInteger(T->getAttrKind());
273*20e90495SChuanqi Xu     AddQualType(T->getModifiedType());
274*20e90495SChuanqi Xu   }
275*20e90495SChuanqi Xu 
276*20e90495SChuanqi Xu   void VisitBuiltinType(const BuiltinType *T) { Hash.AddInteger(T->getKind()); }
277*20e90495SChuanqi Xu 
278*20e90495SChuanqi Xu   void VisitComplexType(const ComplexType *T) {
279*20e90495SChuanqi Xu     AddQualType(T->getElementType());
280*20e90495SChuanqi Xu   }
281*20e90495SChuanqi Xu 
282*20e90495SChuanqi Xu   void VisitDecltypeType(const DecltypeType *T) {
283*20e90495SChuanqi Xu     AddQualType(T->getUnderlyingType());
284*20e90495SChuanqi Xu   }
285*20e90495SChuanqi Xu 
286*20e90495SChuanqi Xu   void VisitDeducedType(const DeducedType *T) {
287*20e90495SChuanqi Xu     AddQualType(T->getDeducedType());
288*20e90495SChuanqi Xu   }
289*20e90495SChuanqi Xu 
290*20e90495SChuanqi Xu   void VisitAutoType(const AutoType *T) { VisitDeducedType(T); }
291*20e90495SChuanqi Xu 
292*20e90495SChuanqi Xu   void VisitDeducedTemplateSpecializationType(
293*20e90495SChuanqi Xu       const DeducedTemplateSpecializationType *T) {
294*20e90495SChuanqi Xu     Hash.AddTemplateName(T->getTemplateName());
295*20e90495SChuanqi Xu     VisitDeducedType(T);
296*20e90495SChuanqi Xu   }
297*20e90495SChuanqi Xu 
298*20e90495SChuanqi Xu   void VisitFunctionType(const FunctionType *T) {
299*20e90495SChuanqi Xu     AddQualType(T->getReturnType());
300*20e90495SChuanqi Xu     T->getExtInfo().Profile(ID);
301*20e90495SChuanqi Xu     Hash.AddInteger(T->isConst());
302*20e90495SChuanqi Xu     Hash.AddInteger(T->isVolatile());
303*20e90495SChuanqi Xu     Hash.AddInteger(T->isRestrict());
304*20e90495SChuanqi Xu   }
305*20e90495SChuanqi Xu 
306*20e90495SChuanqi Xu   void VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
307*20e90495SChuanqi Xu     VisitFunctionType(T);
308*20e90495SChuanqi Xu   }
309*20e90495SChuanqi Xu 
310*20e90495SChuanqi Xu   void VisitFunctionProtoType(const FunctionProtoType *T) {
311*20e90495SChuanqi Xu     Hash.AddInteger(T->getNumParams());
312*20e90495SChuanqi Xu     for (auto ParamType : T->getParamTypes())
313*20e90495SChuanqi Xu       AddQualType(ParamType);
314*20e90495SChuanqi Xu 
315*20e90495SChuanqi Xu     VisitFunctionType(T);
316*20e90495SChuanqi Xu   }
317*20e90495SChuanqi Xu 
318*20e90495SChuanqi Xu   void VisitMemberPointerType(const MemberPointerType *T) {
319*20e90495SChuanqi Xu     AddQualType(T->getPointeeType());
320*20e90495SChuanqi Xu     AddType(T->getClass());
321*20e90495SChuanqi Xu   }
322*20e90495SChuanqi Xu 
323*20e90495SChuanqi Xu   void VisitPackExpansionType(const PackExpansionType *T) {
324*20e90495SChuanqi Xu     AddQualType(T->getPattern());
325*20e90495SChuanqi Xu   }
326*20e90495SChuanqi Xu 
327*20e90495SChuanqi Xu   void VisitParenType(const ParenType *T) { AddQualType(T->getInnerType()); }
328*20e90495SChuanqi Xu 
329*20e90495SChuanqi Xu   void VisitPointerType(const PointerType *T) {
330*20e90495SChuanqi Xu     AddQualType(T->getPointeeType());
331*20e90495SChuanqi Xu   }
332*20e90495SChuanqi Xu 
333*20e90495SChuanqi Xu   void VisitReferenceType(const ReferenceType *T) {
334*20e90495SChuanqi Xu     AddQualType(T->getPointeeTypeAsWritten());
335*20e90495SChuanqi Xu   }
336*20e90495SChuanqi Xu 
337*20e90495SChuanqi Xu   void VisitLValueReferenceType(const LValueReferenceType *T) {
338*20e90495SChuanqi Xu     VisitReferenceType(T);
339*20e90495SChuanqi Xu   }
340*20e90495SChuanqi Xu 
341*20e90495SChuanqi Xu   void VisitRValueReferenceType(const RValueReferenceType *T) {
342*20e90495SChuanqi Xu     VisitReferenceType(T);
343*20e90495SChuanqi Xu   }
344*20e90495SChuanqi Xu 
345*20e90495SChuanqi Xu   void
346*20e90495SChuanqi Xu   VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
347*20e90495SChuanqi Xu     AddDecl(T->getAssociatedDecl());
348*20e90495SChuanqi Xu     Hash.AddTemplateArgument(T->getArgumentPack());
349*20e90495SChuanqi Xu   }
350*20e90495SChuanqi Xu 
351*20e90495SChuanqi Xu   void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
352*20e90495SChuanqi Xu     AddDecl(T->getAssociatedDecl());
353*20e90495SChuanqi Xu     AddQualType(T->getReplacementType());
354*20e90495SChuanqi Xu   }
355*20e90495SChuanqi Xu 
356*20e90495SChuanqi Xu   void VisitTagType(const TagType *T) { AddDecl(T->getDecl()); }
357*20e90495SChuanqi Xu 
358*20e90495SChuanqi Xu   void VisitRecordType(const RecordType *T) { VisitTagType(T); }
359*20e90495SChuanqi Xu   void VisitEnumType(const EnumType *T) { VisitTagType(T); }
360*20e90495SChuanqi Xu 
361*20e90495SChuanqi Xu   void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
362*20e90495SChuanqi Xu     Hash.AddInteger(T->template_arguments().size());
363*20e90495SChuanqi Xu     for (const auto &TA : T->template_arguments()) {
364*20e90495SChuanqi Xu       Hash.AddTemplateArgument(TA);
365*20e90495SChuanqi Xu     }
366*20e90495SChuanqi Xu     Hash.AddTemplateName(T->getTemplateName());
367*20e90495SChuanqi Xu   }
368*20e90495SChuanqi Xu 
369*20e90495SChuanqi Xu   void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
370*20e90495SChuanqi Xu     Hash.AddInteger(T->getDepth());
371*20e90495SChuanqi Xu     Hash.AddInteger(T->getIndex());
372*20e90495SChuanqi Xu     Hash.AddInteger(T->isParameterPack());
373*20e90495SChuanqi Xu   }
374*20e90495SChuanqi Xu 
375*20e90495SChuanqi Xu   void VisitTypedefType(const TypedefType *T) { AddDecl(T->getDecl()); }
376*20e90495SChuanqi Xu 
377*20e90495SChuanqi Xu   void VisitElaboratedType(const ElaboratedType *T) {
378*20e90495SChuanqi Xu     AddQualType(T->getNamedType());
379*20e90495SChuanqi Xu   }
380*20e90495SChuanqi Xu 
381*20e90495SChuanqi Xu   void VisitUnaryTransformType(const UnaryTransformType *T) {
382*20e90495SChuanqi Xu     AddQualType(T->getUnderlyingType());
383*20e90495SChuanqi Xu     AddQualType(T->getBaseType());
384*20e90495SChuanqi Xu   }
385*20e90495SChuanqi Xu 
386*20e90495SChuanqi Xu   void VisitVectorType(const VectorType *T) {
387*20e90495SChuanqi Xu     AddQualType(T->getElementType());
388*20e90495SChuanqi Xu     Hash.AddInteger(T->getNumElements());
389*20e90495SChuanqi Xu     Hash.AddInteger(llvm::to_underlying(T->getVectorKind()));
390*20e90495SChuanqi Xu   }
391*20e90495SChuanqi Xu 
392*20e90495SChuanqi Xu   void VisitExtVectorType(const ExtVectorType *T) { VisitVectorType(T); }
393*20e90495SChuanqi Xu };
394*20e90495SChuanqi Xu 
395*20e90495SChuanqi Xu void TemplateArgumentHasher::AddType(const Type *T) {
396*20e90495SChuanqi Xu   assert(T && "Expecting non-null pointer.");
397*20e90495SChuanqi Xu   TypeVisitorHelper(ID, *this).Visit(T);
398*20e90495SChuanqi Xu }
399*20e90495SChuanqi Xu 
400*20e90495SChuanqi Xu } // namespace
401*20e90495SChuanqi Xu 
402*20e90495SChuanqi Xu unsigned clang::serialization::StableHashForTemplateArguments(
403*20e90495SChuanqi Xu     llvm::ArrayRef<TemplateArgument> Args) {
404*20e90495SChuanqi Xu   TemplateArgumentHasher Hasher;
405*20e90495SChuanqi Xu   Hasher.AddInteger(Args.size());
406*20e90495SChuanqi Xu   for (TemplateArgument Arg : Args)
407*20e90495SChuanqi Xu     Hasher.AddTemplateArgument(Arg);
408*20e90495SChuanqi Xu   return Hasher.getValue();
409*20e90495SChuanqi Xu }
410