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