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