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