blob: ba3b2ee49c54905fa56c4e9e2266bb8ad9375997 [file] [log] [blame]
Richard Trieue7f7ed22017-02-22 01:11:25 +00001//===-- ODRHash.cpp - Hashing to diagnose ODR failures ----------*- C++ -*-===//
2//
Chandler Carruth2946cd72019-01-19 08:50:56 +00003// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Richard Trieue7f7ed22017-02-22 01:11:25 +00006//
7//===----------------------------------------------------------------------===//
8///
9/// \file
10/// This file implements the ODRHash class, which calculates a hash based
11/// on AST nodes, which is stable across different runs.
12///
13//===----------------------------------------------------------------------===//
14
15#include "clang/AST/ODRHash.h"
16
17#include "clang/AST/DeclVisitor.h"
18#include "clang/AST/NestedNameSpecifier.h"
19#include "clang/AST/StmtVisitor.h"
20#include "clang/AST/TypeVisitor.h"
21
22using namespace clang;
23
Richard Trieu639d7b62017-02-22 22:22:42 +000024void ODRHash::AddStmt(const Stmt *S) {
25 assert(S && "Expecting non-null pointer.");
26 S->ProcessODRHash(ID, *this);
27}
Richard Trieud0786092017-02-23 00:23:01 +000028
29void ODRHash::AddIdentifierInfo(const IdentifierInfo *II) {
30 assert(II && "Expecting non-null pointer.");
31 ID.AddString(II->getName());
32}
33
Richard Trieu22ddc282018-09-04 22:53:19 +000034void ODRHash::AddDeclarationName(DeclarationName Name, bool TreatAsDecl) {
35 if (TreatAsDecl)
Richard Trieud8673902018-09-14 01:15:28 +000036 // Matches the NamedDecl check in AddDecl
Richard Trieu22ddc282018-09-04 22:53:19 +000037 AddBoolean(true);
38
Richard Trieud8673902018-09-14 01:15:28 +000039 AddDeclarationNameImpl(Name);
40
41 if (TreatAsDecl)
42 // Matches the ClassTemplateSpecializationDecl check in AddDecl
43 AddBoolean(false);
44}
45
46void ODRHash::AddDeclarationNameImpl(DeclarationName Name) {
Richard Trieuf65efae2018-02-22 05:32:25 +000047 // Index all DeclarationName and use index numbers to refer to them.
48 auto Result = DeclNameMap.insert(std::make_pair(Name, DeclNameMap.size()));
49 ID.AddInteger(Result.first->second);
50 if (!Result.second) {
Raphael Isemannb23ccec2018-12-10 12:37:46 +000051 // If found in map, the DeclarationName has previously been processed.
Richard Trieuf65efae2018-02-22 05:32:25 +000052 return;
53 }
54
55 // First time processing each DeclarationName, also process its details.
Richard Trieu8459ddf2017-02-24 02:59:12 +000056 AddBoolean(Name.isEmpty());
57 if (Name.isEmpty())
58 return;
59
60 auto Kind = Name.getNameKind();
61 ID.AddInteger(Kind);
62 switch (Kind) {
63 case DeclarationName::Identifier:
64 AddIdentifierInfo(Name.getAsIdentifierInfo());
65 break;
66 case DeclarationName::ObjCZeroArgSelector:
67 case DeclarationName::ObjCOneArgSelector:
68 case DeclarationName::ObjCMultiArgSelector: {
69 Selector S = Name.getObjCSelector();
70 AddBoolean(S.isNull());
71 AddBoolean(S.isKeywordSelector());
72 AddBoolean(S.isUnarySelector());
73 unsigned NumArgs = S.getNumArgs();
74 for (unsigned i = 0; i < NumArgs; ++i) {
75 AddIdentifierInfo(S.getIdentifierInfoForSlot(i));
76 }
77 break;
78 }
79 case DeclarationName::CXXConstructorName:
80 case DeclarationName::CXXDestructorName:
81 AddQualType(Name.getCXXNameType());
82 break;
83 case DeclarationName::CXXOperatorName:
84 ID.AddInteger(Name.getCXXOverloadedOperator());
85 break;
86 case DeclarationName::CXXLiteralOperatorName:
87 AddIdentifierInfo(Name.getCXXLiteralIdentifier());
88 break;
89 case DeclarationName::CXXConversionFunctionName:
90 AddQualType(Name.getCXXNameType());
91 break;
92 case DeclarationName::CXXUsingDirective:
93 break;
94 case DeclarationName::CXXDeductionGuideName: {
95 auto *Template = Name.getCXXDeductionGuideTemplate();
96 AddBoolean(Template);
97 if (Template) {
98 AddDecl(Template);
99 }
100 }
101 }
102}
103
Richard Trieuce81b192017-05-17 03:23:35 +0000104void ODRHash::AddNestedNameSpecifier(const NestedNameSpecifier *NNS) {
Richard Trieu96b41642017-07-01 02:00:05 +0000105 assert(NNS && "Expecting non-null pointer.");
106 const auto *Prefix = NNS->getPrefix();
107 AddBoolean(Prefix);
108 if (Prefix) {
109 AddNestedNameSpecifier(Prefix);
Richard Trieuce81b192017-05-17 03:23:35 +0000110 }
111 auto Kind = NNS->getKind();
112 ID.AddInteger(Kind);
113 switch (Kind) {
114 case NestedNameSpecifier::Identifier:
115 AddIdentifierInfo(NNS->getAsIdentifier());
116 break;
117 case NestedNameSpecifier::Namespace:
118 AddDecl(NNS->getAsNamespace());
119 break;
120 case NestedNameSpecifier::NamespaceAlias:
121 AddDecl(NNS->getAsNamespaceAlias());
122 break;
123 case NestedNameSpecifier::TypeSpec:
124 case NestedNameSpecifier::TypeSpecWithTemplate:
125 AddType(NNS->getAsType());
126 break;
127 case NestedNameSpecifier::Global:
128 case NestedNameSpecifier::Super:
129 break;
130 }
131}
132
Richard Trieu96b49622017-05-31 00:31:58 +0000133void ODRHash::AddTemplateName(TemplateName Name) {
134 auto Kind = Name.getKind();
135 ID.AddInteger(Kind);
136
137 switch (Kind) {
138 case TemplateName::Template:
139 AddDecl(Name.getAsTemplateDecl());
140 break;
141 // TODO: Support these cases.
142 case TemplateName::OverloadedTemplate:
Richard Smithb23c5e82019-05-09 03:31:27 +0000143 case TemplateName::AssumedTemplate:
Richard Trieu96b49622017-05-31 00:31:58 +0000144 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) {
Richard Trieucf9bd8a2019-05-04 04:22:33 +0000707 QualType Original = T->getOriginalType();
708 QualType Adjusted = T->getAdjustedType();
709
710 // The original type and pointee type can be the same, as in the case of
711 // function pointers decaying to themselves. Set a bool and only process
712 // the type once, to prevent doubling the work.
713 SplitQualType split = Adjusted.split();
714 if (auto Pointer = dyn_cast<PointerType>(split.Ty)) {
715 if (Pointer->getPointeeType() == Original) {
716 Hash.AddBoolean(true);
717 ID.AddInteger(split.Quals.getAsOpaqueValue());
718 AddQualType(Original);
719 VisitType(T);
720 return;
721 }
722 }
723
724 // The original type and pointee type are different, such as in the case
725 // of a array decaying to an element pointer. Set a bool to false and
726 // process both types.
727 Hash.AddBoolean(false);
728 AddQualType(Original);
729 AddQualType(Adjusted);
730
Richard Trieu02552272017-05-02 23:58:52 +0000731 VisitType(T);
732 }
733
734 void VisitDecayedType(const DecayedType *T) {
Richard Trieucf9bd8a2019-05-04 04:22:33 +0000735 // getDecayedType and getPointeeType are derived from getAdjustedType
736 // and don't need to be separately processed.
Richard Trieu02552272017-05-02 23:58:52 +0000737 VisitAdjustedType(T);
738 }
739
740 void VisitArrayType(const ArrayType *T) {
741 AddQualType(T->getElementType());
742 ID.AddInteger(T->getSizeModifier());
743 VisitQualifiers(T->getIndexTypeQualifiers());
744 VisitType(T);
745 }
746 void VisitConstantArrayType(const ConstantArrayType *T) {
747 T->getSize().Profile(ID);
748 VisitArrayType(T);
749 }
750
751 void VisitDependentSizedArrayType(const DependentSizedArrayType *T) {
752 AddStmt(T->getSizeExpr());
753 VisitArrayType(T);
754 }
755
756 void VisitIncompleteArrayType(const IncompleteArrayType *T) {
757 VisitArrayType(T);
758 }
759
760 void VisitVariableArrayType(const VariableArrayType *T) {
761 AddStmt(T->getSizeExpr());
762 VisitArrayType(T);
763 }
764
Richard Trieu22ddc282018-09-04 22:53:19 +0000765 void VisitAttributedType(const AttributedType *T) {
766 ID.AddInteger(T->getAttrKind());
767 AddQualType(T->getModifiedType());
768 AddQualType(T->getEquivalentType());
769
770 VisitType(T);
771 }
772
773 void VisitBlockPointerType(const BlockPointerType *T) {
774 AddQualType(T->getPointeeType());
775 VisitType(T);
776 }
777
Richard Trieubcaaf962017-02-23 03:25:57 +0000778 void VisitBuiltinType(const BuiltinType *T) {
779 ID.AddInteger(T->getKind());
780 VisitType(T);
781 }
Richard Trieu8459ddf2017-02-24 02:59:12 +0000782
Richard Trieu22ddc282018-09-04 22:53:19 +0000783 void VisitComplexType(const ComplexType *T) {
784 AddQualType(T->getElementType());
785 VisitType(T);
786 }
787
788 void VisitDecltypeType(const DecltypeType *T) {
789 AddStmt(T->getUnderlyingExpr());
790 AddQualType(T->getUnderlyingType());
791 VisitType(T);
792 }
793
794 void VisitDependentDecltypeType(const DependentDecltypeType *T) {
795 VisitDecltypeType(T);
796 }
797
798 void VisitDeducedType(const DeducedType *T) {
799 AddQualType(T->getDeducedType());
800 VisitType(T);
801 }
802
803 void VisitAutoType(const AutoType *T) {
804 ID.AddInteger((unsigned)T->getKeyword());
805 VisitDeducedType(T);
806 }
807
808 void VisitDeducedTemplateSpecializationType(
809 const DeducedTemplateSpecializationType *T) {
810 Hash.AddTemplateName(T->getTemplateName());
811 VisitDeducedType(T);
812 }
813
814 void VisitDependentAddressSpaceType(const DependentAddressSpaceType *T) {
815 AddQualType(T->getPointeeType());
816 AddStmt(T->getAddrSpaceExpr());
817 VisitType(T);
818 }
819
820 void VisitDependentSizedExtVectorType(const DependentSizedExtVectorType *T) {
821 AddQualType(T->getElementType());
822 AddStmt(T->getSizeExpr());
823 VisitType(T);
824 }
825
Richard Trieu02552272017-05-02 23:58:52 +0000826 void VisitFunctionType(const FunctionType *T) {
827 AddQualType(T->getReturnType());
828 T->getExtInfo().Profile(ID);
829 Hash.AddBoolean(T->isConst());
830 Hash.AddBoolean(T->isVolatile());
831 Hash.AddBoolean(T->isRestrict());
832 VisitType(T);
833 }
834
835 void VisitFunctionNoProtoType(const FunctionNoProtoType *T) {
836 VisitFunctionType(T);
837 }
838
839 void VisitFunctionProtoType(const FunctionProtoType *T) {
840 ID.AddInteger(T->getNumParams());
841 for (auto ParamType : T->getParamTypes())
842 AddQualType(ParamType);
843
844 VisitFunctionType(T);
845 }
846
Richard Trieu22ddc282018-09-04 22:53:19 +0000847 void VisitInjectedClassNameType(const InjectedClassNameType *T) {
848 AddDecl(T->getDecl());
849 VisitType(T);
850 }
851
852 void VisitMemberPointerType(const MemberPointerType *T) {
853 AddQualType(T->getPointeeType());
854 AddType(T->getClass());
855 VisitType(T);
856 }
857
858 void VisitObjCObjectPointerType(const ObjCObjectPointerType *T) {
859 AddQualType(T->getPointeeType());
860 VisitType(T);
861 }
862
863 void VisitObjCObjectType(const ObjCObjectType *T) {
864 AddDecl(T->getInterface());
865
866 auto TypeArgs = T->getTypeArgsAsWritten();
867 ID.AddInteger(TypeArgs.size());
868 for (auto Arg : TypeArgs) {
869 AddQualType(Arg);
870 }
871
872 auto Protocols = T->getProtocols();
873 ID.AddInteger(Protocols.size());
874 for (auto Protocol : Protocols) {
875 AddDecl(Protocol);
876 }
877
878 Hash.AddBoolean(T->isKindOfType());
879
880 VisitType(T);
881 }
882
883 void VisitObjCInterfaceType(const ObjCInterfaceType *T) {
884 // This type is handled by the parent type ObjCObjectType.
885 VisitObjCObjectType(T);
886 }
887
888 void VisitObjCTypeParamType(const ObjCTypeParamType *T) {
889 AddDecl(T->getDecl());
890 auto Protocols = T->getProtocols();
891 ID.AddInteger(Protocols.size());
892 for (auto Protocol : Protocols) {
893 AddDecl(Protocol);
894 }
895
896 VisitType(T);
897 }
898
899 void VisitPackExpansionType(const PackExpansionType *T) {
900 AddQualType(T->getPattern());
901 VisitType(T);
902 }
903
904 void VisitParenType(const ParenType *T) {
905 AddQualType(T->getInnerType());
906 VisitType(T);
907 }
908
909 void VisitPipeType(const PipeType *T) {
910 AddQualType(T->getElementType());
911 Hash.AddBoolean(T->isReadOnly());
912 VisitType(T);
913 }
914
Richard Trieu15970af2018-04-13 22:34:43 +0000915 void VisitPointerType(const PointerType *T) {
916 AddQualType(T->getPointeeType());
917 VisitType(T);
918 }
919
920 void VisitReferenceType(const ReferenceType *T) {
921 AddQualType(T->getPointeeTypeAsWritten());
922 VisitType(T);
923 }
924
925 void VisitLValueReferenceType(const LValueReferenceType *T) {
926 VisitReferenceType(T);
927 }
928
929 void VisitRValueReferenceType(const RValueReferenceType *T) {
930 VisitReferenceType(T);
931 }
932
Richard Trieu22ddc282018-09-04 22:53:19 +0000933 void
934 VisitSubstTemplateTypeParmPackType(const SubstTemplateTypeParmPackType *T) {
935 AddType(T->getReplacedParameter());
936 Hash.AddTemplateArgument(T->getArgumentPack());
937 VisitType(T);
938 }
939
940 void VisitSubstTemplateTypeParmType(const SubstTemplateTypeParmType *T) {
941 AddType(T->getReplacedParameter());
942 AddQualType(T->getReplacementType());
943 VisitType(T);
944 }
945
946 void VisitTagType(const TagType *T) {
947 AddDecl(T->getDecl());
948 VisitType(T);
949 }
950
951 void VisitRecordType(const RecordType *T) { VisitTagType(T); }
952 void VisitEnumType(const EnumType *T) { VisitTagType(T); }
953
954 void VisitTemplateSpecializationType(const TemplateSpecializationType *T) {
955 ID.AddInteger(T->getNumArgs());
956 for (const auto &TA : T->template_arguments()) {
957 Hash.AddTemplateArgument(TA);
958 }
959 Hash.AddTemplateName(T->getTemplateName());
960 VisitType(T);
961 }
962
963 void VisitTemplateTypeParmType(const TemplateTypeParmType *T) {
964 ID.AddInteger(T->getDepth());
965 ID.AddInteger(T->getIndex());
966 Hash.AddBoolean(T->isParameterPack());
967 AddDecl(T->getDecl());
968 }
969
Richard Trieu8459ddf2017-02-24 02:59:12 +0000970 void VisitTypedefType(const TypedefType *T) {
971 AddDecl(T->getDecl());
Richard Trieu3e03d3e2017-06-29 22:53:04 +0000972 QualType UnderlyingType = T->getDecl()->getUnderlyingType();
973 VisitQualifiers(UnderlyingType.getQualifiers());
Richard Trieucaaccee2018-04-12 02:26:49 +0000974 while (true) {
975 if (const TypedefType *Underlying =
976 dyn_cast<TypedefType>(UnderlyingType.getTypePtr())) {
977 UnderlyingType = Underlying->getDecl()->getUnderlyingType();
978 continue;
979 }
980 if (const ElaboratedType *Underlying =
981 dyn_cast<ElaboratedType>(UnderlyingType.getTypePtr())) {
982 UnderlyingType = Underlying->getNamedType();
983 continue;
984 }
985
986 break;
Richard Trieu3e03d3e2017-06-29 22:53:04 +0000987 }
988 AddType(UnderlyingType.getTypePtr());
Richard Trieu8459ddf2017-02-24 02:59:12 +0000989 VisitType(T);
990 }
Richard Trieu58bb7bd2017-05-17 02:29:02 +0000991
Richard Trieu22ddc282018-09-04 22:53:19 +0000992 void VisitTypeOfExprType(const TypeOfExprType *T) {
993 AddStmt(T->getUnderlyingExpr());
994 Hash.AddBoolean(T->isSugared());
995 if (T->isSugared())
996 AddQualType(T->desugar());
997
Richard Trieu58bb7bd2017-05-17 02:29:02 +0000998 VisitType(T);
999 }
Richard Trieu22ddc282018-09-04 22:53:19 +00001000 void VisitTypeOfType(const TypeOfType *T) {
1001 AddQualType(T->getUnderlyingType());
1002 VisitType(T);
1003 }
Richard Trieu58bb7bd2017-05-17 02:29:02 +00001004
1005 void VisitTypeWithKeyword(const TypeWithKeyword *T) {
1006 ID.AddInteger(T->getKeyword());
1007 VisitType(T);
1008 };
1009
1010 void VisitDependentNameType(const DependentNameType *T) {
1011 AddNestedNameSpecifier(T->getQualifier());
1012 AddIdentifierInfo(T->getIdentifier());
1013 VisitTypeWithKeyword(T);
1014 }
1015
1016 void VisitDependentTemplateSpecializationType(
1017 const DependentTemplateSpecializationType *T) {
1018 AddIdentifierInfo(T->getIdentifier());
1019 AddNestedNameSpecifier(T->getQualifier());
1020 ID.AddInteger(T->getNumArgs());
1021 for (const auto &TA : T->template_arguments()) {
1022 Hash.AddTemplateArgument(TA);
1023 }
1024 VisitTypeWithKeyword(T);
1025 }
1026
1027 void VisitElaboratedType(const ElaboratedType *T) {
1028 AddNestedNameSpecifier(T->getQualifier());
1029 AddQualType(T->getNamedType());
1030 VisitTypeWithKeyword(T);
1031 }
Richard Trieu96b49622017-05-31 00:31:58 +00001032
Richard Trieu22ddc282018-09-04 22:53:19 +00001033 void VisitUnaryTransformType(const UnaryTransformType *T) {
1034 AddQualType(T->getUnderlyingType());
1035 AddQualType(T->getBaseType());
Richard Trieu96b49622017-05-31 00:31:58 +00001036 VisitType(T);
1037 }
Richard Trieud9201d02017-06-15 01:35:06 +00001038
Richard Trieu22ddc282018-09-04 22:53:19 +00001039 void VisitUnresolvedUsingType(const UnresolvedUsingType *T) {
Richard Trieud9201d02017-06-15 01:35:06 +00001040 AddDecl(T->getDecl());
Richard Trieu22ddc282018-09-04 22:53:19 +00001041 VisitType(T);
1042 }
1043
1044 void VisitVectorType(const VectorType *T) {
1045 AddQualType(T->getElementType());
1046 ID.AddInteger(T->getNumElements());
1047 ID.AddInteger(T->getVectorKind());
1048 VisitType(T);
1049 }
1050
1051 void VisitExtVectorType(const ExtVectorType * T) {
1052 VisitVectorType(T);
Richard Trieud9201d02017-06-15 01:35:06 +00001053 }
Richard Trieubcaaf962017-02-23 03:25:57 +00001054};
Benjamin Kramerbffdf4c2017-08-20 13:02:57 +00001055} // namespace
Richard Trieubcaaf962017-02-23 03:25:57 +00001056
1057void ODRHash::AddType(const Type *T) {
1058 assert(T && "Expecting non-null pointer.");
Richard Trieubcaaf962017-02-23 03:25:57 +00001059 ODRTypeVisitor(ID, *this).Visit(T);
1060}
1061
1062void ODRHash::AddQualType(QualType T) {
1063 AddBoolean(T.isNull());
1064 if (T.isNull())
1065 return;
1066 SplitQualType split = T.split();
1067 ID.AddInteger(split.Quals.getAsOpaqueValue());
1068 AddType(split.Ty);
1069}
1070
Richard Trieue7f7ed22017-02-22 01:11:25 +00001071void ODRHash::AddBoolean(bool Value) {
1072 Bools.push_back(Value);
1073}