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