1//===- MemRegion.cpp - Abstract memory regions for static analysis --------===//
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// This file defines MemRegion and its subclasses. MemRegion defines a
10// partially-typed abstraction of memory useful for path-sensitive dataflow
11// analyses.
12//
13//===----------------------------------------------------------------------===//
14
15#include "clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h"
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/Attr.h"
18#include "clang/AST/CharUnits.h"
19#include "clang/AST/Decl.h"
20#include "clang/AST/DeclCXX.h"
21#include "clang/AST/DeclObjC.h"
22#include "clang/AST/Expr.h"
23#include "clang/AST/PrettyPrinter.h"
24#include "clang/AST/RecordLayout.h"
25#include "clang/AST/Type.h"
26#include "clang/Analysis/AnalysisDeclContext.h"
27#include "clang/Analysis/Support/BumpVector.h"
28#include "clang/Basic/IdentifierTable.h"
29#include "clang/Basic/LLVM.h"
30#include "clang/Basic/SourceManager.h"
31#include "clang/StaticAnalyzer/Core/AnalyzerOptions.h"
32#include "clang/StaticAnalyzer/Core/PathSensitive/DynamicExtent.h"
33#include "clang/StaticAnalyzer/Core/PathSensitive/SValBuilder.h"
34#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
35#include "clang/StaticAnalyzer/Core/PathSensitive/SymbolManager.h"
36#include "llvm/ADT/APInt.h"
37#include "llvm/ADT/FoldingSet.h"
38#include "llvm/ADT/PointerUnion.h"
39#include "llvm/ADT/SmallString.h"
40#include "llvm/ADT/StringRef.h"
41#include "llvm/ADT/Twine.h"
42#include "llvm/ADT/iterator_range.h"
43#include "llvm/Support/Allocator.h"
44#include "llvm/Support/Casting.h"
45#include "llvm/Support/CheckedArithmetic.h"
46#include "llvm/Support/Compiler.h"
47#include "llvm/Support/Debug.h"
48#include "llvm/Support/ErrorHandling.h"
49#include "llvm/Support/raw_ostream.h"
50#include <cassert>
51#include <cstdint>
52#include <functional>
53#include <iterator>
54#include <optional>
55#include <string>
56#include <tuple>
57#include <utility>
58
59using namespace clang;
60using namespace ento;
61
62#define DEBUG_TYPE "MemRegion"
63
64//===----------------------------------------------------------------------===//
65// MemRegion Construction.
66//===----------------------------------------------------------------------===//
67
68template <typename RegionTy, typename SuperTy, typename Arg1Ty>
69RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1,
70 const SuperTy *superRegion) {
71 llvm::FoldingSetNodeID ID;
72 RegionTy::ProfileRegion(ID, arg1, superRegion);
73 void *InsertPos;
74 auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
75
76 if (!R) {
77 R = new (A) RegionTy(arg1, superRegion);
78 Regions.InsertNode(R, InsertPos);
79 }
80
81 return R;
82}
83
84template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty>
85RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
86 const SuperTy *superRegion) {
87 llvm::FoldingSetNodeID ID;
88 RegionTy::ProfileRegion(ID, arg1, arg2, superRegion);
89 void *InsertPos;
90 auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
91
92 if (!R) {
93 R = new (A) RegionTy(arg1, arg2, superRegion);
94 Regions.InsertNode(R, InsertPos);
95 }
96
97 return R;
98}
99
100template <typename RegionTy, typename SuperTy,
101 typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
102RegionTy* MemRegionManager::getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
103 const Arg3Ty arg3,
104 const SuperTy *superRegion) {
105 llvm::FoldingSetNodeID ID;
106 RegionTy::ProfileRegion(ID, arg1, arg2, arg3, superRegion);
107 void *InsertPos;
108 auto *R = cast_or_null<RegionTy>(Regions.FindNodeOrInsertPos(ID, InsertPos));
109
110 if (!R) {
111 R = new (A) RegionTy(arg1, arg2, arg3, superRegion);
112 Regions.InsertNode(R, InsertPos);
113 }
114
115 return R;
116}
117
118//===----------------------------------------------------------------------===//
119// Object destruction.
120//===----------------------------------------------------------------------===//
121
122MemRegion::~MemRegion() = default;
123
124// All regions and their data are BumpPtrAllocated. No need to call their
125// destructors.
126MemRegionManager::~MemRegionManager() = default;
127
128//===----------------------------------------------------------------------===//
129// Basic methods.
130//===----------------------------------------------------------------------===//
131
132bool SubRegion::isSubRegionOf(const MemRegion* R) const {
133 const MemRegion* r = this;
134 do {
135 if (r == R)
136 return true;
137 if (const auto *sr = dyn_cast<SubRegion>(Val: r))
138 r = sr->getSuperRegion();
139 else
140 break;
141 } while (r != nullptr);
142 return false;
143}
144
145MemRegionManager &SubRegion::getMemRegionManager() const {
146 const SubRegion* r = this;
147 do {
148 const MemRegion *superRegion = r->getSuperRegion();
149 if (const auto *sr = dyn_cast<SubRegion>(Val: superRegion)) {
150 r = sr;
151 continue;
152 }
153 return superRegion->getMemRegionManager();
154 } while (true);
155}
156
157const StackFrameContext *VarRegion::getStackFrame() const {
158 const auto *SSR = dyn_cast<StackSpaceRegion>(Val: getMemorySpace());
159 return SSR ? SSR->getStackFrame() : nullptr;
160}
161
162const StackFrameContext *
163CXXLifetimeExtendedObjectRegion::getStackFrame() const {
164 const auto *SSR = dyn_cast<StackSpaceRegion>(Val: getMemorySpace());
165 return SSR ? SSR->getStackFrame() : nullptr;
166}
167
168const StackFrameContext *CXXTempObjectRegion::getStackFrame() const {
169 assert(isa<StackSpaceRegion>(getMemorySpace()) &&
170 "A temporary object can only be allocated on the stack");
171 return cast<StackSpaceRegion>(Val: getMemorySpace())->getStackFrame();
172}
173
174ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg)
175 : DeclRegion(sReg, ObjCIvarRegionKind), IVD(ivd) {
176 assert(IVD);
177}
178
179const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { return IVD; }
180
181QualType ObjCIvarRegion::getValueType() const {
182 return getDecl()->getType();
183}
184
185QualType CXXBaseObjectRegion::getValueType() const {
186 return QualType(getDecl()->getTypeForDecl(), 0);
187}
188
189QualType CXXDerivedObjectRegion::getValueType() const {
190 return QualType(getDecl()->getTypeForDecl(), 0);
191}
192
193QualType ParamVarRegion::getValueType() const {
194 assert(getDecl() &&
195 "`ParamVarRegion` support functions without `Decl` not implemented"
196 " yet.");
197 return getDecl()->getType();
198}
199
200const ParmVarDecl *ParamVarRegion::getDecl() const {
201 const Decl *D = getStackFrame()->getDecl();
202
203 if (const auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
204 assert(Index < FD->param_size());
205 return FD->parameters()[Index];
206 } else if (const auto *BD = dyn_cast<BlockDecl>(Val: D)) {
207 assert(Index < BD->param_size());
208 return BD->parameters()[Index];
209 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(Val: D)) {
210 assert(Index < MD->param_size());
211 return MD->parameters()[Index];
212 } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(Val: D)) {
213 assert(Index < CD->param_size());
214 return CD->parameters()[Index];
215 } else {
216 llvm_unreachable("Unexpected Decl kind!");
217 }
218}
219
220//===----------------------------------------------------------------------===//
221// FoldingSet profiling.
222//===----------------------------------------------------------------------===//
223
224void MemSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
225 ID.AddInteger(I: static_cast<unsigned>(getKind()));
226}
227
228void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
229 ID.AddInteger(I: static_cast<unsigned>(getKind()));
230 ID.AddPointer(Ptr: getStackFrame());
231}
232
233void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
234 ID.AddInteger(I: static_cast<unsigned>(getKind()));
235 ID.AddPointer(Ptr: getCodeRegion());
236}
237
238void StringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
239 const StringLiteral *Str,
240 const MemRegion *superRegion) {
241 ID.AddInteger(I: static_cast<unsigned>(StringRegionKind));
242 ID.AddPointer(Ptr: Str);
243 ID.AddPointer(Ptr: superRegion);
244}
245
246void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
247 const ObjCStringLiteral *Str,
248 const MemRegion *superRegion) {
249 ID.AddInteger(I: static_cast<unsigned>(ObjCStringRegionKind));
250 ID.AddPointer(Ptr: Str);
251 ID.AddPointer(Ptr: superRegion);
252}
253
254void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
255 const Expr *Ex, unsigned cnt,
256 const MemRegion *superRegion) {
257 ID.AddInteger(I: static_cast<unsigned>(AllocaRegionKind));
258 ID.AddPointer(Ptr: Ex);
259 ID.AddInteger(I: cnt);
260 ID.AddPointer(Ptr: superRegion);
261}
262
263void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
264 ProfileRegion(ID, Ex, cnt: Cnt, superRegion);
265}
266
267void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
268 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
269}
270
271void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
272 const CompoundLiteralExpr *CL,
273 const MemRegion* superRegion) {
274 ID.AddInteger(I: static_cast<unsigned>(CompoundLiteralRegionKind));
275 ID.AddPointer(Ptr: CL);
276 ID.AddPointer(Ptr: superRegion);
277}
278
279void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
280 const PointerType *PT,
281 const MemRegion *sRegion) {
282 ID.AddInteger(I: static_cast<unsigned>(CXXThisRegionKind));
283 ID.AddPointer(Ptr: PT);
284 ID.AddPointer(Ptr: sRegion);
285}
286
287void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const {
288 CXXThisRegion::ProfileRegion(ID, PT: ThisPointerTy, sRegion: superRegion);
289}
290
291void FieldRegion::Profile(llvm::FoldingSetNodeID &ID) const {
292 ProfileRegion(ID, FD: getDecl(), superRegion);
293}
294
295void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
296 const ObjCIvarDecl *ivd,
297 const MemRegion* superRegion) {
298 ID.AddInteger(I: static_cast<unsigned>(ObjCIvarRegionKind));
299 ID.AddPointer(Ptr: ivd);
300 ID.AddPointer(Ptr: superRegion);
301}
302
303void ObjCIvarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
304 ProfileRegion(ID, ivd: getDecl(), superRegion);
305}
306
307void NonParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
308 const VarDecl *VD,
309 const MemRegion *superRegion) {
310 ID.AddInteger(I: static_cast<unsigned>(NonParamVarRegionKind));
311 ID.AddPointer(Ptr: VD);
312 ID.AddPointer(Ptr: superRegion);
313}
314
315void NonParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
316 ProfileRegion(ID, VD: getDecl(), superRegion);
317}
318
319void ParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE,
320 unsigned Idx, const MemRegion *SReg) {
321 ID.AddInteger(I: static_cast<unsigned>(ParamVarRegionKind));
322 ID.AddPointer(Ptr: OE);
323 ID.AddInteger(I: Idx);
324 ID.AddPointer(Ptr: SReg);
325}
326
327void ParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
328 ProfileRegion(ID, OE: getOriginExpr(), Idx: getIndex(), SReg: superRegion);
329}
330
331void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
332 const MemRegion *sreg) {
333 ID.AddInteger(I: static_cast<unsigned>(MemRegion::SymbolicRegionKind));
334 ID.Add(x: sym);
335 ID.AddPointer(Ptr: sreg);
336}
337
338void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
339 SymbolicRegion::ProfileRegion(ID, sym, sreg: getSuperRegion());
340}
341
342void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
343 QualType ElementType, SVal Idx,
344 const MemRegion* superRegion) {
345 ID.AddInteger(I: MemRegion::ElementRegionKind);
346 ID.Add(x: ElementType);
347 ID.AddPointer(Ptr: superRegion);
348 Idx.Profile(ID);
349}
350
351void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
352 ElementRegion::ProfileRegion(ID, ElementType, Idx: Index, superRegion);
353}
354
355void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
356 const NamedDecl *FD,
357 const MemRegion*) {
358 ID.AddInteger(I: MemRegion::FunctionCodeRegionKind);
359 ID.AddPointer(Ptr: FD);
360}
361
362void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const {
363 FunctionCodeRegion::ProfileRegion(ID, FD, superRegion);
364}
365
366void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
367 const BlockDecl *BD, CanQualType,
368 const AnalysisDeclContext *AC,
369 const MemRegion*) {
370 ID.AddInteger(I: MemRegion::BlockCodeRegionKind);
371 ID.AddPointer(Ptr: BD);
372}
373
374void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const {
375 BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion);
376}
377
378void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
379 const BlockCodeRegion *BC,
380 const LocationContext *LC,
381 unsigned BlkCount,
382 const MemRegion *sReg) {
383 ID.AddInteger(I: MemRegion::BlockDataRegionKind);
384 ID.AddPointer(Ptr: BC);
385 ID.AddPointer(Ptr: LC);
386 ID.AddInteger(I: BlkCount);
387 ID.AddPointer(Ptr: sReg);
388}
389
390void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
391 BlockDataRegion::ProfileRegion(ID, BC, LC, BlkCount: BlockCount, sReg: getSuperRegion());
392}
393
394void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
395 Expr const *Ex,
396 const MemRegion *sReg) {
397 ID.AddPointer(Ptr: Ex);
398 ID.AddPointer(Ptr: sReg);
399}
400
401void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
402 ProfileRegion(ID, Ex, sReg: getSuperRegion());
403}
404
405void CXXLifetimeExtendedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
406 const Expr *E,
407 const ValueDecl *D,
408 const MemRegion *sReg) {
409 ID.AddPointer(Ptr: E);
410 ID.AddPointer(Ptr: D);
411 ID.AddPointer(Ptr: sReg);
412}
413
414void CXXLifetimeExtendedObjectRegion::Profile(
415 llvm::FoldingSetNodeID &ID) const {
416 ProfileRegion(ID, E: Ex, D: ExD, sReg: getSuperRegion());
417}
418
419void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
420 const CXXRecordDecl *RD,
421 bool IsVirtual,
422 const MemRegion *SReg) {
423 ID.AddPointer(Ptr: RD);
424 ID.AddBoolean(B: IsVirtual);
425 ID.AddPointer(Ptr: SReg);
426}
427
428void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
429 ProfileRegion(ID, RD: getDecl(), IsVirtual: isVirtual(), SReg: superRegion);
430}
431
432void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
433 const CXXRecordDecl *RD,
434 const MemRegion *SReg) {
435 ID.AddPointer(Ptr: RD);
436 ID.AddPointer(Ptr: SReg);
437}
438
439void CXXDerivedObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
440 ProfileRegion(ID, RD: getDecl(), SReg: superRegion);
441}
442
443//===----------------------------------------------------------------------===//
444// Region anchors.
445//===----------------------------------------------------------------------===//
446
447void GlobalsSpaceRegion::anchor() {}
448
449void NonStaticGlobalSpaceRegion::anchor() {}
450
451void StackSpaceRegion::anchor() {}
452
453void TypedRegion::anchor() {}
454
455void TypedValueRegion::anchor() {}
456
457void CodeTextRegion::anchor() {}
458
459void SubRegion::anchor() {}
460
461//===----------------------------------------------------------------------===//
462// Region pretty-printing.
463//===----------------------------------------------------------------------===//
464
465LLVM_DUMP_METHOD void MemRegion::dump() const {
466 dumpToStream(os&: llvm::errs());
467}
468
469std::string MemRegion::getString() const {
470 std::string s;
471 llvm::raw_string_ostream os(s);
472 dumpToStream(os);
473 return s;
474}
475
476void MemRegion::dumpToStream(raw_ostream &os) const {
477 os << "<Unknown Region>";
478}
479
480void AllocaRegion::dumpToStream(raw_ostream &os) const {
481 os << "alloca{S" << Ex->getID(Context: getContext()) << ',' << Cnt << '}';
482}
483
484void FunctionCodeRegion::dumpToStream(raw_ostream &os) const {
485 os << "code{" << getDecl()->getDeclName().getAsString() << '}';
486}
487
488void BlockCodeRegion::dumpToStream(raw_ostream &os) const {
489 os << "block_code{" << static_cast<const void *>(this) << '}';
490}
491
492void BlockDataRegion::dumpToStream(raw_ostream &os) const {
493 os << "block_data{" << BC;
494 os << "; ";
495 for (auto Var : referenced_vars())
496 os << "(" << Var.getCapturedRegion() << "<-" << Var.getOriginalRegion()
497 << ") ";
498 os << '}';
499}
500
501void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const {
502 // FIXME: More elaborate pretty-printing.
503 os << "{ S" << CL->getID(Context: getContext()) << " }";
504}
505
506void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const {
507 os << "temp_object{" << getValueType() << ", "
508 << "S" << Ex->getID(Context: getContext()) << '}';
509}
510
511void CXXLifetimeExtendedObjectRegion::dumpToStream(raw_ostream &os) const {
512 os << "lifetime_extended_object{" << getValueType() << ", ";
513 if (const IdentifierInfo *ID = ExD->getIdentifier())
514 os << ID->getName();
515 else
516 os << "D" << ExD->getID();
517 os << ", "
518 << "S" << Ex->getID(Context: getContext()) << '}';
519}
520
521void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const {
522 os << "Base{" << superRegion << ',' << getDecl()->getName() << '}';
523}
524
525void CXXDerivedObjectRegion::dumpToStream(raw_ostream &os) const {
526 os << "Derived{" << superRegion << ',' << getDecl()->getName() << '}';
527}
528
529void CXXThisRegion::dumpToStream(raw_ostream &os) const {
530 os << "this";
531}
532
533void ElementRegion::dumpToStream(raw_ostream &os) const {
534 os << "Element{" << superRegion << ',' << Index << ',' << getElementType()
535 << '}';
536}
537
538void FieldRegion::dumpToStream(raw_ostream &os) const {
539 os << superRegion << "." << *getDecl();
540}
541
542void ObjCIvarRegion::dumpToStream(raw_ostream &os) const {
543 os << "Ivar{" << superRegion << ',' << *getDecl() << '}';
544}
545
546void StringRegion::dumpToStream(raw_ostream &os) const {
547 assert(Str != nullptr && "Expecting non-null StringLiteral");
548 Str->printPretty(OS&: os, Helper: nullptr, Policy: PrintingPolicy(getContext().getLangOpts()));
549}
550
551void ObjCStringRegion::dumpToStream(raw_ostream &os) const {
552 assert(Str != nullptr && "Expecting non-null ObjCStringLiteral");
553 Str->printPretty(OS&: os, Helper: nullptr, Policy: PrintingPolicy(getContext().getLangOpts()));
554}
555
556void SymbolicRegion::dumpToStream(raw_ostream &os) const {
557 if (isa<HeapSpaceRegion>(Val: getSuperRegion()))
558 os << "Heap";
559 os << "SymRegion{" << sym << '}';
560}
561
562void NonParamVarRegion::dumpToStream(raw_ostream &os) const {
563 if (const IdentifierInfo *ID = VD->getIdentifier())
564 os << ID->getName();
565 else
566 os << "NonParamVarRegion{D" << VD->getID() << '}';
567}
568
569LLVM_DUMP_METHOD void RegionRawOffset::dump() const {
570 dumpToStream(os&: llvm::errs());
571}
572
573void RegionRawOffset::dumpToStream(raw_ostream &os) const {
574 os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}';
575}
576
577void CodeSpaceRegion::dumpToStream(raw_ostream &os) const {
578 os << "CodeSpaceRegion";
579}
580
581void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const {
582 os << "StaticGlobalsMemSpace{" << CR << '}';
583}
584
585void GlobalInternalSpaceRegion::dumpToStream(raw_ostream &os) const {
586 os << "GlobalInternalSpaceRegion";
587}
588
589void GlobalSystemSpaceRegion::dumpToStream(raw_ostream &os) const {
590 os << "GlobalSystemSpaceRegion";
591}
592
593void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const {
594 os << "GlobalImmutableSpaceRegion";
595}
596
597void HeapSpaceRegion::dumpToStream(raw_ostream &os) const {
598 os << "HeapSpaceRegion";
599}
600
601void UnknownSpaceRegion::dumpToStream(raw_ostream &os) const {
602 os << "UnknownSpaceRegion";
603}
604
605void StackArgumentsSpaceRegion::dumpToStream(raw_ostream &os) const {
606 os << "StackArgumentsSpaceRegion";
607}
608
609void StackLocalsSpaceRegion::dumpToStream(raw_ostream &os) const {
610 os << "StackLocalsSpaceRegion";
611}
612
613void ParamVarRegion::dumpToStream(raw_ostream &os) const {
614 const ParmVarDecl *PVD = getDecl();
615 assert(PVD &&
616 "`ParamVarRegion` support functions without `Decl` not implemented"
617 " yet.");
618 if (const IdentifierInfo *ID = PVD->getIdentifier()) {
619 os << ID->getName();
620 } else {
621 os << "ParamVarRegion{P" << PVD->getID() << '}';
622 }
623}
624
625bool MemRegion::canPrintPretty() const {
626 return canPrintPrettyAsExpr();
627}
628
629bool MemRegion::canPrintPrettyAsExpr() const {
630 return false;
631}
632
633StringRef MemRegion::getKindStr() const {
634 switch (getKind()) {
635#define REGION(Id, Parent) \
636 case Id##Kind: \
637 return #Id;
638#include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def"
639#undef REGION
640 }
641 llvm_unreachable("Unkown kind!");
642}
643
644void MemRegion::printPretty(raw_ostream &os) const {
645 assert(canPrintPretty() && "This region cannot be printed pretty.");
646 os << "'";
647 printPrettyAsExpr(os);
648 os << "'";
649}
650
651void MemRegion::printPrettyAsExpr(raw_ostream &) const {
652 llvm_unreachable("This region cannot be printed pretty.");
653}
654
655bool NonParamVarRegion::canPrintPrettyAsExpr() const { return true; }
656
657void NonParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
658 os << getDecl()->getName();
659}
660
661bool ParamVarRegion::canPrintPrettyAsExpr() const { return true; }
662
663void ParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
664 assert(getDecl() &&
665 "`ParamVarRegion` support functions without `Decl` not implemented"
666 " yet.");
667 os << getDecl()->getName();
668}
669
670bool ObjCIvarRegion::canPrintPrettyAsExpr() const {
671 return true;
672}
673
674void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const {
675 os << getDecl()->getName();
676}
677
678bool FieldRegion::canPrintPretty() const {
679 return true;
680}
681
682bool FieldRegion::canPrintPrettyAsExpr() const {
683 return superRegion->canPrintPrettyAsExpr();
684}
685
686void FieldRegion::printPrettyAsExpr(raw_ostream &os) const {
687 assert(canPrintPrettyAsExpr());
688 superRegion->printPrettyAsExpr(os);
689 os << "." << getDecl()->getName();
690}
691
692void FieldRegion::printPretty(raw_ostream &os) const {
693 if (canPrintPrettyAsExpr()) {
694 os << "\'";
695 printPrettyAsExpr(os);
696 os << "'";
697 } else {
698 os << "field " << "\'" << getDecl()->getName() << "'";
699 }
700}
701
702bool CXXBaseObjectRegion::canPrintPrettyAsExpr() const {
703 return superRegion->canPrintPrettyAsExpr();
704}
705
706void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
707 superRegion->printPrettyAsExpr(os);
708}
709
710bool CXXDerivedObjectRegion::canPrintPrettyAsExpr() const {
711 return superRegion->canPrintPrettyAsExpr();
712}
713
714void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
715 superRegion->printPrettyAsExpr(os);
716}
717
718std::string MemRegion::getDescriptiveName(bool UseQuotes) const {
719 std::string VariableName;
720 std::string ArrayIndices;
721 const MemRegion *R = this;
722 SmallString<50> buf;
723 llvm::raw_svector_ostream os(buf);
724
725 // Obtain array indices to add them to the variable name.
726 const ElementRegion *ER = nullptr;
727 while ((ER = R->getAs<ElementRegion>())) {
728 // Index is a ConcreteInt.
729 if (auto CI = ER->getIndex().getAs<nonloc::ConcreteInt>()) {
730 llvm::SmallString<2> Idx;
731 CI->getValue().toString(Str&: Idx);
732 ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str();
733 }
734 // Index is symbolic, but may have a descriptive name.
735 else {
736 auto SI = ER->getIndex().getAs<nonloc::SymbolVal>();
737 if (!SI)
738 return "";
739
740 const MemRegion *OR = SI->getAsSymbol()->getOriginRegion();
741 if (!OR)
742 return "";
743
744 std::string Idx = OR->getDescriptiveName(UseQuotes: false);
745 if (Idx.empty())
746 return "";
747
748 ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str();
749 }
750 R = ER->getSuperRegion();
751 }
752
753 // Get variable name.
754 if (R && R->canPrintPrettyAsExpr()) {
755 R->printPrettyAsExpr(os);
756 if (UseQuotes)
757 return (llvm::Twine("'") + os.str() + ArrayIndices + "'").str();
758 else
759 return (llvm::Twine(os.str()) + ArrayIndices).str();
760 }
761
762 return VariableName;
763}
764
765SourceRange MemRegion::sourceRange() const {
766 // Check for more specific regions first.
767 if (auto *FR = dyn_cast<FieldRegion>(Val: this)) {
768 return FR->getDecl()->getSourceRange();
769 }
770
771 if (auto *VR = dyn_cast<VarRegion>(Val: this->getBaseRegion())) {
772 return VR->getDecl()->getSourceRange();
773 }
774
775 // Return invalid source range (can be checked by client).
776 return {};
777}
778
779//===----------------------------------------------------------------------===//
780// MemRegionManager methods.
781//===----------------------------------------------------------------------===//
782
783DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR,
784 SValBuilder &SVB) const {
785 const auto *SR = cast<SubRegion>(Val: MR);
786 SymbolManager &SymMgr = SVB.getSymbolManager();
787
788 switch (SR->getKind()) {
789 case MemRegion::AllocaRegionKind:
790 case MemRegion::SymbolicRegionKind:
791 return nonloc::SymbolVal(SymMgr.getExtentSymbol(R: SR));
792 case MemRegion::StringRegionKind:
793 return SVB.makeIntVal(
794 integer: cast<StringRegion>(Val: SR)->getStringLiteral()->getByteLength() + 1,
795 type: SVB.getArrayIndexType());
796 case MemRegion::CompoundLiteralRegionKind:
797 case MemRegion::CXXBaseObjectRegionKind:
798 case MemRegion::CXXDerivedObjectRegionKind:
799 case MemRegion::CXXTempObjectRegionKind:
800 case MemRegion::CXXLifetimeExtendedObjectRegionKind:
801 case MemRegion::CXXThisRegionKind:
802 case MemRegion::ObjCIvarRegionKind:
803 case MemRegion::NonParamVarRegionKind:
804 case MemRegion::ParamVarRegionKind:
805 case MemRegion::ElementRegionKind:
806 case MemRegion::ObjCStringRegionKind: {
807 QualType Ty = cast<TypedValueRegion>(Val: SR)->getDesugaredValueType(Context&: Ctx);
808 if (isa<VariableArrayType>(Val: Ty))
809 return nonloc::SymbolVal(SymMgr.getExtentSymbol(R: SR));
810
811 if (Ty->isIncompleteType())
812 return UnknownVal();
813
814 return getElementExtent(Ty, SVB);
815 }
816 case MemRegion::FieldRegionKind: {
817 // Force callers to deal with bitfields explicitly.
818 if (cast<FieldRegion>(Val: SR)->getDecl()->isBitField())
819 return UnknownVal();
820
821 QualType Ty = cast<TypedValueRegion>(Val: SR)->getDesugaredValueType(Context&: Ctx);
822 const DefinedOrUnknownSVal Size = getElementExtent(Ty, SVB);
823
824 // We currently don't model flexible array members (FAMs), which are:
825 // - int array[]; of IncompleteArrayType
826 // - int array[0]; of ConstantArrayType with size 0
827 // - int array[1]; of ConstantArrayType with size 1
828 // https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
829 const auto isFlexibleArrayMemberCandidate =
830 [this](const ArrayType *AT) -> bool {
831 if (!AT)
832 return false;
833
834 auto IsIncompleteArray = [](const ArrayType *AT) {
835 return isa<IncompleteArrayType>(Val: AT);
836 };
837 auto IsArrayOfZero = [](const ArrayType *AT) {
838 const auto *CAT = dyn_cast<ConstantArrayType>(Val: AT);
839 return CAT && CAT->isZeroSize();
840 };
841 auto IsArrayOfOne = [](const ArrayType *AT) {
842 const auto *CAT = dyn_cast<ConstantArrayType>(Val: AT);
843 return CAT && CAT->getSize() == 1;
844 };
845
846 using FAMKind = LangOptions::StrictFlexArraysLevelKind;
847 const FAMKind StrictFlexArraysLevel =
848 Ctx.getLangOpts().getStrictFlexArraysLevel();
849
850 // "Default": Any trailing array member is a FAM.
851 // Since we cannot tell at this point if this array is a trailing member
852 // or not, let's just do the same as for "OneZeroOrIncomplete".
853 if (StrictFlexArraysLevel == FAMKind::Default)
854 return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT);
855
856 if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
857 return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT);
858
859 if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete)
860 return IsArrayOfZero(AT) || IsIncompleteArray(AT);
861
862 assert(StrictFlexArraysLevel == FAMKind::IncompleteOnly);
863 return IsIncompleteArray(AT);
864 };
865
866 if (isFlexibleArrayMemberCandidate(Ctx.getAsArrayType(T: Ty)))
867 return UnknownVal();
868
869 return Size;
870 }
871 // FIXME: The following are being used in 'SimpleSValBuilder' and in
872 // 'ArrayBoundChecker::checkLocation' because there is no symbol to
873 // represent the regions more appropriately.
874 case MemRegion::BlockDataRegionKind:
875 case MemRegion::BlockCodeRegionKind:
876 case MemRegion::FunctionCodeRegionKind:
877 return nonloc::SymbolVal(SymMgr.getExtentSymbol(R: SR));
878 default:
879 llvm_unreachable("Unhandled region");
880 }
881}
882
883template <typename REG>
884const REG *MemRegionManager::LazyAllocate(REG*& region) {
885 if (!region) {
886 region = new (A) REG(*this);
887 }
888
889 return region;
890}
891
892template <typename REG, typename ARG>
893const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) {
894 if (!region) {
895 region = new (A) REG(this, a);
896 }
897
898 return region;
899}
900
901const StackLocalsSpaceRegion*
902MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {
903 assert(STC);
904 StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC];
905
906 if (R)
907 return R;
908
909 R = new (A) StackLocalsSpaceRegion(*this, STC);
910 return R;
911}
912
913const StackArgumentsSpaceRegion *
914MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) {
915 assert(STC);
916 StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC];
917
918 if (R)
919 return R;
920
921 R = new (A) StackArgumentsSpaceRegion(*this, STC);
922 return R;
923}
924
925const GlobalsSpaceRegion
926*MemRegionManager::getGlobalsRegion(MemRegion::Kind K,
927 const CodeTextRegion *CR) {
928 if (!CR) {
929 if (K == MemRegion::GlobalSystemSpaceRegionKind)
930 return LazyAllocate(region&: SystemGlobals);
931 if (K == MemRegion::GlobalImmutableSpaceRegionKind)
932 return LazyAllocate(region&: ImmutableGlobals);
933 assert(K == MemRegion::GlobalInternalSpaceRegionKind);
934 return LazyAllocate(region&: InternalGlobals);
935 }
936
937 assert(K == MemRegion::StaticGlobalSpaceRegionKind);
938 StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR];
939 if (R)
940 return R;
941
942 R = new (A) StaticGlobalSpaceRegion(*this, CR);
943 return R;
944}
945
946const HeapSpaceRegion *MemRegionManager::getHeapRegion() {
947 return LazyAllocate(region&: heap);
948}
949
950const UnknownSpaceRegion *MemRegionManager::getUnknownRegion() {
951 return LazyAllocate(region&: unknown);
952}
953
954const CodeSpaceRegion *MemRegionManager::getCodeRegion() {
955 return LazyAllocate(region&: code);
956}
957
958//===----------------------------------------------------------------------===//
959// Constructing regions.
960//===----------------------------------------------------------------------===//
961
962const StringRegion *MemRegionManager::getStringRegion(const StringLiteral *Str){
963 return getSubRegion<StringRegion>(
964 arg1: Str, superRegion: cast<GlobalInternalSpaceRegion>(Val: getGlobalsRegion()));
965}
966
967const ObjCStringRegion *
968MemRegionManager::getObjCStringRegion(const ObjCStringLiteral *Str){
969 return getSubRegion<ObjCStringRegion>(
970 arg1: Str, superRegion: cast<GlobalInternalSpaceRegion>(Val: getGlobalsRegion()));
971}
972
973/// Look through a chain of LocationContexts to either find the
974/// StackFrameContext that matches a DeclContext, or find a VarRegion
975/// for a variable captured by a block.
976static llvm::PointerUnion<const StackFrameContext *, const VarRegion *>
977getStackOrCaptureRegionForDeclContext(const LocationContext *LC,
978 const DeclContext *DC,
979 const VarDecl *VD) {
980 while (LC) {
981 if (const auto *SFC = dyn_cast<StackFrameContext>(Val: LC)) {
982 if (cast<DeclContext>(Val: SFC->getDecl()) == DC)
983 return SFC;
984 }
985 if (const auto *BC = dyn_cast<BlockInvocationContext>(Val: LC)) {
986 const auto *BR = static_cast<const BlockDataRegion *>(BC->getData());
987 // FIXME: This can be made more efficient.
988 for (auto Var : BR->referenced_vars()) {
989 const TypedValueRegion *OrigR = Var.getOriginalRegion();
990 if (const auto *VR = dyn_cast<VarRegion>(Val: OrigR)) {
991 if (VR->getDecl() == VD)
992 return cast<VarRegion>(Val: Var.getCapturedRegion());
993 }
994 }
995 }
996
997 LC = LC->getParent();
998 }
999 return (const StackFrameContext *)nullptr;
1000}
1001
1002const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
1003 const LocationContext *LC) {
1004 const auto *PVD = dyn_cast<ParmVarDecl>(Val: D);
1005 if (PVD) {
1006 unsigned Index = PVD->getFunctionScopeIndex();
1007 const StackFrameContext *SFC = LC->getStackFrame();
1008 const Stmt *CallSite = SFC->getCallSite();
1009 if (CallSite) {
1010 const Decl *D = SFC->getDecl();
1011 if (const auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
1012 if (Index < FD->param_size() && FD->parameters()[Index] == PVD)
1013 return getSubRegion<ParamVarRegion>(arg1: cast<Expr>(Val: CallSite), arg2: Index,
1014 superRegion: getStackArgumentsRegion(STC: SFC));
1015 } else if (const auto *BD = dyn_cast<BlockDecl>(Val: D)) {
1016 if (Index < BD->param_size() && BD->parameters()[Index] == PVD)
1017 return getSubRegion<ParamVarRegion>(arg1: cast<Expr>(Val: CallSite), arg2: Index,
1018 superRegion: getStackArgumentsRegion(STC: SFC));
1019 } else {
1020 return getSubRegion<ParamVarRegion>(arg1: cast<Expr>(Val: CallSite), arg2: Index,
1021 superRegion: getStackArgumentsRegion(STC: SFC));
1022 }
1023 }
1024 }
1025
1026 D = D->getCanonicalDecl();
1027 const MemRegion *sReg = nullptr;
1028
1029 if (D->hasGlobalStorage() && !D->isStaticLocal()) {
1030 QualType Ty = D->getType();
1031 assert(!Ty.isNull());
1032 if (Ty.isConstQualified()) {
1033 sReg = getGlobalsRegion(K: MemRegion::GlobalImmutableSpaceRegionKind);
1034 } else if (Ctx.getSourceManager().isInSystemHeader(Loc: D->getLocation())) {
1035 sReg = getGlobalsRegion(K: MemRegion::GlobalSystemSpaceRegionKind);
1036 } else {
1037 sReg = getGlobalsRegion(K: MemRegion::GlobalInternalSpaceRegionKind);
1038 }
1039
1040 // Finally handle static locals.
1041 } else {
1042 // FIXME: Once we implement scope handling, we will need to properly lookup
1043 // 'D' to the proper LocationContext.
1044 const DeclContext *DC = D->getDeclContext();
1045 llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V =
1046 getStackOrCaptureRegionForDeclContext(LC, DC, VD: D);
1047
1048 if (V.is<const VarRegion*>())
1049 return V.get<const VarRegion*>();
1050
1051 const auto *STC = V.get<const StackFrameContext *>();
1052
1053 if (!STC) {
1054 // FIXME: Assign a more sensible memory space to static locals
1055 // we see from within blocks that we analyze as top-level declarations.
1056 sReg = getUnknownRegion();
1057 } else {
1058 if (D->hasLocalStorage()) {
1059 sReg =
1060 isa<ParmVarDecl, ImplicitParamDecl>(Val: D)
1061 ? static_cast<const MemRegion *>(getStackArgumentsRegion(STC))
1062 : static_cast<const MemRegion *>(getStackLocalsRegion(STC));
1063 }
1064 else {
1065 assert(D->isStaticLocal());
1066 const Decl *STCD = STC->getDecl();
1067 if (isa<FunctionDecl, ObjCMethodDecl>(Val: STCD))
1068 sReg = getGlobalsRegion(K: MemRegion::StaticGlobalSpaceRegionKind,
1069 CR: getFunctionCodeRegion(FD: cast<NamedDecl>(Val: STCD)));
1070 else if (const auto *BD = dyn_cast<BlockDecl>(Val: STCD)) {
1071 // FIXME: The fallback type here is totally bogus -- though it should
1072 // never be queried, it will prevent uniquing with the real
1073 // BlockCodeRegion. Ideally we'd fix the AST so that we always had a
1074 // signature.
1075 QualType T;
1076 if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten())
1077 T = TSI->getType();
1078 if (T.isNull())
1079 T = getContext().VoidTy;
1080 if (!T->getAs<FunctionType>()) {
1081 FunctionProtoType::ExtProtoInfo Ext;
1082 T = getContext().getFunctionType(ResultTy: T, Args: std::nullopt, EPI: Ext);
1083 }
1084 T = getContext().getBlockPointerType(T);
1085
1086 const BlockCodeRegion *BTR =
1087 getBlockCodeRegion(BD, locTy: Ctx.getCanonicalType(T),
1088 AC: STC->getAnalysisDeclContext());
1089 sReg = getGlobalsRegion(K: MemRegion::StaticGlobalSpaceRegionKind,
1090 CR: BTR);
1091 }
1092 else {
1093 sReg = getGlobalsRegion();
1094 }
1095 }
1096 }
1097 }
1098
1099 return getNonParamVarRegion(VD: D, superR: sReg);
1100}
1101
1102const NonParamVarRegion *
1103MemRegionManager::getNonParamVarRegion(const VarDecl *D,
1104 const MemRegion *superR) {
1105 // Prefer the definition over the canonical decl as the canonical form.
1106 D = D->getCanonicalDecl();
1107 if (const VarDecl *Def = D->getDefinition())
1108 D = Def;
1109 return getSubRegion<NonParamVarRegion>(arg1: D, superRegion: superR);
1110}
1111
1112const ParamVarRegion *
1113MemRegionManager::getParamVarRegion(const Expr *OriginExpr, unsigned Index,
1114 const LocationContext *LC) {
1115 const StackFrameContext *SFC = LC->getStackFrame();
1116 assert(SFC);
1117 return getSubRegion<ParamVarRegion>(arg1: OriginExpr, arg2: Index,
1118 superRegion: getStackArgumentsRegion(STC: SFC));
1119}
1120
1121const BlockDataRegion *
1122MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC,
1123 const LocationContext *LC,
1124 unsigned blockCount) {
1125 const MemSpaceRegion *sReg = nullptr;
1126 const BlockDecl *BD = BC->getDecl();
1127 if (!BD->hasCaptures()) {
1128 // This handles 'static' blocks.
1129 sReg = getGlobalsRegion(K: MemRegion::GlobalImmutableSpaceRegionKind);
1130 }
1131 else {
1132 bool IsArcManagedBlock = Ctx.getLangOpts().ObjCAutoRefCount;
1133
1134 // ARC managed blocks can be initialized on stack or directly in heap
1135 // depending on the implementations. So we initialize them with
1136 // UnknownRegion.
1137 if (!IsArcManagedBlock && LC) {
1138 // FIXME: Once we implement scope handling, we want the parent region
1139 // to be the scope.
1140 const StackFrameContext *STC = LC->getStackFrame();
1141 assert(STC);
1142 sReg = getStackLocalsRegion(STC);
1143 } else {
1144 // We allow 'LC' to be NULL for cases where want BlockDataRegions
1145 // without context-sensitivity.
1146 sReg = getUnknownRegion();
1147 }
1148 }
1149
1150 return getSubRegion<BlockDataRegion>(arg1: BC, arg2: LC, arg3: blockCount, superRegion: sReg);
1151}
1152
1153const CompoundLiteralRegion*
1154MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
1155 const LocationContext *LC) {
1156 const MemSpaceRegion *sReg = nullptr;
1157
1158 if (CL->isFileScope())
1159 sReg = getGlobalsRegion();
1160 else {
1161 const StackFrameContext *STC = LC->getStackFrame();
1162 assert(STC);
1163 sReg = getStackLocalsRegion(STC);
1164 }
1165
1166 return getSubRegion<CompoundLiteralRegion>(arg1: CL, superRegion: sReg);
1167}
1168
1169const ElementRegion *
1170MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
1171 const SubRegion *superRegion,
1172 const ASTContext &Ctx) {
1173 QualType T = Ctx.getCanonicalType(T: elementType).getUnqualifiedType();
1174
1175 llvm::FoldingSetNodeID ID;
1176 ElementRegion::ProfileRegion(ID, ElementType: T, Idx, superRegion);
1177
1178 void *InsertPos;
1179 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
1180 auto *R = cast_or_null<ElementRegion>(Val: data);
1181
1182 if (!R) {
1183 R = new (A) ElementRegion(T, Idx, superRegion);
1184 Regions.InsertNode(N: R, InsertPos);
1185 }
1186
1187 return R;
1188}
1189
1190const FunctionCodeRegion *
1191MemRegionManager::getFunctionCodeRegion(const NamedDecl *FD) {
1192 // To think: should we canonicalize the declaration here?
1193 return getSubRegion<FunctionCodeRegion>(arg1: FD, superRegion: getCodeRegion());
1194}
1195
1196const BlockCodeRegion *
1197MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy,
1198 AnalysisDeclContext *AC) {
1199 return getSubRegion<BlockCodeRegion>(arg1: BD, arg2: locTy, arg3: AC, superRegion: getCodeRegion());
1200}
1201
1202const SymbolicRegion *
1203MemRegionManager::getSymbolicRegion(SymbolRef sym,
1204 const MemSpaceRegion *MemSpace) {
1205 if (MemSpace == nullptr)
1206 MemSpace = getUnknownRegion();
1207 return getSubRegion<SymbolicRegion>(arg1: sym, superRegion: MemSpace);
1208}
1209
1210const SymbolicRegion *MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym) {
1211 return getSubRegion<SymbolicRegion>(arg1: Sym, superRegion: getHeapRegion());
1212}
1213
1214const FieldRegion*
1215MemRegionManager::getFieldRegion(const FieldDecl *d,
1216 const SubRegion* superRegion){
1217 return getSubRegion<FieldRegion>(arg1: d, superRegion);
1218}
1219
1220const ObjCIvarRegion*
1221MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d,
1222 const SubRegion* superRegion) {
1223 return getSubRegion<ObjCIvarRegion>(arg1: d, superRegion);
1224}
1225
1226const CXXTempObjectRegion*
1227MemRegionManager::getCXXTempObjectRegion(Expr const *E,
1228 LocationContext const *LC) {
1229 const StackFrameContext *SFC = LC->getStackFrame();
1230 assert(SFC);
1231 return getSubRegion<CXXTempObjectRegion>(arg1: E, superRegion: getStackLocalsRegion(STC: SFC));
1232}
1233
1234const CXXLifetimeExtendedObjectRegion *
1235MemRegionManager::getCXXLifetimeExtendedObjectRegion(
1236 const Expr *Ex, const ValueDecl *VD, const LocationContext *LC) {
1237 const StackFrameContext *SFC = LC->getStackFrame();
1238 assert(SFC);
1239 return getSubRegion<CXXLifetimeExtendedObjectRegion>(
1240 arg1: Ex, arg2: VD, superRegion: getStackLocalsRegion(STC: SFC));
1241}
1242
1243const CXXLifetimeExtendedObjectRegion *
1244MemRegionManager::getCXXStaticLifetimeExtendedObjectRegion(
1245 const Expr *Ex, const ValueDecl *VD) {
1246 return getSubRegion<CXXLifetimeExtendedObjectRegion>(
1247 arg1: Ex, arg2: VD,
1248 superRegion: getGlobalsRegion(K: MemRegion::GlobalInternalSpaceRegionKind, CR: nullptr));
1249}
1250
1251/// Checks whether \p BaseClass is a valid virtual or direct non-virtual base
1252/// class of the type of \p Super.
1253static bool isValidBaseClass(const CXXRecordDecl *BaseClass,
1254 const TypedValueRegion *Super,
1255 bool IsVirtual) {
1256 BaseClass = BaseClass->getCanonicalDecl();
1257
1258 const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl();
1259 if (!Class)
1260 return true;
1261
1262 if (IsVirtual)
1263 return Class->isVirtuallyDerivedFrom(Base: BaseClass);
1264
1265 for (const auto &I : Class->bases()) {
1266 if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass)
1267 return true;
1268 }
1269
1270 return false;
1271}
1272
1273const CXXBaseObjectRegion *
1274MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
1275 const SubRegion *Super,
1276 bool IsVirtual) {
1277 if (isa<TypedValueRegion>(Val: Super)) {
1278 assert(isValidBaseClass(RD, cast<TypedValueRegion>(Super), IsVirtual));
1279 (void)&isValidBaseClass;
1280
1281 if (IsVirtual) {
1282 // Virtual base regions should not be layered, since the layout rules
1283 // are different.
1284 while (const auto *Base = dyn_cast<CXXBaseObjectRegion>(Val: Super))
1285 Super = cast<SubRegion>(Val: Base->getSuperRegion());
1286 assert(Super && !isa<MemSpaceRegion>(Super));
1287 }
1288 }
1289
1290 return getSubRegion<CXXBaseObjectRegion>(arg1: RD, arg2: IsVirtual, superRegion: Super);
1291}
1292
1293const CXXDerivedObjectRegion *
1294MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl *RD,
1295 const SubRegion *Super) {
1296 return getSubRegion<CXXDerivedObjectRegion>(arg1: RD, superRegion: Super);
1297}
1298
1299const CXXThisRegion*
1300MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
1301 const LocationContext *LC) {
1302 const auto *PT = thisPointerTy->getAs<PointerType>();
1303 assert(PT);
1304 // Inside the body of the operator() of a lambda a this expr might refer to an
1305 // object in one of the parent location contexts.
1306 const auto *D = dyn_cast<CXXMethodDecl>(Val: LC->getDecl());
1307 // FIXME: when operator() of lambda is analyzed as a top level function and
1308 // 'this' refers to a this to the enclosing scope, there is no right region to
1309 // return.
1310 while (!LC->inTopFrame() && (!D || D->isStatic() ||
1311 PT != D->getThisType()->getAs<PointerType>())) {
1312 LC = LC->getParent();
1313 D = dyn_cast<CXXMethodDecl>(Val: LC->getDecl());
1314 }
1315 const StackFrameContext *STC = LC->getStackFrame();
1316 assert(STC);
1317 return getSubRegion<CXXThisRegion>(arg1: PT, superRegion: getStackArgumentsRegion(STC));
1318}
1319
1320const AllocaRegion*
1321MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt,
1322 const LocationContext *LC) {
1323 const StackFrameContext *STC = LC->getStackFrame();
1324 assert(STC);
1325 return getSubRegion<AllocaRegion>(arg1: E, arg2: cnt, superRegion: getStackLocalsRegion(STC));
1326}
1327
1328const MemSpaceRegion *MemRegion::getMemorySpace() const {
1329 const MemRegion *R = this;
1330 const auto *SR = dyn_cast<SubRegion>(Val: this);
1331
1332 while (SR) {
1333 R = SR->getSuperRegion();
1334 SR = dyn_cast<SubRegion>(Val: R);
1335 }
1336
1337 return cast<MemSpaceRegion>(Val: R);
1338}
1339
1340bool MemRegion::hasStackStorage() const {
1341 return isa<StackSpaceRegion>(Val: getMemorySpace());
1342}
1343
1344bool MemRegion::hasStackNonParametersStorage() const {
1345 return isa<StackLocalsSpaceRegion>(Val: getMemorySpace());
1346}
1347
1348bool MemRegion::hasStackParametersStorage() const {
1349 return isa<StackArgumentsSpaceRegion>(Val: getMemorySpace());
1350}
1351
1352// Strips away all elements and fields.
1353// Returns the base region of them.
1354const MemRegion *MemRegion::getBaseRegion() const {
1355 const MemRegion *R = this;
1356 while (true) {
1357 switch (R->getKind()) {
1358 case MemRegion::ElementRegionKind:
1359 case MemRegion::FieldRegionKind:
1360 case MemRegion::ObjCIvarRegionKind:
1361 case MemRegion::CXXBaseObjectRegionKind:
1362 case MemRegion::CXXDerivedObjectRegionKind:
1363 R = cast<SubRegion>(Val: R)->getSuperRegion();
1364 continue;
1365 default:
1366 break;
1367 }
1368 break;
1369 }
1370 return R;
1371}
1372
1373// Returns the region of the root class of a C++ class hierarchy.
1374const MemRegion *MemRegion::getMostDerivedObjectRegion() const {
1375 const MemRegion *R = this;
1376 while (const auto *BR = dyn_cast<CXXBaseObjectRegion>(Val: R))
1377 R = BR->getSuperRegion();
1378 return R;
1379}
1380
1381bool MemRegion::isSubRegionOf(const MemRegion *) const {
1382 return false;
1383}
1384
1385//===----------------------------------------------------------------------===//
1386// View handling.
1387//===----------------------------------------------------------------------===//
1388
1389const MemRegion *MemRegion::StripCasts(bool StripBaseAndDerivedCasts) const {
1390 const MemRegion *R = this;
1391 while (true) {
1392 switch (R->getKind()) {
1393 case ElementRegionKind: {
1394 const auto *ER = cast<ElementRegion>(Val: R);
1395 if (!ER->getIndex().isZeroConstant())
1396 return R;
1397 R = ER->getSuperRegion();
1398 break;
1399 }
1400 case CXXBaseObjectRegionKind:
1401 case CXXDerivedObjectRegionKind:
1402 if (!StripBaseAndDerivedCasts)
1403 return R;
1404 R = cast<TypedValueRegion>(Val: R)->getSuperRegion();
1405 break;
1406 default:
1407 return R;
1408 }
1409 }
1410}
1411
1412const SymbolicRegion *MemRegion::getSymbolicBase() const {
1413 const auto *SubR = dyn_cast<SubRegion>(Val: this);
1414
1415 while (SubR) {
1416 if (const auto *SymR = dyn_cast<SymbolicRegion>(Val: SubR))
1417 return SymR;
1418 SubR = dyn_cast<SubRegion>(Val: SubR->getSuperRegion());
1419 }
1420 return nullptr;
1421}
1422
1423RegionRawOffset ElementRegion::getAsArrayOffset() const {
1424 int64_t offset = 0;
1425 const ElementRegion *ER = this;
1426 const MemRegion *superR = nullptr;
1427 ASTContext &C = getContext();
1428
1429 // FIXME: Handle multi-dimensional arrays.
1430
1431 while (ER) {
1432 superR = ER->getSuperRegion();
1433
1434 // FIXME: generalize to symbolic offsets.
1435 SVal index = ER->getIndex();
1436 if (auto CI = index.getAs<nonloc::ConcreteInt>()) {
1437 // Update the offset.
1438 int64_t i = CI->getValue().getSExtValue();
1439
1440 if (i != 0) {
1441 QualType elemType = ER->getElementType();
1442
1443 // If we are pointing to an incomplete type, go no further.
1444 if (elemType->isIncompleteType()) {
1445 superR = ER;
1446 break;
1447 }
1448
1449 int64_t size = C.getTypeSizeInChars(T: elemType).getQuantity();
1450 if (auto NewOffset = llvm::checkedMulAdd(A: i, B: size, C: offset)) {
1451 offset = *NewOffset;
1452 } else {
1453 LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
1454 << "offset overflowing, returning unknown\n");
1455
1456 return nullptr;
1457 }
1458 }
1459
1460 // Go to the next ElementRegion (if any).
1461 ER = dyn_cast<ElementRegion>(Val: superR);
1462 continue;
1463 }
1464
1465 return nullptr;
1466 }
1467
1468 assert(superR && "super region cannot be NULL");
1469 return RegionRawOffset(superR, CharUnits::fromQuantity(Quantity: offset));
1470}
1471
1472/// Returns true if \p Base is an immediate base class of \p Child
1473static bool isImmediateBase(const CXXRecordDecl *Child,
1474 const CXXRecordDecl *Base) {
1475 assert(Child && "Child must not be null");
1476 // Note that we do NOT canonicalize the base class here, because
1477 // ASTRecordLayout doesn't either. If that leads us down the wrong path,
1478 // so be it; at least we won't crash.
1479 for (const auto &I : Child->bases()) {
1480 if (I.getType()->getAsCXXRecordDecl() == Base)
1481 return true;
1482 }
1483
1484 return false;
1485}
1486
1487static RegionOffset calculateOffset(const MemRegion *R) {
1488 const MemRegion *SymbolicOffsetBase = nullptr;
1489 int64_t Offset = 0;
1490
1491 while (true) {
1492 switch (R->getKind()) {
1493 case MemRegion::CodeSpaceRegionKind:
1494 case MemRegion::StackLocalsSpaceRegionKind:
1495 case MemRegion::StackArgumentsSpaceRegionKind:
1496 case MemRegion::HeapSpaceRegionKind:
1497 case MemRegion::UnknownSpaceRegionKind:
1498 case MemRegion::StaticGlobalSpaceRegionKind:
1499 case MemRegion::GlobalInternalSpaceRegionKind:
1500 case MemRegion::GlobalSystemSpaceRegionKind:
1501 case MemRegion::GlobalImmutableSpaceRegionKind:
1502 // Stores can bind directly to a region space to set a default value.
1503 assert(Offset == 0 && !SymbolicOffsetBase);
1504 goto Finish;
1505
1506 case MemRegion::FunctionCodeRegionKind:
1507 case MemRegion::BlockCodeRegionKind:
1508 case MemRegion::BlockDataRegionKind:
1509 // These will never have bindings, but may end up having values requested
1510 // if the user does some strange casting.
1511 if (Offset != 0)
1512 SymbolicOffsetBase = R;
1513 goto Finish;
1514
1515 case MemRegion::SymbolicRegionKind:
1516 case MemRegion::AllocaRegionKind:
1517 case MemRegion::CompoundLiteralRegionKind:
1518 case MemRegion::CXXThisRegionKind:
1519 case MemRegion::StringRegionKind:
1520 case MemRegion::ObjCStringRegionKind:
1521 case MemRegion::NonParamVarRegionKind:
1522 case MemRegion::ParamVarRegionKind:
1523 case MemRegion::CXXTempObjectRegionKind:
1524 case MemRegion::CXXLifetimeExtendedObjectRegionKind:
1525 // Usual base regions.
1526 goto Finish;
1527
1528 case MemRegion::ObjCIvarRegionKind:
1529 // This is a little strange, but it's a compromise between
1530 // ObjCIvarRegions having unknown compile-time offsets (when using the
1531 // non-fragile runtime) and yet still being distinct, non-overlapping
1532 // regions. Thus we treat them as "like" base regions for the purposes
1533 // of computing offsets.
1534 goto Finish;
1535
1536 case MemRegion::CXXBaseObjectRegionKind: {
1537 const auto *BOR = cast<CXXBaseObjectRegion>(Val: R);
1538 R = BOR->getSuperRegion();
1539
1540 QualType Ty;
1541 bool RootIsSymbolic = false;
1542 if (const auto *TVR = dyn_cast<TypedValueRegion>(Val: R)) {
1543 Ty = TVR->getDesugaredValueType(Context&: R->getContext());
1544 } else if (const auto *SR = dyn_cast<SymbolicRegion>(Val: R)) {
1545 // If our base region is symbolic, we don't know what type it really is.
1546 // Pretend the type of the symbol is the true dynamic type.
1547 // (This will at least be self-consistent for the life of the symbol.)
1548 Ty = SR->getPointeeStaticType();
1549 RootIsSymbolic = true;
1550 }
1551
1552 const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl();
1553 if (!Child) {
1554 // We cannot compute the offset of the base class.
1555 SymbolicOffsetBase = R;
1556 } else {
1557 if (RootIsSymbolic) {
1558 // Base layers on symbolic regions may not be type-correct.
1559 // Double-check the inheritance here, and revert to a symbolic offset
1560 // if it's invalid (e.g. due to a reinterpret_cast).
1561 if (BOR->isVirtual()) {
1562 if (!Child->isVirtuallyDerivedFrom(Base: BOR->getDecl()))
1563 SymbolicOffsetBase = R;
1564 } else {
1565 if (!isImmediateBase(Child, Base: BOR->getDecl()))
1566 SymbolicOffsetBase = R;
1567 }
1568 }
1569 }
1570
1571 // Don't bother calculating precise offsets if we already have a
1572 // symbolic offset somewhere in the chain.
1573 if (SymbolicOffsetBase)
1574 continue;
1575
1576 CharUnits BaseOffset;
1577 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(D: Child);
1578 if (BOR->isVirtual())
1579 BaseOffset = Layout.getVBaseClassOffset(VBase: BOR->getDecl());
1580 else
1581 BaseOffset = Layout.getBaseClassOffset(Base: BOR->getDecl());
1582
1583 // The base offset is in chars, not in bits.
1584 Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth();
1585 break;
1586 }
1587
1588 case MemRegion::CXXDerivedObjectRegionKind: {
1589 // TODO: Store the base type in the CXXDerivedObjectRegion and use it.
1590 goto Finish;
1591 }
1592
1593 case MemRegion::ElementRegionKind: {
1594 const auto *ER = cast<ElementRegion>(Val: R);
1595 R = ER->getSuperRegion();
1596
1597 QualType EleTy = ER->getValueType();
1598 if (EleTy->isIncompleteType()) {
1599 // We cannot compute the offset of the base class.
1600 SymbolicOffsetBase = R;
1601 continue;
1602 }
1603
1604 SVal Index = ER->getIndex();
1605 if (std::optional<nonloc::ConcreteInt> CI =
1606 Index.getAs<nonloc::ConcreteInt>()) {
1607 // Don't bother calculating precise offsets if we already have a
1608 // symbolic offset somewhere in the chain.
1609 if (SymbolicOffsetBase)
1610 continue;
1611
1612 int64_t i = CI->getValue().getSExtValue();
1613 // This type size is in bits.
1614 Offset += i * R->getContext().getTypeSize(T: EleTy);
1615 } else {
1616 // We cannot compute offset for non-concrete index.
1617 SymbolicOffsetBase = R;
1618 }
1619 break;
1620 }
1621 case MemRegion::FieldRegionKind: {
1622 const auto *FR = cast<FieldRegion>(Val: R);
1623 R = FR->getSuperRegion();
1624 assert(R);
1625
1626 const RecordDecl *RD = FR->getDecl()->getParent();
1627 if (RD->isUnion() || !RD->isCompleteDefinition()) {
1628 // We cannot compute offset for incomplete type.
1629 // For unions, we could treat everything as offset 0, but we'd rather
1630 // treat each field as a symbolic offset so they aren't stored on top
1631 // of each other, since we depend on things in typed regions actually
1632 // matching their types.
1633 SymbolicOffsetBase = R;
1634 }
1635
1636 // Don't bother calculating precise offsets if we already have a
1637 // symbolic offset somewhere in the chain.
1638 if (SymbolicOffsetBase)
1639 continue;
1640
1641 // Get the field number.
1642 unsigned idx = 0;
1643 for (RecordDecl::field_iterator FI = RD->field_begin(),
1644 FE = RD->field_end(); FI != FE; ++FI, ++idx) {
1645 if (FR->getDecl() == *FI)
1646 break;
1647 }
1648 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(D: RD);
1649 // This is offset in bits.
1650 Offset += Layout.getFieldOffset(FieldNo: idx);
1651 break;
1652 }
1653 }
1654 }
1655
1656 Finish:
1657 if (SymbolicOffsetBase)
1658 return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic);
1659 return RegionOffset(R, Offset);
1660}
1661
1662RegionOffset MemRegion::getAsOffset() const {
1663 if (!cachedOffset)
1664 cachedOffset = calculateOffset(R: this);
1665 return *cachedOffset;
1666}
1667
1668//===----------------------------------------------------------------------===//
1669// BlockDataRegion
1670//===----------------------------------------------------------------------===//
1671
1672std::pair<const VarRegion *, const VarRegion *>
1673BlockDataRegion::getCaptureRegions(const VarDecl *VD) {
1674 MemRegionManager &MemMgr = getMemRegionManager();
1675 const VarRegion *VR = nullptr;
1676 const VarRegion *OriginalVR = nullptr;
1677
1678 if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) {
1679 VR = MemMgr.getNonParamVarRegion(D: VD, superR: this);
1680 OriginalVR = MemMgr.getVarRegion(D: VD, LC);
1681 }
1682 else {
1683 if (LC) {
1684 VR = MemMgr.getVarRegion(D: VD, LC);
1685 OriginalVR = VR;
1686 }
1687 else {
1688 VR = MemMgr.getNonParamVarRegion(D: VD, superR: MemMgr.getUnknownRegion());
1689 OriginalVR = MemMgr.getVarRegion(D: VD, LC);
1690 }
1691 }
1692 return std::make_pair(x&: VR, y&: OriginalVR);
1693}
1694
1695void BlockDataRegion::LazyInitializeReferencedVars() {
1696 if (ReferencedVars)
1697 return;
1698
1699 AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext();
1700 const auto &ReferencedBlockVars = AC->getReferencedBlockVars(BD: BC->getDecl());
1701 auto NumBlockVars =
1702 std::distance(first: ReferencedBlockVars.begin(), last: ReferencedBlockVars.end());
1703
1704 if (NumBlockVars == 0) {
1705 ReferencedVars = (void*) 0x1;
1706 return;
1707 }
1708
1709 MemRegionManager &MemMgr = getMemRegionManager();
1710 llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
1711 BumpVectorContext BC(A);
1712
1713 using VarVec = BumpVector<const MemRegion *>;
1714
1715 auto *BV = new (A) VarVec(BC, NumBlockVars);
1716 auto *BVOriginal = new (A) VarVec(BC, NumBlockVars);
1717
1718 for (const auto *VD : ReferencedBlockVars) {
1719 const VarRegion *VR = nullptr;
1720 const VarRegion *OriginalVR = nullptr;
1721 std::tie(args&: VR, args&: OriginalVR) = getCaptureRegions(VD);
1722 assert(VR);
1723 assert(OriginalVR);
1724 BV->push_back(Elt: VR, C&: BC);
1725 BVOriginal->push_back(Elt: OriginalVR, C&: BC);
1726 }
1727
1728 ReferencedVars = BV;
1729 OriginalVars = BVOriginal;
1730}
1731
1732BlockDataRegion::referenced_vars_iterator
1733BlockDataRegion::referenced_vars_begin() const {
1734 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
1735
1736 auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
1737
1738 if (Vec == (void*) 0x1)
1739 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
1740
1741 auto *VecOriginal =
1742 static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
1743
1744 return BlockDataRegion::referenced_vars_iterator(Vec->begin(),
1745 VecOriginal->begin());
1746}
1747
1748BlockDataRegion::referenced_vars_iterator
1749BlockDataRegion::referenced_vars_end() const {
1750 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
1751
1752 auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
1753
1754 if (Vec == (void*) 0x1)
1755 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
1756
1757 auto *VecOriginal =
1758 static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
1759
1760 return BlockDataRegion::referenced_vars_iterator(Vec->end(),
1761 VecOriginal->end());
1762}
1763
1764llvm::iterator_range<BlockDataRegion::referenced_vars_iterator>
1765BlockDataRegion::referenced_vars() const {
1766 return llvm::make_range(x: referenced_vars_begin(), y: referenced_vars_end());
1767}
1768
1769const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const {
1770 for (const auto &I : referenced_vars()) {
1771 if (I.getCapturedRegion() == R)
1772 return I.getOriginalRegion();
1773 }
1774 return nullptr;
1775}
1776
1777//===----------------------------------------------------------------------===//
1778// RegionAndSymbolInvalidationTraits
1779//===----------------------------------------------------------------------===//
1780
1781void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym,
1782 InvalidationKinds IK) {
1783 SymTraitsMap[Sym] |= IK;
1784}
1785
1786void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR,
1787 InvalidationKinds IK) {
1788 assert(MR);
1789 if (const auto *SR = dyn_cast<SymbolicRegion>(Val: MR))
1790 setTrait(Sym: SR->getSymbol(), IK);
1791 else
1792 MRTraitsMap[MR] |= IK;
1793}
1794
1795bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym,
1796 InvalidationKinds IK) const {
1797 const_symbol_iterator I = SymTraitsMap.find(Val: Sym);
1798 if (I != SymTraitsMap.end())
1799 return I->second & IK;
1800
1801 return false;
1802}
1803
1804bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion *MR,
1805 InvalidationKinds IK) const {
1806 if (!MR)
1807 return false;
1808
1809 if (const auto *SR = dyn_cast<SymbolicRegion>(Val: MR))
1810 return hasTrait(Sym: SR->getSymbol(), IK);
1811
1812 const_region_iterator I = MRTraitsMap.find(Val: MR);
1813 if (I != MRTraitsMap.end())
1814 return I->second & IK;
1815
1816 return false;
1817}
1818