xref: /openbsd-src/gnu/llvm/clang/lib/AST/ODRHash.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
1e5dd7070Spatrick //===-- ODRHash.cpp - Hashing to diagnose ODR failures ----------*- C++ -*-===//
2e5dd7070Spatrick //
3e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e5dd7070Spatrick //
7e5dd7070Spatrick //===----------------------------------------------------------------------===//
8e5dd7070Spatrick ///
9e5dd7070Spatrick /// \file
10e5dd7070Spatrick /// This file implements the ODRHash class, which calculates a hash based
11e5dd7070Spatrick /// on AST nodes, which is stable across different runs.
12e5dd7070Spatrick ///
13e5dd7070Spatrick //===----------------------------------------------------------------------===//
14e5dd7070Spatrick 
15e5dd7070Spatrick #include "clang/AST/ODRHash.h"
16e5dd7070Spatrick 
17e5dd7070Spatrick #include "clang/AST/DeclVisitor.h"
18e5dd7070Spatrick #include "clang/AST/NestedNameSpecifier.h"
19e5dd7070Spatrick #include "clang/AST/StmtVisitor.h"
20e5dd7070Spatrick #include "clang/AST/TypeVisitor.h"
21e5dd7070Spatrick 
22e5dd7070Spatrick using namespace clang;
23e5dd7070Spatrick 
AddStmt(const Stmt * S)24e5dd7070Spatrick void ODRHash::AddStmt(const Stmt *S) {
25e5dd7070Spatrick   assert(S && "Expecting non-null pointer.");
26e5dd7070Spatrick   S->ProcessODRHash(ID, *this);
27e5dd7070Spatrick }
28e5dd7070Spatrick 
AddIdentifierInfo(const IdentifierInfo * II)29e5dd7070Spatrick void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) {
30e5dd7070Spatrick   assert(II && "Expecting non-null pointer.");
31e5dd7070Spatrick   ID.AddString(II->getName());
32e5dd7070Spatrick }
33e5dd7070Spatrick 
AddDeclarationName(DeclarationName Name,bool TreatAsDecl)34e5dd7070Spatrick void ODRHash::AddDeclarationName(DeclarationName Name, bool TreatAsDecl) {
35e5dd7070Spatrick   if (TreatAsDecl)
36e5dd7070Spatrick     // Matches the NamedDecl check in AddDecl
37e5dd7070Spatrick     AddBoolean(true);
38e5dd7070Spatrick 
39e5dd7070Spatrick   AddDeclarationNameImpl(Name);
40e5dd7070Spatrick 
41e5dd7070Spatrick   if (TreatAsDecl)
42e5dd7070Spatrick     // Matches the ClassTemplateSpecializationDecl check in AddDecl
43e5dd7070Spatrick     AddBoolean(false);
44e5dd7070Spatrick }
45e5dd7070Spatrick 
AddDeclarationNameImpl(DeclarationName Name)46e5dd7070Spatrick void ODRHash::AddDeclarationNameImpl(DeclarationName Name) {
47e5dd7070Spatrick   // Index all DeclarationName and use index numbers to refer to them.
48e5dd7070Spatrick   auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size()));
49e5dd7070Spatrick   ID.AddInteger(Result.first->second);
50e5dd7070Spatrick   if (!Result.second) {
51e5dd7070Spatrick     // If found in map, the DeclarationName has previously been processed.
52e5dd7070Spatrick     return;
53e5dd7070Spatrick   }
54e5dd7070Spatrick 
55e5dd7070Spatrick   // First time processing each DeclarationName, also process its details.
56e5dd7070Spatrick   AddBoolean(Name.isEmpty());
57e5dd7070Spatrick   if (Name.isEmpty())
58e5dd7070Spatrick     return;
59e5dd7070Spatrick 
60e5dd7070Spatrick   auto Kind = Name.getNameKind();
61e5dd7070Spatrick   ID.AddInteger(Kind);
62e5dd7070Spatrick   switch (Kind) {
63e5dd7070Spatrick   case DeclarationName::Identifier:
64e5dd7070Spatrick     AddIdentifierInfo(Name.getAsIdentifierInfo());
65e5dd7070Spatrick     break;
66e5dd7070Spatrick   case DeclarationName::ObjCZeroArgSelector:
67e5dd7070Spatrick   case DeclarationName::ObjCOneArgSelector:
68e5dd7070Spatrick   case DeclarationName::ObjCMultiArgSelector: {
69e5dd7070Spatrick     Selector S = Name.getObjCSelector();
70e5dd7070Spatrick     AddBoolean(S.isNull());
71e5dd7070Spatrick     AddBoolean(S.isKeywordSelector());
72e5dd7070Spatrick     AddBoolean(S.isUnarySelector());
73e5dd7070Spatrick     unsigned NumArgs = S.getNumArgs();
74e5dd7070Spatrick     ID.AddInteger(NumArgs);
75*12c85518Srobert     // Compare all selector slots. For selectors with arguments it means all arg
76*12c85518Srobert     // slots. And if there are no arguments, compare the first-and-only slot.
77*12c85518Srobert     unsigned SlotsToCheck = NumArgs > 0 ? NumArgs : 1;
78*12c85518Srobert     for (unsigned i = 0; i < SlotsToCheck; ++i) {
79e5dd7070Spatrick       const IdentifierInfo *II = S.getIdentifierInfoForSlot(i);
80e5dd7070Spatrick       AddBoolean(II);
81e5dd7070Spatrick       if (II) {
82e5dd7070Spatrick         AddIdentifierInfo(II);
83e5dd7070Spatrick       }
84e5dd7070Spatrick     }
85e5dd7070Spatrick     break;
86e5dd7070Spatrick   }
87e5dd7070Spatrick   case DeclarationName::CXXConstructorName:
88e5dd7070Spatrick   case DeclarationName::CXXDestructorName:
89e5dd7070Spatrick     AddQualType(Name.getCXXNameType());
90e5dd7070Spatrick     break;
91e5dd7070Spatrick   case DeclarationName::CXXOperatorName:
92e5dd7070Spatrick     ID.AddInteger(Name.getCXXOverloadedOperator());
93e5dd7070Spatrick     break;
94e5dd7070Spatrick   case DeclarationName::CXXLiteralOperatorName:
95e5dd7070Spatrick     AddIdentifierInfo(Name.getCXXLiteralIdentifier());
96e5dd7070Spatrick     break;
97e5dd7070Spatrick   case DeclarationName::CXXConversionFunctionName:
98e5dd7070Spatrick     AddQualType(Name.getCXXNameType());
99e5dd7070Spatrick     break;
100e5dd7070Spatrick   case DeclarationName::CXXUsingDirective:
101e5dd7070Spatrick     break;
102e5dd7070Spatrick   case DeclarationName::CXXDeductionGuideName: {
103e5dd7070Spatrick     auto *Template = Name.getCXXDeductionGuideTemplate();
104e5dd7070Spatrick     AddBoolean(Template);
105e5dd7070Spatrick     if (Template) {
106e5dd7070Spatrick       AddDecl(Template);
107e5dd7070Spatrick     }
108e5dd7070Spatrick   }
109e5dd7070Spatrick   }
110e5dd7070Spatrick }
111e5dd7070Spatrick 
AddNestedNameSpecifier(const NestedNameSpecifier * NNS)112e5dd7070Spatrick void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
113e5dd7070Spatrick   assert(NNS && "Expecting non-null pointer.");
114e5dd7070Spatrick   const auto *Prefix = NNS->getPrefix();
115e5dd7070Spatrick   AddBoolean(Prefix);
116e5dd7070Spatrick   if (Prefix) {
117e5dd7070Spatrick     AddNestedNameSpecifier(Prefix);
118e5dd7070Spatrick   }
119e5dd7070Spatrick   auto Kind = NNS->getKind();
120e5dd7070Spatrick   ID.AddInteger(Kind);
121e5dd7070Spatrick   switch (Kind) {
122e5dd7070Spatrick   case NestedNameSpecifier::Identifier:
123e5dd7070Spatrick     AddIdentifierInfo(NNS->getAsIdentifier());
124e5dd7070Spatrick     break;
125e5dd7070Spatrick   case NestedNameSpecifier::Namespace:
126e5dd7070Spatrick     AddDecl(NNS->getAsNamespace());
127e5dd7070Spatrick     break;
128e5dd7070Spatrick   case NestedNameSpecifier::NamespaceAlias:
129e5dd7070Spatrick     AddDecl(NNS->getAsNamespaceAlias());
130e5dd7070Spatrick     break;
131e5dd7070Spatrick   case NestedNameSpecifier::TypeSpec:
132e5dd7070Spatrick   case NestedNameSpecifier::TypeSpecWithTemplate:
133e5dd7070Spatrick     AddType(NNS->getAsType());
134e5dd7070Spatrick     break;
135e5dd7070Spatrick   case NestedNameSpecifier::Global:
136e5dd7070Spatrick   case NestedNameSpecifier::Super:
137e5dd7070Spatrick     break;
138e5dd7070Spatrick   }
139e5dd7070Spatrick }
140e5dd7070Spatrick 
AddTemplateName(TemplateName Name)141e5dd7070Spatrick void ODRHash::AddTemplateName(TemplateName Name) {
142e5dd7070Spatrick   auto Kind = Name.getKind();
143e5dd7070Spatrick   ID.AddInteger(Kind);
144e5dd7070Spatrick 
145e5dd7070Spatrick   switch (Kind) {
146e5dd7070Spatrick   case TemplateName::Template:
147e5dd7070Spatrick     AddDecl(Name.getAsTemplateDecl());
148e5dd7070Spatrick     break;
149e5dd7070Spatrick   // TODO: Support these cases.
150e5dd7070Spatrick   case TemplateName::OverloadedTemplate:
151e5dd7070Spatrick   case TemplateName::AssumedTemplate:
152e5dd7070Spatrick   case TemplateName::QualifiedTemplate:
153e5dd7070Spatrick   case TemplateName::DependentTemplate:
154e5dd7070Spatrick   case TemplateName::SubstTemplateTemplateParm:
155e5dd7070Spatrick   case TemplateName::SubstTemplateTemplateParmPack:
156*12c85518Srobert   case TemplateName::UsingTemplate:
157e5dd7070Spatrick     break;
158e5dd7070Spatrick   }
159e5dd7070Spatrick }
160e5dd7070Spatrick 
AddTemplateArgument(TemplateArgument TA)161e5dd7070Spatrick void ODRHash::AddTemplateArgument(TemplateArgument TA) {
162e5dd7070Spatrick   const auto Kind = TA.getKind();
163e5dd7070Spatrick   ID.AddInteger(Kind);
164e5dd7070Spatrick 
165e5dd7070Spatrick   switch (Kind) {
166e5dd7070Spatrick     case TemplateArgument::Null:
167e5dd7070Spatrick       llvm_unreachable("Expected valid TemplateArgument");
168e5dd7070Spatrick     case TemplateArgument::Type:
169e5dd7070Spatrick       AddQualType(TA.getAsType());
170e5dd7070Spatrick       break;
171e5dd7070Spatrick     case TemplateArgument::Declaration:
172e5dd7070Spatrick       AddDecl(TA.getAsDecl());
173e5dd7070Spatrick       break;
174e5dd7070Spatrick     case TemplateArgument::NullPtr:
175*12c85518Srobert       ID.AddPointer(nullptr);
176e5dd7070Spatrick       break;
177*12c85518Srobert     case TemplateArgument::Integral: {
178*12c85518Srobert       // There are integrals (e.g.: _BitInt(128)) that cannot be represented as
179*12c85518Srobert       // any builtin integral type, so we use the hash of APSInt instead.
180*12c85518Srobert       TA.getAsIntegral().Profile(ID);
181*12c85518Srobert       break;
182*12c85518Srobert     }
183e5dd7070Spatrick     case TemplateArgument::Template:
184e5dd7070Spatrick     case TemplateArgument::TemplateExpansion:
185e5dd7070Spatrick       AddTemplateName(TA.getAsTemplateOrTemplatePattern());
186e5dd7070Spatrick       break;
187e5dd7070Spatrick     case TemplateArgument::Expression:
188e5dd7070Spatrick       AddStmt(TA.getAsExpr());
189e5dd7070Spatrick       break;
190e5dd7070Spatrick     case TemplateArgument::Pack:
191e5dd7070Spatrick       ID.AddInteger(TA.pack_size());
192e5dd7070Spatrick       for (auto SubTA : TA.pack_elements()) {
193e5dd7070Spatrick         AddTemplateArgument(SubTA);
194e5dd7070Spatrick       }
195e5dd7070Spatrick       break;
196e5dd7070Spatrick   }
197e5dd7070Spatrick }
198e5dd7070Spatrick 
AddTemplateParameterList(const TemplateParameterList * TPL)199e5dd7070Spatrick void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {
200e5dd7070Spatrick   assert(TPL && "Expecting non-null pointer.");
201e5dd7070Spatrick 
202e5dd7070Spatrick   ID.AddInteger(TPL->size());
203e5dd7070Spatrick   for (auto *ND : TPL->asArray()) {
204e5dd7070Spatrick     AddSubDecl(ND);
205e5dd7070Spatrick   }
206e5dd7070Spatrick }
207e5dd7070Spatrick 
clear()208e5dd7070Spatrick void ODRHash::clear() {
209e5dd7070Spatrick   DeclNameMap.clear();
210e5dd7070Spatrick   Bools.clear();
211e5dd7070Spatrick   ID.clear();
212e5dd7070Spatrick }
213e5dd7070Spatrick 
CalculateHash()214e5dd7070Spatrick unsigned ODRHash::CalculateHash() {
215e5dd7070Spatrick   // Append the bools to the end of the data segment backwards.  This allows
216e5dd7070Spatrick   // for the bools data to be compressed 32 times smaller compared to using
217e5dd7070Spatrick   // ID.AddBoolean
218e5dd7070Spatrick   const unsigned unsigned_bits = sizeof(unsigned) * CHAR_BIT;
219e5dd7070Spatrick   const unsigned size = Bools.size();
220e5dd7070Spatrick   const unsigned remainder = size % unsigned_bits;
221e5dd7070Spatrick   const unsigned loops = size / unsigned_bits;
222e5dd7070Spatrick   auto I = Bools.rbegin();
223e5dd7070Spatrick   unsigned value = 0;
224e5dd7070Spatrick   for (unsigned i = 0; i < remainder; ++i) {
225e5dd7070Spatrick     value <<= 1;
226e5dd7070Spatrick     value |= *I;
227e5dd7070Spatrick     ++I;
228e5dd7070Spatrick   }
229e5dd7070Spatrick   ID.AddInteger(value);
230e5dd7070Spatrick 
231e5dd7070Spatrick   for (unsigned i = 0; i < loops; ++i) {
232e5dd7070Spatrick     value = 0;
233e5dd7070Spatrick     for (unsigned j = 0; j < unsigned_bits; ++j) {
234e5dd7070Spatrick       value <<= 1;
235e5dd7070Spatrick       value |= *I;
236e5dd7070Spatrick       ++I;
237e5dd7070Spatrick     }
238e5dd7070Spatrick     ID.AddInteger(value);
239e5dd7070Spatrick   }
240e5dd7070Spatrick 
241e5dd7070Spatrick   assert(I == Bools.rend());
242e5dd7070Spatrick   Bools.clear();
243e5dd7070Spatrick   return ID.ComputeHash();
244e5dd7070Spatrick }
245e5dd7070Spatrick 
246e5dd7070Spatrick namespace {
247e5dd7070Spatrick // Process a Decl pointer.  Add* methods call back into ODRHash while Visit*
248e5dd7070Spatrick // methods process the relevant parts of the Decl.
249e5dd7070Spatrick class ODRDeclVisitor : public ConstDeclVisitor<ODRDeclVisitor> {
250e5dd7070Spatrick   typedef ConstDeclVisitor<ODRDeclVisitor> Inherited;
251e5dd7070Spatrick   llvm::FoldingSetNodeID &ID;
252e5dd7070Spatrick   ODRHash &Hash;
253e5dd7070Spatrick 
254e5dd7070Spatrick public:
ODRDeclVisitor(llvm::FoldingSetNodeID & ID,ODRHash & Hash)255e5dd7070Spatrick   ODRDeclVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash)
256e5dd7070Spatrick       : ID(ID), Hash(Hash) {}
257e5dd7070Spatrick 
AddStmt(const Stmt * S)258e5dd7070Spatrick   void AddStmt(const Stmt *S) {
259e5dd7070Spatrick     Hash.AddBoolean(S);
260e5dd7070Spatrick     if (S) {
261e5dd7070Spatrick       Hash.AddStmt(S);
262e5dd7070Spatrick     }
263e5dd7070Spatrick   }
264e5dd7070Spatrick 
AddIdentifierInfo(const IdentifierInfo * II)265e5dd7070Spatrick   void AddIdentifierInfo(const IdentifierInfo *II) {
266e5dd7070Spatrick     Hash.AddBoolean(II);
267e5dd7070Spatrick     if (II) {
268e5dd7070Spatrick       Hash.AddIdentifierInfo(II);
269e5dd7070Spatrick     }
270e5dd7070Spatrick   }
271e5dd7070Spatrick 
AddQualType(QualType T)272e5dd7070Spatrick   void AddQualType(QualType T) {
273e5dd7070Spatrick     Hash.AddQualType(T);
274e5dd7070Spatrick   }
275e5dd7070Spatrick 
AddDecl(const Decl * D)276e5dd7070Spatrick   void AddDecl(const Decl *D) {
277e5dd7070Spatrick     Hash.AddBoolean(D);
278e5dd7070Spatrick     if (D) {
279e5dd7070Spatrick       Hash.AddDecl(D);
280e5dd7070Spatrick     }
281e5dd7070Spatrick   }
282e5dd7070Spatrick 
AddTemplateArgument(TemplateArgument TA)283e5dd7070Spatrick   void AddTemplateArgument(TemplateArgument TA) {
284e5dd7070Spatrick     Hash.AddTemplateArgument(TA);
285e5dd7070Spatrick   }
286e5dd7070Spatrick 
Visit(const Decl * D)287e5dd7070Spatrick   void Visit(const Decl *D) {
288e5dd7070Spatrick     ID.AddInteger(D->getKind());
289e5dd7070Spatrick     Inherited::Visit(D);
290e5dd7070Spatrick   }
291e5dd7070Spatrick 
VisitNamedDecl(const NamedDecl * D)292e5dd7070Spatrick   void VisitNamedDecl(const NamedDecl *D) {
293e5dd7070Spatrick     Hash.AddDeclarationName(D->getDeclName());
294e5dd7070Spatrick     Inherited::VisitNamedDecl(D);
295e5dd7070Spatrick   }
296e5dd7070Spatrick 
VisitValueDecl(const ValueDecl * D)297e5dd7070Spatrick   void VisitValueDecl(const ValueDecl *D) {
298e5dd7070Spatrick     if (!isa<FunctionDecl>(D)) {
299e5dd7070Spatrick       AddQualType(D->getType());
300e5dd7070Spatrick     }
301e5dd7070Spatrick     Inherited::VisitValueDecl(D);
302e5dd7070Spatrick   }
303e5dd7070Spatrick 
VisitVarDecl(const VarDecl * D)304e5dd7070Spatrick   void VisitVarDecl(const VarDecl *D) {
305e5dd7070Spatrick     Hash.AddBoolean(D->isStaticLocal());
306e5dd7070Spatrick     Hash.AddBoolean(D->isConstexpr());
307e5dd7070Spatrick     const bool HasInit = D->hasInit();
308e5dd7070Spatrick     Hash.AddBoolean(HasInit);
309e5dd7070Spatrick     if (HasInit) {
310e5dd7070Spatrick       AddStmt(D->getInit());
311e5dd7070Spatrick     }
312e5dd7070Spatrick     Inherited::VisitVarDecl(D);
313e5dd7070Spatrick   }
314e5dd7070Spatrick 
VisitParmVarDecl(const ParmVarDecl * D)315e5dd7070Spatrick   void VisitParmVarDecl(const ParmVarDecl *D) {
316e5dd7070Spatrick     // TODO: Handle default arguments.
317e5dd7070Spatrick     Inherited::VisitParmVarDecl(D);
318e5dd7070Spatrick   }
319e5dd7070Spatrick 
VisitAccessSpecDecl(const AccessSpecDecl * D)320e5dd7070Spatrick   void VisitAccessSpecDecl(const AccessSpecDecl *D) {
321e5dd7070Spatrick     ID.AddInteger(D->getAccess());
322e5dd7070Spatrick     Inherited::VisitAccessSpecDecl(D);
323e5dd7070Spatrick   }
324e5dd7070Spatrick 
VisitStaticAssertDecl(const StaticAssertDecl * D)325e5dd7070Spatrick   void VisitStaticAssertDecl(const StaticAssertDecl *D) {
326e5dd7070Spatrick     AddStmt(D->getAssertExpr());
327e5dd7070Spatrick     AddStmt(D->getMessage());
328e5dd7070Spatrick 
329e5dd7070Spatrick     Inherited::VisitStaticAssertDecl(D);
330e5dd7070Spatrick   }
331e5dd7070Spatrick 
VisitFieldDecl(const FieldDecl * D)332e5dd7070Spatrick   void VisitFieldDecl(const FieldDecl *D) {
333e5dd7070Spatrick     const bool IsBitfield = D->isBitField();
334e5dd7070Spatrick     Hash.AddBoolean(IsBitfield);
335e5dd7070Spatrick 
336e5dd7070Spatrick     if (IsBitfield) {
337e5dd7070Spatrick       AddStmt(D->getBitWidth());
338e5dd7070Spatrick     }
339e5dd7070Spatrick 
340e5dd7070Spatrick     Hash.AddBoolean(D->isMutable());
341e5dd7070Spatrick     AddStmt(D->getInClassInitializer());
342e5dd7070Spatrick 
343e5dd7070Spatrick     Inherited::VisitFieldDecl(D);
344e5dd7070Spatrick   }
345e5dd7070Spatrick 
VisitObjCIvarDecl(const ObjCIvarDecl * D)346*12c85518Srobert   void VisitObjCIvarDecl(const ObjCIvarDecl *D) {
347*12c85518Srobert     ID.AddInteger(D->getCanonicalAccessControl());
348*12c85518Srobert     Inherited::VisitObjCIvarDecl(D);
349*12c85518Srobert   }
350*12c85518Srobert 
VisitObjCPropertyDecl(const ObjCPropertyDecl * D)351*12c85518Srobert   void VisitObjCPropertyDecl(const ObjCPropertyDecl *D) {
352*12c85518Srobert     ID.AddInteger(D->getPropertyAttributes());
353*12c85518Srobert     ID.AddInteger(D->getPropertyImplementation());
354*12c85518Srobert     AddQualType(D->getType());
355*12c85518Srobert     AddDecl(D);
356*12c85518Srobert 
357*12c85518Srobert     Inherited::VisitObjCPropertyDecl(D);
358*12c85518Srobert   }
359*12c85518Srobert 
VisitFunctionDecl(const FunctionDecl * D)360e5dd7070Spatrick   void VisitFunctionDecl(const FunctionDecl *D) {
361e5dd7070Spatrick     // Handled by the ODRHash for FunctionDecl
362e5dd7070Spatrick     ID.AddInteger(D->getODRHash());
363e5dd7070Spatrick 
364e5dd7070Spatrick     Inherited::VisitFunctionDecl(D);
365e5dd7070Spatrick   }
366e5dd7070Spatrick 
VisitCXXMethodDecl(const CXXMethodDecl * D)367e5dd7070Spatrick   void VisitCXXMethodDecl(const CXXMethodDecl *D) {
368e5dd7070Spatrick     // Handled by the ODRHash for FunctionDecl
369e5dd7070Spatrick 
370e5dd7070Spatrick     Inherited::VisitCXXMethodDecl(D);
371e5dd7070Spatrick   }
372e5dd7070Spatrick 
VisitObjCMethodDecl(const ObjCMethodDecl * Method)373*12c85518Srobert   void VisitObjCMethodDecl(const ObjCMethodDecl *Method) {
374*12c85518Srobert     ID.AddInteger(Method->getDeclKind());
375*12c85518Srobert     Hash.AddBoolean(Method->isInstanceMethod()); // false if class method
376*12c85518Srobert     Hash.AddBoolean(Method->isPropertyAccessor());
377*12c85518Srobert     Hash.AddBoolean(Method->isVariadic());
378*12c85518Srobert     Hash.AddBoolean(Method->isSynthesizedAccessorStub());
379*12c85518Srobert     Hash.AddBoolean(Method->isDefined());
380*12c85518Srobert     Hash.AddBoolean(Method->isOverriding());
381*12c85518Srobert     Hash.AddBoolean(Method->isDirectMethod());
382*12c85518Srobert     Hash.AddBoolean(Method->isThisDeclarationADesignatedInitializer());
383*12c85518Srobert     Hash.AddBoolean(Method->hasSkippedBody());
384*12c85518Srobert 
385*12c85518Srobert     ID.AddInteger(Method->getImplementationControl());
386*12c85518Srobert     ID.AddInteger(Method->getMethodFamily());
387*12c85518Srobert     ImplicitParamDecl *Cmd = Method->getCmdDecl();
388*12c85518Srobert     Hash.AddBoolean(Cmd);
389*12c85518Srobert     if (Cmd)
390*12c85518Srobert       ID.AddInteger(Cmd->getParameterKind());
391*12c85518Srobert 
392*12c85518Srobert     ImplicitParamDecl *Self = Method->getSelfDecl();
393*12c85518Srobert     Hash.AddBoolean(Self);
394*12c85518Srobert     if (Self)
395*12c85518Srobert       ID.AddInteger(Self->getParameterKind());
396*12c85518Srobert 
397*12c85518Srobert     AddDecl(Method);
398*12c85518Srobert 
399*12c85518Srobert     AddQualType(Method->getReturnType());
400*12c85518Srobert     ID.AddInteger(Method->param_size());
401*12c85518Srobert     for (auto Param : Method->parameters())
402*12c85518Srobert       Hash.AddSubDecl(Param);
403*12c85518Srobert 
404*12c85518Srobert     if (Method->hasBody()) {
405*12c85518Srobert       const bool IsDefinition = Method->isThisDeclarationADefinition();
406*12c85518Srobert       Hash.AddBoolean(IsDefinition);
407*12c85518Srobert       if (IsDefinition) {
408*12c85518Srobert         Stmt *Body = Method->getBody();
409*12c85518Srobert         Hash.AddBoolean(Body);
410*12c85518Srobert         if (Body)
411*12c85518Srobert           AddStmt(Body);
412*12c85518Srobert 
413*12c85518Srobert         // Filter out sub-Decls which will not be processed in order to get an
414*12c85518Srobert         // accurate count of Decl's.
415*12c85518Srobert         llvm::SmallVector<const Decl *, 16> Decls;
416*12c85518Srobert         for (Decl *SubDecl : Method->decls())
417*12c85518Srobert           if (ODRHash::isSubDeclToBeProcessed(SubDecl, Method))
418*12c85518Srobert             Decls.push_back(SubDecl);
419*12c85518Srobert 
420*12c85518Srobert         ID.AddInteger(Decls.size());
421*12c85518Srobert         for (auto SubDecl : Decls)
422*12c85518Srobert           Hash.AddSubDecl(SubDecl);
423*12c85518Srobert       }
424*12c85518Srobert     } else {
425*12c85518Srobert       Hash.AddBoolean(false);
426*12c85518Srobert     }
427*12c85518Srobert 
428*12c85518Srobert     Inherited::VisitObjCMethodDecl(Method);
429*12c85518Srobert   }
430*12c85518Srobert 
VisitTypedefNameDecl(const TypedefNameDecl * D)431e5dd7070Spatrick   void VisitTypedefNameDecl(const TypedefNameDecl *D) {
432e5dd7070Spatrick     AddQualType(D->getUnderlyingType());
433e5dd7070Spatrick 
434e5dd7070Spatrick     Inherited::VisitTypedefNameDecl(D);
435e5dd7070Spatrick   }
436e5dd7070Spatrick 
VisitTypedefDecl(const TypedefDecl * D)437e5dd7070Spatrick   void VisitTypedefDecl(const TypedefDecl *D) {
438e5dd7070Spatrick     Inherited::VisitTypedefDecl(D);
439e5dd7070Spatrick   }
440e5dd7070Spatrick 
VisitTypeAliasDecl(const TypeAliasDecl * D)441e5dd7070Spatrick   void VisitTypeAliasDecl(const TypeAliasDecl *D) {
442e5dd7070Spatrick     Inherited::VisitTypeAliasDecl(D);
443e5dd7070Spatrick   }
444e5dd7070Spatrick 
VisitFriendDecl(const FriendDecl * D)445e5dd7070Spatrick   void VisitFriendDecl(const FriendDecl *D) {
446e5dd7070Spatrick     TypeSourceInfo *TSI = D->getFriendType();
447e5dd7070Spatrick     Hash.AddBoolean(TSI);
448e5dd7070Spatrick     if (TSI) {
449e5dd7070Spatrick       AddQualType(TSI->getType());
450e5dd7070Spatrick     } else {
451e5dd7070Spatrick       AddDecl(D->getFriendDecl());
452e5dd7070Spatrick     }
453e5dd7070Spatrick   }
454e5dd7070Spatrick 
VisitTemplateTypeParmDecl(const TemplateTypeParmDecl * D)455e5dd7070Spatrick   void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
456e5dd7070Spatrick     // Only care about default arguments as part of the definition.
457e5dd7070Spatrick     const bool hasDefaultArgument =
458e5dd7070Spatrick         D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
459e5dd7070Spatrick     Hash.AddBoolean(hasDefaultArgument);
460e5dd7070Spatrick     if (hasDefaultArgument) {
461e5dd7070Spatrick       AddTemplateArgument(D->getDefaultArgument());
462e5dd7070Spatrick     }
463e5dd7070Spatrick     Hash.AddBoolean(D->isParameterPack());
464e5dd7070Spatrick 
465e5dd7070Spatrick     const TypeConstraint *TC = D->getTypeConstraint();
466e5dd7070Spatrick     Hash.AddBoolean(TC != nullptr);
467e5dd7070Spatrick     if (TC)
468e5dd7070Spatrick       AddStmt(TC->getImmediatelyDeclaredConstraint());
469e5dd7070Spatrick 
470e5dd7070Spatrick     Inherited::VisitTemplateTypeParmDecl(D);
471e5dd7070Spatrick   }
472e5dd7070Spatrick 
VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl * D)473e5dd7070Spatrick   void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
474e5dd7070Spatrick     // Only care about default arguments as part of the definition.
475e5dd7070Spatrick     const bool hasDefaultArgument =
476e5dd7070Spatrick         D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
477e5dd7070Spatrick     Hash.AddBoolean(hasDefaultArgument);
478e5dd7070Spatrick     if (hasDefaultArgument) {
479e5dd7070Spatrick       AddStmt(D->getDefaultArgument());
480e5dd7070Spatrick     }
481e5dd7070Spatrick     Hash.AddBoolean(D->isParameterPack());
482e5dd7070Spatrick 
483e5dd7070Spatrick     Inherited::VisitNonTypeTemplateParmDecl(D);
484e5dd7070Spatrick   }
485e5dd7070Spatrick 
VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl * D)486e5dd7070Spatrick   void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) {
487e5dd7070Spatrick     // Only care about default arguments as part of the definition.
488e5dd7070Spatrick     const bool hasDefaultArgument =
489e5dd7070Spatrick         D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
490e5dd7070Spatrick     Hash.AddBoolean(hasDefaultArgument);
491e5dd7070Spatrick     if (hasDefaultArgument) {
492e5dd7070Spatrick       AddTemplateArgument(D->getDefaultArgument().getArgument());
493e5dd7070Spatrick     }
494e5dd7070Spatrick     Hash.AddBoolean(D->isParameterPack());
495e5dd7070Spatrick 
496e5dd7070Spatrick     Inherited::VisitTemplateTemplateParmDecl(D);
497e5dd7070Spatrick   }
498e5dd7070Spatrick 
VisitTemplateDecl(const TemplateDecl * D)499e5dd7070Spatrick   void VisitTemplateDecl(const TemplateDecl *D) {
500e5dd7070Spatrick     Hash.AddTemplateParameterList(D->getTemplateParameters());
501e5dd7070Spatrick 
502e5dd7070Spatrick     Inherited::VisitTemplateDecl(D);
503e5dd7070Spatrick   }
504e5dd7070Spatrick 
VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl * D)505e5dd7070Spatrick   void VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl *D) {
506e5dd7070Spatrick     Hash.AddBoolean(D->isMemberSpecialization());
507e5dd7070Spatrick     Inherited::VisitRedeclarableTemplateDecl(D);
508e5dd7070Spatrick   }
509e5dd7070Spatrick 
VisitFunctionTemplateDecl(const FunctionTemplateDecl * D)510e5dd7070Spatrick   void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
511e5dd7070Spatrick     AddDecl(D->getTemplatedDecl());
512e5dd7070Spatrick     ID.AddInteger(D->getTemplatedDecl()->getODRHash());
513e5dd7070Spatrick     Inherited::VisitFunctionTemplateDecl(D);
514e5dd7070Spatrick   }
515e5dd7070Spatrick 
VisitEnumConstantDecl(const EnumConstantDecl * D)516e5dd7070Spatrick   void VisitEnumConstantDecl(const EnumConstantDecl *D) {
517e5dd7070Spatrick     AddStmt(D->getInitExpr());
518e5dd7070Spatrick     Inherited::VisitEnumConstantDecl(D);
519e5dd7070Spatrick   }
520e5dd7070Spatrick };
521e5dd7070Spatrick } // namespace
522e5dd7070Spatrick 
523e5dd7070Spatrick // Only allow a small portion of Decl's to be processed.  Remove this once
524e5dd7070Spatrick // all Decl's can be handled.
isSubDeclToBeProcessed(const Decl * D,const DeclContext * Parent)525*12c85518Srobert bool ODRHash::isSubDeclToBeProcessed(const Decl *D, const DeclContext *Parent) {
526e5dd7070Spatrick   if (D->isImplicit()) return false;
527e5dd7070Spatrick   if (D->getDeclContext() != Parent) return false;
528e5dd7070Spatrick 
529e5dd7070Spatrick   switch (D->getKind()) {
530e5dd7070Spatrick     default:
531e5dd7070Spatrick       return false;
532e5dd7070Spatrick     case Decl::AccessSpec:
533e5dd7070Spatrick     case Decl::CXXConstructor:
534e5dd7070Spatrick     case Decl::CXXDestructor:
535e5dd7070Spatrick     case Decl::CXXMethod:
536e5dd7070Spatrick     case Decl::EnumConstant: // Only found in EnumDecl's.
537e5dd7070Spatrick     case Decl::Field:
538e5dd7070Spatrick     case Decl::Friend:
539e5dd7070Spatrick     case Decl::FunctionTemplate:
540e5dd7070Spatrick     case Decl::StaticAssert:
541e5dd7070Spatrick     case Decl::TypeAlias:
542e5dd7070Spatrick     case Decl::Typedef:
543e5dd7070Spatrick     case Decl::Var:
544*12c85518Srobert     case Decl::ObjCMethod:
545*12c85518Srobert     case Decl::ObjCIvar:
546*12c85518Srobert     case Decl::ObjCProperty:
547e5dd7070Spatrick       return true;
548e5dd7070Spatrick   }
549e5dd7070Spatrick }
550e5dd7070Spatrick 
AddSubDecl(const Decl * D)551e5dd7070Spatrick void ODRHash::AddSubDecl(const Decl *D) {
552e5dd7070Spatrick   assert(D && "Expecting non-null pointer.");
553e5dd7070Spatrick 
554e5dd7070Spatrick   ODRDeclVisitor(ID, *this).Visit(D);
555e5dd7070Spatrick }
556e5dd7070Spatrick 
AddCXXRecordDecl(const CXXRecordDecl * Record)557e5dd7070Spatrick void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) {
558e5dd7070Spatrick   assert(Record && Record->hasDefinition() &&
559e5dd7070Spatrick          "Expected non-null record to be a definition.");
560e5dd7070Spatrick 
561e5dd7070Spatrick   const DeclContext *DC = Record;
562e5dd7070Spatrick   while (DC) {
563e5dd7070Spatrick     if (isa<ClassTemplateSpecializationDecl>(DC)) {
564e5dd7070Spatrick       return;
565e5dd7070Spatrick     }
566e5dd7070Spatrick     DC = DC->getParent();
567e5dd7070Spatrick   }
568e5dd7070Spatrick 
569e5dd7070Spatrick   AddDecl(Record);
570e5dd7070Spatrick 
571e5dd7070Spatrick   // Filter out sub-Decls which will not be processed in order to get an
572e5dd7070Spatrick   // accurate count of Decl's.
573e5dd7070Spatrick   llvm::SmallVector<const Decl *, 16> Decls;
574e5dd7070Spatrick   for (Decl *SubDecl : Record->decls()) {
575*12c85518Srobert     if (isSubDeclToBeProcessed(SubDecl, Record)) {
576e5dd7070Spatrick       Decls.push_back(SubDecl);
577e5dd7070Spatrick       if (auto *Function = dyn_cast<FunctionDecl>(SubDecl)) {
578e5dd7070Spatrick         // Compute/Preload ODRHash into FunctionDecl.
579e5dd7070Spatrick         Function->getODRHash();
580e5dd7070Spatrick       }
581e5dd7070Spatrick     }
582e5dd7070Spatrick   }
583e5dd7070Spatrick 
584e5dd7070Spatrick   ID.AddInteger(Decls.size());
585e5dd7070Spatrick   for (auto SubDecl : Decls) {
586e5dd7070Spatrick     AddSubDecl(SubDecl);
587e5dd7070Spatrick   }
588e5dd7070Spatrick 
589e5dd7070Spatrick   const ClassTemplateDecl *TD = Record->getDescribedClassTemplate();
590e5dd7070Spatrick   AddBoolean(TD);
591e5dd7070Spatrick   if (TD) {
592e5dd7070Spatrick     AddTemplateParameterList(TD->getTemplateParameters());
593e5dd7070Spatrick   }
594e5dd7070Spatrick 
595e5dd7070Spatrick   ID.AddInteger(Record->getNumBases());
596e5dd7070Spatrick   auto Bases = Record->bases();
597e5dd7070Spatrick   for (auto Base : Bases) {
598e5dd7070Spatrick     AddQualType(Base.getType());
599e5dd7070Spatrick     ID.AddInteger(Base.isVirtual());
600e5dd7070Spatrick     ID.AddInteger(Base.getAccessSpecifierAsWritten());
601e5dd7070Spatrick   }
602e5dd7070Spatrick }
603e5dd7070Spatrick 
AddRecordDecl(const RecordDecl * Record)604*12c85518Srobert void ODRHash::AddRecordDecl(const RecordDecl *Record) {
605*12c85518Srobert   assert(!isa<CXXRecordDecl>(Record) &&
606*12c85518Srobert          "For CXXRecordDecl should call AddCXXRecordDecl.");
607*12c85518Srobert   AddDecl(Record);
608*12c85518Srobert 
609*12c85518Srobert   // Filter out sub-Decls which will not be processed in order to get an
610*12c85518Srobert   // accurate count of Decl's.
611*12c85518Srobert   llvm::SmallVector<const Decl *, 16> Decls;
612*12c85518Srobert   for (Decl *SubDecl : Record->decls()) {
613*12c85518Srobert     if (isSubDeclToBeProcessed(SubDecl, Record))
614*12c85518Srobert       Decls.push_back(SubDecl);
615*12c85518Srobert   }
616*12c85518Srobert 
617*12c85518Srobert   ID.AddInteger(Decls.size());
618*12c85518Srobert   for (const Decl *SubDecl : Decls)
619*12c85518Srobert     AddSubDecl(SubDecl);
620*12c85518Srobert }
621*12c85518Srobert 
AddObjCInterfaceDecl(const ObjCInterfaceDecl * IF)622*12c85518Srobert void ODRHash::AddObjCInterfaceDecl(const ObjCInterfaceDecl *IF) {
623*12c85518Srobert   AddDecl(IF);
624*12c85518Srobert 
625*12c85518Srobert   auto *SuperClass = IF->getSuperClass();
626*12c85518Srobert   AddBoolean(SuperClass);
627*12c85518Srobert   if (SuperClass)
628*12c85518Srobert     ID.AddInteger(SuperClass->getODRHash());
629*12c85518Srobert 
630*12c85518Srobert   // Hash referenced protocols.
631*12c85518Srobert   ID.AddInteger(IF->getReferencedProtocols().size());
632*12c85518Srobert   for (const ObjCProtocolDecl *RefP : IF->protocols()) {
633*12c85518Srobert     // Hash the name only as a referenced protocol can be a forward declaration.
634*12c85518Srobert     AddDeclarationName(RefP->getDeclName());
635*12c85518Srobert   }
636*12c85518Srobert 
637*12c85518Srobert   // Filter out sub-Decls which will not be processed in order to get an
638*12c85518Srobert   // accurate count of Decl's.
639*12c85518Srobert   llvm::SmallVector<const Decl *, 16> Decls;
640*12c85518Srobert   for (Decl *SubDecl : IF->decls())
641*12c85518Srobert     if (isSubDeclToBeProcessed(SubDecl, IF))
642*12c85518Srobert       Decls.push_back(SubDecl);
643*12c85518Srobert 
644*12c85518Srobert   ID.AddInteger(Decls.size());
645*12c85518Srobert   for (auto *SubDecl : Decls)
646*12c85518Srobert     AddSubDecl(SubDecl);
647*12c85518Srobert }
648*12c85518Srobert 
AddFunctionDecl(const FunctionDecl * Function,bool SkipBody)649e5dd7070Spatrick void ODRHash::AddFunctionDecl(const FunctionDecl *Function,
650e5dd7070Spatrick                               bool SkipBody) {
651e5dd7070Spatrick   assert(Function && "Expecting non-null pointer.");
652e5dd7070Spatrick 
653e5dd7070Spatrick   // Skip functions that are specializations or in specialization context.
654e5dd7070Spatrick   const DeclContext *DC = Function;
655e5dd7070Spatrick   while (DC) {
656e5dd7070Spatrick     if (isa<ClassTemplateSpecializationDecl>(DC)) return;
657e5dd7070Spatrick     if (auto *F = dyn_cast<FunctionDecl>(DC)) {
658e5dd7070Spatrick       if (F->isFunctionTemplateSpecialization()) {
659e5dd7070Spatrick         if (!isa<CXXMethodDecl>(DC)) return;
660e5dd7070Spatrick         if (DC->getLexicalParent()->isFileContext()) return;
661e5dd7070Spatrick         // Inline method specializations are the only supported
662e5dd7070Spatrick         // specialization for now.
663e5dd7070Spatrick       }
664e5dd7070Spatrick     }
665e5dd7070Spatrick     DC = DC->getParent();
666e5dd7070Spatrick   }
667e5dd7070Spatrick 
668e5dd7070Spatrick   ID.AddInteger(Function->getDeclKind());
669e5dd7070Spatrick 
670e5dd7070Spatrick   const auto *SpecializationArgs = Function->getTemplateSpecializationArgs();
671e5dd7070Spatrick   AddBoolean(SpecializationArgs);
672e5dd7070Spatrick   if (SpecializationArgs) {
673e5dd7070Spatrick     ID.AddInteger(SpecializationArgs->size());
674e5dd7070Spatrick     for (const TemplateArgument &TA : SpecializationArgs->asArray()) {
675e5dd7070Spatrick       AddTemplateArgument(TA);
676e5dd7070Spatrick     }
677e5dd7070Spatrick   }
678e5dd7070Spatrick 
679e5dd7070Spatrick   if (const auto *Method = dyn_cast<CXXMethodDecl>(Function)) {
680e5dd7070Spatrick     AddBoolean(Method->isConst());
681e5dd7070Spatrick     AddBoolean(Method->isVolatile());
682e5dd7070Spatrick   }
683e5dd7070Spatrick 
684e5dd7070Spatrick   ID.AddInteger(Function->getStorageClass());
685e5dd7070Spatrick   AddBoolean(Function->isInlineSpecified());
686e5dd7070Spatrick   AddBoolean(Function->isVirtualAsWritten());
687e5dd7070Spatrick   AddBoolean(Function->isPure());
688e5dd7070Spatrick   AddBoolean(Function->isDeletedAsWritten());
689e5dd7070Spatrick   AddBoolean(Function->isExplicitlyDefaulted());
690e5dd7070Spatrick 
691e5dd7070Spatrick   AddDecl(Function);
692e5dd7070Spatrick 
693e5dd7070Spatrick   AddQualType(Function->getReturnType());
694e5dd7070Spatrick 
695e5dd7070Spatrick   ID.AddInteger(Function->param_size());
696*12c85518Srobert   for (auto *Param : Function->parameters())
697e5dd7070Spatrick     AddSubDecl(Param);
698e5dd7070Spatrick 
699e5dd7070Spatrick   if (SkipBody) {
700e5dd7070Spatrick     AddBoolean(false);
701e5dd7070Spatrick     return;
702e5dd7070Spatrick   }
703e5dd7070Spatrick 
704e5dd7070Spatrick   const bool HasBody = Function->isThisDeclarationADefinition() &&
705e5dd7070Spatrick                        !Function->isDefaulted() && !Function->isDeleted() &&
706e5dd7070Spatrick                        !Function->isLateTemplateParsed();
707e5dd7070Spatrick   AddBoolean(HasBody);
708e5dd7070Spatrick   if (!HasBody) {
709e5dd7070Spatrick     return;
710e5dd7070Spatrick   }
711e5dd7070Spatrick 
712e5dd7070Spatrick   auto *Body = Function->getBody();
713e5dd7070Spatrick   AddBoolean(Body);
714e5dd7070Spatrick   if (Body)
715e5dd7070Spatrick     AddStmt(Body);
716e5dd7070Spatrick 
717e5dd7070Spatrick   // Filter out sub-Decls which will not be processed in order to get an
718e5dd7070Spatrick   // accurate count of Decl's.
719e5dd7070Spatrick   llvm::SmallVector<const Decl *, 16> Decls;
720e5dd7070Spatrick   for (Decl *SubDecl : Function->decls()) {
721*12c85518Srobert     if (isSubDeclToBeProcessed(SubDecl, Function)) {
722e5dd7070Spatrick       Decls.push_back(SubDecl);
723e5dd7070Spatrick     }
724e5dd7070Spatrick   }
725e5dd7070Spatrick 
726e5dd7070Spatrick   ID.AddInteger(Decls.size());
727e5dd7070Spatrick   for (auto SubDecl : Decls) {
728e5dd7070Spatrick     AddSubDecl(SubDecl);
729e5dd7070Spatrick   }
730e5dd7070Spatrick }
731e5dd7070Spatrick 
AddEnumDecl(const EnumDecl * Enum)732e5dd7070Spatrick void ODRHash::AddEnumDecl(const EnumDecl *Enum) {
733e5dd7070Spatrick   assert(Enum);
734e5dd7070Spatrick   AddDeclarationName(Enum->getDeclName());
735e5dd7070Spatrick 
736e5dd7070Spatrick   AddBoolean(Enum->isScoped());
737e5dd7070Spatrick   if (Enum->isScoped())
738e5dd7070Spatrick     AddBoolean(Enum->isScopedUsingClassTag());
739e5dd7070Spatrick 
740e5dd7070Spatrick   if (Enum->getIntegerTypeSourceInfo())
741e5dd7070Spatrick     AddQualType(Enum->getIntegerType());
742e5dd7070Spatrick 
743e5dd7070Spatrick   // Filter out sub-Decls which will not be processed in order to get an
744e5dd7070Spatrick   // accurate count of Decl's.
745e5dd7070Spatrick   llvm::SmallVector<const Decl *, 16> Decls;
746e5dd7070Spatrick   for (Decl *SubDecl : Enum->decls()) {
747*12c85518Srobert     if (isSubDeclToBeProcessed(SubDecl, Enum)) {
748e5dd7070Spatrick       assert(isa<EnumConstantDecl>(SubDecl) && "Unexpected Decl");
749e5dd7070Spatrick       Decls.push_back(SubDecl);
750e5dd7070Spatrick     }
751e5dd7070Spatrick   }
752e5dd7070Spatrick 
753e5dd7070Spatrick   ID.AddInteger(Decls.size());
754e5dd7070Spatrick   for (auto SubDecl : Decls) {
755e5dd7070Spatrick     AddSubDecl(SubDecl);
756e5dd7070Spatrick   }
757e5dd7070Spatrick 
758e5dd7070Spatrick }
759e5dd7070Spatrick 
AddObjCProtocolDecl(const ObjCProtocolDecl * P)760*12c85518Srobert void ODRHash::AddObjCProtocolDecl(const ObjCProtocolDecl *P) {
761*12c85518Srobert   AddDecl(P);
762*12c85518Srobert 
763*12c85518Srobert   // Hash referenced protocols.
764*12c85518Srobert   ID.AddInteger(P->getReferencedProtocols().size());
765*12c85518Srobert   for (const ObjCProtocolDecl *RefP : P->protocols()) {
766*12c85518Srobert     // Hash the name only as a referenced protocol can be a forward declaration.
767*12c85518Srobert     AddDeclarationName(RefP->getDeclName());
768*12c85518Srobert   }
769*12c85518Srobert 
770*12c85518Srobert   // Filter out sub-Decls which will not be processed in order to get an
771*12c85518Srobert   // accurate count of Decl's.
772*12c85518Srobert   llvm::SmallVector<const Decl *, 16> Decls;
773*12c85518Srobert   for (Decl *SubDecl : P->decls()) {
774*12c85518Srobert     if (isSubDeclToBeProcessed(SubDecl, P)) {
775*12c85518Srobert       Decls.push_back(SubDecl);
776*12c85518Srobert     }
777*12c85518Srobert   }
778*12c85518Srobert 
779*12c85518Srobert   ID.AddInteger(Decls.size());
780*12c85518Srobert   for (auto *SubDecl : Decls) {
781*12c85518Srobert     AddSubDecl(SubDecl);
782*12c85518Srobert   }
783*12c85518Srobert }
784*12c85518Srobert 
AddDecl(const Decl * D)785e5dd7070Spatrick void ODRHash::AddDecl(const Decl *D) {
786e5dd7070Spatrick   assert(D && "Expecting non-null pointer.");
787e5dd7070Spatrick   D = D->getCanonicalDecl();
788e5dd7070Spatrick 
789e5dd7070Spatrick   const NamedDecl *ND = dyn_cast<NamedDecl>(D);
790e5dd7070Spatrick   AddBoolean(ND);
791e5dd7070Spatrick   if (!ND) {
792e5dd7070Spatrick     ID.AddInteger(D->getKind());
793e5dd7070Spatrick     return;
794e5dd7070Spatrick   }
795e5dd7070Spatrick 
796e5dd7070Spatrick   AddDeclarationName(ND->getDeclName());
797e5dd7070Spatrick 
798e5dd7070Spatrick   const auto *Specialization =
799e5dd7070Spatrick             dyn_cast<ClassTemplateSpecializationDecl>(D);
800e5dd7070Spatrick   AddBoolean(Specialization);
801e5dd7070Spatrick   if (Specialization) {
802e5dd7070Spatrick     const TemplateArgumentList &List = Specialization->getTemplateArgs();
803e5dd7070Spatrick     ID.AddInteger(List.size());
804e5dd7070Spatrick     for (const TemplateArgument &TA : List.asArray())
805e5dd7070Spatrick       AddTemplateArgument(TA);
806e5dd7070Spatrick   }
807e5dd7070Spatrick }
808e5dd7070Spatrick 
809e5dd7070Spatrick namespace {
810e5dd7070Spatrick // Process a Type pointer.  Add* methods call back into ODRHash while Visit*
811e5dd7070Spatrick // methods process the relevant parts of the Type.
812e5dd7070Spatrick class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
813e5dd7070Spatrick   typedef TypeVisitor<ODRTypeVisitor> Inherited;
814e5dd7070Spatrick   llvm::FoldingSetNodeID &ID;
815e5dd7070Spatrick   ODRHash &Hash;
816e5dd7070Spatrick 
817e5dd7070Spatrick public:
ODRTypeVisitor(llvm::FoldingSetNodeID & ID,ODRHash & Hash)818e5dd7070Spatrick   ODRTypeVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash)
819e5dd7070Spatrick       : ID(ID), Hash(Hash) {}
820e5dd7070Spatrick 
AddStmt(Stmt * S)821e5dd7070Spatrick   void AddStmt(Stmt *S) {
822e5dd7070Spatrick     Hash.AddBoolean(S);
823e5dd7070Spatrick     if (S) {
824e5dd7070Spatrick       Hash.AddStmt(S);
825e5dd7070Spatrick     }
826e5dd7070Spatrick   }
827e5dd7070Spatrick 
AddDecl(const Decl * D)828*12c85518Srobert   void AddDecl(const Decl *D) {
829e5dd7070Spatrick     Hash.AddBoolean(D);
830e5dd7070Spatrick     if (D) {
831e5dd7070Spatrick       Hash.AddDecl(D);
832e5dd7070Spatrick     }
833e5dd7070Spatrick   }
834e5dd7070Spatrick 
AddQualType(QualType T)835e5dd7070Spatrick   void AddQualType(QualType T) {
836e5dd7070Spatrick     Hash.AddQualType(T);
837e5dd7070Spatrick   }
838e5dd7070Spatrick 
AddType(const Type * T)839e5dd7070Spatrick   void AddType(const Type *T) {
840e5dd7070Spatrick     Hash.AddBoolean(T);
841e5dd7070Spatrick     if (T) {
842e5dd7070Spatrick       Hash.AddType(T);
843e5dd7070Spatrick     }
844e5dd7070Spatrick   }
845e5dd7070Spatrick 
AddNestedNameSpecifier(const NestedNameSpecifier * NNS)846e5dd7070Spatrick   void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
847e5dd7070Spatrick     Hash.AddBoolean(NNS);
848e5dd7070Spatrick     if (NNS) {
849e5dd7070Spatrick       Hash.AddNestedNameSpecifier(NNS);
850e5dd7070Spatrick     }
851e5dd7070Spatrick   }
852e5dd7070Spatrick 
AddIdentifierInfo(const IdentifierInfo * II)853e5dd7070Spatrick   void AddIdentifierInfo(const IdentifierInfo *II) {
854e5dd7070Spatrick     Hash.AddBoolean(II);
855e5dd7070Spatrick     if (II) {
856e5dd7070Spatrick       Hash.AddIdentifierInfo(II);
857e5dd7070Spatrick     }
858e5dd7070Spatrick   }
859e5dd7070Spatrick 
VisitQualifiers(Qualifiers Quals)860e5dd7070Spatrick   void VisitQualifiers(Qualifiers Quals) {
861e5dd7070Spatrick     ID.AddInteger(Quals.getAsOpaqueValue());
862e5dd7070Spatrick   }
863e5dd7070Spatrick 
864e5dd7070Spatrick   // Return the RecordType if the typedef only strips away a keyword.
865e5dd7070Spatrick   // Otherwise, return the original type.
RemoveTypedef(const Type * T)866e5dd7070Spatrick   static const Type *RemoveTypedef(const Type *T) {
867e5dd7070Spatrick     const auto *TypedefT = dyn_cast<TypedefType>(T);
868e5dd7070Spatrick     if (!TypedefT) {
869e5dd7070Spatrick       return T;
870e5dd7070Spatrick     }
871e5dd7070Spatrick 
872e5dd7070Spatrick     const TypedefNameDecl *D = TypedefT->getDecl();
873e5dd7070Spatrick     QualType UnderlyingType = D->getUnderlyingType();
874e5dd7070Spatrick 
875e5dd7070Spatrick     if (UnderlyingType.hasLocalQualifiers()) {
876e5dd7070Spatrick       return T;
877e5dd7070Spatrick     }
878e5dd7070Spatrick 
879e5dd7070Spatrick     const auto *ElaboratedT = dyn_cast<ElaboratedType>(UnderlyingType);
880e5dd7070Spatrick     if (!ElaboratedT) {
881e5dd7070Spatrick       return T;
882e5dd7070Spatrick     }
883e5dd7070Spatrick 
884e5dd7070Spatrick     if (ElaboratedT->getQualifier() != nullptr) {
885e5dd7070Spatrick       return T;
886e5dd7070Spatrick     }
887e5dd7070Spatrick 
888e5dd7070Spatrick     QualType NamedType = ElaboratedT->getNamedType();
889e5dd7070Spatrick     if (NamedType.hasLocalQualifiers()) {
890e5dd7070Spatrick       return T;
891e5dd7070Spatrick     }
892e5dd7070Spatrick 
893e5dd7070Spatrick     const auto *RecordT = dyn_cast<RecordType>(NamedType);
894e5dd7070Spatrick     if (!RecordT) {
895e5dd7070Spatrick       return T;
896e5dd7070Spatrick     }
897e5dd7070Spatrick 
898e5dd7070Spatrick     const IdentifierInfo *TypedefII = TypedefT->getDecl()->getIdentifier();
899e5dd7070Spatrick     const IdentifierInfo *RecordII = RecordT->getDecl()->getIdentifier();
900e5dd7070Spatrick     if (!TypedefII || !RecordII ||
901e5dd7070Spatrick         TypedefII->getName() != RecordII->getName()) {
902e5dd7070Spatrick       return T;
903e5dd7070Spatrick     }
904e5dd7070Spatrick 
905e5dd7070Spatrick     return RecordT;
906e5dd7070Spatrick   }
907e5dd7070Spatrick 
Visit(const Type * T)908e5dd7070Spatrick   void Visit(const Type *T) {
909e5dd7070Spatrick     T = RemoveTypedef(T);
910e5dd7070Spatrick     ID.AddInteger(T->getTypeClass());
911e5dd7070Spatrick     Inherited::Visit(T);
912e5dd7070Spatrick   }
913e5dd7070Spatrick 
VisitType(const Type * T)914e5dd7070Spatrick   void VisitType(const Type *T) {}
915e5dd7070Spatrick 
VisitAdjustedType(const AdjustedType * T)916e5dd7070Spatrick   void VisitAdjustedType(const AdjustedType *T) {
917e5dd7070Spatrick     QualType Original = T->getOriginalType();
918e5dd7070Spatrick     QualType Adjusted = T->getAdjustedType();
919e5dd7070Spatrick 
920e5dd7070Spatrick     // The original type and pointee type can be the same, as in the case of
921e5dd7070Spatrick     // function pointers decaying to themselves.  Set a bool and only process
922e5dd7070Spatrick     // the type once, to prevent doubling the work.
923e5dd7070Spatrick     SplitQualType split = Adjusted.split();
924e5dd7070Spatrick     if (auto Pointer = dyn_cast<PointerType>(split.Ty)) {
925e5dd7070Spatrick       if (Pointer->getPointeeType() == Original) {
926e5dd7070Spatrick         Hash.AddBoolean(true);
927e5dd7070Spatrick         ID.AddInteger(split.Quals.getAsOpaqueValue());
928e5dd7070Spatrick         AddQualType(Original);
929e5dd7070Spatrick         VisitType(T);
930e5dd7070Spatrick         return;
931e5dd7070Spatrick       }
932e5dd7070Spatrick     }
933e5dd7070Spatrick 
934e5dd7070Spatrick     // The original type and pointee type are different, such as in the case
935e5dd7070Spatrick     // of a array decaying to an element pointer.  Set a bool to false and
936e5dd7070Spatrick     // process both types.
937e5dd7070Spatrick     Hash.AddBoolean(false);
938e5dd7070Spatrick     AddQualType(Original);
939e5dd7070Spatrick     AddQualType(Adjusted);
940e5dd7070Spatrick 
941e5dd7070Spatrick     VisitType(T);
942e5dd7070Spatrick   }
943e5dd7070Spatrick 
VisitDecayedType(const DecayedType * T)944e5dd7070Spatrick   void VisitDecayedType(const DecayedType *T) {
945e5dd7070Spatrick     // getDecayedType and getPointeeType are derived from getAdjustedType
946e5dd7070Spatrick     // and don't need to be separately processed.
947e5dd7070Spatrick     VisitAdjustedType(T);
948e5dd7070Spatrick   }
949e5dd7070Spatrick 
VisitArrayType(const ArrayType * T)950e5dd7070Spatrick   void VisitArrayType(const ArrayType *T) {
951e5dd7070Spatrick     AddQualType(T->getElementType());
952e5dd7070Spatrick     ID.AddInteger(T->getSizeModifier());
953e5dd7070Spatrick     VisitQualifiers(T->getIndexTypeQualifiers());
954e5dd7070Spatrick     VisitType(T);
955e5dd7070Spatrick   }
VisitConstantArrayType(const ConstantArrayType * T)956e5dd7070Spatrick   void VisitConstantArrayType(const ConstantArrayType *T) {
957e5dd7070Spatrick     T->getSize().Profile(ID);
958e5dd7070Spatrick     VisitArrayType(T);
959e5dd7070Spatrick   }
960e5dd7070Spatrick 
VisitDependentSizedArrayType(const DependentSizedArrayType * T)961e5dd7070Spatrick   void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
962e5dd7070Spatrick     AddStmt(T->getSizeExpr());
963e5dd7070Spatrick     VisitArrayType(T);
964e5dd7070Spatrick   }
965e5dd7070Spatrick 
VisitIncompleteArrayType(const IncompleteArrayType * T)966e5dd7070Spatrick   void VisitIncompleteArrayType(const IncompleteArrayType *T) {
967e5dd7070Spatrick     VisitArrayType(T);
968e5dd7070Spatrick   }
969e5dd7070Spatrick 
VisitVariableArrayType(const VariableArrayType * T)970e5dd7070Spatrick   void VisitVariableArrayType(const VariableArrayType *T) {
971e5dd7070Spatrick     AddStmt(T->getSizeExpr());
972e5dd7070Spatrick     VisitArrayType(T);
973e5dd7070Spatrick   }
974e5dd7070Spatrick 
VisitAttributedType(const AttributedType * T)975e5dd7070Spatrick   void VisitAttributedType(const AttributedType *T) {
976e5dd7070Spatrick     ID.AddInteger(T->getAttrKind());
977e5dd7070Spatrick     AddQualType(T->getModifiedType());
978e5dd7070Spatrick     AddQualType(T->getEquivalentType());
979e5dd7070Spatrick 
980e5dd7070Spatrick     VisitType(T);
981e5dd7070Spatrick   }
982e5dd7070Spatrick 
VisitBlockPointerType(const BlockPointerType * T)983e5dd7070Spatrick   void VisitBlockPointerType(const BlockPointerType *T) {
984e5dd7070Spatrick     AddQualType(T->getPointeeType());
985e5dd7070Spatrick     VisitType(T);
986e5dd7070Spatrick   }
987e5dd7070Spatrick 
VisitBuiltinType(const BuiltinType * T)988e5dd7070Spatrick   void VisitBuiltinType(const BuiltinType *T) {
989e5dd7070Spatrick     ID.AddInteger(T->getKind());
990e5dd7070Spatrick     VisitType(T);
991e5dd7070Spatrick   }
992e5dd7070Spatrick 
VisitComplexType(const ComplexType * T)993e5dd7070Spatrick   void VisitComplexType(const ComplexType *T) {
994e5dd7070Spatrick     AddQualType(T->getElementType());
995e5dd7070Spatrick     VisitType(T);
996e5dd7070Spatrick   }
997e5dd7070Spatrick 
VisitDecltypeType(const DecltypeType * T)998e5dd7070Spatrick   void VisitDecltypeType(const DecltypeType *T) {
999e5dd7070Spatrick     AddStmt(T->getUnderlyingExpr());
1000e5dd7070Spatrick     AddQualType(T->getUnderlyingType());
1001e5dd7070Spatrick     VisitType(T);
1002e5dd7070Spatrick   }
1003e5dd7070Spatrick 
VisitDependentDecltypeType(const DependentDecltypeType * T)1004e5dd7070Spatrick   void VisitDependentDecltypeType(const DependentDecltypeType *T) {
1005e5dd7070Spatrick     VisitDecltypeType(T);
1006e5dd7070Spatrick   }
1007e5dd7070Spatrick 
VisitDeducedType(const DeducedType * T)1008e5dd7070Spatrick   void VisitDeducedType(const DeducedType *T) {
1009e5dd7070Spatrick     AddQualType(T->getDeducedType());
1010e5dd7070Spatrick     VisitType(T);
1011e5dd7070Spatrick   }
1012e5dd7070Spatrick 
VisitAutoType(const AutoType * T)1013e5dd7070Spatrick   void VisitAutoType(const AutoType *T) {
1014e5dd7070Spatrick     ID.AddInteger((unsigned)T->getKeyword());
1015e5dd7070Spatrick     ID.AddInteger(T->isConstrained());
1016e5dd7070Spatrick     if (T->isConstrained()) {
1017e5dd7070Spatrick       AddDecl(T->getTypeConstraintConcept());
1018*12c85518Srobert       ID.AddInteger(T->getTypeConstraintArguments().size());
1019e5dd7070Spatrick       for (const auto &TA : T->getTypeConstraintArguments())
1020e5dd7070Spatrick         Hash.AddTemplateArgument(TA);
1021e5dd7070Spatrick     }
1022e5dd7070Spatrick     VisitDeducedType(T);
1023e5dd7070Spatrick   }
1024e5dd7070Spatrick 
VisitDeducedTemplateSpecializationType(const DeducedTemplateSpecializationType * T)1025e5dd7070Spatrick   void VisitDeducedTemplateSpecializationType(
1026e5dd7070Spatrick       const DeducedTemplateSpecializationType *T) {
1027e5dd7070Spatrick     Hash.AddTemplateName(T->getTemplateName());
1028e5dd7070Spatrick     VisitDeducedType(T);
1029e5dd7070Spatrick   }
1030e5dd7070Spatrick 
VisitDependentAddressSpaceType(const DependentAddressSpaceType * T)1031e5dd7070Spatrick   void VisitDependentAddressSpaceType(const DependentAddressSpaceType *T) {
1032e5dd7070Spatrick     AddQualType(T->getPointeeType());
1033e5dd7070Spatrick     AddStmt(T->getAddrSpaceExpr());
1034e5dd7070Spatrick     VisitType(T);
1035e5dd7070Spatrick   }
1036e5dd7070Spatrick 
VisitDependentSizedExtVectorType(const DependentSizedExtVectorType * T)1037e5dd7070Spatrick   void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) {
1038e5dd7070Spatrick     AddQualType(T->getElementType());
1039e5dd7070Spatrick     AddStmt(T->getSizeExpr());
1040e5dd7070Spatrick     VisitType(T);
1041e5dd7070Spatrick   }
1042e5dd7070Spatrick 
VisitFunctionType(const FunctionType * T)1043e5dd7070Spatrick   void VisitFunctionType(const FunctionType *T) {
1044e5dd7070Spatrick     AddQualType(T->getReturnType());
1045e5dd7070Spatrick     T->getExtInfo().Profile(ID);
1046e5dd7070Spatrick     Hash.AddBoolean(T->isConst());
1047e5dd7070Spatrick     Hash.AddBoolean(T->isVolatile());
1048e5dd7070Spatrick     Hash.AddBoolean(T->isRestrict());
1049e5dd7070Spatrick     VisitType(T);
1050e5dd7070Spatrick   }
1051e5dd7070Spatrick 
VisitFunctionNoProtoType(const FunctionNoProtoType * T)1052e5dd7070Spatrick   void VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
1053e5dd7070Spatrick     VisitFunctionType(T);
1054e5dd7070Spatrick   }
1055e5dd7070Spatrick 
VisitFunctionProtoType(const FunctionProtoType * T)1056e5dd7070Spatrick   void VisitFunctionProtoType(const FunctionProtoType *T) {
1057e5dd7070Spatrick     ID.AddInteger(T->getNumParams());
1058e5dd7070Spatrick     for (auto ParamType : T->getParamTypes())
1059e5dd7070Spatrick       AddQualType(ParamType);
1060e5dd7070Spatrick 
1061e5dd7070Spatrick     VisitFunctionType(T);
1062e5dd7070Spatrick   }
1063e5dd7070Spatrick 
VisitInjectedClassNameType(const InjectedClassNameType * T)1064e5dd7070Spatrick   void VisitInjectedClassNameType(const InjectedClassNameType *T) {
1065e5dd7070Spatrick     AddDecl(T->getDecl());
1066e5dd7070Spatrick     VisitType(T);
1067e5dd7070Spatrick   }
1068e5dd7070Spatrick 
VisitMemberPointerType(const MemberPointerType * T)1069e5dd7070Spatrick   void VisitMemberPointerType(const MemberPointerType *T) {
1070e5dd7070Spatrick     AddQualType(T->getPointeeType());
1071e5dd7070Spatrick     AddType(T->getClass());
1072e5dd7070Spatrick     VisitType(T);
1073e5dd7070Spatrick   }
1074e5dd7070Spatrick 
VisitObjCObjectPointerType(const ObjCObjectPointerType * T)1075e5dd7070Spatrick   void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
1076e5dd7070Spatrick     AddQualType(T->getPointeeType());
1077e5dd7070Spatrick     VisitType(T);
1078e5dd7070Spatrick   }
1079e5dd7070Spatrick 
VisitObjCObjectType(const ObjCObjectType * T)1080e5dd7070Spatrick   void VisitObjCObjectType(const ObjCObjectType *T) {
1081e5dd7070Spatrick     AddDecl(T->getInterface());
1082e5dd7070Spatrick 
1083e5dd7070Spatrick     auto TypeArgs = T->getTypeArgsAsWritten();
1084e5dd7070Spatrick     ID.AddInteger(TypeArgs.size());
1085e5dd7070Spatrick     for (auto Arg : TypeArgs) {
1086e5dd7070Spatrick       AddQualType(Arg);
1087e5dd7070Spatrick     }
1088e5dd7070Spatrick 
1089e5dd7070Spatrick     auto Protocols = T->getProtocols();
1090e5dd7070Spatrick     ID.AddInteger(Protocols.size());
1091*12c85518Srobert     for (auto *Protocol : Protocols) {
1092e5dd7070Spatrick       AddDecl(Protocol);
1093e5dd7070Spatrick     }
1094e5dd7070Spatrick 
1095e5dd7070Spatrick     Hash.AddBoolean(T->isKindOfType());
1096e5dd7070Spatrick 
1097e5dd7070Spatrick     VisitType(T);
1098e5dd7070Spatrick   }
1099e5dd7070Spatrick 
VisitObjCInterfaceType(const ObjCInterfaceType * T)1100e5dd7070Spatrick   void VisitObjCInterfaceType(const ObjCInterfaceType *T) {
1101e5dd7070Spatrick     // This type is handled by the parent type ObjCObjectType.
1102e5dd7070Spatrick     VisitObjCObjectType(T);
1103e5dd7070Spatrick   }
1104e5dd7070Spatrick 
VisitObjCTypeParamType(const ObjCTypeParamType * T)1105e5dd7070Spatrick   void VisitObjCTypeParamType(const ObjCTypeParamType *T) {
1106e5dd7070Spatrick     AddDecl(T->getDecl());
1107e5dd7070Spatrick     auto Protocols = T->getProtocols();
1108e5dd7070Spatrick     ID.AddInteger(Protocols.size());
1109*12c85518Srobert     for (auto *Protocol : Protocols) {
1110e5dd7070Spatrick       AddDecl(Protocol);
1111e5dd7070Spatrick     }
1112e5dd7070Spatrick 
1113e5dd7070Spatrick     VisitType(T);
1114e5dd7070Spatrick   }
1115e5dd7070Spatrick 
VisitPackExpansionType(const PackExpansionType * T)1116e5dd7070Spatrick   void VisitPackExpansionType(const PackExpansionType *T) {
1117e5dd7070Spatrick     AddQualType(T->getPattern());
1118e5dd7070Spatrick     VisitType(T);
1119e5dd7070Spatrick   }
1120e5dd7070Spatrick 
VisitParenType(const ParenType * T)1121e5dd7070Spatrick   void VisitParenType(const ParenType *T) {
1122e5dd7070Spatrick     AddQualType(T->getInnerType());
1123e5dd7070Spatrick     VisitType(T);
1124e5dd7070Spatrick   }
1125e5dd7070Spatrick 
VisitPipeType(const PipeType * T)1126e5dd7070Spatrick   void VisitPipeType(const PipeType *T) {
1127e5dd7070Spatrick     AddQualType(T->getElementType());
1128e5dd7070Spatrick     Hash.AddBoolean(T->isReadOnly());
1129e5dd7070Spatrick     VisitType(T);
1130e5dd7070Spatrick   }
1131e5dd7070Spatrick 
VisitPointerType(const PointerType * T)1132e5dd7070Spatrick   void VisitPointerType(const PointerType *T) {
1133e5dd7070Spatrick     AddQualType(T->getPointeeType());
1134e5dd7070Spatrick     VisitType(T);
1135e5dd7070Spatrick   }
1136e5dd7070Spatrick 
VisitReferenceType(const ReferenceType * T)1137e5dd7070Spatrick   void VisitReferenceType(const ReferenceType *T) {
1138e5dd7070Spatrick     AddQualType(T->getPointeeTypeAsWritten());
1139e5dd7070Spatrick     VisitType(T);
1140e5dd7070Spatrick   }
1141e5dd7070Spatrick 
VisitLValueReferenceType(const LValueReferenceType * T)1142e5dd7070Spatrick   void VisitLValueReferenceType(const LValueReferenceType *T) {
1143e5dd7070Spatrick     VisitReferenceType(T);
1144e5dd7070Spatrick   }
1145e5dd7070Spatrick 
VisitRValueReferenceType(const RValueReferenceType * T)1146e5dd7070Spatrick   void VisitRValueReferenceType(const RValueReferenceType *T) {
1147e5dd7070Spatrick     VisitReferenceType(T);
1148e5dd7070Spatrick   }
1149e5dd7070Spatrick 
1150e5dd7070Spatrick   void
VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType * T)1151e5dd7070Spatrick   VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
1152*12c85518Srobert     AddDecl(T->getAssociatedDecl());
1153e5dd7070Spatrick     Hash.AddTemplateArgument(T->getArgumentPack());
1154e5dd7070Spatrick     VisitType(T);
1155e5dd7070Spatrick   }
1156e5dd7070Spatrick 
VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType * T)1157e5dd7070Spatrick   void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
1158*12c85518Srobert     AddDecl(T->getAssociatedDecl());
1159e5dd7070Spatrick     AddQualType(T->getReplacementType());
1160e5dd7070Spatrick     VisitType(T);
1161e5dd7070Spatrick   }
1162e5dd7070Spatrick 
VisitTagType(const TagType * T)1163e5dd7070Spatrick   void VisitTagType(const TagType *T) {
1164e5dd7070Spatrick     AddDecl(T->getDecl());
1165e5dd7070Spatrick     VisitType(T);
1166e5dd7070Spatrick   }
1167e5dd7070Spatrick 
VisitRecordType(const RecordType * T)1168e5dd7070Spatrick   void VisitRecordType(const RecordType *T) { VisitTagType(T); }
VisitEnumType(const EnumType * T)1169e5dd7070Spatrick   void VisitEnumType(const EnumType *T) { VisitTagType(T); }
1170e5dd7070Spatrick 
VisitTemplateSpecializationType(const TemplateSpecializationType * T)1171e5dd7070Spatrick   void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
1172*12c85518Srobert     ID.AddInteger(T->template_arguments().size());
1173e5dd7070Spatrick     for (const auto &TA : T->template_arguments()) {
1174e5dd7070Spatrick       Hash.AddTemplateArgument(TA);
1175e5dd7070Spatrick     }
1176e5dd7070Spatrick     Hash.AddTemplateName(T->getTemplateName());
1177e5dd7070Spatrick     VisitType(T);
1178e5dd7070Spatrick   }
1179e5dd7070Spatrick 
VisitTemplateTypeParmType(const TemplateTypeParmType * T)1180e5dd7070Spatrick   void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
1181e5dd7070Spatrick     ID.AddInteger(T->getDepth());
1182e5dd7070Spatrick     ID.AddInteger(T->getIndex());
1183e5dd7070Spatrick     Hash.AddBoolean(T->isParameterPack());
1184e5dd7070Spatrick     AddDecl(T->getDecl());
1185e5dd7070Spatrick   }
1186e5dd7070Spatrick 
VisitTypedefType(const TypedefType * T)1187e5dd7070Spatrick   void VisitTypedefType(const TypedefType *T) {
1188e5dd7070Spatrick     AddDecl(T->getDecl());
1189e5dd7070Spatrick     QualType UnderlyingType = T->getDecl()->getUnderlyingType();
1190e5dd7070Spatrick     VisitQualifiers(UnderlyingType.getQualifiers());
1191e5dd7070Spatrick     while (true) {
1192e5dd7070Spatrick       if (const TypedefType *Underlying =
1193e5dd7070Spatrick               dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) {
1194e5dd7070Spatrick         UnderlyingType = Underlying->getDecl()->getUnderlyingType();
1195e5dd7070Spatrick         continue;
1196e5dd7070Spatrick       }
1197e5dd7070Spatrick       if (const ElaboratedType *Underlying =
1198e5dd7070Spatrick               dyn_cast<ElaboratedType>(UnderlyingType.getTypePtr())) {
1199e5dd7070Spatrick         UnderlyingType = Underlying->getNamedType();
1200e5dd7070Spatrick         continue;
1201e5dd7070Spatrick       }
1202e5dd7070Spatrick 
1203e5dd7070Spatrick       break;
1204e5dd7070Spatrick     }
1205e5dd7070Spatrick     AddType(UnderlyingType.getTypePtr());
1206e5dd7070Spatrick     VisitType(T);
1207e5dd7070Spatrick   }
1208e5dd7070Spatrick 
VisitTypeOfExprType(const TypeOfExprType * T)1209e5dd7070Spatrick   void VisitTypeOfExprType(const TypeOfExprType *T) {
1210e5dd7070Spatrick     AddStmt(T->getUnderlyingExpr());
1211e5dd7070Spatrick     Hash.AddBoolean(T->isSugared());
1212e5dd7070Spatrick     if (T->isSugared())
1213e5dd7070Spatrick       AddQualType(T->desugar());
1214e5dd7070Spatrick 
1215e5dd7070Spatrick     VisitType(T);
1216e5dd7070Spatrick   }
VisitTypeOfType(const TypeOfType * T)1217e5dd7070Spatrick   void VisitTypeOfType(const TypeOfType *T) {
1218*12c85518Srobert     AddQualType(T->getUnmodifiedType());
1219e5dd7070Spatrick     VisitType(T);
1220e5dd7070Spatrick   }
1221e5dd7070Spatrick 
VisitTypeWithKeyword(const TypeWithKeyword * T)1222e5dd7070Spatrick   void VisitTypeWithKeyword(const TypeWithKeyword *T) {
1223e5dd7070Spatrick     ID.AddInteger(T->getKeyword());
1224e5dd7070Spatrick     VisitType(T);
1225e5dd7070Spatrick   };
1226e5dd7070Spatrick 
VisitDependentNameType(const DependentNameType * T)1227e5dd7070Spatrick   void VisitDependentNameType(const DependentNameType *T) {
1228e5dd7070Spatrick     AddNestedNameSpecifier(T->getQualifier());
1229e5dd7070Spatrick     AddIdentifierInfo(T->getIdentifier());
1230e5dd7070Spatrick     VisitTypeWithKeyword(T);
1231e5dd7070Spatrick   }
1232e5dd7070Spatrick 
VisitDependentTemplateSpecializationType(const DependentTemplateSpecializationType * T)1233e5dd7070Spatrick   void VisitDependentTemplateSpecializationType(
1234e5dd7070Spatrick       const DependentTemplateSpecializationType *T) {
1235e5dd7070Spatrick     AddIdentifierInfo(T->getIdentifier());
1236e5dd7070Spatrick     AddNestedNameSpecifier(T->getQualifier());
1237*12c85518Srobert     ID.AddInteger(T->template_arguments().size());
1238e5dd7070Spatrick     for (const auto &TA : T->template_arguments()) {
1239e5dd7070Spatrick       Hash.AddTemplateArgument(TA);
1240e5dd7070Spatrick     }
1241e5dd7070Spatrick     VisitTypeWithKeyword(T);
1242e5dd7070Spatrick   }
1243e5dd7070Spatrick 
VisitElaboratedType(const ElaboratedType * T)1244e5dd7070Spatrick   void VisitElaboratedType(const ElaboratedType *T) {
1245e5dd7070Spatrick     AddNestedNameSpecifier(T->getQualifier());
1246e5dd7070Spatrick     AddQualType(T->getNamedType());
1247e5dd7070Spatrick     VisitTypeWithKeyword(T);
1248e5dd7070Spatrick   }
1249e5dd7070Spatrick 
VisitUnaryTransformType(const UnaryTransformType * T)1250e5dd7070Spatrick   void VisitUnaryTransformType(const UnaryTransformType *T) {
1251e5dd7070Spatrick     AddQualType(T->getUnderlyingType());
1252e5dd7070Spatrick     AddQualType(T->getBaseType());
1253e5dd7070Spatrick     VisitType(T);
1254e5dd7070Spatrick   }
1255e5dd7070Spatrick 
VisitUnresolvedUsingType(const UnresolvedUsingType * T)1256e5dd7070Spatrick   void VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
1257e5dd7070Spatrick     AddDecl(T->getDecl());
1258e5dd7070Spatrick     VisitType(T);
1259e5dd7070Spatrick   }
1260e5dd7070Spatrick 
VisitVectorType(const VectorType * T)1261e5dd7070Spatrick   void VisitVectorType(const VectorType *T) {
1262e5dd7070Spatrick     AddQualType(T->getElementType());
1263e5dd7070Spatrick     ID.AddInteger(T->getNumElements());
1264e5dd7070Spatrick     ID.AddInteger(T->getVectorKind());
1265e5dd7070Spatrick     VisitType(T);
1266e5dd7070Spatrick   }
1267e5dd7070Spatrick 
VisitExtVectorType(const ExtVectorType * T)1268e5dd7070Spatrick   void VisitExtVectorType(const ExtVectorType * T) {
1269e5dd7070Spatrick     VisitVectorType(T);
1270e5dd7070Spatrick   }
1271e5dd7070Spatrick };
1272e5dd7070Spatrick } // namespace
1273e5dd7070Spatrick 
AddType(const Type * T)1274e5dd7070Spatrick void ODRHash::AddType(const Type *T) {
1275e5dd7070Spatrick   assert(T && "Expecting non-null pointer.");
1276e5dd7070Spatrick   ODRTypeVisitor(ID, *this).Visit(T);
1277e5dd7070Spatrick }
1278e5dd7070Spatrick 
AddQualType(QualType T)1279e5dd7070Spatrick void ODRHash::AddQualType(QualType T) {
1280e5dd7070Spatrick   AddBoolean(T.isNull());
1281e5dd7070Spatrick   if (T.isNull())
1282e5dd7070Spatrick     return;
1283e5dd7070Spatrick   SplitQualType split = T.split();
1284e5dd7070Spatrick   ID.AddInteger(split.Quals.getAsOpaqueValue());
1285e5dd7070Spatrick   AddType(split.Ty);
1286e5dd7070Spatrick }
1287e5dd7070Spatrick 
AddBoolean(bool Value)1288e5dd7070Spatrick void ODRHash::AddBoolean(bool Value) {
1289e5dd7070Spatrick   Bools.push_back(Value);
1290e5dd7070Spatrick }
1291