17330f729Sjoerg //===-- ODRHash.cpp - Hashing to diagnose ODR failures ----------*- C++ -*-===//
27330f729Sjoerg //
37330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
47330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
57330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
67330f729Sjoerg //
77330f729Sjoerg //===----------------------------------------------------------------------===//
87330f729Sjoerg ///
97330f729Sjoerg /// \file
107330f729Sjoerg /// This file implements the ODRHash class, which calculates a hash based
117330f729Sjoerg /// on AST nodes, which is stable across different runs.
127330f729Sjoerg ///
137330f729Sjoerg //===----------------------------------------------------------------------===//
147330f729Sjoerg
157330f729Sjoerg #include "clang/AST/ODRHash.h"
167330f729Sjoerg
177330f729Sjoerg #include "clang/AST/DeclVisitor.h"
187330f729Sjoerg #include "clang/AST/NestedNameSpecifier.h"
197330f729Sjoerg #include "clang/AST/StmtVisitor.h"
207330f729Sjoerg #include "clang/AST/TypeVisitor.h"
217330f729Sjoerg
227330f729Sjoerg using namespace clang;
237330f729Sjoerg
AddStmt(const Stmt * S)247330f729Sjoerg void ODRHash::AddStmt(const Stmt *S) {
257330f729Sjoerg assert(S && "Expecting non-null pointer.");
267330f729Sjoerg S->ProcessODRHash(ID, *this);
277330f729Sjoerg }
287330f729Sjoerg
AddIdentifierInfo(const IdentifierInfo * II)297330f729Sjoerg void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) {
307330f729Sjoerg assert(II && "Expecting non-null pointer.");
317330f729Sjoerg ID.AddString(II->getName());
327330f729Sjoerg }
337330f729Sjoerg
AddDeclarationName(DeclarationName Name,bool TreatAsDecl)347330f729Sjoerg void ODRHash::AddDeclarationName(DeclarationName Name, bool TreatAsDecl) {
357330f729Sjoerg if (TreatAsDecl)
367330f729Sjoerg // Matches the NamedDecl check in AddDecl
377330f729Sjoerg AddBoolean(true);
387330f729Sjoerg
397330f729Sjoerg AddDeclarationNameImpl(Name);
407330f729Sjoerg
417330f729Sjoerg if (TreatAsDecl)
427330f729Sjoerg // Matches the ClassTemplateSpecializationDecl check in AddDecl
437330f729Sjoerg AddBoolean(false);
447330f729Sjoerg }
457330f729Sjoerg
AddDeclarationNameImpl(DeclarationName Name)467330f729Sjoerg void ODRHash::AddDeclarationNameImpl(DeclarationName Name) {
477330f729Sjoerg // Index all DeclarationName and use index numbers to refer to them.
487330f729Sjoerg auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size()));
497330f729Sjoerg ID.AddInteger(Result.first->second);
507330f729Sjoerg if (!Result.second) {
517330f729Sjoerg // If found in map, the DeclarationName has previously been processed.
527330f729Sjoerg return;
537330f729Sjoerg }
547330f729Sjoerg
557330f729Sjoerg // First time processing each DeclarationName, also process its details.
567330f729Sjoerg AddBoolean(Name.isEmpty());
577330f729Sjoerg if (Name.isEmpty())
587330f729Sjoerg return;
597330f729Sjoerg
607330f729Sjoerg auto Kind = Name.getNameKind();
617330f729Sjoerg ID.AddInteger(Kind);
627330f729Sjoerg switch (Kind) {
637330f729Sjoerg case DeclarationName::Identifier:
647330f729Sjoerg AddIdentifierInfo(Name.getAsIdentifierInfo());
657330f729Sjoerg break;
667330f729Sjoerg case DeclarationName::ObjCZeroArgSelector:
677330f729Sjoerg case DeclarationName::ObjCOneArgSelector:
687330f729Sjoerg case DeclarationName::ObjCMultiArgSelector: {
697330f729Sjoerg Selector S = Name.getObjCSelector();
707330f729Sjoerg AddBoolean(S.isNull());
717330f729Sjoerg AddBoolean(S.isKeywordSelector());
727330f729Sjoerg AddBoolean(S.isUnarySelector());
737330f729Sjoerg unsigned NumArgs = S.getNumArgs();
747330f729Sjoerg ID.AddInteger(NumArgs);
757330f729Sjoerg for (unsigned i = 0; i < NumArgs; ++i) {
767330f729Sjoerg const IdentifierInfo *II = S.getIdentifierInfoForSlot(i);
777330f729Sjoerg AddBoolean(II);
787330f729Sjoerg if (II) {
797330f729Sjoerg AddIdentifierInfo(II);
807330f729Sjoerg }
817330f729Sjoerg }
827330f729Sjoerg break;
837330f729Sjoerg }
847330f729Sjoerg case DeclarationName::CXXConstructorName:
857330f729Sjoerg case DeclarationName::CXXDestructorName:
867330f729Sjoerg AddQualType(Name.getCXXNameType());
877330f729Sjoerg break;
887330f729Sjoerg case DeclarationName::CXXOperatorName:
897330f729Sjoerg ID.AddInteger(Name.getCXXOverloadedOperator());
907330f729Sjoerg break;
917330f729Sjoerg case DeclarationName::CXXLiteralOperatorName:
927330f729Sjoerg AddIdentifierInfo(Name.getCXXLiteralIdentifier());
937330f729Sjoerg break;
947330f729Sjoerg case DeclarationName::CXXConversionFunctionName:
957330f729Sjoerg AddQualType(Name.getCXXNameType());
967330f729Sjoerg break;
977330f729Sjoerg case DeclarationName::CXXUsingDirective:
987330f729Sjoerg break;
997330f729Sjoerg case DeclarationName::CXXDeductionGuideName: {
1007330f729Sjoerg auto *Template = Name.getCXXDeductionGuideTemplate();
1017330f729Sjoerg AddBoolean(Template);
1027330f729Sjoerg if (Template) {
1037330f729Sjoerg AddDecl(Template);
1047330f729Sjoerg }
1057330f729Sjoerg }
1067330f729Sjoerg }
1077330f729Sjoerg }
1087330f729Sjoerg
AddNestedNameSpecifier(const NestedNameSpecifier * NNS)1097330f729Sjoerg void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
1107330f729Sjoerg assert(NNS && "Expecting non-null pointer.");
1117330f729Sjoerg const auto *Prefix = NNS->getPrefix();
1127330f729Sjoerg AddBoolean(Prefix);
1137330f729Sjoerg if (Prefix) {
1147330f729Sjoerg AddNestedNameSpecifier(Prefix);
1157330f729Sjoerg }
1167330f729Sjoerg auto Kind = NNS->getKind();
1177330f729Sjoerg ID.AddInteger(Kind);
1187330f729Sjoerg switch (Kind) {
1197330f729Sjoerg case NestedNameSpecifier::Identifier:
1207330f729Sjoerg AddIdentifierInfo(NNS->getAsIdentifier());
1217330f729Sjoerg break;
1227330f729Sjoerg case NestedNameSpecifier::Namespace:
1237330f729Sjoerg AddDecl(NNS->getAsNamespace());
1247330f729Sjoerg break;
1257330f729Sjoerg case NestedNameSpecifier::NamespaceAlias:
1267330f729Sjoerg AddDecl(NNS->getAsNamespaceAlias());
1277330f729Sjoerg break;
1287330f729Sjoerg case NestedNameSpecifier::TypeSpec:
1297330f729Sjoerg case NestedNameSpecifier::TypeSpecWithTemplate:
1307330f729Sjoerg AddType(NNS->getAsType());
1317330f729Sjoerg break;
1327330f729Sjoerg case NestedNameSpecifier::Global:
1337330f729Sjoerg case NestedNameSpecifier::Super:
1347330f729Sjoerg break;
1357330f729Sjoerg }
1367330f729Sjoerg }
1377330f729Sjoerg
AddTemplateName(TemplateName Name)1387330f729Sjoerg void ODRHash::AddTemplateName(TemplateName Name) {
1397330f729Sjoerg auto Kind = Name.getKind();
1407330f729Sjoerg ID.AddInteger(Kind);
1417330f729Sjoerg
1427330f729Sjoerg switch (Kind) {
1437330f729Sjoerg case TemplateName::Template:
1447330f729Sjoerg AddDecl(Name.getAsTemplateDecl());
1457330f729Sjoerg break;
1467330f729Sjoerg // TODO: Support these cases.
1477330f729Sjoerg case TemplateName::OverloadedTemplate:
1487330f729Sjoerg case TemplateName::AssumedTemplate:
1497330f729Sjoerg case TemplateName::QualifiedTemplate:
1507330f729Sjoerg case TemplateName::DependentTemplate:
1517330f729Sjoerg case TemplateName::SubstTemplateTemplateParm:
1527330f729Sjoerg case TemplateName::SubstTemplateTemplateParmPack:
1537330f729Sjoerg break;
1547330f729Sjoerg }
1557330f729Sjoerg }
1567330f729Sjoerg
AddTemplateArgument(TemplateArgument TA)1577330f729Sjoerg void ODRHash::AddTemplateArgument(TemplateArgument TA) {
1587330f729Sjoerg const auto Kind = TA.getKind();
1597330f729Sjoerg ID.AddInteger(Kind);
1607330f729Sjoerg
1617330f729Sjoerg switch (Kind) {
1627330f729Sjoerg case TemplateArgument::Null:
1637330f729Sjoerg llvm_unreachable("Expected valid TemplateArgument");
1647330f729Sjoerg case TemplateArgument::Type:
1657330f729Sjoerg AddQualType(TA.getAsType());
1667330f729Sjoerg break;
1677330f729Sjoerg case TemplateArgument::Declaration:
1687330f729Sjoerg AddDecl(TA.getAsDecl());
1697330f729Sjoerg break;
1707330f729Sjoerg case TemplateArgument::NullPtr:
1717330f729Sjoerg case TemplateArgument::Integral:
1727330f729Sjoerg break;
1737330f729Sjoerg case TemplateArgument::Template:
1747330f729Sjoerg case TemplateArgument::TemplateExpansion:
1757330f729Sjoerg AddTemplateName(TA.getAsTemplateOrTemplatePattern());
1767330f729Sjoerg break;
1777330f729Sjoerg case TemplateArgument::Expression:
1787330f729Sjoerg AddStmt(TA.getAsExpr());
1797330f729Sjoerg break;
1807330f729Sjoerg case TemplateArgument::Pack:
1817330f729Sjoerg ID.AddInteger(TA.pack_size());
1827330f729Sjoerg for (auto SubTA : TA.pack_elements()) {
1837330f729Sjoerg AddTemplateArgument(SubTA);
1847330f729Sjoerg }
1857330f729Sjoerg break;
1867330f729Sjoerg }
1877330f729Sjoerg }
1887330f729Sjoerg
AddTemplateParameterList(const TemplateParameterList * TPL)1897330f729Sjoerg void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {
1907330f729Sjoerg assert(TPL && "Expecting non-null pointer.");
1917330f729Sjoerg
1927330f729Sjoerg ID.AddInteger(TPL->size());
1937330f729Sjoerg for (auto *ND : TPL->asArray()) {
1947330f729Sjoerg AddSubDecl(ND);
1957330f729Sjoerg }
1967330f729Sjoerg }
1977330f729Sjoerg
clear()1987330f729Sjoerg void ODRHash::clear() {
1997330f729Sjoerg DeclNameMap.clear();
2007330f729Sjoerg Bools.clear();
2017330f729Sjoerg ID.clear();
2027330f729Sjoerg }
2037330f729Sjoerg
CalculateHash()2047330f729Sjoerg unsigned ODRHash::CalculateHash() {
2057330f729Sjoerg // Append the bools to the end of the data segment backwards. This allows
2067330f729Sjoerg // for the bools data to be compressed 32 times smaller compared to using
2077330f729Sjoerg // ID.AddBoolean
2087330f729Sjoerg const unsigned unsigned_bits = sizeof(unsigned) * CHAR_BIT;
2097330f729Sjoerg const unsigned size = Bools.size();
2107330f729Sjoerg const unsigned remainder = size % unsigned_bits;
2117330f729Sjoerg const unsigned loops = size / unsigned_bits;
2127330f729Sjoerg auto I = Bools.rbegin();
2137330f729Sjoerg unsigned value = 0;
2147330f729Sjoerg for (unsigned i = 0; i < remainder; ++i) {
2157330f729Sjoerg value <<= 1;
2167330f729Sjoerg value |= *I;
2177330f729Sjoerg ++I;
2187330f729Sjoerg }
2197330f729Sjoerg ID.AddInteger(value);
2207330f729Sjoerg
2217330f729Sjoerg for (unsigned i = 0; i < loops; ++i) {
2227330f729Sjoerg value = 0;
2237330f729Sjoerg for (unsigned j = 0; j < unsigned_bits; ++j) {
2247330f729Sjoerg value <<= 1;
2257330f729Sjoerg value |= *I;
2267330f729Sjoerg ++I;
2277330f729Sjoerg }
2287330f729Sjoerg ID.AddInteger(value);
2297330f729Sjoerg }
2307330f729Sjoerg
2317330f729Sjoerg assert(I == Bools.rend());
2327330f729Sjoerg Bools.clear();
2337330f729Sjoerg return ID.ComputeHash();
2347330f729Sjoerg }
2357330f729Sjoerg
2367330f729Sjoerg namespace {
2377330f729Sjoerg // Process a Decl pointer. Add* methods call back into ODRHash while Visit*
2387330f729Sjoerg // methods process the relevant parts of the Decl.
2397330f729Sjoerg class ODRDeclVisitor : public ConstDeclVisitor<ODRDeclVisitor> {
2407330f729Sjoerg typedef ConstDeclVisitor<ODRDeclVisitor> Inherited;
2417330f729Sjoerg llvm::FoldingSetNodeID &ID;
2427330f729Sjoerg ODRHash &Hash;
2437330f729Sjoerg
2447330f729Sjoerg public:
ODRDeclVisitor(llvm::FoldingSetNodeID & ID,ODRHash & Hash)2457330f729Sjoerg ODRDeclVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash)
2467330f729Sjoerg : ID(ID), Hash(Hash) {}
2477330f729Sjoerg
AddStmt(const Stmt * S)2487330f729Sjoerg void AddStmt(const Stmt *S) {
2497330f729Sjoerg Hash.AddBoolean(S);
2507330f729Sjoerg if (S) {
2517330f729Sjoerg Hash.AddStmt(S);
2527330f729Sjoerg }
2537330f729Sjoerg }
2547330f729Sjoerg
AddIdentifierInfo(const IdentifierInfo * II)2557330f729Sjoerg void AddIdentifierInfo(const IdentifierInfo *II) {
2567330f729Sjoerg Hash.AddBoolean(II);
2577330f729Sjoerg if (II) {
2587330f729Sjoerg Hash.AddIdentifierInfo(II);
2597330f729Sjoerg }
2607330f729Sjoerg }
2617330f729Sjoerg
AddQualType(QualType T)2627330f729Sjoerg void AddQualType(QualType T) {
2637330f729Sjoerg Hash.AddQualType(T);
2647330f729Sjoerg }
2657330f729Sjoerg
AddDecl(const Decl * D)2667330f729Sjoerg void AddDecl(const Decl *D) {
2677330f729Sjoerg Hash.AddBoolean(D);
2687330f729Sjoerg if (D) {
2697330f729Sjoerg Hash.AddDecl(D);
2707330f729Sjoerg }
2717330f729Sjoerg }
2727330f729Sjoerg
AddTemplateArgument(TemplateArgument TA)2737330f729Sjoerg void AddTemplateArgument(TemplateArgument TA) {
2747330f729Sjoerg Hash.AddTemplateArgument(TA);
2757330f729Sjoerg }
2767330f729Sjoerg
Visit(const Decl * D)2777330f729Sjoerg void Visit(const Decl *D) {
2787330f729Sjoerg ID.AddInteger(D->getKind());
2797330f729Sjoerg Inherited::Visit(D);
2807330f729Sjoerg }
2817330f729Sjoerg
VisitNamedDecl(const NamedDecl * D)2827330f729Sjoerg void VisitNamedDecl(const NamedDecl *D) {
2837330f729Sjoerg Hash.AddDeclarationName(D->getDeclName());
2847330f729Sjoerg Inherited::VisitNamedDecl(D);
2857330f729Sjoerg }
2867330f729Sjoerg
VisitValueDecl(const ValueDecl * D)2877330f729Sjoerg void VisitValueDecl(const ValueDecl *D) {
2887330f729Sjoerg if (!isa<FunctionDecl>(D)) {
2897330f729Sjoerg AddQualType(D->getType());
2907330f729Sjoerg }
2917330f729Sjoerg Inherited::VisitValueDecl(D);
2927330f729Sjoerg }
2937330f729Sjoerg
VisitVarDecl(const VarDecl * D)2947330f729Sjoerg void VisitVarDecl(const VarDecl *D) {
2957330f729Sjoerg Hash.AddBoolean(D->isStaticLocal());
2967330f729Sjoerg Hash.AddBoolean(D->isConstexpr());
2977330f729Sjoerg const bool HasInit = D->hasInit();
2987330f729Sjoerg Hash.AddBoolean(HasInit);
2997330f729Sjoerg if (HasInit) {
3007330f729Sjoerg AddStmt(D->getInit());
3017330f729Sjoerg }
3027330f729Sjoerg Inherited::VisitVarDecl(D);
3037330f729Sjoerg }
3047330f729Sjoerg
VisitParmVarDecl(const ParmVarDecl * D)3057330f729Sjoerg void VisitParmVarDecl(const ParmVarDecl *D) {
3067330f729Sjoerg // TODO: Handle default arguments.
3077330f729Sjoerg Inherited::VisitParmVarDecl(D);
3087330f729Sjoerg }
3097330f729Sjoerg
VisitAccessSpecDecl(const AccessSpecDecl * D)3107330f729Sjoerg void VisitAccessSpecDecl(const AccessSpecDecl *D) {
3117330f729Sjoerg ID.AddInteger(D->getAccess());
3127330f729Sjoerg Inherited::VisitAccessSpecDecl(D);
3137330f729Sjoerg }
3147330f729Sjoerg
VisitStaticAssertDecl(const StaticAssertDecl * D)3157330f729Sjoerg void VisitStaticAssertDecl(const StaticAssertDecl *D) {
3167330f729Sjoerg AddStmt(D->getAssertExpr());
3177330f729Sjoerg AddStmt(D->getMessage());
3187330f729Sjoerg
3197330f729Sjoerg Inherited::VisitStaticAssertDecl(D);
3207330f729Sjoerg }
3217330f729Sjoerg
VisitFieldDecl(const FieldDecl * D)3227330f729Sjoerg void VisitFieldDecl(const FieldDecl *D) {
3237330f729Sjoerg const bool IsBitfield = D->isBitField();
3247330f729Sjoerg Hash.AddBoolean(IsBitfield);
3257330f729Sjoerg
3267330f729Sjoerg if (IsBitfield) {
3277330f729Sjoerg AddStmt(D->getBitWidth());
3287330f729Sjoerg }
3297330f729Sjoerg
3307330f729Sjoerg Hash.AddBoolean(D->isMutable());
3317330f729Sjoerg AddStmt(D->getInClassInitializer());
3327330f729Sjoerg
3337330f729Sjoerg Inherited::VisitFieldDecl(D);
3347330f729Sjoerg }
3357330f729Sjoerg
VisitFunctionDecl(const FunctionDecl * D)3367330f729Sjoerg void VisitFunctionDecl(const FunctionDecl *D) {
3377330f729Sjoerg // Handled by the ODRHash for FunctionDecl
3387330f729Sjoerg ID.AddInteger(D->getODRHash());
3397330f729Sjoerg
3407330f729Sjoerg Inherited::VisitFunctionDecl(D);
3417330f729Sjoerg }
3427330f729Sjoerg
VisitCXXMethodDecl(const CXXMethodDecl * D)3437330f729Sjoerg void VisitCXXMethodDecl(const CXXMethodDecl *D) {
3447330f729Sjoerg // Handled by the ODRHash for FunctionDecl
3457330f729Sjoerg
3467330f729Sjoerg Inherited::VisitCXXMethodDecl(D);
3477330f729Sjoerg }
3487330f729Sjoerg
VisitTypedefNameDecl(const TypedefNameDecl * D)3497330f729Sjoerg void VisitTypedefNameDecl(const TypedefNameDecl *D) {
3507330f729Sjoerg AddQualType(D->getUnderlyingType());
3517330f729Sjoerg
3527330f729Sjoerg Inherited::VisitTypedefNameDecl(D);
3537330f729Sjoerg }
3547330f729Sjoerg
VisitTypedefDecl(const TypedefDecl * D)3557330f729Sjoerg void VisitTypedefDecl(const TypedefDecl *D) {
3567330f729Sjoerg Inherited::VisitTypedefDecl(D);
3577330f729Sjoerg }
3587330f729Sjoerg
VisitTypeAliasDecl(const TypeAliasDecl * D)3597330f729Sjoerg void VisitTypeAliasDecl(const TypeAliasDecl *D) {
3607330f729Sjoerg Inherited::VisitTypeAliasDecl(D);
3617330f729Sjoerg }
3627330f729Sjoerg
VisitFriendDecl(const FriendDecl * D)3637330f729Sjoerg void VisitFriendDecl(const FriendDecl *D) {
3647330f729Sjoerg TypeSourceInfo *TSI = D->getFriendType();
3657330f729Sjoerg Hash.AddBoolean(TSI);
3667330f729Sjoerg if (TSI) {
3677330f729Sjoerg AddQualType(TSI->getType());
3687330f729Sjoerg } else {
3697330f729Sjoerg AddDecl(D->getFriendDecl());
3707330f729Sjoerg }
3717330f729Sjoerg }
3727330f729Sjoerg
VisitTemplateTypeParmDecl(const TemplateTypeParmDecl * D)3737330f729Sjoerg void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
3747330f729Sjoerg // Only care about default arguments as part of the definition.
3757330f729Sjoerg const bool hasDefaultArgument =
3767330f729Sjoerg D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
3777330f729Sjoerg Hash.AddBoolean(hasDefaultArgument);
3787330f729Sjoerg if (hasDefaultArgument) {
3797330f729Sjoerg AddTemplateArgument(D->getDefaultArgument());
3807330f729Sjoerg }
3817330f729Sjoerg Hash.AddBoolean(D->isParameterPack());
3827330f729Sjoerg
383*e038c9c4Sjoerg const TypeConstraint *TC = D->getTypeConstraint();
384*e038c9c4Sjoerg Hash.AddBoolean(TC != nullptr);
385*e038c9c4Sjoerg if (TC)
386*e038c9c4Sjoerg AddStmt(TC->getImmediatelyDeclaredConstraint());
387*e038c9c4Sjoerg
3887330f729Sjoerg Inherited::VisitTemplateTypeParmDecl(D);
3897330f729Sjoerg }
3907330f729Sjoerg
VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl * D)3917330f729Sjoerg void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
3927330f729Sjoerg // Only care about default arguments as part of the definition.
3937330f729Sjoerg const bool hasDefaultArgument =
3947330f729Sjoerg D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
3957330f729Sjoerg Hash.AddBoolean(hasDefaultArgument);
3967330f729Sjoerg if (hasDefaultArgument) {
3977330f729Sjoerg AddStmt(D->getDefaultArgument());
3987330f729Sjoerg }
3997330f729Sjoerg Hash.AddBoolean(D->isParameterPack());
4007330f729Sjoerg
4017330f729Sjoerg Inherited::VisitNonTypeTemplateParmDecl(D);
4027330f729Sjoerg }
4037330f729Sjoerg
VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl * D)4047330f729Sjoerg void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) {
4057330f729Sjoerg // Only care about default arguments as part of the definition.
4067330f729Sjoerg const bool hasDefaultArgument =
4077330f729Sjoerg D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
4087330f729Sjoerg Hash.AddBoolean(hasDefaultArgument);
4097330f729Sjoerg if (hasDefaultArgument) {
4107330f729Sjoerg AddTemplateArgument(D->getDefaultArgument().getArgument());
4117330f729Sjoerg }
4127330f729Sjoerg Hash.AddBoolean(D->isParameterPack());
4137330f729Sjoerg
4147330f729Sjoerg Inherited::VisitTemplateTemplateParmDecl(D);
4157330f729Sjoerg }
4167330f729Sjoerg
VisitTemplateDecl(const TemplateDecl * D)4177330f729Sjoerg void VisitTemplateDecl(const TemplateDecl *D) {
4187330f729Sjoerg Hash.AddTemplateParameterList(D->getTemplateParameters());
4197330f729Sjoerg
4207330f729Sjoerg Inherited::VisitTemplateDecl(D);
4217330f729Sjoerg }
4227330f729Sjoerg
VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl * D)4237330f729Sjoerg void VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl *D) {
4247330f729Sjoerg Hash.AddBoolean(D->isMemberSpecialization());
4257330f729Sjoerg Inherited::VisitRedeclarableTemplateDecl(D);
4267330f729Sjoerg }
4277330f729Sjoerg
VisitFunctionTemplateDecl(const FunctionTemplateDecl * D)4287330f729Sjoerg void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
4297330f729Sjoerg AddDecl(D->getTemplatedDecl());
4307330f729Sjoerg ID.AddInteger(D->getTemplatedDecl()->getODRHash());
4317330f729Sjoerg Inherited::VisitFunctionTemplateDecl(D);
4327330f729Sjoerg }
4337330f729Sjoerg
VisitEnumConstantDecl(const EnumConstantDecl * D)4347330f729Sjoerg void VisitEnumConstantDecl(const EnumConstantDecl *D) {
4357330f729Sjoerg AddStmt(D->getInitExpr());
4367330f729Sjoerg Inherited::VisitEnumConstantDecl(D);
4377330f729Sjoerg }
4387330f729Sjoerg };
4397330f729Sjoerg } // namespace
4407330f729Sjoerg
4417330f729Sjoerg // Only allow a small portion of Decl's to be processed. Remove this once
4427330f729Sjoerg // all Decl's can be handled.
isDeclToBeProcessed(const Decl * D,const DeclContext * Parent)443*e038c9c4Sjoerg bool ODRHash::isDeclToBeProcessed(const Decl *D, const DeclContext *Parent) {
4447330f729Sjoerg if (D->isImplicit()) return false;
4457330f729Sjoerg if (D->getDeclContext() != Parent) return false;
4467330f729Sjoerg
4477330f729Sjoerg switch (D->getKind()) {
4487330f729Sjoerg default:
4497330f729Sjoerg return false;
4507330f729Sjoerg case Decl::AccessSpec:
4517330f729Sjoerg case Decl::CXXConstructor:
4527330f729Sjoerg case Decl::CXXDestructor:
4537330f729Sjoerg case Decl::CXXMethod:
4547330f729Sjoerg case Decl::EnumConstant: // Only found in EnumDecl's.
4557330f729Sjoerg case Decl::Field:
4567330f729Sjoerg case Decl::Friend:
4577330f729Sjoerg case Decl::FunctionTemplate:
4587330f729Sjoerg case Decl::StaticAssert:
4597330f729Sjoerg case Decl::TypeAlias:
4607330f729Sjoerg case Decl::Typedef:
4617330f729Sjoerg case Decl::Var:
4627330f729Sjoerg return true;
4637330f729Sjoerg }
4647330f729Sjoerg }
4657330f729Sjoerg
AddSubDecl(const Decl * D)4667330f729Sjoerg void ODRHash::AddSubDecl(const Decl *D) {
4677330f729Sjoerg assert(D && "Expecting non-null pointer.");
4687330f729Sjoerg
4697330f729Sjoerg ODRDeclVisitor(ID, *this).Visit(D);
4707330f729Sjoerg }
4717330f729Sjoerg
AddCXXRecordDecl(const CXXRecordDecl * Record)4727330f729Sjoerg void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) {
4737330f729Sjoerg assert(Record && Record->hasDefinition() &&
4747330f729Sjoerg "Expected non-null record to be a definition.");
4757330f729Sjoerg
4767330f729Sjoerg const DeclContext *DC = Record;
4777330f729Sjoerg while (DC) {
4787330f729Sjoerg if (isa<ClassTemplateSpecializationDecl>(DC)) {
4797330f729Sjoerg return;
4807330f729Sjoerg }
4817330f729Sjoerg DC = DC->getParent();
4827330f729Sjoerg }
4837330f729Sjoerg
4847330f729Sjoerg AddDecl(Record);
4857330f729Sjoerg
4867330f729Sjoerg // Filter out sub-Decls which will not be processed in order to get an
4877330f729Sjoerg // accurate count of Decl's.
4887330f729Sjoerg llvm::SmallVector<const Decl *, 16> Decls;
4897330f729Sjoerg for (Decl *SubDecl : Record->decls()) {
490*e038c9c4Sjoerg if (isDeclToBeProcessed(SubDecl, Record)) {
4917330f729Sjoerg Decls.push_back(SubDecl);
4927330f729Sjoerg if (auto *Function = dyn_cast<FunctionDecl>(SubDecl)) {
4937330f729Sjoerg // Compute/Preload ODRHash into FunctionDecl.
4947330f729Sjoerg Function->getODRHash();
4957330f729Sjoerg }
4967330f729Sjoerg }
4977330f729Sjoerg }
4987330f729Sjoerg
4997330f729Sjoerg ID.AddInteger(Decls.size());
5007330f729Sjoerg for (auto SubDecl : Decls) {
5017330f729Sjoerg AddSubDecl(SubDecl);
5027330f729Sjoerg }
5037330f729Sjoerg
5047330f729Sjoerg const ClassTemplateDecl *TD = Record->getDescribedClassTemplate();
5057330f729Sjoerg AddBoolean(TD);
5067330f729Sjoerg if (TD) {
5077330f729Sjoerg AddTemplateParameterList(TD->getTemplateParameters());
5087330f729Sjoerg }
5097330f729Sjoerg
5107330f729Sjoerg ID.AddInteger(Record->getNumBases());
5117330f729Sjoerg auto Bases = Record->bases();
5127330f729Sjoerg for (auto Base : Bases) {
5137330f729Sjoerg AddQualType(Base.getType());
5147330f729Sjoerg ID.AddInteger(Base.isVirtual());
5157330f729Sjoerg ID.AddInteger(Base.getAccessSpecifierAsWritten());
5167330f729Sjoerg }
5177330f729Sjoerg }
5187330f729Sjoerg
AddFunctionDecl(const FunctionDecl * Function,bool SkipBody)5197330f729Sjoerg void ODRHash::AddFunctionDecl(const FunctionDecl *Function,
5207330f729Sjoerg bool SkipBody) {
5217330f729Sjoerg assert(Function && "Expecting non-null pointer.");
5227330f729Sjoerg
5237330f729Sjoerg // Skip functions that are specializations or in specialization context.
5247330f729Sjoerg const DeclContext *DC = Function;
5257330f729Sjoerg while (DC) {
5267330f729Sjoerg if (isa<ClassTemplateSpecializationDecl>(DC)) return;
5277330f729Sjoerg if (auto *F = dyn_cast<FunctionDecl>(DC)) {
5287330f729Sjoerg if (F->isFunctionTemplateSpecialization()) {
5297330f729Sjoerg if (!isa<CXXMethodDecl>(DC)) return;
5307330f729Sjoerg if (DC->getLexicalParent()->isFileContext()) return;
5317330f729Sjoerg // Inline method specializations are the only supported
5327330f729Sjoerg // specialization for now.
5337330f729Sjoerg }
5347330f729Sjoerg }
5357330f729Sjoerg DC = DC->getParent();
5367330f729Sjoerg }
5377330f729Sjoerg
5387330f729Sjoerg ID.AddInteger(Function->getDeclKind());
5397330f729Sjoerg
5407330f729Sjoerg const auto *SpecializationArgs = Function->getTemplateSpecializationArgs();
5417330f729Sjoerg AddBoolean(SpecializationArgs);
5427330f729Sjoerg if (SpecializationArgs) {
5437330f729Sjoerg ID.AddInteger(SpecializationArgs->size());
5447330f729Sjoerg for (const TemplateArgument &TA : SpecializationArgs->asArray()) {
5457330f729Sjoerg AddTemplateArgument(TA);
5467330f729Sjoerg }
5477330f729Sjoerg }
5487330f729Sjoerg
5497330f729Sjoerg if (const auto *Method = dyn_cast<CXXMethodDecl>(Function)) {
5507330f729Sjoerg AddBoolean(Method->isConst());
5517330f729Sjoerg AddBoolean(Method->isVolatile());
5527330f729Sjoerg }
5537330f729Sjoerg
5547330f729Sjoerg ID.AddInteger(Function->getStorageClass());
5557330f729Sjoerg AddBoolean(Function->isInlineSpecified());
5567330f729Sjoerg AddBoolean(Function->isVirtualAsWritten());
5577330f729Sjoerg AddBoolean(Function->isPure());
5587330f729Sjoerg AddBoolean(Function->isDeletedAsWritten());
5597330f729Sjoerg AddBoolean(Function->isExplicitlyDefaulted());
5607330f729Sjoerg
5617330f729Sjoerg AddDecl(Function);
5627330f729Sjoerg
5637330f729Sjoerg AddQualType(Function->getReturnType());
5647330f729Sjoerg
5657330f729Sjoerg ID.AddInteger(Function->param_size());
5667330f729Sjoerg for (auto Param : Function->parameters())
5677330f729Sjoerg AddSubDecl(Param);
5687330f729Sjoerg
5697330f729Sjoerg if (SkipBody) {
5707330f729Sjoerg AddBoolean(false);
5717330f729Sjoerg return;
5727330f729Sjoerg }
5737330f729Sjoerg
5747330f729Sjoerg const bool HasBody = Function->isThisDeclarationADefinition() &&
5757330f729Sjoerg !Function->isDefaulted() && !Function->isDeleted() &&
5767330f729Sjoerg !Function->isLateTemplateParsed();
5777330f729Sjoerg AddBoolean(HasBody);
5787330f729Sjoerg if (!HasBody) {
5797330f729Sjoerg return;
5807330f729Sjoerg }
5817330f729Sjoerg
5827330f729Sjoerg auto *Body = Function->getBody();
5837330f729Sjoerg AddBoolean(Body);
5847330f729Sjoerg if (Body)
5857330f729Sjoerg AddStmt(Body);
5867330f729Sjoerg
5877330f729Sjoerg // Filter out sub-Decls which will not be processed in order to get an
5887330f729Sjoerg // accurate count of Decl's.
5897330f729Sjoerg llvm::SmallVector<const Decl *, 16> Decls;
5907330f729Sjoerg for (Decl *SubDecl : Function->decls()) {
591*e038c9c4Sjoerg if (isDeclToBeProcessed(SubDecl, Function)) {
5927330f729Sjoerg Decls.push_back(SubDecl);
5937330f729Sjoerg }
5947330f729Sjoerg }
5957330f729Sjoerg
5967330f729Sjoerg ID.AddInteger(Decls.size());
5977330f729Sjoerg for (auto SubDecl : Decls) {
5987330f729Sjoerg AddSubDecl(SubDecl);
5997330f729Sjoerg }
6007330f729Sjoerg }
6017330f729Sjoerg
AddEnumDecl(const EnumDecl * Enum)6027330f729Sjoerg void ODRHash::AddEnumDecl(const EnumDecl *Enum) {
6037330f729Sjoerg assert(Enum);
6047330f729Sjoerg AddDeclarationName(Enum->getDeclName());
6057330f729Sjoerg
6067330f729Sjoerg AddBoolean(Enum->isScoped());
6077330f729Sjoerg if (Enum->isScoped())
6087330f729Sjoerg AddBoolean(Enum->isScopedUsingClassTag());
6097330f729Sjoerg
6107330f729Sjoerg if (Enum->getIntegerTypeSourceInfo())
6117330f729Sjoerg AddQualType(Enum->getIntegerType());
6127330f729Sjoerg
6137330f729Sjoerg // Filter out sub-Decls which will not be processed in order to get an
6147330f729Sjoerg // accurate count of Decl's.
6157330f729Sjoerg llvm::SmallVector<const Decl *, 16> Decls;
6167330f729Sjoerg for (Decl *SubDecl : Enum->decls()) {
617*e038c9c4Sjoerg if (isDeclToBeProcessed(SubDecl, Enum)) {
6187330f729Sjoerg assert(isa<EnumConstantDecl>(SubDecl) && "Unexpected Decl");
6197330f729Sjoerg Decls.push_back(SubDecl);
6207330f729Sjoerg }
6217330f729Sjoerg }
6227330f729Sjoerg
6237330f729Sjoerg ID.AddInteger(Decls.size());
6247330f729Sjoerg for (auto SubDecl : Decls) {
6257330f729Sjoerg AddSubDecl(SubDecl);
6267330f729Sjoerg }
6277330f729Sjoerg
6287330f729Sjoerg }
6297330f729Sjoerg
AddDecl(const Decl * D)6307330f729Sjoerg void ODRHash::AddDecl(const Decl *D) {
6317330f729Sjoerg assert(D && "Expecting non-null pointer.");
6327330f729Sjoerg D = D->getCanonicalDecl();
6337330f729Sjoerg
6347330f729Sjoerg const NamedDecl *ND = dyn_cast<NamedDecl>(D);
6357330f729Sjoerg AddBoolean(ND);
6367330f729Sjoerg if (!ND) {
6377330f729Sjoerg ID.AddInteger(D->getKind());
6387330f729Sjoerg return;
6397330f729Sjoerg }
6407330f729Sjoerg
6417330f729Sjoerg AddDeclarationName(ND->getDeclName());
6427330f729Sjoerg
6437330f729Sjoerg const auto *Specialization =
6447330f729Sjoerg dyn_cast<ClassTemplateSpecializationDecl>(D);
6457330f729Sjoerg AddBoolean(Specialization);
6467330f729Sjoerg if (Specialization) {
6477330f729Sjoerg const TemplateArgumentList &List = Specialization->getTemplateArgs();
6487330f729Sjoerg ID.AddInteger(List.size());
6497330f729Sjoerg for (const TemplateArgument &TA : List.asArray())
6507330f729Sjoerg AddTemplateArgument(TA);
6517330f729Sjoerg }
6527330f729Sjoerg }
6537330f729Sjoerg
6547330f729Sjoerg namespace {
6557330f729Sjoerg // Process a Type pointer. Add* methods call back into ODRHash while Visit*
6567330f729Sjoerg // methods process the relevant parts of the Type.
6577330f729Sjoerg class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
6587330f729Sjoerg typedef TypeVisitor<ODRTypeVisitor> Inherited;
6597330f729Sjoerg llvm::FoldingSetNodeID &ID;
6607330f729Sjoerg ODRHash &Hash;
6617330f729Sjoerg
6627330f729Sjoerg public:
ODRTypeVisitor(llvm::FoldingSetNodeID & ID,ODRHash & Hash)6637330f729Sjoerg ODRTypeVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash)
6647330f729Sjoerg : ID(ID), Hash(Hash) {}
6657330f729Sjoerg
AddStmt(Stmt * S)6667330f729Sjoerg void AddStmt(Stmt *S) {
6677330f729Sjoerg Hash.AddBoolean(S);
6687330f729Sjoerg if (S) {
6697330f729Sjoerg Hash.AddStmt(S);
6707330f729Sjoerg }
6717330f729Sjoerg }
6727330f729Sjoerg
AddDecl(Decl * D)6737330f729Sjoerg void AddDecl(Decl *D) {
6747330f729Sjoerg Hash.AddBoolean(D);
6757330f729Sjoerg if (D) {
6767330f729Sjoerg Hash.AddDecl(D);
6777330f729Sjoerg }
6787330f729Sjoerg }
6797330f729Sjoerg
AddQualType(QualType T)6807330f729Sjoerg void AddQualType(QualType T) {
6817330f729Sjoerg Hash.AddQualType(T);
6827330f729Sjoerg }
6837330f729Sjoerg
AddType(const Type * T)6847330f729Sjoerg void AddType(const Type *T) {
6857330f729Sjoerg Hash.AddBoolean(T);
6867330f729Sjoerg if (T) {
6877330f729Sjoerg Hash.AddType(T);
6887330f729Sjoerg }
6897330f729Sjoerg }
6907330f729Sjoerg
AddNestedNameSpecifier(const NestedNameSpecifier * NNS)6917330f729Sjoerg void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
6927330f729Sjoerg Hash.AddBoolean(NNS);
6937330f729Sjoerg if (NNS) {
6947330f729Sjoerg Hash.AddNestedNameSpecifier(NNS);
6957330f729Sjoerg }
6967330f729Sjoerg }
6977330f729Sjoerg
AddIdentifierInfo(const IdentifierInfo * II)6987330f729Sjoerg void AddIdentifierInfo(const IdentifierInfo *II) {
6997330f729Sjoerg Hash.AddBoolean(II);
7007330f729Sjoerg if (II) {
7017330f729Sjoerg Hash.AddIdentifierInfo(II);
7027330f729Sjoerg }
7037330f729Sjoerg }
7047330f729Sjoerg
VisitQualifiers(Qualifiers Quals)7057330f729Sjoerg void VisitQualifiers(Qualifiers Quals) {
7067330f729Sjoerg ID.AddInteger(Quals.getAsOpaqueValue());
7077330f729Sjoerg }
7087330f729Sjoerg
7097330f729Sjoerg // Return the RecordType if the typedef only strips away a keyword.
7107330f729Sjoerg // Otherwise, return the original type.
RemoveTypedef(const Type * T)7117330f729Sjoerg static const Type *RemoveTypedef(const Type *T) {
7127330f729Sjoerg const auto *TypedefT = dyn_cast<TypedefType>(T);
7137330f729Sjoerg if (!TypedefT) {
7147330f729Sjoerg return T;
7157330f729Sjoerg }
7167330f729Sjoerg
7177330f729Sjoerg const TypedefNameDecl *D = TypedefT->getDecl();
7187330f729Sjoerg QualType UnderlyingType = D->getUnderlyingType();
7197330f729Sjoerg
7207330f729Sjoerg if (UnderlyingType.hasLocalQualifiers()) {
7217330f729Sjoerg return T;
7227330f729Sjoerg }
7237330f729Sjoerg
7247330f729Sjoerg const auto *ElaboratedT = dyn_cast<ElaboratedType>(UnderlyingType);
7257330f729Sjoerg if (!ElaboratedT) {
7267330f729Sjoerg return T;
7277330f729Sjoerg }
7287330f729Sjoerg
7297330f729Sjoerg if (ElaboratedT->getQualifier() != nullptr) {
7307330f729Sjoerg return T;
7317330f729Sjoerg }
7327330f729Sjoerg
7337330f729Sjoerg QualType NamedType = ElaboratedT->getNamedType();
7347330f729Sjoerg if (NamedType.hasLocalQualifiers()) {
7357330f729Sjoerg return T;
7367330f729Sjoerg }
7377330f729Sjoerg
7387330f729Sjoerg const auto *RecordT = dyn_cast<RecordType>(NamedType);
7397330f729Sjoerg if (!RecordT) {
7407330f729Sjoerg return T;
7417330f729Sjoerg }
7427330f729Sjoerg
7437330f729Sjoerg const IdentifierInfo *TypedefII = TypedefT->getDecl()->getIdentifier();
7447330f729Sjoerg const IdentifierInfo *RecordII = RecordT->getDecl()->getIdentifier();
7457330f729Sjoerg if (!TypedefII || !RecordII ||
7467330f729Sjoerg TypedefII->getName() != RecordII->getName()) {
7477330f729Sjoerg return T;
7487330f729Sjoerg }
7497330f729Sjoerg
7507330f729Sjoerg return RecordT;
7517330f729Sjoerg }
7527330f729Sjoerg
Visit(const Type * T)7537330f729Sjoerg void Visit(const Type *T) {
7547330f729Sjoerg T = RemoveTypedef(T);
7557330f729Sjoerg ID.AddInteger(T->getTypeClass());
7567330f729Sjoerg Inherited::Visit(T);
7577330f729Sjoerg }
7587330f729Sjoerg
VisitType(const Type * T)7597330f729Sjoerg void VisitType(const Type *T) {}
7607330f729Sjoerg
VisitAdjustedType(const AdjustedType * T)7617330f729Sjoerg void VisitAdjustedType(const AdjustedType *T) {
7627330f729Sjoerg QualType Original = T->getOriginalType();
7637330f729Sjoerg QualType Adjusted = T->getAdjustedType();
7647330f729Sjoerg
7657330f729Sjoerg // The original type and pointee type can be the same, as in the case of
7667330f729Sjoerg // function pointers decaying to themselves. Set a bool and only process
7677330f729Sjoerg // the type once, to prevent doubling the work.
7687330f729Sjoerg SplitQualType split = Adjusted.split();
7697330f729Sjoerg if (auto Pointer = dyn_cast<PointerType>(split.Ty)) {
7707330f729Sjoerg if (Pointer->getPointeeType() == Original) {
7717330f729Sjoerg Hash.AddBoolean(true);
7727330f729Sjoerg ID.AddInteger(split.Quals.getAsOpaqueValue());
7737330f729Sjoerg AddQualType(Original);
7747330f729Sjoerg VisitType(T);
7757330f729Sjoerg return;
7767330f729Sjoerg }
7777330f729Sjoerg }
7787330f729Sjoerg
7797330f729Sjoerg // The original type and pointee type are different, such as in the case
7807330f729Sjoerg // of a array decaying to an element pointer. Set a bool to false and
7817330f729Sjoerg // process both types.
7827330f729Sjoerg Hash.AddBoolean(false);
7837330f729Sjoerg AddQualType(Original);
7847330f729Sjoerg AddQualType(Adjusted);
7857330f729Sjoerg
7867330f729Sjoerg VisitType(T);
7877330f729Sjoerg }
7887330f729Sjoerg
VisitDecayedType(const DecayedType * T)7897330f729Sjoerg void VisitDecayedType(const DecayedType *T) {
7907330f729Sjoerg // getDecayedType and getPointeeType are derived from getAdjustedType
7917330f729Sjoerg // and don't need to be separately processed.
7927330f729Sjoerg VisitAdjustedType(T);
7937330f729Sjoerg }
7947330f729Sjoerg
VisitArrayType(const ArrayType * T)7957330f729Sjoerg void VisitArrayType(const ArrayType *T) {
7967330f729Sjoerg AddQualType(T->getElementType());
7977330f729Sjoerg ID.AddInteger(T->getSizeModifier());
7987330f729Sjoerg VisitQualifiers(T->getIndexTypeQualifiers());
7997330f729Sjoerg VisitType(T);
8007330f729Sjoerg }
VisitConstantArrayType(const ConstantArrayType * T)8017330f729Sjoerg void VisitConstantArrayType(const ConstantArrayType *T) {
8027330f729Sjoerg T->getSize().Profile(ID);
8037330f729Sjoerg VisitArrayType(T);
8047330f729Sjoerg }
8057330f729Sjoerg
VisitDependentSizedArrayType(const DependentSizedArrayType * T)8067330f729Sjoerg void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
8077330f729Sjoerg AddStmt(T->getSizeExpr());
8087330f729Sjoerg VisitArrayType(T);
8097330f729Sjoerg }
8107330f729Sjoerg
VisitIncompleteArrayType(const IncompleteArrayType * T)8117330f729Sjoerg void VisitIncompleteArrayType(const IncompleteArrayType *T) {
8127330f729Sjoerg VisitArrayType(T);
8137330f729Sjoerg }
8147330f729Sjoerg
VisitVariableArrayType(const VariableArrayType * T)8157330f729Sjoerg void VisitVariableArrayType(const VariableArrayType *T) {
8167330f729Sjoerg AddStmt(T->getSizeExpr());
8177330f729Sjoerg VisitArrayType(T);
8187330f729Sjoerg }
8197330f729Sjoerg
VisitAttributedType(const AttributedType * T)8207330f729Sjoerg void VisitAttributedType(const AttributedType *T) {
8217330f729Sjoerg ID.AddInteger(T->getAttrKind());
8227330f729Sjoerg AddQualType(T->getModifiedType());
8237330f729Sjoerg AddQualType(T->getEquivalentType());
8247330f729Sjoerg
8257330f729Sjoerg VisitType(T);
8267330f729Sjoerg }
8277330f729Sjoerg
VisitBlockPointerType(const BlockPointerType * T)8287330f729Sjoerg void VisitBlockPointerType(const BlockPointerType *T) {
8297330f729Sjoerg AddQualType(T->getPointeeType());
8307330f729Sjoerg VisitType(T);
8317330f729Sjoerg }
8327330f729Sjoerg
VisitBuiltinType(const BuiltinType * T)8337330f729Sjoerg void VisitBuiltinType(const BuiltinType *T) {
8347330f729Sjoerg ID.AddInteger(T->getKind());
8357330f729Sjoerg VisitType(T);
8367330f729Sjoerg }
8377330f729Sjoerg
VisitComplexType(const ComplexType * T)8387330f729Sjoerg void VisitComplexType(const ComplexType *T) {
8397330f729Sjoerg AddQualType(T->getElementType());
8407330f729Sjoerg VisitType(T);
8417330f729Sjoerg }
8427330f729Sjoerg
VisitDecltypeType(const DecltypeType * T)8437330f729Sjoerg void VisitDecltypeType(const DecltypeType *T) {
8447330f729Sjoerg AddStmt(T->getUnderlyingExpr());
8457330f729Sjoerg AddQualType(T->getUnderlyingType());
8467330f729Sjoerg VisitType(T);
8477330f729Sjoerg }
8487330f729Sjoerg
VisitDependentDecltypeType(const DependentDecltypeType * T)8497330f729Sjoerg void VisitDependentDecltypeType(const DependentDecltypeType *T) {
8507330f729Sjoerg VisitDecltypeType(T);
8517330f729Sjoerg }
8527330f729Sjoerg
VisitDeducedType(const DeducedType * T)8537330f729Sjoerg void VisitDeducedType(const DeducedType *T) {
8547330f729Sjoerg AddQualType(T->getDeducedType());
8557330f729Sjoerg VisitType(T);
8567330f729Sjoerg }
8577330f729Sjoerg
VisitAutoType(const AutoType * T)8587330f729Sjoerg void VisitAutoType(const AutoType *T) {
8597330f729Sjoerg ID.AddInteger((unsigned)T->getKeyword());
860*e038c9c4Sjoerg ID.AddInteger(T->isConstrained());
861*e038c9c4Sjoerg if (T->isConstrained()) {
862*e038c9c4Sjoerg AddDecl(T->getTypeConstraintConcept());
863*e038c9c4Sjoerg ID.AddInteger(T->getNumArgs());
864*e038c9c4Sjoerg for (const auto &TA : T->getTypeConstraintArguments())
865*e038c9c4Sjoerg Hash.AddTemplateArgument(TA);
866*e038c9c4Sjoerg }
8677330f729Sjoerg VisitDeducedType(T);
8687330f729Sjoerg }
8697330f729Sjoerg
VisitDeducedTemplateSpecializationType(const DeducedTemplateSpecializationType * T)8707330f729Sjoerg void VisitDeducedTemplateSpecializationType(
8717330f729Sjoerg const DeducedTemplateSpecializationType *T) {
8727330f729Sjoerg Hash.AddTemplateName(T->getTemplateName());
8737330f729Sjoerg VisitDeducedType(T);
8747330f729Sjoerg }
8757330f729Sjoerg
VisitDependentAddressSpaceType(const DependentAddressSpaceType * T)8767330f729Sjoerg void VisitDependentAddressSpaceType(const DependentAddressSpaceType *T) {
8777330f729Sjoerg AddQualType(T->getPointeeType());
8787330f729Sjoerg AddStmt(T->getAddrSpaceExpr());
8797330f729Sjoerg VisitType(T);
8807330f729Sjoerg }
8817330f729Sjoerg
VisitDependentSizedExtVectorType(const DependentSizedExtVectorType * T)8827330f729Sjoerg void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) {
8837330f729Sjoerg AddQualType(T->getElementType());
8847330f729Sjoerg AddStmt(T->getSizeExpr());
8857330f729Sjoerg VisitType(T);
8867330f729Sjoerg }
8877330f729Sjoerg
VisitFunctionType(const FunctionType * T)8887330f729Sjoerg void VisitFunctionType(const FunctionType *T) {
8897330f729Sjoerg AddQualType(T->getReturnType());
8907330f729Sjoerg T->getExtInfo().Profile(ID);
8917330f729Sjoerg Hash.AddBoolean(T->isConst());
8927330f729Sjoerg Hash.AddBoolean(T->isVolatile());
8937330f729Sjoerg Hash.AddBoolean(T->isRestrict());
8947330f729Sjoerg VisitType(T);
8957330f729Sjoerg }
8967330f729Sjoerg
VisitFunctionNoProtoType(const FunctionNoProtoType * T)8977330f729Sjoerg void VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
8987330f729Sjoerg VisitFunctionType(T);
8997330f729Sjoerg }
9007330f729Sjoerg
VisitFunctionProtoType(const FunctionProtoType * T)9017330f729Sjoerg void VisitFunctionProtoType(const FunctionProtoType *T) {
9027330f729Sjoerg ID.AddInteger(T->getNumParams());
9037330f729Sjoerg for (auto ParamType : T->getParamTypes())
9047330f729Sjoerg AddQualType(ParamType);
9057330f729Sjoerg
9067330f729Sjoerg VisitFunctionType(T);
9077330f729Sjoerg }
9087330f729Sjoerg
VisitInjectedClassNameType(const InjectedClassNameType * T)9097330f729Sjoerg void VisitInjectedClassNameType(const InjectedClassNameType *T) {
9107330f729Sjoerg AddDecl(T->getDecl());
9117330f729Sjoerg VisitType(T);
9127330f729Sjoerg }
9137330f729Sjoerg
VisitMemberPointerType(const MemberPointerType * T)9147330f729Sjoerg void VisitMemberPointerType(const MemberPointerType *T) {
9157330f729Sjoerg AddQualType(T->getPointeeType());
9167330f729Sjoerg AddType(T->getClass());
9177330f729Sjoerg VisitType(T);
9187330f729Sjoerg }
9197330f729Sjoerg
VisitObjCObjectPointerType(const ObjCObjectPointerType * T)9207330f729Sjoerg void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
9217330f729Sjoerg AddQualType(T->getPointeeType());
9227330f729Sjoerg VisitType(T);
9237330f729Sjoerg }
9247330f729Sjoerg
VisitObjCObjectType(const ObjCObjectType * T)9257330f729Sjoerg void VisitObjCObjectType(const ObjCObjectType *T) {
9267330f729Sjoerg AddDecl(T->getInterface());
9277330f729Sjoerg
9287330f729Sjoerg auto TypeArgs = T->getTypeArgsAsWritten();
9297330f729Sjoerg ID.AddInteger(TypeArgs.size());
9307330f729Sjoerg for (auto Arg : TypeArgs) {
9317330f729Sjoerg AddQualType(Arg);
9327330f729Sjoerg }
9337330f729Sjoerg
9347330f729Sjoerg auto Protocols = T->getProtocols();
9357330f729Sjoerg ID.AddInteger(Protocols.size());
9367330f729Sjoerg for (auto Protocol : Protocols) {
9377330f729Sjoerg AddDecl(Protocol);
9387330f729Sjoerg }
9397330f729Sjoerg
9407330f729Sjoerg Hash.AddBoolean(T->isKindOfType());
9417330f729Sjoerg
9427330f729Sjoerg VisitType(T);
9437330f729Sjoerg }
9447330f729Sjoerg
VisitObjCInterfaceType(const ObjCInterfaceType * T)9457330f729Sjoerg void VisitObjCInterfaceType(const ObjCInterfaceType *T) {
9467330f729Sjoerg // This type is handled by the parent type ObjCObjectType.
9477330f729Sjoerg VisitObjCObjectType(T);
9487330f729Sjoerg }
9497330f729Sjoerg
VisitObjCTypeParamType(const ObjCTypeParamType * T)9507330f729Sjoerg void VisitObjCTypeParamType(const ObjCTypeParamType *T) {
9517330f729Sjoerg AddDecl(T->getDecl());
9527330f729Sjoerg auto Protocols = T->getProtocols();
9537330f729Sjoerg ID.AddInteger(Protocols.size());
9547330f729Sjoerg for (auto Protocol : Protocols) {
9557330f729Sjoerg AddDecl(Protocol);
9567330f729Sjoerg }
9577330f729Sjoerg
9587330f729Sjoerg VisitType(T);
9597330f729Sjoerg }
9607330f729Sjoerg
VisitPackExpansionType(const PackExpansionType * T)9617330f729Sjoerg void VisitPackExpansionType(const PackExpansionType *T) {
9627330f729Sjoerg AddQualType(T->getPattern());
9637330f729Sjoerg VisitType(T);
9647330f729Sjoerg }
9657330f729Sjoerg
VisitParenType(const ParenType * T)9667330f729Sjoerg void VisitParenType(const ParenType *T) {
9677330f729Sjoerg AddQualType(T->getInnerType());
9687330f729Sjoerg VisitType(T);
9697330f729Sjoerg }
9707330f729Sjoerg
VisitPipeType(const PipeType * T)9717330f729Sjoerg void VisitPipeType(const PipeType *T) {
9727330f729Sjoerg AddQualType(T->getElementType());
9737330f729Sjoerg Hash.AddBoolean(T->isReadOnly());
9747330f729Sjoerg VisitType(T);
9757330f729Sjoerg }
9767330f729Sjoerg
VisitPointerType(const PointerType * T)9777330f729Sjoerg void VisitPointerType(const PointerType *T) {
9787330f729Sjoerg AddQualType(T->getPointeeType());
9797330f729Sjoerg VisitType(T);
9807330f729Sjoerg }
9817330f729Sjoerg
VisitReferenceType(const ReferenceType * T)9827330f729Sjoerg void VisitReferenceType(const ReferenceType *T) {
9837330f729Sjoerg AddQualType(T->getPointeeTypeAsWritten());
9847330f729Sjoerg VisitType(T);
9857330f729Sjoerg }
9867330f729Sjoerg
VisitLValueReferenceType(const LValueReferenceType * T)9877330f729Sjoerg void VisitLValueReferenceType(const LValueReferenceType *T) {
9887330f729Sjoerg VisitReferenceType(T);
9897330f729Sjoerg }
9907330f729Sjoerg
VisitRValueReferenceType(const RValueReferenceType * T)9917330f729Sjoerg void VisitRValueReferenceType(const RValueReferenceType *T) {
9927330f729Sjoerg VisitReferenceType(T);
9937330f729Sjoerg }
9947330f729Sjoerg
9957330f729Sjoerg void
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType * T)9967330f729Sjoerg VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
9977330f729Sjoerg AddType(T->getReplacedParameter());
9987330f729Sjoerg Hash.AddTemplateArgument(T->getArgumentPack());
9997330f729Sjoerg VisitType(T);
10007330f729Sjoerg }
10017330f729Sjoerg
VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType * T)10027330f729Sjoerg void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
10037330f729Sjoerg AddType(T->getReplacedParameter());
10047330f729Sjoerg AddQualType(T->getReplacementType());
10057330f729Sjoerg VisitType(T);
10067330f729Sjoerg }
10077330f729Sjoerg
VisitTagType(const TagType * T)10087330f729Sjoerg void VisitTagType(const TagType *T) {
10097330f729Sjoerg AddDecl(T->getDecl());
10107330f729Sjoerg VisitType(T);
10117330f729Sjoerg }
10127330f729Sjoerg
VisitRecordType(const RecordType * T)10137330f729Sjoerg void VisitRecordType(const RecordType *T) { VisitTagType(T); }
VisitEnumType(const EnumType * T)10147330f729Sjoerg void VisitEnumType(const EnumType *T) { VisitTagType(T); }
10157330f729Sjoerg
VisitTemplateSpecializationType(const TemplateSpecializationType * T)10167330f729Sjoerg void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
10177330f729Sjoerg ID.AddInteger(T->getNumArgs());
10187330f729Sjoerg for (const auto &TA : T->template_arguments()) {
10197330f729Sjoerg Hash.AddTemplateArgument(TA);
10207330f729Sjoerg }
10217330f729Sjoerg Hash.AddTemplateName(T->getTemplateName());
10227330f729Sjoerg VisitType(T);
10237330f729Sjoerg }
10247330f729Sjoerg
VisitTemplateTypeParmType(const TemplateTypeParmType * T)10257330f729Sjoerg void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
10267330f729Sjoerg ID.AddInteger(T->getDepth());
10277330f729Sjoerg ID.AddInteger(T->getIndex());
10287330f729Sjoerg Hash.AddBoolean(T->isParameterPack());
10297330f729Sjoerg AddDecl(T->getDecl());
10307330f729Sjoerg }
10317330f729Sjoerg
VisitTypedefType(const TypedefType * T)10327330f729Sjoerg void VisitTypedefType(const TypedefType *T) {
10337330f729Sjoerg AddDecl(T->getDecl());
10347330f729Sjoerg QualType UnderlyingType = T->getDecl()->getUnderlyingType();
10357330f729Sjoerg VisitQualifiers(UnderlyingType.getQualifiers());
10367330f729Sjoerg while (true) {
10377330f729Sjoerg if (const TypedefType *Underlying =
10387330f729Sjoerg dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) {
10397330f729Sjoerg UnderlyingType = Underlying->getDecl()->getUnderlyingType();
10407330f729Sjoerg continue;
10417330f729Sjoerg }
10427330f729Sjoerg if (const ElaboratedType *Underlying =
10437330f729Sjoerg dyn_cast<ElaboratedType>(UnderlyingType.getTypePtr())) {
10447330f729Sjoerg UnderlyingType = Underlying->getNamedType();
10457330f729Sjoerg continue;
10467330f729Sjoerg }
10477330f729Sjoerg
10487330f729Sjoerg break;
10497330f729Sjoerg }
10507330f729Sjoerg AddType(UnderlyingType.getTypePtr());
10517330f729Sjoerg VisitType(T);
10527330f729Sjoerg }
10537330f729Sjoerg
VisitTypeOfExprType(const TypeOfExprType * T)10547330f729Sjoerg void VisitTypeOfExprType(const TypeOfExprType *T) {
10557330f729Sjoerg AddStmt(T->getUnderlyingExpr());
10567330f729Sjoerg Hash.AddBoolean(T->isSugared());
10577330f729Sjoerg if (T->isSugared())
10587330f729Sjoerg AddQualType(T->desugar());
10597330f729Sjoerg
10607330f729Sjoerg VisitType(T);
10617330f729Sjoerg }
VisitTypeOfType(const TypeOfType * T)10627330f729Sjoerg void VisitTypeOfType(const TypeOfType *T) {
10637330f729Sjoerg AddQualType(T->getUnderlyingType());
10647330f729Sjoerg VisitType(T);
10657330f729Sjoerg }
10667330f729Sjoerg
VisitTypeWithKeyword(const TypeWithKeyword * T)10677330f729Sjoerg void VisitTypeWithKeyword(const TypeWithKeyword *T) {
10687330f729Sjoerg ID.AddInteger(T->getKeyword());
10697330f729Sjoerg VisitType(T);
10707330f729Sjoerg };
10717330f729Sjoerg
VisitDependentNameType(const DependentNameType * T)10727330f729Sjoerg void VisitDependentNameType(const DependentNameType *T) {
10737330f729Sjoerg AddNestedNameSpecifier(T->getQualifier());
10747330f729Sjoerg AddIdentifierInfo(T->getIdentifier());
10757330f729Sjoerg VisitTypeWithKeyword(T);
10767330f729Sjoerg }
10777330f729Sjoerg
VisitDependentTemplateSpecializationType(const DependentTemplateSpecializationType * T)10787330f729Sjoerg void VisitDependentTemplateSpecializationType(
10797330f729Sjoerg const DependentTemplateSpecializationType *T) {
10807330f729Sjoerg AddIdentifierInfo(T->getIdentifier());
10817330f729Sjoerg AddNestedNameSpecifier(T->getQualifier());
10827330f729Sjoerg ID.AddInteger(T->getNumArgs());
10837330f729Sjoerg for (const auto &TA : T->template_arguments()) {
10847330f729Sjoerg Hash.AddTemplateArgument(TA);
10857330f729Sjoerg }
10867330f729Sjoerg VisitTypeWithKeyword(T);
10877330f729Sjoerg }
10887330f729Sjoerg
VisitElaboratedType(const ElaboratedType * T)10897330f729Sjoerg void VisitElaboratedType(const ElaboratedType *T) {
10907330f729Sjoerg AddNestedNameSpecifier(T->getQualifier());
10917330f729Sjoerg AddQualType(T->getNamedType());
10927330f729Sjoerg VisitTypeWithKeyword(T);
10937330f729Sjoerg }
10947330f729Sjoerg
VisitUnaryTransformType(const UnaryTransformType * T)10957330f729Sjoerg void VisitUnaryTransformType(const UnaryTransformType *T) {
10967330f729Sjoerg AddQualType(T->getUnderlyingType());
10977330f729Sjoerg AddQualType(T->getBaseType());
10987330f729Sjoerg VisitType(T);
10997330f729Sjoerg }
11007330f729Sjoerg
VisitUnresolvedUsingType(const UnresolvedUsingType * T)11017330f729Sjoerg void VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
11027330f729Sjoerg AddDecl(T->getDecl());
11037330f729Sjoerg VisitType(T);
11047330f729Sjoerg }
11057330f729Sjoerg
VisitVectorType(const VectorType * T)11067330f729Sjoerg void VisitVectorType(const VectorType *T) {
11077330f729Sjoerg AddQualType(T->getElementType());
11087330f729Sjoerg ID.AddInteger(T->getNumElements());
11097330f729Sjoerg ID.AddInteger(T->getVectorKind());
11107330f729Sjoerg VisitType(T);
11117330f729Sjoerg }
11127330f729Sjoerg
VisitExtVectorType(const ExtVectorType * T)11137330f729Sjoerg void VisitExtVectorType(const ExtVectorType * T) {
11147330f729Sjoerg VisitVectorType(T);
11157330f729Sjoerg }
11167330f729Sjoerg };
11177330f729Sjoerg } // namespace
11187330f729Sjoerg
AddType(const Type * T)11197330f729Sjoerg void ODRHash::AddType(const Type *T) {
11207330f729Sjoerg assert(T && "Expecting non-null pointer.");
11217330f729Sjoerg ODRTypeVisitor(ID, *this).Visit(T);
11227330f729Sjoerg }
11237330f729Sjoerg
AddQualType(QualType T)11247330f729Sjoerg void ODRHash::AddQualType(QualType T) {
11257330f729Sjoerg AddBoolean(T.isNull());
11267330f729Sjoerg if (T.isNull())
11277330f729Sjoerg return;
11287330f729Sjoerg SplitQualType split = T.split();
11297330f729Sjoerg ID.AddInteger(split.Quals.getAsOpaqueValue());
11307330f729Sjoerg AddType(split.Ty);
11317330f729Sjoerg }
11327330f729Sjoerg
AddBoolean(bool Value)11337330f729Sjoerg void ODRHash::AddBoolean(bool Value) {
11347330f729Sjoerg Bools.push_back(Value);
11357330f729Sjoerg }
1136