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