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