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

Provided by KDAB

Privacy Policy
Update your C++ knowledge – Modern C++11/14/17 Training
Find out more

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