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, 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(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(getContext()) << " }";
504}
505
506void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const {
507 os << "temp_object{" << getValueType() << ", "
508 << "S" << Ex->getID(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(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, nullptr, PrintingPolicy(getContext().getLangOpts()));
549}
550
551void ObjCStringRegion::dumpToStream(raw_ostream &os) const {
552 assert(Str != nullptr && "Expecting non-null ObjCStringLiteral");
553 Str->printPretty(os, nullptr, 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
633void MemRegion::printPretty(raw_ostream &os) const {
634 assert(canPrintPretty() && "This region cannot be printed pretty.");
635 os << "'";
636 printPrettyAsExpr(os);
637 os << "'";
638}
639
640void MemRegion::printPrettyAsExpr(raw_ostream &) const {
641 llvm_unreachable("This region cannot be printed pretty.");
642}
643
644bool NonParamVarRegion::canPrintPrettyAsExpr() const { return true; }
645
646void NonParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
647 os << getDecl()->getName();
648}
649
650bool ParamVarRegion::canPrintPrettyAsExpr() const { return true; }
651
652void ParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
653 assert(getDecl() &&
654 "`ParamVarRegion` support functions without `Decl` not implemented"
655 " yet.");
656 os << getDecl()->getName();
657}
658
659bool ObjCIvarRegion::canPrintPrettyAsExpr() const {
660 return true;
661}
662
663void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const {
664 os << getDecl()->getName();
665}
666
667bool FieldRegion::canPrintPretty() const {
668 return true;
669}
670
671bool FieldRegion::canPrintPrettyAsExpr() const {
672 return superRegion->canPrintPrettyAsExpr();
673}
674
675void FieldRegion::printPrettyAsExpr(raw_ostream &os) const {
676 assert(canPrintPrettyAsExpr());
677 superRegion->printPrettyAsExpr(os);
678 os << "." << getDecl()->getName();
679}
680
681void FieldRegion::printPretty(raw_ostream &os) const {
682 if (canPrintPrettyAsExpr()) {
683 os << "\'";
684 printPrettyAsExpr(os);
685 os << "'";
686 } else {
687 os << "field " << "\'" << getDecl()->getName() << "'";
688 }
689}
690
691bool CXXBaseObjectRegion::canPrintPrettyAsExpr() const {
692 return superRegion->canPrintPrettyAsExpr();
693}
694
695void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
696 superRegion->printPrettyAsExpr(os);
697}
698
699bool CXXDerivedObjectRegion::canPrintPrettyAsExpr() const {
700 return superRegion->canPrintPrettyAsExpr();
701}
702
703void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
704 superRegion->printPrettyAsExpr(os);
705}
706
707std::string MemRegion::getDescriptiveName(bool UseQuotes) const {
708 std::string VariableName;
709 std::string ArrayIndices;
710 const MemRegion *R = this;
711 SmallString<50> buf;
712 llvm::raw_svector_ostream os(buf);
713
714 // Obtain array indices to add them to the variable name.
715 const ElementRegion *ER = nullptr;
716 while ((ER = R->getAs<ElementRegion>())) {
717 // Index is a ConcreteInt.
718 if (auto CI = ER->getIndex().getAs<nonloc::ConcreteInt>()) {
719 llvm::SmallString<2> Idx;
720 CI->getValue().toString(Str&: Idx);
721 ArrayIndices = (llvm::Twine("[") + Idx.str() + "]" + ArrayIndices).str();
722 }
723 // Index is symbolic, but may have a descriptive name.
724 else {
725 auto SI = ER->getIndex().getAs<nonloc::SymbolVal>();
726 if (!SI)
727 return "";
728
729 const MemRegion *OR = SI->getAsSymbol()->getOriginRegion();
730 if (!OR)
731 return "";
732
733 std::string Idx = OR->getDescriptiveName(UseQuotes: false);
734 if (Idx.empty())
735 return "";
736
737 ArrayIndices = (llvm::Twine("[") + Idx + "]" + ArrayIndices).str();
738 }
739 R = ER->getSuperRegion();
740 }
741
742 // Get variable name.
743 if (R && R->canPrintPrettyAsExpr()) {
744 R->printPrettyAsExpr(os);
745 if (UseQuotes)
746 return (llvm::Twine("'") + os.str() + ArrayIndices + "'").str();
747 else
748 return (llvm::Twine(os.str()) + ArrayIndices).str();
749 }
750
751 return VariableName;
752}
753
754SourceRange MemRegion::sourceRange() const {
755 // Check for more specific regions first.
756 if (auto *FR = dyn_cast<FieldRegion>(Val: this)) {
757 return FR->getDecl()->getSourceRange();
758 }
759
760 if (auto *VR = dyn_cast<VarRegion>(Val: this->getBaseRegion())) {
761 return VR->getDecl()->getSourceRange();
762 }
763
764 // Return invalid source range (can be checked by client).
765 return {};
766}
767
768//===----------------------------------------------------------------------===//
769// MemRegionManager methods.
770//===----------------------------------------------------------------------===//
771
772DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR,
773 SValBuilder &SVB) const {
774 const auto *SR = cast<SubRegion>(Val: MR);
775 SymbolManager &SymMgr = SVB.getSymbolManager();
776
777 switch (SR->getKind()) {
778 case MemRegion::AllocaRegionKind:
779 case MemRegion::SymbolicRegionKind:
780 return nonloc::SymbolVal(SymMgr.getExtentSymbol(R: SR));
781 case MemRegion::StringRegionKind:
782 return SVB.makeIntVal(
783 integer: cast<StringRegion>(Val: SR)->getStringLiteral()->getByteLength() + 1,
784 type: SVB.getArrayIndexType());
785 case MemRegion::CompoundLiteralRegionKind:
786 case MemRegion::CXXBaseObjectRegionKind:
787 case MemRegion::CXXDerivedObjectRegionKind:
788 case MemRegion::CXXTempObjectRegionKind:
789 case MemRegion::CXXLifetimeExtendedObjectRegionKind:
790 case MemRegion::CXXThisRegionKind:
791 case MemRegion::ObjCIvarRegionKind:
792 case MemRegion::NonParamVarRegionKind:
793 case MemRegion::ParamVarRegionKind:
794 case MemRegion::ElementRegionKind:
795 case MemRegion::ObjCStringRegionKind: {
796 QualType Ty = cast<TypedValueRegion>(Val: SR)->getDesugaredValueType(Context&: Ctx);
797 if (isa<VariableArrayType>(Val: Ty))
798 return nonloc::SymbolVal(SymMgr.getExtentSymbol(R: SR));
799
800 if (Ty->isIncompleteType())
801 return UnknownVal();
802
803 return getElementExtent(Ty, SVB);
804 }
805 case MemRegion::FieldRegionKind: {
806 // Force callers to deal with bitfields explicitly.
807 if (cast<FieldRegion>(Val: SR)->getDecl()->isBitField())
808 return UnknownVal();
809
810 QualType Ty = cast<TypedValueRegion>(Val: SR)->getDesugaredValueType(Context&: Ctx);
811 const DefinedOrUnknownSVal Size = getElementExtent(Ty, SVB);
812
813 // We currently don't model flexible array members (FAMs), which are:
814 // - int array[]; of IncompleteArrayType
815 // - int array[0]; of ConstantArrayType with size 0
816 // - int array[1]; of ConstantArrayType with size 1
817 // https://gcc.gnu.org/onlinedocs/gcc/Zero-Length.html
818 const auto isFlexibleArrayMemberCandidate =
819 [this](const ArrayType *AT) -> bool {
820 if (!AT)
821 return false;
822
823 auto IsIncompleteArray = [](const ArrayType *AT) {
824 return isa<IncompleteArrayType>(Val: AT);
825 };
826 auto IsArrayOfZero = [](const ArrayType *AT) {
827 const auto *CAT = dyn_cast<ConstantArrayType>(Val: AT);
828 return CAT && CAT->isZeroSize();
829 };
830 auto IsArrayOfOne = [](const ArrayType *AT) {
831 const auto *CAT = dyn_cast<ConstantArrayType>(Val: AT);
832 return CAT && CAT->getSize() == 1;
833 };
834
835 using FAMKind = LangOptions::StrictFlexArraysLevelKind;
836 const FAMKind StrictFlexArraysLevel =
837 Ctx.getLangOpts().getStrictFlexArraysLevel();
838
839 // "Default": Any trailing array member is a FAM.
840 // Since we cannot tell at this point if this array is a trailing member
841 // or not, let's just do the same as for "OneZeroOrIncomplete".
842 if (StrictFlexArraysLevel == FAMKind::Default)
843 return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT);
844
845 if (StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
846 return IsArrayOfOne(AT) || IsArrayOfZero(AT) || IsIncompleteArray(AT);
847
848 if (StrictFlexArraysLevel == FAMKind::ZeroOrIncomplete)
849 return IsArrayOfZero(AT) || IsIncompleteArray(AT);
850
851 assert(StrictFlexArraysLevel == FAMKind::IncompleteOnly);
852 return IsIncompleteArray(AT);
853 };
854
855 if (isFlexibleArrayMemberCandidate(Ctx.getAsArrayType(T: Ty)))
856 return UnknownVal();
857
858 return Size;
859 }
860 // FIXME: The following are being used in 'SimpleSValBuilder' and in
861 // 'ArrayBoundChecker::checkLocation' because there is no symbol to
862 // represent the regions more appropriately.
863 case MemRegion::BlockDataRegionKind:
864 case MemRegion::BlockCodeRegionKind:
865 case MemRegion::FunctionCodeRegionKind:
866 return nonloc::SymbolVal(SymMgr.getExtentSymbol(R: SR));
867 default:
868 llvm_unreachable("Unhandled region");
869 }
870}
871
872template <typename REG>
873const REG *MemRegionManager::LazyAllocate(REG*& region) {
874 if (!region) {
875 region = new (A) REG(*this);
876 }
877
878 return region;
879}
880
881template <typename REG, typename ARG>
882const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) {
883 if (!region) {
884 region = new (A) REG(this, a);
885 }
886
887 return region;
888}
889
890const StackLocalsSpaceRegion*
891MemRegionManager::getStackLocalsRegion(const StackFrameContext *STC) {
892 assert(STC);
893 StackLocalsSpaceRegion *&R = StackLocalsSpaceRegions[STC];
894
895 if (R)
896 return R;
897
898 R = new (A) StackLocalsSpaceRegion(*this, STC);
899 return R;
900}
901
902const StackArgumentsSpaceRegion *
903MemRegionManager::getStackArgumentsRegion(const StackFrameContext *STC) {
904 assert(STC);
905 StackArgumentsSpaceRegion *&R = StackArgumentsSpaceRegions[STC];
906
907 if (R)
908 return R;
909
910 R = new (A) StackArgumentsSpaceRegion(*this, STC);
911 return R;
912}
913
914const GlobalsSpaceRegion
915*MemRegionManager::getGlobalsRegion(MemRegion::Kind K,
916 const CodeTextRegion *CR) {
917 if (!CR) {
918 if (K == MemRegion::GlobalSystemSpaceRegionKind)
919 return LazyAllocate(region&: SystemGlobals);
920 if (K == MemRegion::GlobalImmutableSpaceRegionKind)
921 return LazyAllocate(region&: ImmutableGlobals);
922 assert(K == MemRegion::GlobalInternalSpaceRegionKind);
923 return LazyAllocate(region&: InternalGlobals);
924 }
925
926 assert(K == MemRegion::StaticGlobalSpaceRegionKind);
927 StaticGlobalSpaceRegion *&R = StaticsGlobalSpaceRegions[CR];
928 if (R)
929 return R;
930
931 R = new (A) StaticGlobalSpaceRegion(*this, CR);
932 return R;
933}
934
935const HeapSpaceRegion *MemRegionManager::getHeapRegion() {
936 return LazyAllocate(region&: heap);
937}
938
939const UnknownSpaceRegion *MemRegionManager::getUnknownRegion() {
940 return LazyAllocate(region&: unknown);
941}
942
943const CodeSpaceRegion *MemRegionManager::getCodeRegion() {
944 return LazyAllocate(region&: code);
945}
946
947//===----------------------------------------------------------------------===//
948// Constructing regions.
949//===----------------------------------------------------------------------===//
950
951const StringRegion *MemRegionManager::getStringRegion(const StringLiteral *Str){
952 return getSubRegion<StringRegion>(
953 arg1: Str, superRegion: cast<GlobalInternalSpaceRegion>(Val: getGlobalsRegion()));
954}
955
956const ObjCStringRegion *
957MemRegionManager::getObjCStringRegion(const ObjCStringLiteral *Str){
958 return getSubRegion<ObjCStringRegion>(
959 arg1: Str, superRegion: cast<GlobalInternalSpaceRegion>(Val: getGlobalsRegion()));
960}
961
962/// Look through a chain of LocationContexts to either find the
963/// StackFrameContext that matches a DeclContext, or find a VarRegion
964/// for a variable captured by a block.
965static llvm::PointerUnion<const StackFrameContext *, const VarRegion *>
966getStackOrCaptureRegionForDeclContext(const LocationContext *LC,
967 const DeclContext *DC,
968 const VarDecl *VD) {
969 while (LC) {
970 if (const auto *SFC = dyn_cast<StackFrameContext>(Val: LC)) {
971 if (cast<DeclContext>(Val: SFC->getDecl()) == DC)
972 return SFC;
973 }
974 if (const auto *BC = dyn_cast<BlockInvocationContext>(Val: LC)) {
975 const auto *BR = static_cast<const BlockDataRegion *>(BC->getData());
976 // FIXME: This can be made more efficient.
977 for (auto Var : BR->referenced_vars()) {
978 const TypedValueRegion *OrigR = Var.getOriginalRegion();
979 if (const auto *VR = dyn_cast<VarRegion>(Val: OrigR)) {
980 if (VR->getDecl() == VD)
981 return cast<VarRegion>(Val: Var.getCapturedRegion());
982 }
983 }
984 }
985
986 LC = LC->getParent();
987 }
988 return (const StackFrameContext *)nullptr;
989}
990
991const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
992 const LocationContext *LC) {
993 const auto *PVD = dyn_cast<ParmVarDecl>(Val: D);
994 if (PVD) {
995 unsigned Index = PVD->getFunctionScopeIndex();
996 const StackFrameContext *SFC = LC->getStackFrame();
997 const Stmt *CallSite = SFC->getCallSite();
998 if (CallSite) {
999 const Decl *D = SFC->getDecl();
1000 if (const auto *FD = dyn_cast<FunctionDecl>(Val: D)) {
1001 if (Index < FD->param_size() && FD->parameters()[Index] == PVD)
1002 return getSubRegion<ParamVarRegion>(arg1: cast<Expr>(Val: CallSite), arg2: Index,
1003 superRegion: getStackArgumentsRegion(STC: SFC));
1004 } else if (const auto *BD = dyn_cast<BlockDecl>(Val: D)) {
1005 if (Index < BD->param_size() && BD->parameters()[Index] == PVD)
1006 return getSubRegion<ParamVarRegion>(arg1: cast<Expr>(Val: CallSite), arg2: Index,
1007 superRegion: getStackArgumentsRegion(STC: SFC));
1008 } else {
1009 return getSubRegion<ParamVarRegion>(arg1: cast<Expr>(Val: CallSite), arg2: Index,
1010 superRegion: getStackArgumentsRegion(STC: SFC));
1011 }
1012 }
1013 }
1014
1015 D = D->getCanonicalDecl();
1016 const MemRegion *sReg = nullptr;
1017
1018 if (D->hasGlobalStorage() && !D->isStaticLocal()) {
1019 QualType Ty = D->getType();
1020 assert(!Ty.isNull());
1021 if (Ty.isConstQualified()) {
1022 sReg = getGlobalsRegion(K: MemRegion::GlobalImmutableSpaceRegionKind);
1023 } else if (Ctx.getSourceManager().isInSystemHeader(Loc: D->getLocation())) {
1024 sReg = getGlobalsRegion(K: MemRegion::GlobalSystemSpaceRegionKind);
1025 } else {
1026 sReg = getGlobalsRegion(K: MemRegion::GlobalInternalSpaceRegionKind);
1027 }
1028
1029 // Finally handle static locals.
1030 } else {
1031 // FIXME: Once we implement scope handling, we will need to properly lookup
1032 // 'D' to the proper LocationContext.
1033 const DeclContext *DC = D->getDeclContext();
1034 llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V =
1035 getStackOrCaptureRegionForDeclContext(LC, DC, VD: D);
1036
1037 if (V.is<const VarRegion*>())
1038 return V.get<const VarRegion*>();
1039
1040 const auto *STC = V.get<const StackFrameContext *>();
1041
1042 if (!STC) {
1043 // FIXME: Assign a more sensible memory space to static locals
1044 // we see from within blocks that we analyze as top-level declarations.
1045 sReg = getUnknownRegion();
1046 } else {
1047 if (D->hasLocalStorage()) {
1048 sReg =
1049 isa<ParmVarDecl, ImplicitParamDecl>(Val: D)
1050 ? static_cast<const MemRegion *>(getStackArgumentsRegion(STC: STC))
1051 : static_cast<const MemRegion *>(getStackLocalsRegion(STC: STC));
1052 }
1053 else {
1054 assert(D->isStaticLocal());
1055 const Decl *STCD = STC->getDecl();
1056 if (isa<FunctionDecl, ObjCMethodDecl>(Val: STCD))
1057 sReg = getGlobalsRegion(K: MemRegion::StaticGlobalSpaceRegionKind,
1058 CR: getFunctionCodeRegion(FD: cast<NamedDecl>(Val: STCD)));
1059 else if (const auto *BD = dyn_cast<BlockDecl>(STCD)) {
1060 // FIXME: The fallback type here is totally bogus -- though it should
1061 // never be queried, it will prevent uniquing with the real
1062 // BlockCodeRegion. Ideally we'd fix the AST so that we always had a
1063 // signature.
1064 QualType T;
1065 if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten())
1066 T = TSI->getType();
1067 if (T.isNull())
1068 T = getContext().VoidTy;
1069 if (!T->getAs<FunctionType>()) {
1070 FunctionProtoType::ExtProtoInfo Ext;
1071 T = getContext().getFunctionType(ResultTy: T, Args: std::nullopt, EPI: Ext);
1072 }
1073 T = getContext().getBlockPointerType(T);
1074
1075 const BlockCodeRegion *BTR =
1076 getBlockCodeRegion(BD: BD, locTy: Ctx.getCanonicalType(T),
1077 AC: STC->getAnalysisDeclContext());
1078 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
1079 BTR);
1080 }
1081 else {
1082 sReg = getGlobalsRegion();
1083 }
1084 }
1085 }
1086 }
1087
1088 return getNonParamVarRegion(VD: D, superR: sReg);
1089}
1090
1091const NonParamVarRegion *
1092MemRegionManager::getNonParamVarRegion(const VarDecl *D,
1093 const MemRegion *superR) {
1094 // Prefer the definition over the canonical decl as the canonical form.
1095 D = D->getCanonicalDecl();
1096 if (const VarDecl *Def = D->getDefinition())
1097 D = Def;
1098 return getSubRegion<NonParamVarRegion>(arg1: D, superRegion: superR);
1099}
1100
1101const ParamVarRegion *
1102MemRegionManager::getParamVarRegion(const Expr *OriginExpr, unsigned Index,
1103 const LocationContext *LC) {
1104 const StackFrameContext *SFC = LC->getStackFrame();
1105 assert(SFC);
1106 return getSubRegion<ParamVarRegion>(arg1: OriginExpr, arg2: Index,
1107 superRegion: getStackArgumentsRegion(STC: SFC));
1108}
1109
1110const BlockDataRegion *
1111MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC,
1112 const LocationContext *LC,
1113 unsigned blockCount) {
1114 const MemSpaceRegion *sReg = nullptr;
1115 const BlockDecl *BD = BC->getDecl();
1116 if (!BD->hasCaptures()) {
1117 // This handles 'static' blocks.
1118 sReg = getGlobalsRegion(K: MemRegion::GlobalImmutableSpaceRegionKind);
1119 }
1120 else {
1121 bool IsArcManagedBlock = Ctx.getLangOpts().ObjCAutoRefCount;
1122
1123 // ARC managed blocks can be initialized on stack or directly in heap
1124 // depending on the implementations. So we initialize them with
1125 // UnknownRegion.
1126 if (!IsArcManagedBlock && LC) {
1127 // FIXME: Once we implement scope handling, we want the parent region
1128 // to be the scope.
1129 const StackFrameContext *STC = LC->getStackFrame();
1130 assert(STC);
1131 sReg = getStackLocalsRegion(STC);
1132 } else {
1133 // We allow 'LC' to be NULL for cases where want BlockDataRegions
1134 // without context-sensitivity.
1135 sReg = getUnknownRegion();
1136 }
1137 }
1138
1139 return getSubRegion<BlockDataRegion>(arg1: BC, arg2: LC, arg3: blockCount, superRegion: sReg);
1140}
1141
1142const CompoundLiteralRegion*
1143MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
1144 const LocationContext *LC) {
1145 const MemSpaceRegion *sReg = nullptr;
1146
1147 if (CL->isFileScope())
1148 sReg = getGlobalsRegion();
1149 else {
1150 const StackFrameContext *STC = LC->getStackFrame();
1151 assert(STC);
1152 sReg = getStackLocalsRegion(STC);
1153 }
1154
1155 return getSubRegion<CompoundLiteralRegion>(arg1: CL, superRegion: sReg);
1156}
1157
1158const ElementRegion*
1159MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
1160 const SubRegion* superRegion,
1161 ASTContext &Ctx){
1162 QualType T = Ctx.getCanonicalType(T: elementType).getUnqualifiedType();
1163
1164 llvm::FoldingSetNodeID ID;
1165 ElementRegion::ProfileRegion(ID, ElementType: T, Idx, superRegion);
1166
1167 void *InsertPos;
1168 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
1169 auto *R = cast_or_null<ElementRegion>(Val: data);
1170
1171 if (!R) {
1172 R = new (A) ElementRegion(T, Idx, superRegion);
1173 Regions.InsertNode(R, InsertPos);
1174 }
1175
1176 return R;
1177}
1178
1179const FunctionCodeRegion *
1180MemRegionManager::getFunctionCodeRegion(const NamedDecl *FD) {
1181 // To think: should we canonicalize the declaration here?
1182 return getSubRegion<FunctionCodeRegion>(arg1: FD, superRegion: getCodeRegion());
1183}
1184
1185const BlockCodeRegion *
1186MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy,
1187 AnalysisDeclContext *AC) {
1188 return getSubRegion<BlockCodeRegion>(arg1: BD, arg2: locTy, arg3: AC, superRegion: getCodeRegion());
1189}
1190
1191const SymbolicRegion *
1192MemRegionManager::getSymbolicRegion(SymbolRef sym,
1193 const MemSpaceRegion *MemSpace) {
1194 if (MemSpace == nullptr)
1195 MemSpace = getUnknownRegion();
1196 return getSubRegion<SymbolicRegion>(arg1: sym, superRegion: MemSpace);
1197}
1198
1199const SymbolicRegion *MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym) {
1200 return getSubRegion<SymbolicRegion>(arg1: Sym, superRegion: getHeapRegion());
1201}
1202
1203const FieldRegion*
1204MemRegionManager::getFieldRegion(const FieldDecl *d,
1205 const SubRegion* superRegion){
1206 return getSubRegion<FieldRegion>(arg1: d, superRegion);
1207}
1208
1209const ObjCIvarRegion*
1210MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d,
1211 const SubRegion* superRegion) {
1212 return getSubRegion<ObjCIvarRegion>(arg1: d, superRegion);
1213}
1214
1215const CXXTempObjectRegion*
1216MemRegionManager::getCXXTempObjectRegion(Expr const *E,
1217 LocationContext const *LC) {
1218 const StackFrameContext *SFC = LC->getStackFrame();
1219 assert(SFC);
1220 return getSubRegion<CXXTempObjectRegion>(arg1: E, superRegion: getStackLocalsRegion(STC: SFC));
1221}
1222
1223const CXXLifetimeExtendedObjectRegion *
1224MemRegionManager::getCXXLifetimeExtendedObjectRegion(
1225 const Expr *Ex, const ValueDecl *VD, const LocationContext *LC) {
1226 const StackFrameContext *SFC = LC->getStackFrame();
1227 assert(SFC);
1228 return getSubRegion<CXXLifetimeExtendedObjectRegion>(
1229 arg1: Ex, arg2: VD, superRegion: getStackLocalsRegion(STC: SFC));
1230}
1231
1232const CXXLifetimeExtendedObjectRegion *
1233MemRegionManager::getCXXStaticLifetimeExtendedObjectRegion(
1234 const Expr *Ex, const ValueDecl *VD) {
1235 return getSubRegion<CXXLifetimeExtendedObjectRegion>(
1236 arg1: Ex, arg2: VD,
1237 superRegion: getGlobalsRegion(K: MemRegion::GlobalInternalSpaceRegionKind, CR: nullptr));
1238}
1239
1240/// Checks whether \p BaseClass is a valid virtual or direct non-virtual base
1241/// class of the type of \p Super.
1242static bool isValidBaseClass(const CXXRecordDecl *BaseClass,
1243 const TypedValueRegion *Super,
1244 bool IsVirtual) {
1245 BaseClass = BaseClass->getCanonicalDecl();
1246
1247 const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl();
1248 if (!Class)
1249 return true;
1250
1251 if (IsVirtual)
1252 return Class->isVirtuallyDerivedFrom(Base: BaseClass);
1253
1254 for (const auto &I : Class->bases()) {
1255 if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass)
1256 return true;
1257 }
1258
1259 return false;
1260}
1261
1262const CXXBaseObjectRegion *
1263MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
1264 const SubRegion *Super,
1265 bool IsVirtual) {
1266 if (isa<TypedValueRegion>(Val: Super)) {
1267 assert(isValidBaseClass(RD, cast<TypedValueRegion>(Super), IsVirtual));
1268 (void)&isValidBaseClass;
1269
1270 if (IsVirtual) {
1271 // Virtual base regions should not be layered, since the layout rules
1272 // are different.
1273 while (const auto *Base = dyn_cast<CXXBaseObjectRegion>(Val: Super))
1274 Super = cast<SubRegion>(Val: Base->getSuperRegion());
1275 assert(Super && !isa<MemSpaceRegion>(Super));
1276 }
1277 }
1278
1279 return getSubRegion<CXXBaseObjectRegion>(arg1: RD, arg2: IsVirtual, superRegion: Super);
1280}
1281
1282const CXXDerivedObjectRegion *
1283MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl *RD,
1284 const SubRegion *Super) {
1285 return getSubRegion<CXXDerivedObjectRegion>(arg1: RD, superRegion: Super);
1286}
1287
1288const CXXThisRegion*
1289MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
1290 const LocationContext *LC) {
1291 const auto *PT = thisPointerTy->getAs<PointerType>();
1292 assert(PT);
1293 // Inside the body of the operator() of a lambda a this expr might refer to an
1294 // object in one of the parent location contexts.
1295 const auto *D = dyn_cast<CXXMethodDecl>(Val: LC->getDecl());
1296 // FIXME: when operator() of lambda is analyzed as a top level function and
1297 // 'this' refers to a this to the enclosing scope, there is no right region to
1298 // return.
1299 while (!LC->inTopFrame() && (!D || D->isStatic() ||
1300 PT != D->getThisType()->getAs<PointerType>())) {
1301 LC = LC->getParent();
1302 D = dyn_cast<CXXMethodDecl>(Val: LC->getDecl());
1303 }
1304 const StackFrameContext *STC = LC->getStackFrame();
1305 assert(STC);
1306 return getSubRegion<CXXThisRegion>(arg1: PT, superRegion: getStackArgumentsRegion(STC));
1307}
1308
1309const AllocaRegion*
1310MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt,
1311 const LocationContext *LC) {
1312 const StackFrameContext *STC = LC->getStackFrame();
1313 assert(STC);
1314 return getSubRegion<AllocaRegion>(arg1: E, arg2: cnt, superRegion: getStackLocalsRegion(STC));
1315}
1316
1317const MemSpaceRegion *MemRegion::getMemorySpace() const {
1318 const MemRegion *R = this;
1319 const auto *SR = dyn_cast<SubRegion>(Val: this);
1320
1321 while (SR) {
1322 R = SR->getSuperRegion();
1323 SR = dyn_cast<SubRegion>(Val: R);
1324 }
1325
1326 return cast<MemSpaceRegion>(Val: R);
1327}
1328
1329bool MemRegion::hasStackStorage() const {
1330 return isa<StackSpaceRegion>(Val: getMemorySpace());
1331}
1332
1333bool MemRegion::hasStackNonParametersStorage() const {
1334 return isa<StackLocalsSpaceRegion>(Val: getMemorySpace());
1335}
1336
1337bool MemRegion::hasStackParametersStorage() const {
1338 return isa<StackArgumentsSpaceRegion>(Val: getMemorySpace());
1339}
1340
1341// Strips away all elements and fields.
1342// Returns the base region of them.
1343const MemRegion *MemRegion::getBaseRegion() const {
1344 const MemRegion *R = this;
1345 while (true) {
1346 switch (R->getKind()) {
1347 case MemRegion::ElementRegionKind:
1348 case MemRegion::FieldRegionKind:
1349 case MemRegion::ObjCIvarRegionKind:
1350 case MemRegion::CXXBaseObjectRegionKind:
1351 case MemRegion::CXXDerivedObjectRegionKind:
1352 R = cast<SubRegion>(Val: R)->getSuperRegion();
1353 continue;
1354 default:
1355 break;
1356 }
1357 break;
1358 }
1359 return R;
1360}
1361
1362// Returns the region of the root class of a C++ class hierarchy.
1363const MemRegion *MemRegion::getMostDerivedObjectRegion() const {
1364 const MemRegion *R = this;
1365 while (const auto *BR = dyn_cast<CXXBaseObjectRegion>(Val: R))
1366 R = BR->getSuperRegion();
1367 return R;
1368}
1369
1370bool MemRegion::isSubRegionOf(const MemRegion *) const {
1371 return false;
1372}
1373
1374//===----------------------------------------------------------------------===//
1375// View handling.
1376//===----------------------------------------------------------------------===//
1377
1378const MemRegion *MemRegion::StripCasts(bool StripBaseAndDerivedCasts) const {
1379 const MemRegion *R = this;
1380 while (true) {
1381 switch (R->getKind()) {
1382 case ElementRegionKind: {
1383 const auto *ER = cast<ElementRegion>(Val: R);
1384 if (!ER->getIndex().isZeroConstant())
1385 return R;
1386 R = ER->getSuperRegion();
1387 break;
1388 }
1389 case CXXBaseObjectRegionKind:
1390 case CXXDerivedObjectRegionKind:
1391 if (!StripBaseAndDerivedCasts)
1392 return R;
1393 R = cast<TypedValueRegion>(Val: R)->getSuperRegion();
1394 break;
1395 default:
1396 return R;
1397 }
1398 }
1399}
1400
1401const SymbolicRegion *MemRegion::getSymbolicBase() const {
1402 const auto *SubR = dyn_cast<SubRegion>(Val: this);
1403
1404 while (SubR) {
1405 if (const auto *SymR = dyn_cast<SymbolicRegion>(Val: SubR))
1406 return SymR;
1407 SubR = dyn_cast<SubRegion>(Val: SubR->getSuperRegion());
1408 }
1409 return nullptr;
1410}
1411
1412RegionRawOffset ElementRegion::getAsArrayOffset() const {
1413 int64_t offset = 0;
1414 const ElementRegion *ER = this;
1415 const MemRegion *superR = nullptr;
1416 ASTContext &C = getContext();
1417
1418 // FIXME: Handle multi-dimensional arrays.
1419
1420 while (ER) {
1421 superR = ER->getSuperRegion();
1422
1423 // FIXME: generalize to symbolic offsets.
1424 SVal index = ER->getIndex();
1425 if (auto CI = index.getAs<nonloc::ConcreteInt>()) {
1426 // Update the offset.
1427 int64_t i = CI->getValue().getSExtValue();
1428
1429 if (i != 0) {
1430 QualType elemType = ER->getElementType();
1431
1432 // If we are pointing to an incomplete type, go no further.
1433 if (elemType->isIncompleteType()) {
1434 superR = ER;
1435 break;
1436 }
1437
1438 int64_t size = C.getTypeSizeInChars(T: elemType).getQuantity();
1439 if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) {
1440 offset = *NewOffset;
1441 } else {
1442 LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
1443 << "offset overflowing, returning unknown\n");
1444
1445 return nullptr;
1446 }
1447 }
1448
1449 // Go to the next ElementRegion (if any).
1450 ER = dyn_cast<ElementRegion>(Val: superR);
1451 continue;
1452 }
1453
1454 return nullptr;
1455 }
1456
1457 assert(superR && "super region cannot be NULL");
1458 return RegionRawOffset(superR, CharUnits::fromQuantity(Quantity: offset));
1459}
1460
1461/// Returns true if \p Base is an immediate base class of \p Child
1462static bool isImmediateBase(const CXXRecordDecl *Child,
1463 const CXXRecordDecl *Base) {
1464 assert(Child && "Child must not be null");
1465 // Note that we do NOT canonicalize the base class here, because
1466 // ASTRecordLayout doesn't either. If that leads us down the wrong path,
1467 // so be it; at least we won't crash.
1468 for (const auto &I : Child->bases()) {
1469 if (I.getType()->getAsCXXRecordDecl() == Base)
1470 return true;
1471 }
1472
1473 return false;
1474}
1475
1476static RegionOffset calculateOffset(const MemRegion *R) {
1477 const MemRegion *SymbolicOffsetBase = nullptr;
1478 int64_t Offset = 0;
1479
1480 while (true) {
1481 switch (R->getKind()) {
1482 case MemRegion::CodeSpaceRegionKind:
1483 case MemRegion::StackLocalsSpaceRegionKind:
1484 case MemRegion::StackArgumentsSpaceRegionKind:
1485 case MemRegion::HeapSpaceRegionKind:
1486 case MemRegion::UnknownSpaceRegionKind:
1487 case MemRegion::StaticGlobalSpaceRegionKind:
1488 case MemRegion::GlobalInternalSpaceRegionKind:
1489 case MemRegion::GlobalSystemSpaceRegionKind:
1490 case MemRegion::GlobalImmutableSpaceRegionKind:
1491 // Stores can bind directly to a region space to set a default value.
1492 assert(Offset == 0 && !SymbolicOffsetBase);
1493 goto Finish;
1494
1495 case MemRegion::FunctionCodeRegionKind:
1496 case MemRegion::BlockCodeRegionKind:
1497 case MemRegion::BlockDataRegionKind:
1498 // These will never have bindings, but may end up having values requested
1499 // if the user does some strange casting.
1500 if (Offset != 0)
1501 SymbolicOffsetBase = R;
1502 goto Finish;
1503
1504 case MemRegion::SymbolicRegionKind:
1505 case MemRegion::AllocaRegionKind:
1506 case MemRegion::CompoundLiteralRegionKind:
1507 case MemRegion::CXXThisRegionKind:
1508 case MemRegion::StringRegionKind:
1509 case MemRegion::ObjCStringRegionKind:
1510 case MemRegion::NonParamVarRegionKind:
1511 case MemRegion::ParamVarRegionKind:
1512 case MemRegion::CXXTempObjectRegionKind:
1513 case MemRegion::CXXLifetimeExtendedObjectRegionKind:
1514 // Usual base regions.
1515 goto Finish;
1516
1517 case MemRegion::ObjCIvarRegionKind:
1518 // This is a little strange, but it's a compromise between
1519 // ObjCIvarRegions having unknown compile-time offsets (when using the
1520 // non-fragile runtime) and yet still being distinct, non-overlapping
1521 // regions. Thus we treat them as "like" base regions for the purposes
1522 // of computing offsets.
1523 goto Finish;
1524
1525 case MemRegion::CXXBaseObjectRegionKind: {
1526 const auto *BOR = cast<CXXBaseObjectRegion>(Val: R);
1527 R = BOR->getSuperRegion();
1528
1529 QualType Ty;
1530 bool RootIsSymbolic = false;
1531 if (const auto *TVR = dyn_cast<TypedValueRegion>(Val: R)) {
1532 Ty = TVR->getDesugaredValueType(Context&: R->getContext());
1533 } else if (const auto *SR = dyn_cast<SymbolicRegion>(Val: R)) {
1534 // If our base region is symbolic, we don't know what type it really is.
1535 // Pretend the type of the symbol is the true dynamic type.
1536 // (This will at least be self-consistent for the life of the symbol.)
1537 Ty = SR->getPointeeStaticType();
1538 RootIsSymbolic = true;
1539 }
1540
1541 const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl();
1542 if (!Child) {
1543 // We cannot compute the offset of the base class.
1544 SymbolicOffsetBase = R;
1545 } else {
1546 if (RootIsSymbolic) {
1547 // Base layers on symbolic regions may not be type-correct.
1548 // Double-check the inheritance here, and revert to a symbolic offset
1549 // if it's invalid (e.g. due to a reinterpret_cast).
1550 if (BOR->isVirtual()) {
1551 if (!Child->isVirtuallyDerivedFrom(Base: BOR->getDecl()))
1552 SymbolicOffsetBase = R;
1553 } else {
1554 if (!isImmediateBase(Child, Base: BOR->getDecl()))
1555 SymbolicOffsetBase = R;
1556 }
1557 }
1558 }
1559
1560 // Don't bother calculating precise offsets if we already have a
1561 // symbolic offset somewhere in the chain.
1562 if (SymbolicOffsetBase)
1563 continue;
1564
1565 CharUnits BaseOffset;
1566 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(Child);
1567 if (BOR->isVirtual())
1568 BaseOffset = Layout.getVBaseClassOffset(VBase: BOR->getDecl());
1569 else
1570 BaseOffset = Layout.getBaseClassOffset(Base: BOR->getDecl());
1571
1572 // The base offset is in chars, not in bits.
1573 Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth();
1574 break;
1575 }
1576
1577 case MemRegion::CXXDerivedObjectRegionKind: {
1578 // TODO: Store the base type in the CXXDerivedObjectRegion and use it.
1579 goto Finish;
1580 }
1581
1582 case MemRegion::ElementRegionKind: {
1583 const auto *ER = cast<ElementRegion>(Val: R);
1584 R = ER->getSuperRegion();
1585
1586 QualType EleTy = ER->getValueType();
1587 if (EleTy->isIncompleteType()) {
1588 // We cannot compute the offset of the base class.
1589 SymbolicOffsetBase = R;
1590 continue;
1591 }
1592
1593 SVal Index = ER->getIndex();
1594 if (std::optional<nonloc::ConcreteInt> CI =
1595 Index.getAs<nonloc::ConcreteInt>()) {
1596 // Don't bother calculating precise offsets if we already have a
1597 // symbolic offset somewhere in the chain.
1598 if (SymbolicOffsetBase)
1599 continue;
1600
1601 int64_t i = CI->getValue().getSExtValue();
1602 // This type size is in bits.
1603 Offset += i * R->getContext().getTypeSize(T: EleTy);
1604 } else {
1605 // We cannot compute offset for non-concrete index.
1606 SymbolicOffsetBase = R;
1607 }
1608 break;
1609 }
1610 case MemRegion::FieldRegionKind: {
1611 const auto *FR = cast<FieldRegion>(Val: R);
1612 R = FR->getSuperRegion();
1613 assert(R);
1614
1615 const RecordDecl *RD = FR->getDecl()->getParent();
1616 if (RD->isUnion() || !RD->isCompleteDefinition()) {
1617 // We cannot compute offset for incomplete type.
1618 // For unions, we could treat everything as offset 0, but we'd rather
1619 // treat each field as a symbolic offset so they aren't stored on top
1620 // of each other, since we depend on things in typed regions actually
1621 // matching their types.
1622 SymbolicOffsetBase = R;
1623 }
1624
1625 // Don't bother calculating precise offsets if we already have a
1626 // symbolic offset somewhere in the chain.
1627 if (SymbolicOffsetBase)
1628 continue;
1629
1630 // Get the field number.
1631 unsigned idx = 0;
1632 for (RecordDecl::field_iterator FI = RD->field_begin(),
1633 FE = RD->field_end(); FI != FE; ++FI, ++idx) {
1634 if (FR->getDecl() == *FI)
1635 break;
1636 }
1637 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(D: RD);
1638 // This is offset in bits.
1639 Offset += Layout.getFieldOffset(FieldNo: idx);
1640 break;
1641 }
1642 }
1643 }
1644
1645 Finish:
1646 if (SymbolicOffsetBase)
1647 return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic);
1648 return RegionOffset(R, Offset);
1649}
1650
1651RegionOffset MemRegion::getAsOffset() const {
1652 if (!cachedOffset)
1653 cachedOffset = calculateOffset(R: this);
1654 return *cachedOffset;
1655}
1656
1657//===----------------------------------------------------------------------===//
1658// BlockDataRegion
1659//===----------------------------------------------------------------------===//
1660
1661std::pair<const VarRegion *, const VarRegion *>
1662BlockDataRegion::getCaptureRegions(const VarDecl *VD) {
1663 MemRegionManager &MemMgr = getMemRegionManager();
1664 const VarRegion *VR = nullptr;
1665 const VarRegion *OriginalVR = nullptr;
1666
1667 if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) {
1668 VR = MemMgr.getNonParamVarRegion(D: VD, superR: this);
1669 OriginalVR = MemMgr.getVarRegion(D: VD, LC);
1670 }
1671 else {
1672 if (LC) {
1673 VR = MemMgr.getVarRegion(D: VD, LC);
1674 OriginalVR = VR;
1675 }
1676 else {
1677 VR = MemMgr.getNonParamVarRegion(D: VD, superR: MemMgr.getUnknownRegion());
1678 OriginalVR = MemMgr.getVarRegion(D: VD, LC);
1679 }
1680 }
1681 return std::make_pair(x&: VR, y&: OriginalVR);
1682}
1683
1684void BlockDataRegion::LazyInitializeReferencedVars() {
1685 if (ReferencedVars)
1686 return;
1687
1688 AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext();
1689 const auto &ReferencedBlockVars = AC->getReferencedBlockVars(BD: BC->getDecl());
1690 auto NumBlockVars =
1691 std::distance(first: ReferencedBlockVars.begin(), last: ReferencedBlockVars.end());
1692
1693 if (NumBlockVars == 0) {
1694 ReferencedVars = (void*) 0x1;
1695 return;
1696 }
1697
1698 MemRegionManager &MemMgr = getMemRegionManager();
1699 llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
1700 BumpVectorContext BC(A);
1701
1702 using VarVec = BumpVector<const MemRegion *>;
1703
1704 auto *BV = new (A) VarVec(BC, NumBlockVars);
1705 auto *BVOriginal = new (A) VarVec(BC, NumBlockVars);
1706
1707 for (const auto *VD : ReferencedBlockVars) {
1708 const VarRegion *VR = nullptr;
1709 const VarRegion *OriginalVR = nullptr;
1710 std::tie(args&: VR, args&: OriginalVR) = getCaptureRegions(VD);
1711 assert(VR);
1712 assert(OriginalVR);
1713 BV->push_back(Elt: VR, C&: BC);
1714 BVOriginal->push_back(Elt: OriginalVR, C&: BC);
1715 }
1716
1717 ReferencedVars = BV;
1718 OriginalVars = BVOriginal;
1719}
1720
1721BlockDataRegion::referenced_vars_iterator
1722BlockDataRegion::referenced_vars_begin() const {
1723 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
1724
1725 auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
1726
1727 if (Vec == (void*) 0x1)
1728 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
1729
1730 auto *VecOriginal =
1731 static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
1732
1733 return BlockDataRegion::referenced_vars_iterator(Vec->begin(),
1734 VecOriginal->begin());
1735}
1736
1737BlockDataRegion::referenced_vars_iterator
1738BlockDataRegion::referenced_vars_end() const {
1739 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
1740
1741 auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
1742
1743 if (Vec == (void*) 0x1)
1744 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
1745
1746 auto *VecOriginal =
1747 static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
1748
1749 return BlockDataRegion::referenced_vars_iterator(Vec->end(),
1750 VecOriginal->end());
1751}
1752
1753llvm::iterator_range<BlockDataRegion::referenced_vars_iterator>
1754BlockDataRegion::referenced_vars() const {
1755 return llvm::make_range(x: referenced_vars_begin(), y: referenced_vars_end());
1756}
1757
1758const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const {
1759 for (const auto &I : referenced_vars()) {
1760 if (I.getCapturedRegion() == R)
1761 return I.getOriginalRegion();
1762 }
1763 return nullptr;
1764}
1765
1766//===----------------------------------------------------------------------===//
1767// RegionAndSymbolInvalidationTraits
1768//===----------------------------------------------------------------------===//
1769
1770void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym,
1771 InvalidationKinds IK) {
1772 SymTraitsMap[Sym] |= IK;
1773}
1774
1775void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR,
1776 InvalidationKinds IK) {
1777 assert(MR);
1778 if (const auto *SR = dyn_cast<SymbolicRegion>(Val: MR))
1779 setTrait(Sym: SR->getSymbol(), IK);
1780 else
1781 MRTraitsMap[MR] |= IK;
1782}
1783
1784bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym,
1785 InvalidationKinds IK) const {
1786 const_symbol_iterator I = SymTraitsMap.find(Val: Sym);
1787 if (I != SymTraitsMap.end())
1788 return I->second & IK;
1789
1790 return false;
1791}
1792
1793bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion *MR,
1794 InvalidationKinds IK) const {
1795 if (!MR)
1796 return false;
1797
1798 if (const auto *SR = dyn_cast<SymbolicRegion>(Val: MR))
1799 return hasTrait(Sym: SR->getSymbol(), IK);
1800
1801 const_region_iterator I = MRTraitsMap.find(Val: MR);
1802 if (I != MRTraitsMap.end())
1803 return I->second & IK;
1804
1805 return false;
1806}
1807

source code of clang/lib/StaticAnalyzer/Core/MemRegion.cpp