blob: 3aeb7e6fbb213c311a4a403bc9a42fd9ec7633af [file] [log] [blame]
Richard Trieue7f7ed22017-02-22 01:11:25 +00001//===-- ODRHash.cpp - Hashing to diagnose ODR failures ----------*- C++ -*-===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9///
10/// \file
11/// This file implements the ODRHash class, which calculates a hash based
12/// on AST nodes, which is stable across different runs.
13///
14//===----------------------------------------------------------------------===//
15
16#include "clang/AST/ODRHash.h"
17
18#include "clang/AST/DeclVisitor.h"
19#include "clang/AST/NestedNameSpecifier.h"
20#include "clang/AST/StmtVisitor.h"
21#include "clang/AST/TypeVisitor.h"
22
23using namespace clang;
24
Richard Trieu639d7b62017-02-22 22:22:42 +000025void ODRHash::AddStmt(const Stmt *S) {
26 assert(S && "Expecting non-null pointer.");
27 S->ProcessODRHash(ID, *this);
28}
Richard Trieud0786092017-02-23 00:23:01 +000029
30void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) {
31 assert(II && "Expecting non-null pointer.");
32 ID.AddString(II->getName());
33}
34
Richard Trieu22ddc282018-09-04 22:53:19 +000035void ODRHash::AddDeclarationName(DeclarationName Name, bool TreatAsDecl) {
36 if (TreatAsDecl)
Richard Trieud8673902018-09-14 01:15:28 +000037 // Matches the NamedDecl check in AddDecl
Richard Trieu22ddc282018-09-04 22:53:19 +000038 AddBoolean(true);
39
Richard Trieud8673902018-09-14 01:15:28 +000040 AddDeclarationNameImpl(Name);
41
42 if (TreatAsDecl)
43 // Matches the ClassTemplateSpecializationDecl check in AddDecl
44 AddBoolean(false);
45}
46
47void ODRHash::AddDeclarationNameImpl(DeclarationName Name) {
Richard Trieuf65efae2018-02-22 05:32:25 +000048 // Index all DeclarationName and use index numbers to refer to them.
49 auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size()));
50 ID.AddInteger(Result.first->second);
51 if (!Result.second) {
52 // If found in map, the the DeclarationName has previously been processed.
53 return;
54 }
55
56 // First time processing each DeclarationName, also process its details.
Richard Trieu8459ddf2017-02-24 02:59:12 +000057 AddBoolean(Name.isEmpty());
58 if (Name.isEmpty())
59 return;
60
61 auto Kind = Name.getNameKind();
62 ID.AddInteger(Kind);
63 switch (Kind) {
64 case DeclarationName::Identifier:
65 AddIdentifierInfo(Name.getAsIdentifierInfo());
66 break;
67 case DeclarationName::ObjCZeroArgSelector:
68 case DeclarationName::ObjCOneArgSelector:
69 case DeclarationName::ObjCMultiArgSelector: {
70 Selector S = Name.getObjCSelector();
71 AddBoolean(S.isNull());
72 AddBoolean(S.isKeywordSelector());
73 AddBoolean(S.isUnarySelector());
74 unsigned NumArgs = S.getNumArgs();
75 for (unsigned i = 0; i < NumArgs; ++i) {
76 AddIdentifierInfo(S.getIdentifierInfoForSlot(i));
77 }
78 break;
79 }
80 case DeclarationName::CXXConstructorName:
81 case DeclarationName::CXXDestructorName:
82 AddQualType(Name.getCXXNameType());
83 break;
84 case DeclarationName::CXXOperatorName:
85 ID.AddInteger(Name.getCXXOverloadedOperator());
86 break;
87 case DeclarationName::CXXLiteralOperatorName:
88 AddIdentifierInfo(Name.getCXXLiteralIdentifier());
89 break;
90 case DeclarationName::CXXConversionFunctionName:
91 AddQualType(Name.getCXXNameType());
92 break;
93 case DeclarationName::CXXUsingDirective:
94 break;
95 case DeclarationName::CXXDeductionGuideName: {
96 auto *Template = Name.getCXXDeductionGuideTemplate();
97 AddBoolean(Template);
98 if (Template) {
99 AddDecl(Template);
100 }
101 }
102 }
103}
104
Richard Trieuce81b192017-05-17 03:23:35 +0000105void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
Richard Trieu96b41642017-07-01 02:00:05 +0000106 assert(NNS && "Expecting non-null pointer.");
107 const auto *Prefix = NNS->getPrefix();
108 AddBoolean(Prefix);
109 if (Prefix) {
110 AddNestedNameSpecifier(Prefix);
Richard Trieuce81b192017-05-17 03:23:35 +0000111 }
112 auto Kind = NNS->getKind();
113 ID.AddInteger(Kind);
114 switch (Kind) {
115 case NestedNameSpecifier::Identifier:
116 AddIdentifierInfo(NNS->getAsIdentifier());
117 break;
118 case NestedNameSpecifier::Namespace:
119 AddDecl(NNS->getAsNamespace());
120 break;
121 case NestedNameSpecifier::NamespaceAlias:
122 AddDecl(NNS->getAsNamespaceAlias());
123 break;
124 case NestedNameSpecifier::TypeSpec:
125 case NestedNameSpecifier::TypeSpecWithTemplate:
126 AddType(NNS->getAsType());
127 break;
128 case NestedNameSpecifier::Global:
129 case NestedNameSpecifier::Super:
130 break;
131 }
132}
133
Richard Trieu96b49622017-05-31 00:31:58 +0000134void ODRHash::AddTemplateName(TemplateName Name) {
135 auto Kind = Name.getKind();
136 ID.AddInteger(Kind);
137
138 switch (Kind) {
139 case TemplateName::Template:
140 AddDecl(Name.getAsTemplateDecl());
141 break;
142 // TODO: Support these cases.
143 case TemplateName::OverloadedTemplate:
144 case TemplateName::QualifiedTemplate:
145 case TemplateName::DependentTemplate:
146 case TemplateName::SubstTemplateTemplateParm:
147 case TemplateName::SubstTemplateTemplateParmPack:
148 break;
149 }
150}
151
Richard Trieu3b261bb72017-06-13 22:21:18 +0000152void ODRHash::AddTemplateArgument(TemplateArgument TA) {
153 const auto Kind = TA.getKind();
154 ID.AddInteger(Kind);
Richard Trieu1dcb4052017-06-14 01:28:00 +0000155
156 switch (Kind) {
157 case TemplateArgument::Null:
Richard Trieu8844c522017-06-30 22:40:33 +0000158 llvm_unreachable("Expected valid TemplateArgument");
Richard Trieu1dcb4052017-06-14 01:28:00 +0000159 case TemplateArgument::Type:
Richard Trieu8844c522017-06-30 22:40:33 +0000160 AddQualType(TA.getAsType());
161 break;
Richard Trieu1dcb4052017-06-14 01:28:00 +0000162 case TemplateArgument::Declaration:
Richard Trieu7282d322018-04-25 00:31:15 +0000163 AddDecl(TA.getAsDecl());
164 break;
Richard Trieu1dcb4052017-06-14 01:28:00 +0000165 case TemplateArgument::NullPtr:
166 case TemplateArgument::Integral:
Richard Trieuee132d62017-06-14 03:17:26 +0000167 break;
Richard Trieu1dcb4052017-06-14 01:28:00 +0000168 case TemplateArgument::Template:
169 case TemplateArgument::TemplateExpansion:
Richard Trieuee132d62017-06-14 03:17:26 +0000170 AddTemplateName(TA.getAsTemplateOrTemplatePattern());
Richard Trieu1dcb4052017-06-14 01:28:00 +0000171 break;
172 case TemplateArgument::Expression:
173 AddStmt(TA.getAsExpr());
174 break;
175 case TemplateArgument::Pack:
Richard Trieud9201d02017-06-15 01:35:06 +0000176 ID.AddInteger(TA.pack_size());
177 for (auto SubTA : TA.pack_elements()) {
178 AddTemplateArgument(SubTA);
179 }
Richard Trieu1dcb4052017-06-14 01:28:00 +0000180 break;
181 }
Richard Trieu3b261bb72017-06-13 22:21:18 +0000182}
183
Richard Trieu498117b2017-08-23 02:43:59 +0000184void ODRHash::AddTemplateParameterList(const TemplateParameterList *TPL) {
185 assert(TPL && "Expecting non-null pointer.");
186
187 ID.AddInteger(TPL->size());
188 for (auto *ND : TPL->asArray()) {
189 AddSubDecl(ND);
190 }
191}
Richard Trieue7f7ed22017-02-22 01:11:25 +0000192
193void ODRHash::clear() {
Richard Trieuf65efae2018-02-22 05:32:25 +0000194 DeclNameMap.clear();
Richard Trieue7f7ed22017-02-22 01:11:25 +0000195 Bools.clear();
196 ID.clear();
197}
198
199unsigned ODRHash::CalculateHash() {
200 // Append the bools to the end of the data segment backwards. This allows
201 // for the bools data to be compressed 32 times smaller compared to using
202 // ID.AddBoolean
203 const unsigned unsigned_bits = sizeof(unsigned) * CHAR_BIT;
204 const unsigned size = Bools.size();
205 const unsigned remainder = size % unsigned_bits;
206 const unsigned loops = size / unsigned_bits;
207 auto I = Bools.rbegin();
208 unsigned value = 0;
209 for (unsigned i = 0; i < remainder; ++i) {
210 value <<= 1;
211 value |= *I;
212 ++I;
213 }
214 ID.AddInteger(value);
215
216 for (unsigned i = 0; i < loops; ++i) {
217 value = 0;
218 for (unsigned j = 0; j < unsigned_bits; ++j) {
219 value <<= 1;
220 value |= *I;
221 ++I;
222 }
223 ID.AddInteger(value);
224 }
225
226 assert(I == Bools.rend());
227 Bools.clear();
228 return ID.ComputeHash();
229}
230
Benjamin Kramerbffdf4c2017-08-20 13:02:57 +0000231namespace {
Richard Trieue7f7ed22017-02-22 01:11:25 +0000232// Process a Decl pointer. Add* methods call back into ODRHash while Visit*
233// methods process the relevant parts of the Decl.
234class ODRDeclVisitor : public ConstDeclVisitor<ODRDeclVisitor> {
235 typedef ConstDeclVisitor<ODRDeclVisitor> Inherited;
236 llvm::FoldingSetNodeID &ID;
Richard Trieu639d7b62017-02-22 22:22:42 +0000237 ODRHash &Hash;
Richard Trieue7f7ed22017-02-22 01:11:25 +0000238
239public:
Richard Trieu639d7b62017-02-22 22:22:42 +0000240 ODRDeclVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash)
241 : ID(ID), Hash(Hash) {}
242
243 void AddStmt(const Stmt *S) {
244 Hash.AddBoolean(S);
245 if (S) {
246 Hash.AddStmt(S);
247 }
248 }
Richard Trieue7f7ed22017-02-22 01:11:25 +0000249
Richard Trieud0786092017-02-23 00:23:01 +0000250 void AddIdentifierInfo(const IdentifierInfo *II) {
251 Hash.AddBoolean(II);
252 if (II) {
253 Hash.AddIdentifierInfo(II);
254 }
255 }
256
Richard Trieubcaaf962017-02-23 03:25:57 +0000257 void AddQualType(QualType T) {
258 Hash.AddQualType(T);
259 }
260
Richard Trieuac6a1b62017-07-08 02:04:42 +0000261 void AddDecl(const Decl *D) {
262 Hash.AddBoolean(D);
263 if (D) {
264 Hash.AddDecl(D);
265 }
266 }
267
Richard Trieu498117b2017-08-23 02:43:59 +0000268 void AddTemplateArgument(TemplateArgument TA) {
269 Hash.AddTemplateArgument(TA);
270 }
271
Richard Trieue7f7ed22017-02-22 01:11:25 +0000272 void Visit(const Decl *D) {
273 ID.AddInteger(D->getKind());
274 Inherited::Visit(D);
275 }
276
Richard Trieud0786092017-02-23 00:23:01 +0000277 void VisitNamedDecl(const NamedDecl *D) {
Richard Trieu583e2c12017-03-04 00:08:58 +0000278 Hash.AddDeclarationName(D->getDeclName());
Richard Trieud0786092017-02-23 00:23:01 +0000279 Inherited::VisitNamedDecl(D);
280 }
281
Richard Trieubcaaf962017-02-23 03:25:57 +0000282 void VisitValueDecl(const ValueDecl *D) {
Richard Trieu9747a7c2017-07-14 01:36:41 +0000283 if (!isa<FunctionDecl>(D)) {
284 AddQualType(D->getType());
285 }
Richard Trieubcaaf962017-02-23 03:25:57 +0000286 Inherited::VisitValueDecl(D);
287 }
288
Richard Trieu6e13ff32017-06-16 02:44:29 +0000289 void VisitVarDecl(const VarDecl *D) {
290 Hash.AddBoolean(D->isStaticLocal());
291 Hash.AddBoolean(D->isConstexpr());
292 const bool HasInit = D->hasInit();
293 Hash.AddBoolean(HasInit);
294 if (HasInit) {
295 AddStmt(D->getInit());
296 }
297 Inherited::VisitVarDecl(D);
298 }
299
Richard Trieu02552272017-05-02 23:58:52 +0000300 void VisitParmVarDecl(const ParmVarDecl *D) {
301 // TODO: Handle default arguments.
302 Inherited::VisitParmVarDecl(D);
303 }
304
Richard Trieue7f7ed22017-02-22 01:11:25 +0000305 void VisitAccessSpecDecl(const AccessSpecDecl *D) {
306 ID.AddInteger(D->getAccess());
307 Inherited::VisitAccessSpecDecl(D);
308 }
Richard Trieu639d7b62017-02-22 22:22:42 +0000309
310 void VisitStaticAssertDecl(const StaticAssertDecl *D) {
311 AddStmt(D->getAssertExpr());
312 AddStmt(D->getMessage());
313
314 Inherited::VisitStaticAssertDecl(D);
315 }
Richard Trieud0786092017-02-23 00:23:01 +0000316
317 void VisitFieldDecl(const FieldDecl *D) {
Richard Trieu93772fc2017-02-24 20:59:28 +0000318 const bool IsBitfield = D->isBitField();
319 Hash.AddBoolean(IsBitfield);
320
321 if (IsBitfield) {
322 AddStmt(D->getBitWidth());
323 }
Richard Trieu8d543e22017-02-24 23:35:37 +0000324
325 Hash.AddBoolean(D->isMutable());
326 AddStmt(D->getInClassInitializer());
Richard Trieuff60e0f2017-02-25 01:29:34 +0000327
328 Inherited::VisitFieldDecl(D);
Richard Trieud0786092017-02-23 00:23:01 +0000329 }
Richard Trieu48143742017-02-28 21:24:38 +0000330
331 void VisitFunctionDecl(const FunctionDecl *D) {
Richard Trieu27c1b1a2018-07-10 01:40:50 +0000332 // Handled by the ODRHash for FunctionDecl
333 ID.AddInteger(D->getODRHash());
Richard Trieu7282d322018-04-25 00:31:15 +0000334
Richard Trieu48143742017-02-28 21:24:38 +0000335 Inherited::VisitFunctionDecl(D);
336 }
337
338 void VisitCXXMethodDecl(const CXXMethodDecl *D) {
Richard Trieu27c1b1a2018-07-10 01:40:50 +0000339 // Handled by the ODRHash for FunctionDecl
Richard Trieu583e2c12017-03-04 00:08:58 +0000340
Richard Trieu48143742017-02-28 21:24:38 +0000341 Inherited::VisitCXXMethodDecl(D);
342 }
Richard Trieu33562c22017-03-08 00:13:19 +0000343
344 void VisitTypedefNameDecl(const TypedefNameDecl *D) {
345 AddQualType(D->getUnderlyingType());
346
347 Inherited::VisitTypedefNameDecl(D);
348 }
349
350 void VisitTypedefDecl(const TypedefDecl *D) {
351 Inherited::VisitTypedefDecl(D);
352 }
353
354 void VisitTypeAliasDecl(const TypeAliasDecl *D) {
355 Inherited::VisitTypeAliasDecl(D);
356 }
Richard Trieuac6a1b62017-07-08 02:04:42 +0000357
358 void VisitFriendDecl(const FriendDecl *D) {
359 TypeSourceInfo *TSI = D->getFriendType();
360 Hash.AddBoolean(TSI);
361 if (TSI) {
362 AddQualType(TSI->getType());
363 } else {
364 AddDecl(D->getFriendDecl());
365 }
366 }
Richard Trieu498117b2017-08-23 02:43:59 +0000367
368 void VisitTemplateTypeParmDecl(const TemplateTypeParmDecl *D) {
369 // Only care about default arguments as part of the definition.
370 const bool hasDefaultArgument =
371 D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
372 Hash.AddBoolean(hasDefaultArgument);
373 if (hasDefaultArgument) {
374 AddTemplateArgument(D->getDefaultArgument());
375 }
Richard Trieu9359e8f2018-05-30 01:12:26 +0000376 Hash.AddBoolean(D->isParameterPack());
Richard Trieu498117b2017-08-23 02:43:59 +0000377
378 Inherited::VisitTemplateTypeParmDecl(D);
379 }
380
381 void VisitNonTypeTemplateParmDecl(const NonTypeTemplateParmDecl *D) {
382 // Only care about default arguments as part of the definition.
383 const bool hasDefaultArgument =
384 D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
385 Hash.AddBoolean(hasDefaultArgument);
386 if (hasDefaultArgument) {
387 AddStmt(D->getDefaultArgument());
388 }
Richard Trieu9359e8f2018-05-30 01:12:26 +0000389 Hash.AddBoolean(D->isParameterPack());
Richard Trieu498117b2017-08-23 02:43:59 +0000390
391 Inherited::VisitNonTypeTemplateParmDecl(D);
392 }
393
394 void VisitTemplateTemplateParmDecl(const TemplateTemplateParmDecl *D) {
395 // Only care about default arguments as part of the definition.
396 const bool hasDefaultArgument =
397 D->hasDefaultArgument() && !D->defaultArgumentWasInherited();
398 Hash.AddBoolean(hasDefaultArgument);
399 if (hasDefaultArgument) {
400 AddTemplateArgument(D->getDefaultArgument().getArgument());
401 }
Richard Trieu9359e8f2018-05-30 01:12:26 +0000402 Hash.AddBoolean(D->isParameterPack());
Richard Trieu498117b2017-08-23 02:43:59 +0000403
404 Inherited::VisitTemplateTemplateParmDecl(D);
405 }
Richard Trieu9359e8f2018-05-30 01:12:26 +0000406
407 void VisitTemplateDecl(const TemplateDecl *D) {
408 Hash.AddTemplateParameterList(D->getTemplateParameters());
409
410 Inherited::VisitTemplateDecl(D);
411 }
412
413 void VisitRedeclarableTemplateDecl(const RedeclarableTemplateDecl *D) {
414 Hash.AddBoolean(D->isMemberSpecialization());
415 Inherited::VisitRedeclarableTemplateDecl(D);
416 }
417
418 void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
Richard Trieu5d014062018-06-07 00:20:58 +0000419 AddDecl(D->getTemplatedDecl());
Richard Trieu22ddc282018-09-04 22:53:19 +0000420 ID.AddInteger(D->getTemplatedDecl()->getODRHash());
Richard Trieu9359e8f2018-05-30 01:12:26 +0000421 Inherited::VisitFunctionTemplateDecl(D);
422 }
Richard Trieuab4d7302018-07-25 22:52:05 +0000423
424 void VisitEnumConstantDecl(const EnumConstantDecl *D) {
425 AddStmt(D->getInitExpr());
426 Inherited::VisitEnumConstantDecl(D);
427 }
Richard Trieue7f7ed22017-02-22 01:11:25 +0000428};
Benjamin Kramerbffdf4c2017-08-20 13:02:57 +0000429} // namespace
Richard Trieue7f7ed22017-02-22 01:11:25 +0000430
431// Only allow a small portion of Decl's to be processed. Remove this once
432// all Decl's can be handled.
Richard Trieuab4d7302018-07-25 22:52:05 +0000433bool ODRHash::isWhitelistedDecl(const Decl *D, const DeclContext *Parent) {
Richard Trieue7f7ed22017-02-22 01:11:25 +0000434 if (D->isImplicit()) return false;
435 if (D->getDeclContext() != Parent) return false;
436
437 switch (D->getKind()) {
438 default:
439 return false;
440 case Decl::AccessSpec:
Richard Trieu1c71d512017-07-15 02:55:13 +0000441 case Decl::CXXConstructor:
442 case Decl::CXXDestructor:
Richard Trieu48143742017-02-28 21:24:38 +0000443 case Decl::CXXMethod:
Richard Trieuab4d7302018-07-25 22:52:05 +0000444 case Decl::EnumConstant: // Only found in EnumDecl's.
Richard Trieud0786092017-02-23 00:23:01 +0000445 case Decl::Field:
Richard Trieuac6a1b62017-07-08 02:04:42 +0000446 case Decl::Friend:
Richard Trieu9359e8f2018-05-30 01:12:26 +0000447 case Decl::FunctionTemplate:
Richard Trieu639d7b62017-02-22 22:22:42 +0000448 case Decl::StaticAssert:
Richard Trieu33562c22017-03-08 00:13:19 +0000449 case Decl::TypeAlias:
450 case Decl::Typedef:
Richard Trieu6e13ff32017-06-16 02:44:29 +0000451 case Decl::Var:
Richard Trieue7f7ed22017-02-22 01:11:25 +0000452 return true;
453 }
454}
455
456void ODRHash::AddSubDecl(const Decl *D) {
457 assert(D && "Expecting non-null pointer.");
Richard Trieue7f7ed22017-02-22 01:11:25 +0000458
Richard Trieu639d7b62017-02-22 22:22:42 +0000459 ODRDeclVisitor(ID, *this).Visit(D);
Richard Trieue7f7ed22017-02-22 01:11:25 +0000460}
461
462void ODRHash::AddCXXRecordDecl(const CXXRecordDecl *Record) {
463 assert(Record && Record->hasDefinition() &&
464 "Expected non-null record to be a definition.");
Richard Trieu02552272017-05-02 23:58:52 +0000465
Richard Trieu5fb82ef2017-08-05 00:54:19 +0000466 const DeclContext *DC = Record;
467 while (DC) {
468 if (isa<ClassTemplateSpecializationDecl>(DC)) {
469 return;
470 }
471 DC = DC->getParent();
Richard Trieu02552272017-05-02 23:58:52 +0000472 }
473
Richard Trieue7f7ed22017-02-22 01:11:25 +0000474 AddDecl(Record);
475
476 // Filter out sub-Decls which will not be processed in order to get an
477 // accurate count of Decl's.
478 llvm::SmallVector<const Decl *, 16> Decls;
Richard Trieu27c1b1a2018-07-10 01:40:50 +0000479 for (Decl *SubDecl : Record->decls()) {
Richard Trieue7f7ed22017-02-22 01:11:25 +0000480 if (isWhitelistedDecl(SubDecl, Record)) {
481 Decls.push_back(SubDecl);
Richard Trieu27c1b1a2018-07-10 01:40:50 +0000482 if (auto *Function = dyn_cast<FunctionDecl>(SubDecl)) {
483 // Compute/Preload ODRHash into FunctionDecl.
484 Function->getODRHash();
485 }
Richard Trieue7f7ed22017-02-22 01:11:25 +0000486 }
487 }
488
489 ID.AddInteger(Decls.size());
490 for (auto SubDecl : Decls) {
491 AddSubDecl(SubDecl);
492 }
Richard Trieu498117b2017-08-23 02:43:59 +0000493
494 const ClassTemplateDecl *TD = Record->getDescribedClassTemplate();
495 AddBoolean(TD);
496 if (TD) {
497 AddTemplateParameterList(TD->getTemplateParameters());
498 }
Richard Trieue13eabe2017-09-30 02:19:17 +0000499
500 ID.AddInteger(Record->getNumBases());
501 auto Bases = Record->bases();
502 for (auto Base : Bases) {
503 AddQualType(Base.getType());
504 ID.AddInteger(Base.isVirtual());
505 ID.AddInteger(Base.getAccessSpecifierAsWritten());
506 }
Richard Trieue7f7ed22017-02-22 01:11:25 +0000507}
508
Richard Trieu27c1b1a2018-07-10 01:40:50 +0000509void ODRHash::AddFunctionDecl(const FunctionDecl *Function,
510 bool SkipBody) {
Richard Trieue6caa262017-12-23 00:41:01 +0000511 assert(Function && "Expecting non-null pointer.");
512
Richard Trieue6caa262017-12-23 00:41:01 +0000513 // Skip functions that are specializations or in specialization context.
514 const DeclContext *DC = Function;
515 while (DC) {
516 if (isa<ClassTemplateSpecializationDecl>(DC)) return;
Richard Trieu27c1b1a2018-07-10 01:40:50 +0000517 if (auto *F = dyn_cast<FunctionDecl>(DC)) {
518 if (F->isFunctionTemplateSpecialization()) {
519 if (!isa<CXXMethodDecl>(DC)) return;
520 if (DC->getLexicalParent()->isFileContext()) return;
521 // Inline method specializations are the only supported
522 // specialization for now.
523 }
524 }
Richard Trieue6caa262017-12-23 00:41:01 +0000525 DC = DC->getParent();
526 }
527
Richard Trieu27c1b1a2018-07-10 01:40:50 +0000528 ID.AddInteger(Function->getDeclKind());
529
530 const auto *SpecializationArgs = Function->getTemplateSpecializationArgs();
531 AddBoolean(SpecializationArgs);
532 if (SpecializationArgs) {
533 ID.AddInteger(SpecializationArgs->size());
534 for (const TemplateArgument &TA : SpecializationArgs->asArray()) {
535 AddTemplateArgument(TA);
536 }
537 }
538
539 if (const auto *Method = dyn_cast<CXXMethodDecl>(Function)) {
540 AddBoolean(Method->isConst());
541 AddBoolean(Method->isVolatile());
542 }
543
544 ID.AddInteger(Function->getStorageClass());
545 AddBoolean(Function->isInlineSpecified());
546 AddBoolean(Function->isVirtualAsWritten());
547 AddBoolean(Function->isPure());
548 AddBoolean(Function->isDeletedAsWritten());
549 AddBoolean(Function->isExplicitlyDefaulted());
550
Richard Trieue6caa262017-12-23 00:41:01 +0000551 AddDecl(Function);
552
553 AddQualType(Function->getReturnType());
554
555 ID.AddInteger(Function->param_size());
556 for (auto Param : Function->parameters())
557 AddSubDecl(Param);
558
Richard Trieu27c1b1a2018-07-10 01:40:50 +0000559 if (SkipBody) {
560 AddBoolean(false);
561 return;
562 }
563
564 const bool HasBody = Function->isThisDeclarationADefinition() &&
565 !Function->isDefaulted() && !Function->isDeleted() &&
566 !Function->isLateTemplateParsed();
567 AddBoolean(HasBody);
Richard Trieu22ddc282018-09-04 22:53:19 +0000568 if (!HasBody) {
569 return;
570 }
571
572 auto *Body = Function->getBody();
573 AddBoolean(Body);
574 if (Body)
575 AddStmt(Body);
576
577 // Filter out sub-Decls which will not be processed in order to get an
578 // accurate count of Decl's.
579 llvm::SmallVector<const Decl *, 16> Decls;
580 for (Decl *SubDecl : Function->decls()) {
581 if (isWhitelistedDecl(SubDecl, Function)) {
582 Decls.push_back(SubDecl);
583 }
584 }
585
586 ID.AddInteger(Decls.size());
587 for (auto SubDecl : Decls) {
588 AddSubDecl(SubDecl);
Richard Trieu27c1b1a2018-07-10 01:40:50 +0000589 }
Richard Trieue6caa262017-12-23 00:41:01 +0000590}
591
Richard Trieuab4d7302018-07-25 22:52:05 +0000592void ODRHash::AddEnumDecl(const EnumDecl *Enum) {
593 assert(Enum);
594 AddDeclarationName(Enum->getDeclName());
595
596 AddBoolean(Enum->isScoped());
597 if (Enum->isScoped())
598 AddBoolean(Enum->isScopedUsingClassTag());
599
600 if (Enum->getIntegerTypeSourceInfo())
601 AddQualType(Enum->getIntegerType());
602
603 // Filter out sub-Decls which will not be processed in order to get an
604 // accurate count of Decl's.
605 llvm::SmallVector<const Decl *, 16> Decls;
606 for (Decl *SubDecl : Enum->decls()) {
607 if (isWhitelistedDecl(SubDecl, Enum)) {
608 assert(isa<EnumConstantDecl>(SubDecl) && "Unexpected Decl");
609 Decls.push_back(SubDecl);
610 }
611 }
612
613 ID.AddInteger(Decls.size());
614 for (auto SubDecl : Decls) {
615 AddSubDecl(SubDecl);
616 }
617
618}
619
Richard Trieue7f7ed22017-02-22 01:11:25 +0000620void ODRHash::AddDecl(const Decl *D) {
621 assert(D && "Expecting non-null pointer.");
Richard Trieuf72fb7e2017-12-21 22:38:29 +0000622 D = D->getCanonicalDecl();
Richard Trieuf65efae2018-02-22 05:32:25 +0000623
Richard Trieu22ddc282018-09-04 22:53:19 +0000624 const NamedDecl *ND = dyn_cast<NamedDecl>(D);
625 AddBoolean(ND);
626 if (!ND) {
627 ID.AddInteger(D->getKind());
Richard Trieue7f7ed22017-02-22 01:11:25 +0000628 return;
629 }
630
Richard Trieu22ddc282018-09-04 22:53:19 +0000631 AddDeclarationName(ND->getDeclName());
632
633 const auto *Specialization =
634 dyn_cast<ClassTemplateSpecializationDecl>(D);
635 AddBoolean(Specialization);
636 if (Specialization) {
637 const TemplateArgumentList &List = Specialization->getTemplateArgs();
638 ID.AddInteger(List.size());
639 for (const TemplateArgument &TA : List.asArray())
640 AddTemplateArgument(TA);
641 }
Richard Trieue7f7ed22017-02-22 01:11:25 +0000642}
643
Benjamin Kramerbffdf4c2017-08-20 13:02:57 +0000644namespace {
Richard Trieubcaaf962017-02-23 03:25:57 +0000645// Process a Type pointer. Add* methods call back into ODRHash while Visit*
646// methods process the relevant parts of the Type.
647class ODRTypeVisitor : public TypeVisitor<ODRTypeVisitor> {
648 typedef TypeVisitor<ODRTypeVisitor> Inherited;
649 llvm::FoldingSetNodeID &ID;
650 ODRHash &Hash;
651
652public:
653 ODRTypeVisitor(llvm::FoldingSetNodeID &ID, ODRHash &Hash)
654 : ID(ID), Hash(Hash) {}
655
656 void AddStmt(Stmt *S) {
657 Hash.AddBoolean(S);
658 if (S) {
659 Hash.AddStmt(S);
660 }
661 }
662
Richard Trieu8459ddf2017-02-24 02:59:12 +0000663 void AddDecl(Decl *D) {
664 Hash.AddBoolean(D);
665 if (D) {
666 Hash.AddDecl(D);
667 }
668 }
669
Richard Trieu02552272017-05-02 23:58:52 +0000670 void AddQualType(QualType T) {
671 Hash.AddQualType(T);
672 }
673
Richard Trieu3e03d3e2017-06-29 22:53:04 +0000674 void AddType(const Type *T) {
675 Hash.AddBoolean(T);
676 if (T) {
677 Hash.AddType(T);
678 }
679 }
680
Richard Trieu58bb7bd2017-05-17 02:29:02 +0000681 void AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
Richard Trieu96b41642017-07-01 02:00:05 +0000682 Hash.AddBoolean(NNS);
683 if (NNS) {
684 Hash.AddNestedNameSpecifier(NNS);
685 }
Richard Trieu58bb7bd2017-05-17 02:29:02 +0000686 }
687
688 void AddIdentifierInfo(const IdentifierInfo *II) {
689 Hash.AddBoolean(II);
690 if (II) {
691 Hash.AddIdentifierInfo(II);
692 }
693 }
694
Richard Trieu02552272017-05-02 23:58:52 +0000695 void VisitQualifiers(Qualifiers Quals) {
696 ID.AddInteger(Quals.getAsOpaqueValue());
697 }
698
Richard Trieubcaaf962017-02-23 03:25:57 +0000699 void Visit(const Type *T) {
700 ID.AddInteger(T->getTypeClass());
701 Inherited::Visit(T);
702 }
703
704 void VisitType(const Type *T) {}
705
Richard Trieu02552272017-05-02 23:58:52 +0000706 void VisitAdjustedType(const AdjustedType *T) {
707 AddQualType(T->getOriginalType());
708 AddQualType(T->getAdjustedType());
709 VisitType(T);
710 }
711
712 void VisitDecayedType(const DecayedType *T) {
713 AddQualType(T->getDecayedType());
714 AddQualType(T->getPointeeType());
715 VisitAdjustedType(T);
716 }
717
718 void VisitArrayType(const ArrayType *T) {
719 AddQualType(T->getElementType());
720 ID.AddInteger(T->getSizeModifier());
721 VisitQualifiers(T->getIndexTypeQualifiers());
722 VisitType(T);
723 }
724 void VisitConstantArrayType(const ConstantArrayType *T) {
725 T->getSize().Profile(ID);
726 VisitArrayType(T);
727 }
728
729 void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
730 AddStmt(T->getSizeExpr());
731 VisitArrayType(T);
732 }
733
734 void VisitIncompleteArrayType(const IncompleteArrayType *T) {
735 VisitArrayType(T);
736 }
737
738 void VisitVariableArrayType(const VariableArrayType *T) {
739 AddStmt(T->getSizeExpr());
740 VisitArrayType(T);
741 }
742
Richard Trieu22ddc282018-09-04 22:53:19 +0000743 void VisitAttributedType(const AttributedType *T) {
744 ID.AddInteger(T->getAttrKind());
745 AddQualType(T->getModifiedType());
746 AddQualType(T->getEquivalentType());
747
748 VisitType(T);
749 }
750
751 void VisitBlockPointerType(const BlockPointerType *T) {
752 AddQualType(T->getPointeeType());
753 VisitType(T);
754 }
755
Richard Trieubcaaf962017-02-23 03:25:57 +0000756 void VisitBuiltinType(const BuiltinType *T) {
757 ID.AddInteger(T->getKind());
758 VisitType(T);
759 }
Richard Trieu8459ddf2017-02-24 02:59:12 +0000760
Richard Trieu22ddc282018-09-04 22:53:19 +0000761 void VisitComplexType(const ComplexType *T) {
762 AddQualType(T->getElementType());
763 VisitType(T);
764 }
765
766 void VisitDecltypeType(const DecltypeType *T) {
767 AddStmt(T->getUnderlyingExpr());
768 AddQualType(T->getUnderlyingType());
769 VisitType(T);
770 }
771
772 void VisitDependentDecltypeType(const DependentDecltypeType *T) {
773 VisitDecltypeType(T);
774 }
775
776 void VisitDeducedType(const DeducedType *T) {
777 AddQualType(T->getDeducedType());
778 VisitType(T);
779 }
780
781 void VisitAutoType(const AutoType *T) {
782 ID.AddInteger((unsigned)T->getKeyword());
783 VisitDeducedType(T);
784 }
785
786 void VisitDeducedTemplateSpecializationType(
787 const DeducedTemplateSpecializationType *T) {
788 Hash.AddTemplateName(T->getTemplateName());
789 VisitDeducedType(T);
790 }
791
792 void VisitDependentAddressSpaceType(const DependentAddressSpaceType *T) {
793 AddQualType(T->getPointeeType());
794 AddStmt(T->getAddrSpaceExpr());
795 VisitType(T);
796 }
797
798 void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) {
799 AddQualType(T->getElementType());
800 AddStmt(T->getSizeExpr());
801 VisitType(T);
802 }
803
Richard Trieu02552272017-05-02 23:58:52 +0000804 void VisitFunctionType(const FunctionType *T) {
805 AddQualType(T->getReturnType());
806 T->getExtInfo().Profile(ID);
807 Hash.AddBoolean(T->isConst());
808 Hash.AddBoolean(T->isVolatile());
809 Hash.AddBoolean(T->isRestrict());
810 VisitType(T);
811 }
812
813 void VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
814 VisitFunctionType(T);
815 }
816
817 void VisitFunctionProtoType(const FunctionProtoType *T) {
818 ID.AddInteger(T->getNumParams());
819 for (auto ParamType : T->getParamTypes())
820 AddQualType(ParamType);
821
822 VisitFunctionType(T);
823 }
824
Richard Trieu22ddc282018-09-04 22:53:19 +0000825 void VisitInjectedClassNameType(const InjectedClassNameType *T) {
826 AddDecl(T->getDecl());
827 VisitType(T);
828 }
829
830 void VisitMemberPointerType(const MemberPointerType *T) {
831 AddQualType(T->getPointeeType());
832 AddType(T->getClass());
833 VisitType(T);
834 }
835
836 void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
837 AddQualType(T->getPointeeType());
838 VisitType(T);
839 }
840
841 void VisitObjCObjectType(const ObjCObjectType *T) {
842 AddDecl(T->getInterface());
843
844 auto TypeArgs = T->getTypeArgsAsWritten();
845 ID.AddInteger(TypeArgs.size());
846 for (auto Arg : TypeArgs) {
847 AddQualType(Arg);
848 }
849
850 auto Protocols = T->getProtocols();
851 ID.AddInteger(Protocols.size());
852 for (auto Protocol : Protocols) {
853 AddDecl(Protocol);
854 }
855
856 Hash.AddBoolean(T->isKindOfType());
857
858 VisitType(T);
859 }
860
861 void VisitObjCInterfaceType(const ObjCInterfaceType *T) {
862 // This type is handled by the parent type ObjCObjectType.
863 VisitObjCObjectType(T);
864 }
865
866 void VisitObjCTypeParamType(const ObjCTypeParamType *T) {
867 AddDecl(T->getDecl());
868 auto Protocols = T->getProtocols();
869 ID.AddInteger(Protocols.size());
870 for (auto Protocol : Protocols) {
871 AddDecl(Protocol);
872 }
873
874 VisitType(T);
875 }
876
877 void VisitPackExpansionType(const PackExpansionType *T) {
878 AddQualType(T->getPattern());
879 VisitType(T);
880 }
881
882 void VisitParenType(const ParenType *T) {
883 AddQualType(T->getInnerType());
884 VisitType(T);
885 }
886
887 void VisitPipeType(const PipeType *T) {
888 AddQualType(T->getElementType());
889 Hash.AddBoolean(T->isReadOnly());
890 VisitType(T);
891 }
892
Richard Trieu15970af2018-04-13 22:34:43 +0000893 void VisitPointerType(const PointerType *T) {
894 AddQualType(T->getPointeeType());
895 VisitType(T);
896 }
897
898 void VisitReferenceType(const ReferenceType *T) {
899 AddQualType(T->getPointeeTypeAsWritten());
900 VisitType(T);
901 }
902
903 void VisitLValueReferenceType(const LValueReferenceType *T) {
904 VisitReferenceType(T);
905 }
906
907 void VisitRValueReferenceType(const RValueReferenceType *T) {
908 VisitReferenceType(T);
909 }
910
Richard Trieu22ddc282018-09-04 22:53:19 +0000911 void
912 VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
913 AddType(T->getReplacedParameter());
914 Hash.AddTemplateArgument(T->getArgumentPack());
915 VisitType(T);
916 }
917
918 void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
919 AddType(T->getReplacedParameter());
920 AddQualType(T->getReplacementType());
921 VisitType(T);
922 }
923
924 void VisitTagType(const TagType *T) {
925 AddDecl(T->getDecl());
926 VisitType(T);
927 }
928
929 void VisitRecordType(const RecordType *T) { VisitTagType(T); }
930 void VisitEnumType(const EnumType *T) { VisitTagType(T); }
931
932 void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
933 ID.AddInteger(T->getNumArgs());
934 for (const auto &TA : T->template_arguments()) {
935 Hash.AddTemplateArgument(TA);
936 }
937 Hash.AddTemplateName(T->getTemplateName());
938 VisitType(T);
939 }
940
941 void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
942 ID.AddInteger(T->getDepth());
943 ID.AddInteger(T->getIndex());
944 Hash.AddBoolean(T->isParameterPack());
945 AddDecl(T->getDecl());
946 }
947
Richard Trieu8459ddf2017-02-24 02:59:12 +0000948 void VisitTypedefType(const TypedefType *T) {
949 AddDecl(T->getDecl());
Richard Trieu3e03d3e2017-06-29 22:53:04 +0000950 QualType UnderlyingType = T->getDecl()->getUnderlyingType();
951 VisitQualifiers(UnderlyingType.getQualifiers());
Richard Trieucaaccee2018-04-12 02:26:49 +0000952 while (true) {
953 if (const TypedefType *Underlying =
954 dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) {
955 UnderlyingType = Underlying->getDecl()->getUnderlyingType();
956 continue;
957 }
958 if (const ElaboratedType *Underlying =
959 dyn_cast<ElaboratedType>(UnderlyingType.getTypePtr())) {
960 UnderlyingType = Underlying->getNamedType();
961 continue;
962 }
963
964 break;
Richard Trieu3e03d3e2017-06-29 22:53:04 +0000965 }
966 AddType(UnderlyingType.getTypePtr());
Richard Trieu8459ddf2017-02-24 02:59:12 +0000967 VisitType(T);
968 }
Richard Trieu58bb7bd2017-05-17 02:29:02 +0000969
Richard Trieu22ddc282018-09-04 22:53:19 +0000970 void VisitTypeOfExprType(const TypeOfExprType *T) {
971 AddStmt(T->getUnderlyingExpr());
972 Hash.AddBoolean(T->isSugared());
973 if (T->isSugared())
974 AddQualType(T->desugar());
975
Richard Trieu58bb7bd2017-05-17 02:29:02 +0000976 VisitType(T);
977 }
Richard Trieu22ddc282018-09-04 22:53:19 +0000978 void VisitTypeOfType(const TypeOfType *T) {
979 AddQualType(T->getUnderlyingType());
980 VisitType(T);
981 }
Richard Trieu58bb7bd2017-05-17 02:29:02 +0000982
983 void VisitTypeWithKeyword(const TypeWithKeyword *T) {
984 ID.AddInteger(T->getKeyword());
985 VisitType(T);
986 };
987
988 void VisitDependentNameType(const DependentNameType *T) {
989 AddNestedNameSpecifier(T->getQualifier());
990 AddIdentifierInfo(T->getIdentifier());
991 VisitTypeWithKeyword(T);
992 }
993
994 void VisitDependentTemplateSpecializationType(
995 const DependentTemplateSpecializationType *T) {
996 AddIdentifierInfo(T->getIdentifier());
997 AddNestedNameSpecifier(T->getQualifier());
998 ID.AddInteger(T->getNumArgs());
999 for (const auto &TA : T->template_arguments()) {
1000 Hash.AddTemplateArgument(TA);
1001 }
1002 VisitTypeWithKeyword(T);
1003 }
1004
1005 void VisitElaboratedType(const ElaboratedType *T) {
1006 AddNestedNameSpecifier(T->getQualifier());
1007 AddQualType(T->getNamedType());
1008 VisitTypeWithKeyword(T);
1009 }
Richard Trieu96b49622017-05-31 00:31:58 +00001010
Richard Trieu22ddc282018-09-04 22:53:19 +00001011 void VisitUnaryTransformType(const UnaryTransformType *T) {
1012 AddQualType(T->getUnderlyingType());
1013 AddQualType(T->getBaseType());
Richard Trieu96b49622017-05-31 00:31:58 +00001014 VisitType(T);
1015 }
Richard Trieud9201d02017-06-15 01:35:06 +00001016
Richard Trieu22ddc282018-09-04 22:53:19 +00001017 void VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
Richard Trieud9201d02017-06-15 01:35:06 +00001018 AddDecl(T->getDecl());
Richard Trieu22ddc282018-09-04 22:53:19 +00001019 VisitType(T);
1020 }
1021
1022 void VisitVectorType(const VectorType *T) {
1023 AddQualType(T->getElementType());
1024 ID.AddInteger(T->getNumElements());
1025 ID.AddInteger(T->getVectorKind());
1026 VisitType(T);
1027 }
1028
1029 void VisitExtVectorType(const ExtVectorType * T) {
1030 VisitVectorType(T);
Richard Trieud9201d02017-06-15 01:35:06 +00001031 }
Richard Trieubcaaf962017-02-23 03:25:57 +00001032};
Benjamin Kramerbffdf4c2017-08-20 13:02:57 +00001033} // namespace
Richard Trieubcaaf962017-02-23 03:25:57 +00001034
1035void ODRHash::AddType(const Type *T) {
1036 assert(T && "Expecting non-null pointer.");
Richard Trieubcaaf962017-02-23 03:25:57 +00001037 ODRTypeVisitor(ID, *this).Visit(T);
1038}
1039
1040void ODRHash::AddQualType(QualType T) {
1041 AddBoolean(T.isNull());
1042 if (T.isNull())
1043 return;
1044 SplitQualType split = T.split();
1045 ID.AddInteger(split.Quals.getAsOpaqueValue());
1046 AddType(split.Ty);
1047}
1048
Richard Trieue7f7ed22017-02-22 01:11:25 +00001049void ODRHash::AddBoolean(bool Value) {
1050 Bools.push_back(Value);
1051}