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

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/lib/AST/ODRHash.cpp