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
57 using namespace clang;
58 using namespace ento;
59
60 #define DEBUG_TYPE "MemRegion"
61
REGISTER_MAP_WITH_PROGRAMSTATE(MemSpacesMap,const MemRegion *,const MemSpaceRegion *)62 REGISTER_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>(R);
71 return TyReg && TyReg->getValueType()->isReferenceType();
72 }
73
74 template <typename RegionTy, typename SuperTy, typename Arg1Ty>
getSubRegion(const Arg1Ty arg1,const SuperTy * superRegion)75 RegionTy* 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
91 template <typename RegionTy, typename SuperTy, typename Arg1Ty, typename Arg2Ty>
getSubRegion(const Arg1Ty arg1,const Arg2Ty arg2,const SuperTy * superRegion)92 RegionTy* 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
108 template <typename RegionTy, typename SuperTy,
109 typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
getSubRegion(const Arg1Ty arg1,const Arg2Ty arg2,const Arg3Ty arg3,const SuperTy * superRegion)110 RegionTy* 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
131 MemRegion::~MemRegion() = default;
132
133 // All regions and their data are BumpPtrAllocated. No need to call their
134 // destructors.
135 MemRegionManager::~MemRegionManager() = default;
136
137 //===----------------------------------------------------------------------===//
138 // Basic methods.
139 //===----------------------------------------------------------------------===//
140
isSubRegionOf(const MemRegion * R) const141 bool 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>(r))
147 r = sr->getSuperRegion();
148 else
149 break;
150 } while (r != nullptr);
151 return false;
152 }
153
getMemRegionManager() const154 MemRegionManager &SubRegion::getMemRegionManager() const {
155 const SubRegion* r = this;
156 do {
157 const MemRegion *superRegion = r->getSuperRegion();
158 if (const auto *sr = dyn_cast<SubRegion>(superRegion)) {
159 r = sr;
160 continue;
161 }
162 return superRegion->getMemRegionManager();
163 } while (true);
164 }
165
getStackFrame() const166 const StackFrameContext *VarRegion::getStackFrame() const {
167 const auto *SSR = dyn_cast<StackSpaceRegion>(getRawMemorySpace());
168 return SSR ? SSR->getStackFrame() : nullptr;
169 }
170
171 const StackFrameContext *
getStackFrame() const172 CXXLifetimeExtendedObjectRegion::getStackFrame() const {
173 const auto *SSR = dyn_cast<StackSpaceRegion>(getRawMemorySpace());
174 return SSR ? SSR->getStackFrame() : nullptr;
175 }
176
getStackFrame() const177 const StackFrameContext *CXXTempObjectRegion::getStackFrame() const {
178 assert(isa<StackSpaceRegion>(getRawMemorySpace()) &&
179 "A temporary object can only be allocated on the stack");
180 return cast<StackSpaceRegion>(getRawMemorySpace())->getStackFrame();
181 }
182
ObjCIvarRegion(const ObjCIvarDecl * ivd,const SubRegion * sReg)183 ObjCIvarRegion::ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg)
184 : DeclRegion(sReg, ObjCIvarRegionKind), IVD(ivd) {
185 assert(IVD);
186 }
187
getDecl() const188 const ObjCIvarDecl *ObjCIvarRegion::getDecl() const { return IVD; }
189
getValueType() const190 QualType ObjCIvarRegion::getValueType() const {
191 return getDecl()->getType();
192 }
193
getValueType() const194 QualType CXXBaseObjectRegion::getValueType() const {
195 return QualType(getDecl()->getTypeForDecl(), 0);
196 }
197
getValueType() const198 QualType CXXDerivedObjectRegion::getValueType() const {
199 return QualType(getDecl()->getTypeForDecl(), 0);
200 }
201
getValueType() const202 QualType ParamVarRegion::getValueType() const {
203 assert(getDecl() &&
204 "`ParamVarRegion` support functions without `Decl` not implemented"
205 " yet.");
206 return getDecl()->getType();
207 }
208
getDecl() const209 const ParmVarDecl *ParamVarRegion::getDecl() const {
210 const Decl *D = getStackFrame()->getDecl();
211
212 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
213 assert(Index < FD->param_size());
214 return FD->parameters()[Index];
215 } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
216 assert(Index < BD->param_size());
217 return BD->parameters()[Index];
218 } else if (const auto *MD = dyn_cast<ObjCMethodDecl>(D)) {
219 assert(Index < MD->param_size());
220 return MD->parameters()[Index];
221 } else if (const auto *CD = dyn_cast<CXXConstructorDecl>(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
Profile(llvm::FoldingSetNodeID & ID) const233 void MemSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
234 ID.AddInteger(static_cast<unsigned>(getKind()));
235 }
236
Profile(llvm::FoldingSetNodeID & ID) const237 void StackSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
238 ID.AddInteger(static_cast<unsigned>(getKind()));
239 ID.AddPointer(getStackFrame());
240 }
241
Profile(llvm::FoldingSetNodeID & ID) const242 void StaticGlobalSpaceRegion::Profile(llvm::FoldingSetNodeID &ID) const {
243 ID.AddInteger(static_cast<unsigned>(getKind()));
244 ID.AddPointer(getCodeRegion());
245 }
246
ProfileRegion(llvm::FoldingSetNodeID & ID,const StringLiteral * Str,const MemRegion * superRegion)247 void StringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
248 const StringLiteral *Str,
249 const MemRegion *superRegion) {
250 ID.AddInteger(static_cast<unsigned>(StringRegionKind));
251 ID.AddPointer(Str);
252 ID.AddPointer(superRegion);
253 }
254
ProfileRegion(llvm::FoldingSetNodeID & ID,const ObjCStringLiteral * Str,const MemRegion * superRegion)255 void ObjCStringRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
256 const ObjCStringLiteral *Str,
257 const MemRegion *superRegion) {
258 ID.AddInteger(static_cast<unsigned>(ObjCStringRegionKind));
259 ID.AddPointer(Str);
260 ID.AddPointer(superRegion);
261 }
262
ProfileRegion(llvm::FoldingSetNodeID & ID,const Expr * Ex,unsigned cnt,const MemRegion * superRegion)263 void AllocaRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
264 const Expr *Ex, unsigned cnt,
265 const MemRegion *superRegion) {
266 ID.AddInteger(static_cast<unsigned>(AllocaRegionKind));
267 ID.AddPointer(Ex);
268 ID.AddInteger(cnt);
269 ID.AddPointer(superRegion);
270 }
271
Profile(llvm::FoldingSetNodeID & ID) const272 void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
273 ProfileRegion(ID, Ex, Cnt, superRegion);
274 }
275
Profile(llvm::FoldingSetNodeID & ID) const276 void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
277 CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
278 }
279
ProfileRegion(llvm::FoldingSetNodeID & ID,const CompoundLiteralExpr * CL,const MemRegion * superRegion)280 void CompoundLiteralRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
281 const CompoundLiteralExpr *CL,
282 const MemRegion* superRegion) {
283 ID.AddInteger(static_cast<unsigned>(CompoundLiteralRegionKind));
284 ID.AddPointer(CL);
285 ID.AddPointer(superRegion);
286 }
287
ProfileRegion(llvm::FoldingSetNodeID & ID,const PointerType * PT,const MemRegion * sRegion)288 void CXXThisRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
289 const PointerType *PT,
290 const MemRegion *sRegion) {
291 ID.AddInteger(static_cast<unsigned>(CXXThisRegionKind));
292 ID.AddPointer(PT);
293 ID.AddPointer(sRegion);
294 }
295
Profile(llvm::FoldingSetNodeID & ID) const296 void CXXThisRegion::Profile(llvm::FoldingSetNodeID &ID) const {
297 CXXThisRegion::ProfileRegion(ID, ThisPointerTy, superRegion);
298 }
299
Profile(llvm::FoldingSetNodeID & ID) const300 void FieldRegion::Profile(llvm::FoldingSetNodeID &ID) const {
301 ProfileRegion(ID, getDecl(), superRegion);
302 }
303
ProfileRegion(llvm::FoldingSetNodeID & ID,const ObjCIvarDecl * ivd,const MemRegion * superRegion)304 void ObjCIvarRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
305 const ObjCIvarDecl *ivd,
306 const MemRegion* superRegion) {
307 ID.AddInteger(static_cast<unsigned>(ObjCIvarRegionKind));
308 ID.AddPointer(ivd);
309 ID.AddPointer(superRegion);
310 }
311
Profile(llvm::FoldingSetNodeID & ID) const312 void ObjCIvarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
313 ProfileRegion(ID, getDecl(), superRegion);
314 }
315
ProfileRegion(llvm::FoldingSetNodeID & ID,const VarDecl * VD,const MemRegion * superRegion)316 void NonParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
317 const VarDecl *VD,
318 const MemRegion *superRegion) {
319 ID.AddInteger(static_cast<unsigned>(NonParamVarRegionKind));
320 ID.AddPointer(VD);
321 ID.AddPointer(superRegion);
322 }
323
Profile(llvm::FoldingSetNodeID & ID) const324 void NonParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
325 ProfileRegion(ID, getDecl(), superRegion);
326 }
327
ProfileRegion(llvm::FoldingSetNodeID & ID,const Expr * OE,unsigned Idx,const MemRegion * SReg)328 void ParamVarRegion::ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE,
329 unsigned Idx, const MemRegion *SReg) {
330 ID.AddInteger(static_cast<unsigned>(ParamVarRegionKind));
331 ID.AddPointer(OE);
332 ID.AddInteger(Idx);
333 ID.AddPointer(SReg);
334 }
335
Profile(llvm::FoldingSetNodeID & ID) const336 void ParamVarRegion::Profile(llvm::FoldingSetNodeID &ID) const {
337 ProfileRegion(ID, getOriginExpr(), getIndex(), superRegion);
338 }
339
ProfileRegion(llvm::FoldingSetNodeID & ID,SymbolRef sym,const MemRegion * sreg)340 void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolRef sym,
341 const MemRegion *sreg) {
342 ID.AddInteger(static_cast<unsigned>(MemRegion::SymbolicRegionKind));
343 ID.Add(sym);
344 ID.AddPointer(sreg);
345 }
346
Profile(llvm::FoldingSetNodeID & ID) const347 void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
348 SymbolicRegion::ProfileRegion(ID, sym, getSuperRegion());
349 }
350
ProfileRegion(llvm::FoldingSetNodeID & ID,QualType ElementType,SVal Idx,const MemRegion * superRegion)351 void ElementRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
352 QualType ElementType, SVal Idx,
353 const MemRegion* superRegion) {
354 ID.AddInteger(MemRegion::ElementRegionKind);
355 ID.Add(ElementType);
356 ID.AddPointer(superRegion);
357 Idx.Profile(ID);
358 }
359
Profile(llvm::FoldingSetNodeID & ID) const360 void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
361 ElementRegion::ProfileRegion(ID, ElementType, Index, superRegion);
362 }
363
ProfileRegion(llvm::FoldingSetNodeID & ID,const NamedDecl * FD,const MemRegion *)364 void FunctionCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
365 const NamedDecl *FD,
366 const MemRegion*) {
367 ID.AddInteger(MemRegion::FunctionCodeRegionKind);
368 ID.AddPointer(FD);
369 }
370
Profile(llvm::FoldingSetNodeID & ID) const371 void FunctionCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const {
372 FunctionCodeRegion::ProfileRegion(ID, FD, superRegion);
373 }
374
ProfileRegion(llvm::FoldingSetNodeID & ID,const BlockDecl * BD,CanQualType,const AnalysisDeclContext * AC,const MemRegion *)375 void BlockCodeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
376 const BlockDecl *BD, CanQualType,
377 const AnalysisDeclContext *AC,
378 const MemRegion*) {
379 ID.AddInteger(MemRegion::BlockCodeRegionKind);
380 ID.AddPointer(BD);
381 }
382
Profile(llvm::FoldingSetNodeID & ID) const383 void BlockCodeRegion::Profile(llvm::FoldingSetNodeID& ID) const {
384 BlockCodeRegion::ProfileRegion(ID, BD, locTy, AC, superRegion);
385 }
386
ProfileRegion(llvm::FoldingSetNodeID & ID,const BlockCodeRegion * BC,const LocationContext * LC,unsigned BlkCount,const MemRegion * sReg)387 void BlockDataRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
388 const BlockCodeRegion *BC,
389 const LocationContext *LC,
390 unsigned BlkCount,
391 const MemRegion *sReg) {
392 ID.AddInteger(MemRegion::BlockDataRegionKind);
393 ID.AddPointer(BC);
394 ID.AddPointer(LC);
395 ID.AddInteger(BlkCount);
396 ID.AddPointer(sReg);
397 }
398
Profile(llvm::FoldingSetNodeID & ID) const399 void BlockDataRegion::Profile(llvm::FoldingSetNodeID& ID) const {
400 BlockDataRegion::ProfileRegion(ID, BC, LC, BlockCount, getSuperRegion());
401 }
402
ProfileRegion(llvm::FoldingSetNodeID & ID,Expr const * Ex,const MemRegion * sReg)403 void CXXTempObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
404 Expr const *Ex,
405 const MemRegion *sReg) {
406 ID.AddPointer(Ex);
407 ID.AddPointer(sReg);
408 }
409
Profile(llvm::FoldingSetNodeID & ID) const410 void CXXTempObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
411 ProfileRegion(ID, Ex, getSuperRegion());
412 }
413
ProfileRegion(llvm::FoldingSetNodeID & ID,const Expr * E,const ValueDecl * D,const MemRegion * sReg)414 void CXXLifetimeExtendedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
415 const Expr *E,
416 const ValueDecl *D,
417 const MemRegion *sReg) {
418 ID.AddPointer(E);
419 ID.AddPointer(D);
420 ID.AddPointer(sReg);
421 }
422
Profile(llvm::FoldingSetNodeID & ID) const423 void CXXLifetimeExtendedObjectRegion::Profile(
424 llvm::FoldingSetNodeID &ID) const {
425 ProfileRegion(ID, Ex, ExD, getSuperRegion());
426 }
427
ProfileRegion(llvm::FoldingSetNodeID & ID,const CXXRecordDecl * RD,bool IsVirtual,const MemRegion * SReg)428 void CXXBaseObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
429 const CXXRecordDecl *RD,
430 bool IsVirtual,
431 const MemRegion *SReg) {
432 ID.AddPointer(RD);
433 ID.AddBoolean(IsVirtual);
434 ID.AddPointer(SReg);
435 }
436
Profile(llvm::FoldingSetNodeID & ID) const437 void CXXBaseObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
438 ProfileRegion(ID, getDecl(), isVirtual(), superRegion);
439 }
440
ProfileRegion(llvm::FoldingSetNodeID & ID,const CXXRecordDecl * RD,const MemRegion * SReg)441 void CXXDerivedObjectRegion::ProfileRegion(llvm::FoldingSetNodeID &ID,
442 const CXXRecordDecl *RD,
443 const MemRegion *SReg) {
444 ID.AddPointer(RD);
445 ID.AddPointer(SReg);
446 }
447
Profile(llvm::FoldingSetNodeID & ID) const448 void CXXDerivedObjectRegion::Profile(llvm::FoldingSetNodeID &ID) const {
449 ProfileRegion(ID, getDecl(), superRegion);
450 }
451
452 //===----------------------------------------------------------------------===//
453 // Region anchors.
454 //===----------------------------------------------------------------------===//
455
anchor()456 void GlobalsSpaceRegion::anchor() {}
457
anchor()458 void NonStaticGlobalSpaceRegion::anchor() {}
459
anchor()460 void StackSpaceRegion::anchor() {}
461
anchor()462 void TypedRegion::anchor() {}
463
anchor()464 void TypedValueRegion::anchor() {}
465
anchor()466 void CodeTextRegion::anchor() {}
467
anchor()468 void SubRegion::anchor() {}
469
470 //===----------------------------------------------------------------------===//
471 // Region pretty-printing.
472 //===----------------------------------------------------------------------===//
473
dump() const474 LLVM_DUMP_METHOD void MemRegion::dump() const {
475 dumpToStream(llvm::errs());
476 }
477
getString() const478 std::string MemRegion::getString() const {
479 std::string s;
480 llvm::raw_string_ostream os(s);
481 dumpToStream(os);
482 return s;
483 }
484
dumpToStream(raw_ostream & os) const485 void MemRegion::dumpToStream(raw_ostream &os) const {
486 os << "<Unknown Region>";
487 }
488
dumpToStream(raw_ostream & os) const489 void AllocaRegion::dumpToStream(raw_ostream &os) const {
490 os << "alloca{S" << Ex->getID(getContext()) << ',' << Cnt << '}';
491 }
492
dumpToStream(raw_ostream & os) const493 void FunctionCodeRegion::dumpToStream(raw_ostream &os) const {
494 os << "code{" << getDecl()->getDeclName().getAsString() << '}';
495 }
496
dumpToStream(raw_ostream & os) const497 void BlockCodeRegion::dumpToStream(raw_ostream &os) const {
498 os << "block_code{" << static_cast<const void *>(this) << '}';
499 }
500
dumpToStream(raw_ostream & os) const501 void 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
dumpToStream(raw_ostream & os) const510 void CompoundLiteralRegion::dumpToStream(raw_ostream &os) const {
511 // FIXME: More elaborate pretty-printing.
512 os << "{ S" << CL->getID(getContext()) << " }";
513 }
514
dumpToStream(raw_ostream & os) const515 void CXXTempObjectRegion::dumpToStream(raw_ostream &os) const {
516 os << "temp_object{" << getValueType() << ", "
517 << "S" << Ex->getID(getContext()) << '}';
518 }
519
dumpToStream(raw_ostream & os) const520 void 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
dumpToStream(raw_ostream & os) const530 void CXXBaseObjectRegion::dumpToStream(raw_ostream &os) const {
531 os << "Base{" << superRegion << ',' << getDecl()->getName() << '}';
532 }
533
dumpToStream(raw_ostream & os) const534 void CXXDerivedObjectRegion::dumpToStream(raw_ostream &os) const {
535 os << "Derived{" << superRegion << ',' << getDecl()->getName() << '}';
536 }
537
dumpToStream(raw_ostream & os) const538 void CXXThisRegion::dumpToStream(raw_ostream &os) const {
539 os << "this";
540 }
541
dumpToStream(raw_ostream & os) const542 void ElementRegion::dumpToStream(raw_ostream &os) const {
543 os << "Element{" << superRegion << ',' << Index << ',' << getElementType()
544 << '}';
545 }
546
dumpToStream(raw_ostream & os) const547 void FieldRegion::dumpToStream(raw_ostream &os) const {
548 os << superRegion << "." << *getDecl();
549 }
550
dumpToStream(raw_ostream & os) const551 void ObjCIvarRegion::dumpToStream(raw_ostream &os) const {
552 os << "Ivar{" << superRegion << ',' << *getDecl() << '}';
553 }
554
dumpToStream(raw_ostream & os) const555 void StringRegion::dumpToStream(raw_ostream &os) const {
556 assert(Str != nullptr && "Expecting non-null StringLiteral");
557 Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts()));
558 }
559
dumpToStream(raw_ostream & os) const560 void ObjCStringRegion::dumpToStream(raw_ostream &os) const {
561 assert(Str != nullptr && "Expecting non-null ObjCStringLiteral");
562 Str->printPretty(os, nullptr, PrintingPolicy(getContext().getLangOpts()));
563 }
564
dumpToStream(raw_ostream & os) const565 void SymbolicRegion::dumpToStream(raw_ostream &os) const {
566 if (isa<HeapSpaceRegion>(getSuperRegion()))
567 os << "Heap";
568 os << "SymRegion{" << sym << '}';
569 }
570
dumpToStream(raw_ostream & os) const571 void 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
dump() const578 LLVM_DUMP_METHOD void RegionRawOffset::dump() const {
579 dumpToStream(llvm::errs());
580 }
581
dumpToStream(raw_ostream & os) const582 void RegionRawOffset::dumpToStream(raw_ostream &os) const {
583 os << "raw_offset{" << getRegion() << ',' << getOffset().getQuantity() << '}';
584 }
585
dumpToStream(raw_ostream & os) const586 void CodeSpaceRegion::dumpToStream(raw_ostream &os) const {
587 os << "CodeSpaceRegion";
588 }
589
dumpToStream(raw_ostream & os) const590 void StaticGlobalSpaceRegion::dumpToStream(raw_ostream &os) const {
591 os << "StaticGlobalsMemSpace{" << CR << '}';
592 }
593
dumpToStream(raw_ostream & os) const594 void GlobalInternalSpaceRegion::dumpToStream(raw_ostream &os) const {
595 os << "GlobalInternalSpaceRegion";
596 }
597
dumpToStream(raw_ostream & os) const598 void GlobalSystemSpaceRegion::dumpToStream(raw_ostream &os) const {
599 os << "GlobalSystemSpaceRegion";
600 }
601
dumpToStream(raw_ostream & os) const602 void GlobalImmutableSpaceRegion::dumpToStream(raw_ostream &os) const {
603 os << "GlobalImmutableSpaceRegion";
604 }
605
dumpToStream(raw_ostream & os) const606 void HeapSpaceRegion::dumpToStream(raw_ostream &os) const {
607 os << "HeapSpaceRegion";
608 }
609
dumpToStream(raw_ostream & os) const610 void UnknownSpaceRegion::dumpToStream(raw_ostream &os) const {
611 os << "UnknownSpaceRegion";
612 }
613
dumpToStream(raw_ostream & os) const614 void StackArgumentsSpaceRegion::dumpToStream(raw_ostream &os) const {
615 os << "StackArgumentsSpaceRegion";
616 }
617
dumpToStream(raw_ostream & os) const618 void StackLocalsSpaceRegion::dumpToStream(raw_ostream &os) const {
619 os << "StackLocalsSpaceRegion";
620 }
621
dumpToStream(raw_ostream & os) const622 void 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
canPrintPretty() const634 bool MemRegion::canPrintPretty() const {
635 return canPrintPrettyAsExpr();
636 }
637
canPrintPrettyAsExpr() const638 bool MemRegion::canPrintPrettyAsExpr() const {
639 return false;
640 }
641
getKindStr() const642 StringRef 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
printPretty(raw_ostream & os) const653 void MemRegion::printPretty(raw_ostream &os) const {
654 assert(canPrintPretty() && "This region cannot be printed pretty.");
655 os << "'";
656 printPrettyAsExpr(os);
657 os << "'";
658 }
659
printPrettyAsExpr(raw_ostream &) const660 void MemRegion::printPrettyAsExpr(raw_ostream &) const {
661 llvm_unreachable("This region cannot be printed pretty.");
662 }
663
canPrintPrettyAsExpr() const664 bool NonParamVarRegion::canPrintPrettyAsExpr() const { return true; }
665
printPrettyAsExpr(raw_ostream & os) const666 void NonParamVarRegion::printPrettyAsExpr(raw_ostream &os) const {
667 os << getDecl()->getName();
668 }
669
canPrintPrettyAsExpr() const670 bool ParamVarRegion::canPrintPrettyAsExpr() const { return true; }
671
printPrettyAsExpr(raw_ostream & os) const672 void 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
canPrintPrettyAsExpr() const679 bool ObjCIvarRegion::canPrintPrettyAsExpr() const {
680 return true;
681 }
682
printPrettyAsExpr(raw_ostream & os) const683 void ObjCIvarRegion::printPrettyAsExpr(raw_ostream &os) const {
684 os << getDecl()->getName();
685 }
686
canPrintPretty() const687 bool FieldRegion::canPrintPretty() const {
688 return true;
689 }
690
canPrintPrettyAsExpr() const691 bool FieldRegion::canPrintPrettyAsExpr() const {
692 return superRegion->canPrintPrettyAsExpr();
693 }
694
printPrettyAsExpr(raw_ostream & os) const695 void FieldRegion::printPrettyAsExpr(raw_ostream &os) const {
696 assert(canPrintPrettyAsExpr());
697 superRegion->printPrettyAsExpr(os);
698 os << "." << getDecl()->getName();
699 }
700
printPretty(raw_ostream & os) const701 void 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
canPrintPrettyAsExpr() const711 bool CXXBaseObjectRegion::canPrintPrettyAsExpr() const {
712 return superRegion->canPrintPrettyAsExpr();
713 }
714
printPrettyAsExpr(raw_ostream & os) const715 void CXXBaseObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
716 superRegion->printPrettyAsExpr(os);
717 }
718
canPrintPrettyAsExpr() const719 bool CXXDerivedObjectRegion::canPrintPrettyAsExpr() const {
720 return superRegion->canPrintPrettyAsExpr();
721 }
722
printPrettyAsExpr(raw_ostream & os) const723 void CXXDerivedObjectRegion::printPrettyAsExpr(raw_ostream &os) const {
724 superRegion->printPrettyAsExpr(os);
725 }
726
getDescriptiveName(bool UseQuotes) const727 std::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(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(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(false);
780 if (Super.empty())
781 return "";
782 return QuoteIfNeeded(Super + "." + FR->getDecl()->getName());
783 }
784 }
785
786 return VariableName;
787 }
788
sourceRange() const789 SourceRange MemRegion::sourceRange() const {
790 // Check for more specific regions first.
791 if (auto *FR = dyn_cast<FieldRegion>(this)) {
792 return FR->getDecl()->getSourceRange();
793 }
794
795 if (auto *VR = dyn_cast<VarRegion>(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
getStaticSize(const MemRegion * MR,SValBuilder & SVB) const807 DefinedOrUnknownSVal MemRegionManager::getStaticSize(const MemRegion *MR,
808 SValBuilder &SVB) const {
809 const auto *SR = cast<SubRegion>(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>(SR));
816 case MemRegion::StringRegionKind:
817 return SVB.makeIntVal(
818 cast<StringRegion>(SR)->getStringLiteral()->getByteLength() + 1,
819 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>(SR)->getDesugaredValueType(Ctx);
832 if (isa<VariableArrayType>(Ty))
833 return nonloc::SymbolVal(SymMgr.acquire<SymbolExtent>(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>(SR)->getDecl()->isBitField())
843 return UnknownVal();
844
845 QualType Ty = cast<TypedValueRegion>(SR)->getDesugaredValueType(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>(AT);
860 };
861 auto IsArrayOfZero = [](const ArrayType *AT) {
862 const auto *CAT = dyn_cast<ConstantArrayType>(AT);
863 return CAT && CAT->isZeroSize();
864 };
865 auto IsArrayOfOne = [](const ArrayType *AT) {
866 const auto *CAT = dyn_cast<ConstantArrayType>(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(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>(SR));
901 default:
902 llvm_unreachable("Unhandled region");
903 }
904 }
905
906 template <typename REG>
LazyAllocate(REG * & region)907 const REG *MemRegionManager::LazyAllocate(REG*& region) {
908 if (!region) {
909 region = new (A) REG(*this);
910 }
911
912 return region;
913 }
914
915 template <typename REG, typename ARG>
LazyAllocate(REG * & region,ARG a)916 const REG *MemRegionManager::LazyAllocate(REG*& region, ARG a) {
917 if (!region) {
918 region = new (A) REG(this, a);
919 }
920
921 return region;
922 }
923
924 const StackLocalsSpaceRegion*
getStackLocalsRegion(const StackFrameContext * STC)925 MemRegionManager::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
936 const StackArgumentsSpaceRegion *
getStackArgumentsRegion(const StackFrameContext * STC)937 MemRegionManager::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
948 const GlobalsSpaceRegion
getGlobalsRegion(MemRegion::Kind K,const CodeTextRegion * CR)949 *MemRegionManager::getGlobalsRegion(MemRegion::Kind K,
950 const CodeTextRegion *CR) {
951 if (!CR) {
952 if (K == MemRegion::GlobalSystemSpaceRegionKind)
953 return LazyAllocate(SystemGlobals);
954 if (K == MemRegion::GlobalImmutableSpaceRegionKind)
955 return LazyAllocate(ImmutableGlobals);
956 assert(K == MemRegion::GlobalInternalSpaceRegionKind);
957 return LazyAllocate(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
getHeapRegion()969 const HeapSpaceRegion *MemRegionManager::getHeapRegion() {
970 return LazyAllocate(heap);
971 }
972
getUnknownRegion()973 const UnknownSpaceRegion *MemRegionManager::getUnknownRegion() {
974 return LazyAllocate(unknown);
975 }
976
getCodeRegion()977 const CodeSpaceRegion *MemRegionManager::getCodeRegion() {
978 return LazyAllocate(code);
979 }
980
981 //===----------------------------------------------------------------------===//
982 // Constructing regions.
983 //===----------------------------------------------------------------------===//
984
getStringRegion(const StringLiteral * Str)985 const StringRegion *MemRegionManager::getStringRegion(const StringLiteral *Str){
986 return getSubRegion<StringRegion>(
987 Str, cast<GlobalInternalSpaceRegion>(getGlobalsRegion()));
988 }
989
990 const ObjCStringRegion *
getObjCStringRegion(const ObjCStringLiteral * Str)991 MemRegionManager::getObjCStringRegion(const ObjCStringLiteral *Str){
992 return getSubRegion<ObjCStringRegion>(
993 Str, cast<GlobalInternalSpaceRegion>(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.
999 static llvm::PointerUnion<const StackFrameContext *, const VarRegion *>
getStackOrCaptureRegionForDeclContext(const LocationContext * LC,const DeclContext * DC,const VarDecl * VD)1000 getStackOrCaptureRegionForDeclContext(const LocationContext *LC,
1001 const DeclContext *DC,
1002 const VarDecl *VD) {
1003 while (LC) {
1004 if (const auto *SFC = dyn_cast<StackFrameContext>(LC)) {
1005 if (cast<DeclContext>(SFC->getDecl()) == DC)
1006 return SFC;
1007 }
1008 if (const auto *BC = dyn_cast<BlockInvocationContext>(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>(OrigR)) {
1014 if (VR->getDecl() == VD)
1015 return cast<VarRegion>(Var.getCapturedRegion());
1016 }
1017 }
1018 }
1019
1020 LC = LC->getParent();
1021 }
1022 return (const StackFrameContext *)nullptr;
1023 }
1024
isStdStreamVar(const VarDecl * D)1025 static bool isStdStreamVar(const VarDecl *D) {
1026 const IdentifierInfo *II = D->getIdentifier();
1027 if (!II)
1028 return false;
1029 if (!D->getDeclContext()->isTranslationUnit())
1030 return false;
1031 StringRef N = II->getName();
1032 QualType FILETy = D->getASTContext().getFILEType();
1033 if (FILETy.isNull())
1034 return false;
1035 FILETy = FILETy.getCanonicalType();
1036 QualType Ty = D->getType().getCanonicalType();
1037 return Ty->isPointerType() && Ty->getPointeeType() == FILETy &&
1038 (N == "stdin" || N == "stdout" || N == "stderr");
1039 }
1040
getVarRegion(const VarDecl * D,const LocationContext * LC)1041 const VarRegion *MemRegionManager::getVarRegion(const VarDecl *D,
1042 const LocationContext *LC) {
1043 const auto *PVD = dyn_cast<ParmVarDecl>(D);
1044 if (PVD) {
1045 unsigned Index = PVD->getFunctionScopeIndex();
1046 const StackFrameContext *SFC = LC->getStackFrame();
1047 const Stmt *CallSite = SFC->getCallSite();
1048 if (CallSite) {
1049 const Decl *D = SFC->getDecl();
1050 if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
1051 if (Index < FD->param_size() && FD->parameters()[Index] == PVD)
1052 return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
1053 getStackArgumentsRegion(SFC));
1054 } else if (const auto *BD = dyn_cast<BlockDecl>(D)) {
1055 if (Index < BD->param_size() && BD->parameters()[Index] == PVD)
1056 return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
1057 getStackArgumentsRegion(SFC));
1058 } else {
1059 return getSubRegion<ParamVarRegion>(cast<Expr>(CallSite), Index,
1060 getStackArgumentsRegion(SFC));
1061 }
1062 }
1063 }
1064
1065 D = D->getCanonicalDecl();
1066 const MemRegion *sReg = nullptr;
1067
1068 if (D->hasGlobalStorage() && !D->isStaticLocal()) {
1069 QualType Ty = D->getType();
1070 assert(!Ty.isNull());
1071 if (Ty.isConstQualified()) {
1072 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
1073 } else {
1074 // Pointer value of C standard streams is usually not modified by calls
1075 // to functions declared in system headers. This means that they should
1076 // not get invalidated by calls to functions declared in system headers,
1077 // so they are placed in the global internal space, which is not
1078 // invalidated by calls to functions declared in system headers.
1079 if (Ctx.getSourceManager().isInSystemHeader(D->getLocation()) &&
1080 !isStdStreamVar(D)) {
1081 sReg = getGlobalsRegion(MemRegion::GlobalSystemSpaceRegionKind);
1082 } else {
1083 sReg = getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind);
1084 }
1085 }
1086
1087 // Finally handle static locals.
1088 } else {
1089 // FIXME: Once we implement scope handling, we will need to properly lookup
1090 // 'D' to the proper LocationContext.
1091 const DeclContext *DC = D->getDeclContext();
1092 llvm::PointerUnion<const StackFrameContext *, const VarRegion *> V =
1093 getStackOrCaptureRegionForDeclContext(LC, DC, D);
1094
1095 if (const auto *VR = dyn_cast_if_present<const VarRegion *>(V))
1096 return VR;
1097
1098 const auto *STC = cast<const StackFrameContext *>(V);
1099
1100 if (!STC) {
1101 // FIXME: Assign a more sensible memory space to static locals
1102 // we see from within blocks that we analyze as top-level declarations.
1103 sReg = getUnknownRegion();
1104 } else {
1105 if (D->hasLocalStorage()) {
1106 sReg =
1107 isa<ParmVarDecl, ImplicitParamDecl>(D)
1108 ? static_cast<const MemRegion *>(getStackArgumentsRegion(STC))
1109 : static_cast<const MemRegion *>(getStackLocalsRegion(STC));
1110 }
1111 else {
1112 assert(D->isStaticLocal());
1113 const Decl *STCD = STC->getDecl();
1114 if (isa<FunctionDecl, ObjCMethodDecl>(STCD))
1115 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
1116 getFunctionCodeRegion(cast<NamedDecl>(STCD)));
1117 else if (const auto *BD = dyn_cast<BlockDecl>(STCD)) {
1118 // FIXME: The fallback type here is totally bogus -- though it should
1119 // never be queried, it will prevent uniquing with the real
1120 // BlockCodeRegion. Ideally we'd fix the AST so that we always had a
1121 // signature.
1122 QualType T;
1123 if (const TypeSourceInfo *TSI = BD->getSignatureAsWritten())
1124 T = TSI->getType();
1125 if (T.isNull())
1126 T = getContext().VoidTy;
1127 if (!T->getAs<FunctionType>()) {
1128 FunctionProtoType::ExtProtoInfo Ext;
1129 T = getContext().getFunctionType(T, {}, Ext);
1130 }
1131 T = getContext().getBlockPointerType(T);
1132
1133 const BlockCodeRegion *BTR =
1134 getBlockCodeRegion(BD, Ctx.getCanonicalType(T),
1135 STC->getAnalysisDeclContext());
1136 sReg = getGlobalsRegion(MemRegion::StaticGlobalSpaceRegionKind,
1137 BTR);
1138 }
1139 else {
1140 sReg = getGlobalsRegion();
1141 }
1142 }
1143 }
1144 }
1145
1146 return getNonParamVarRegion(D, sReg);
1147 }
1148
1149 const NonParamVarRegion *
getNonParamVarRegion(const VarDecl * D,const MemRegion * superR)1150 MemRegionManager::getNonParamVarRegion(const VarDecl *D,
1151 const MemRegion *superR) {
1152 // Prefer the definition over the canonical decl as the canonical form.
1153 D = D->getCanonicalDecl();
1154 if (const VarDecl *Def = D->getDefinition())
1155 D = Def;
1156 return getSubRegion<NonParamVarRegion>(D, superR);
1157 }
1158
1159 const ParamVarRegion *
getParamVarRegion(const Expr * OriginExpr,unsigned Index,const LocationContext * LC)1160 MemRegionManager::getParamVarRegion(const Expr *OriginExpr, unsigned Index,
1161 const LocationContext *LC) {
1162 const StackFrameContext *SFC = LC->getStackFrame();
1163 assert(SFC);
1164 return getSubRegion<ParamVarRegion>(OriginExpr, Index,
1165 getStackArgumentsRegion(SFC));
1166 }
1167
1168 const BlockDataRegion *
getBlockDataRegion(const BlockCodeRegion * BC,const LocationContext * LC,unsigned blockCount)1169 MemRegionManager::getBlockDataRegion(const BlockCodeRegion *BC,
1170 const LocationContext *LC,
1171 unsigned blockCount) {
1172 const MemSpaceRegion *sReg = nullptr;
1173 const BlockDecl *BD = BC->getDecl();
1174 if (!BD->hasCaptures()) {
1175 // This handles 'static' blocks.
1176 sReg = getGlobalsRegion(MemRegion::GlobalImmutableSpaceRegionKind);
1177 }
1178 else {
1179 bool IsArcManagedBlock = Ctx.getLangOpts().ObjCAutoRefCount;
1180
1181 // ARC managed blocks can be initialized on stack or directly in heap
1182 // depending on the implementations. So we initialize them with
1183 // UnknownRegion.
1184 if (!IsArcManagedBlock && LC) {
1185 // FIXME: Once we implement scope handling, we want the parent region
1186 // to be the scope.
1187 const StackFrameContext *STC = LC->getStackFrame();
1188 assert(STC);
1189 sReg = getStackLocalsRegion(STC);
1190 } else {
1191 // We allow 'LC' to be NULL for cases where want BlockDataRegions
1192 // without context-sensitivity.
1193 sReg = getUnknownRegion();
1194 }
1195 }
1196
1197 return getSubRegion<BlockDataRegion>(BC, LC, blockCount, sReg);
1198 }
1199
1200 const CompoundLiteralRegion*
getCompoundLiteralRegion(const CompoundLiteralExpr * CL,const LocationContext * LC)1201 MemRegionManager::getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
1202 const LocationContext *LC) {
1203 const MemSpaceRegion *sReg = nullptr;
1204
1205 if (CL->isFileScope())
1206 sReg = getGlobalsRegion();
1207 else {
1208 const StackFrameContext *STC = LC->getStackFrame();
1209 assert(STC);
1210 sReg = getStackLocalsRegion(STC);
1211 }
1212
1213 return getSubRegion<CompoundLiteralRegion>(CL, sReg);
1214 }
1215
1216 const ElementRegion *
getElementRegion(QualType elementType,NonLoc Idx,const SubRegion * superRegion,const ASTContext & Ctx)1217 MemRegionManager::getElementRegion(QualType elementType, NonLoc Idx,
1218 const SubRegion *superRegion,
1219 const ASTContext &Ctx) {
1220 QualType T = Ctx.getCanonicalType(elementType).getUnqualifiedType();
1221
1222 llvm::FoldingSetNodeID ID;
1223 ElementRegion::ProfileRegion(ID, T, Idx, superRegion);
1224
1225 void *InsertPos;
1226 MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
1227 auto *R = cast_or_null<ElementRegion>(data);
1228
1229 if (!R) {
1230 R = new (A) ElementRegion(T, Idx, superRegion);
1231 Regions.InsertNode(R, InsertPos);
1232 }
1233
1234 return R;
1235 }
1236
1237 const FunctionCodeRegion *
getFunctionCodeRegion(const NamedDecl * FD)1238 MemRegionManager::getFunctionCodeRegion(const NamedDecl *FD) {
1239 // To think: should we canonicalize the declaration here?
1240 return getSubRegion<FunctionCodeRegion>(FD, getCodeRegion());
1241 }
1242
1243 const BlockCodeRegion *
getBlockCodeRegion(const BlockDecl * BD,CanQualType locTy,AnalysisDeclContext * AC)1244 MemRegionManager::getBlockCodeRegion(const BlockDecl *BD, CanQualType locTy,
1245 AnalysisDeclContext *AC) {
1246 return getSubRegion<BlockCodeRegion>(BD, locTy, AC, getCodeRegion());
1247 }
1248
1249 const SymbolicRegion *
getSymbolicRegion(SymbolRef sym,const MemSpaceRegion * MemSpace)1250 MemRegionManager::getSymbolicRegion(SymbolRef sym,
1251 const MemSpaceRegion *MemSpace) {
1252 if (MemSpace == nullptr)
1253 MemSpace = getUnknownRegion();
1254 return getSubRegion<SymbolicRegion>(sym, MemSpace);
1255 }
1256
getSymbolicHeapRegion(SymbolRef Sym)1257 const SymbolicRegion *MemRegionManager::getSymbolicHeapRegion(SymbolRef Sym) {
1258 return getSubRegion<SymbolicRegion>(Sym, getHeapRegion());
1259 }
1260
1261 const FieldRegion*
getFieldRegion(const FieldDecl * d,const SubRegion * superRegion)1262 MemRegionManager::getFieldRegion(const FieldDecl *d,
1263 const SubRegion* superRegion){
1264 return getSubRegion<FieldRegion>(d, superRegion);
1265 }
1266
1267 const ObjCIvarRegion*
getObjCIvarRegion(const ObjCIvarDecl * d,const SubRegion * superRegion)1268 MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl *d,
1269 const SubRegion* superRegion) {
1270 return getSubRegion<ObjCIvarRegion>(d, superRegion);
1271 }
1272
1273 const CXXTempObjectRegion*
getCXXTempObjectRegion(Expr const * E,LocationContext const * LC)1274 MemRegionManager::getCXXTempObjectRegion(Expr const *E,
1275 LocationContext const *LC) {
1276 const StackFrameContext *SFC = LC->getStackFrame();
1277 assert(SFC);
1278 return getSubRegion<CXXTempObjectRegion>(E, getStackLocalsRegion(SFC));
1279 }
1280
1281 const CXXLifetimeExtendedObjectRegion *
getCXXLifetimeExtendedObjectRegion(const Expr * Ex,const ValueDecl * VD,const LocationContext * LC)1282 MemRegionManager::getCXXLifetimeExtendedObjectRegion(
1283 const Expr *Ex, const ValueDecl *VD, const LocationContext *LC) {
1284 const StackFrameContext *SFC = LC->getStackFrame();
1285 assert(SFC);
1286 return getSubRegion<CXXLifetimeExtendedObjectRegion>(
1287 Ex, VD, getStackLocalsRegion(SFC));
1288 }
1289
1290 const CXXLifetimeExtendedObjectRegion *
getCXXStaticLifetimeExtendedObjectRegion(const Expr * Ex,const ValueDecl * VD)1291 MemRegionManager::getCXXStaticLifetimeExtendedObjectRegion(
1292 const Expr *Ex, const ValueDecl *VD) {
1293 return getSubRegion<CXXLifetimeExtendedObjectRegion>(
1294 Ex, VD,
1295 getGlobalsRegion(MemRegion::GlobalInternalSpaceRegionKind, nullptr));
1296 }
1297
1298 /// Checks whether \p BaseClass is a valid virtual or direct non-virtual base
1299 /// class of the type of \p Super.
isValidBaseClass(const CXXRecordDecl * BaseClass,const TypedValueRegion * Super,bool IsVirtual)1300 static bool isValidBaseClass(const CXXRecordDecl *BaseClass,
1301 const TypedValueRegion *Super,
1302 bool IsVirtual) {
1303 BaseClass = BaseClass->getCanonicalDecl();
1304
1305 const CXXRecordDecl *Class = Super->getValueType()->getAsCXXRecordDecl();
1306 if (!Class)
1307 return true;
1308
1309 if (IsVirtual)
1310 return Class->isVirtuallyDerivedFrom(BaseClass);
1311
1312 for (const auto &I : Class->bases()) {
1313 if (I.getType()->getAsCXXRecordDecl()->getCanonicalDecl() == BaseClass)
1314 return true;
1315 }
1316
1317 return false;
1318 }
1319
1320 const CXXBaseObjectRegion *
getCXXBaseObjectRegion(const CXXRecordDecl * RD,const SubRegion * Super,bool IsVirtual)1321 MemRegionManager::getCXXBaseObjectRegion(const CXXRecordDecl *RD,
1322 const SubRegion *Super,
1323 bool IsVirtual) {
1324 if (isa<TypedValueRegion>(Super)) {
1325 assert(isValidBaseClass(RD, cast<TypedValueRegion>(Super), IsVirtual));
1326 (void)&isValidBaseClass;
1327
1328 if (IsVirtual) {
1329 // Virtual base regions should not be layered, since the layout rules
1330 // are different.
1331 while (const auto *Base = dyn_cast<CXXBaseObjectRegion>(Super))
1332 Super = cast<SubRegion>(Base->getSuperRegion());
1333 assert(Super && !isa<MemSpaceRegion>(Super));
1334 }
1335 }
1336
1337 return getSubRegion<CXXBaseObjectRegion>(RD, IsVirtual, Super);
1338 }
1339
1340 const CXXDerivedObjectRegion *
getCXXDerivedObjectRegion(const CXXRecordDecl * RD,const SubRegion * Super)1341 MemRegionManager::getCXXDerivedObjectRegion(const CXXRecordDecl *RD,
1342 const SubRegion *Super) {
1343 return getSubRegion<CXXDerivedObjectRegion>(RD, Super);
1344 }
1345
1346 const CXXThisRegion*
getCXXThisRegion(QualType thisPointerTy,const LocationContext * LC)1347 MemRegionManager::getCXXThisRegion(QualType thisPointerTy,
1348 const LocationContext *LC) {
1349 const auto *PT = thisPointerTy->getAs<PointerType>();
1350 assert(PT);
1351 // Inside the body of the operator() of a lambda a this expr might refer to an
1352 // object in one of the parent location contexts.
1353 const auto *D = dyn_cast<CXXMethodDecl>(LC->getDecl());
1354 // FIXME: when operator() of lambda is analyzed as a top level function and
1355 // 'this' refers to a this to the enclosing scope, there is no right region to
1356 // return.
1357 while (!LC->inTopFrame() && (!D || D->isStatic() ||
1358 PT != D->getThisType()->getAs<PointerType>())) {
1359 LC = LC->getParent();
1360 D = dyn_cast<CXXMethodDecl>(LC->getDecl());
1361 }
1362 const StackFrameContext *STC = LC->getStackFrame();
1363 assert(STC);
1364 return getSubRegion<CXXThisRegion>(PT, getStackArgumentsRegion(STC));
1365 }
1366
1367 const AllocaRegion*
getAllocaRegion(const Expr * E,unsigned cnt,const LocationContext * LC)1368 MemRegionManager::getAllocaRegion(const Expr *E, unsigned cnt,
1369 const LocationContext *LC) {
1370 const StackFrameContext *STC = LC->getStackFrame();
1371 assert(STC);
1372 return getSubRegion<AllocaRegion>(E, cnt, getStackLocalsRegion(STC));
1373 }
1374
getRawMemorySpace() const1375 const MemSpaceRegion *MemRegion::getRawMemorySpace() const {
1376 const MemRegion *R = this;
1377 const auto *SR = dyn_cast<SubRegion>(this);
1378
1379 while (SR) {
1380 R = SR->getSuperRegion();
1381 SR = dyn_cast<SubRegion>(R);
1382 }
1383
1384 return cast<MemSpaceRegion>(R);
1385 }
1386
getMemorySpace(ProgramStateRef State) const1387 const MemSpaceRegion *MemRegion::getMemorySpace(ProgramStateRef State) const {
1388 const MemRegion *MR = getBaseRegion();
1389
1390 const MemSpaceRegion *RawSpace = MR->getRawMemorySpace();
1391 if (!isa<UnknownSpaceRegion>(RawSpace))
1392 return RawSpace;
1393
1394 const MemSpaceRegion *const *AssociatedSpace = State->get<MemSpacesMap>(MR);
1395 return AssociatedSpace ? *AssociatedSpace : RawSpace;
1396 }
1397
setMemorySpace(ProgramStateRef State,const MemSpaceRegion * Space) const1398 ProgramStateRef MemRegion::setMemorySpace(ProgramStateRef State,
1399 const MemSpaceRegion *Space) const {
1400 const MemRegion *Base = getBaseRegion();
1401
1402 // Shouldn't set unknown space.
1403 assert(!isa<UnknownSpaceRegion>(Space));
1404
1405 // Currently, it we should have no accurate memspace for this region.
1406 assert(Base->hasMemorySpace<UnknownSpaceRegion>(State));
1407 return State->set<MemSpacesMap>(Base, Space);
1408 }
1409
1410 // Strips away all elements and fields.
1411 // Returns the base region of them.
getBaseRegion() const1412 const MemRegion *MemRegion::getBaseRegion() const {
1413 const MemRegion *R = this;
1414 while (true) {
1415 switch (R->getKind()) {
1416 case MemRegion::ElementRegionKind:
1417 case MemRegion::FieldRegionKind:
1418 case MemRegion::ObjCIvarRegionKind:
1419 case MemRegion::CXXBaseObjectRegionKind:
1420 case MemRegion::CXXDerivedObjectRegionKind:
1421 R = cast<SubRegion>(R)->getSuperRegion();
1422 continue;
1423 default:
1424 break;
1425 }
1426 break;
1427 }
1428 return R;
1429 }
1430
1431 // Returns the region of the root class of a C++ class hierarchy.
getMostDerivedObjectRegion() const1432 const MemRegion *MemRegion::getMostDerivedObjectRegion() const {
1433 const MemRegion *R = this;
1434 while (const auto *BR = dyn_cast<CXXBaseObjectRegion>(R))
1435 R = BR->getSuperRegion();
1436 return R;
1437 }
1438
isSubRegionOf(const MemRegion *) const1439 bool MemRegion::isSubRegionOf(const MemRegion *) const {
1440 return false;
1441 }
1442
1443 //===----------------------------------------------------------------------===//
1444 // View handling.
1445 //===----------------------------------------------------------------------===//
1446
StripCasts(bool StripBaseAndDerivedCasts) const1447 const MemRegion *MemRegion::StripCasts(bool StripBaseAndDerivedCasts) const {
1448 const MemRegion *R = this;
1449 while (true) {
1450 switch (R->getKind()) {
1451 case ElementRegionKind: {
1452 const auto *ER = cast<ElementRegion>(R);
1453 if (!ER->getIndex().isZeroConstant())
1454 return R;
1455 R = ER->getSuperRegion();
1456 break;
1457 }
1458 case CXXBaseObjectRegionKind:
1459 case CXXDerivedObjectRegionKind:
1460 if (!StripBaseAndDerivedCasts)
1461 return R;
1462 R = cast<TypedValueRegion>(R)->getSuperRegion();
1463 break;
1464 default:
1465 return R;
1466 }
1467 }
1468 }
1469
getSymbolicBase() const1470 const SymbolicRegion *MemRegion::getSymbolicBase() const {
1471 const auto *SubR = dyn_cast<SubRegion>(this);
1472
1473 while (SubR) {
1474 if (const auto *SymR = dyn_cast<SymbolicRegion>(SubR))
1475 return SymR;
1476 SubR = dyn_cast<SubRegion>(SubR->getSuperRegion());
1477 }
1478 return nullptr;
1479 }
1480
getAsArrayOffset() const1481 RegionRawOffset ElementRegion::getAsArrayOffset() const {
1482 int64_t offset = 0;
1483 const ElementRegion *ER = this;
1484 const MemRegion *superR = nullptr;
1485 ASTContext &C = getContext();
1486
1487 // FIXME: Handle multi-dimensional arrays.
1488
1489 while (ER) {
1490 superR = ER->getSuperRegion();
1491
1492 // FIXME: generalize to symbolic offsets.
1493 SVal index = ER->getIndex();
1494 if (auto CI = index.getAs<nonloc::ConcreteInt>()) {
1495 // Update the offset.
1496 if (int64_t i = CI->getValue()->getSExtValue(); i != 0) {
1497 QualType elemType = ER->getElementType();
1498
1499 // If we are pointing to an incomplete type, go no further.
1500 if (elemType->isIncompleteType()) {
1501 superR = ER;
1502 break;
1503 }
1504
1505 int64_t size = C.getTypeSizeInChars(elemType).getQuantity();
1506 if (auto NewOffset = llvm::checkedMulAdd(i, size, offset)) {
1507 offset = *NewOffset;
1508 } else {
1509 LLVM_DEBUG(llvm::dbgs() << "MemRegion::getAsArrayOffset: "
1510 << "offset overflowing, returning unknown\n");
1511
1512 return nullptr;
1513 }
1514 }
1515
1516 // Go to the next ElementRegion (if any).
1517 ER = dyn_cast<ElementRegion>(superR);
1518 continue;
1519 }
1520
1521 return nullptr;
1522 }
1523
1524 assert(superR && "super region cannot be NULL");
1525 return RegionRawOffset(superR, CharUnits::fromQuantity(offset));
1526 }
1527
1528 /// Returns true if \p Base is an immediate base class of \p Child
isImmediateBase(const CXXRecordDecl * Child,const CXXRecordDecl * Base)1529 static bool isImmediateBase(const CXXRecordDecl *Child,
1530 const CXXRecordDecl *Base) {
1531 assert(Child && "Child must not be null");
1532 // Note that we do NOT canonicalize the base class here, because
1533 // ASTRecordLayout doesn't either. If that leads us down the wrong path,
1534 // so be it; at least we won't crash.
1535 for (const auto &I : Child->bases()) {
1536 if (I.getType()->getAsCXXRecordDecl() == Base)
1537 return true;
1538 }
1539
1540 return false;
1541 }
1542
calculateOffset(const MemRegion * R)1543 static RegionOffset calculateOffset(const MemRegion *R) {
1544 const MemRegion *SymbolicOffsetBase = nullptr;
1545 int64_t Offset = 0;
1546
1547 while (true) {
1548 switch (R->getKind()) {
1549 case MemRegion::CodeSpaceRegionKind:
1550 case MemRegion::StackLocalsSpaceRegionKind:
1551 case MemRegion::StackArgumentsSpaceRegionKind:
1552 case MemRegion::HeapSpaceRegionKind:
1553 case MemRegion::UnknownSpaceRegionKind:
1554 case MemRegion::StaticGlobalSpaceRegionKind:
1555 case MemRegion::GlobalInternalSpaceRegionKind:
1556 case MemRegion::GlobalSystemSpaceRegionKind:
1557 case MemRegion::GlobalImmutableSpaceRegionKind:
1558 // Stores can bind directly to a region space to set a default value.
1559 assert(Offset == 0 && !SymbolicOffsetBase);
1560 goto Finish;
1561
1562 case MemRegion::FunctionCodeRegionKind:
1563 case MemRegion::BlockCodeRegionKind:
1564 case MemRegion::BlockDataRegionKind:
1565 // These will never have bindings, but may end up having values requested
1566 // if the user does some strange casting.
1567 if (Offset != 0)
1568 SymbolicOffsetBase = R;
1569 goto Finish;
1570
1571 case MemRegion::SymbolicRegionKind:
1572 case MemRegion::AllocaRegionKind:
1573 case MemRegion::CompoundLiteralRegionKind:
1574 case MemRegion::CXXThisRegionKind:
1575 case MemRegion::StringRegionKind:
1576 case MemRegion::ObjCStringRegionKind:
1577 case MemRegion::NonParamVarRegionKind:
1578 case MemRegion::ParamVarRegionKind:
1579 case MemRegion::CXXTempObjectRegionKind:
1580 case MemRegion::CXXLifetimeExtendedObjectRegionKind:
1581 // Usual base regions.
1582 goto Finish;
1583
1584 case MemRegion::ObjCIvarRegionKind:
1585 // This is a little strange, but it's a compromise between
1586 // ObjCIvarRegions having unknown compile-time offsets (when using the
1587 // non-fragile runtime) and yet still being distinct, non-overlapping
1588 // regions. Thus we treat them as "like" base regions for the purposes
1589 // of computing offsets.
1590 goto Finish;
1591
1592 case MemRegion::CXXBaseObjectRegionKind: {
1593 const auto *BOR = cast<CXXBaseObjectRegion>(R);
1594 R = BOR->getSuperRegion();
1595
1596 QualType Ty;
1597 bool RootIsSymbolic = false;
1598 if (const auto *TVR = dyn_cast<TypedValueRegion>(R)) {
1599 Ty = TVR->getDesugaredValueType(R->getContext());
1600 } else if (const auto *SR = dyn_cast<SymbolicRegion>(R)) {
1601 // If our base region is symbolic, we don't know what type it really is.
1602 // Pretend the type of the symbol is the true dynamic type.
1603 // (This will at least be self-consistent for the life of the symbol.)
1604 Ty = SR->getPointeeStaticType();
1605 RootIsSymbolic = true;
1606 }
1607
1608 const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl();
1609 if (!Child) {
1610 // We cannot compute the offset of the base class.
1611 SymbolicOffsetBase = R;
1612 } else {
1613 if (RootIsSymbolic) {
1614 // Base layers on symbolic regions may not be type-correct.
1615 // Double-check the inheritance here, and revert to a symbolic offset
1616 // if it's invalid (e.g. due to a reinterpret_cast).
1617 if (BOR->isVirtual()) {
1618 if (!Child->isVirtuallyDerivedFrom(BOR->getDecl()))
1619 SymbolicOffsetBase = R;
1620 } else {
1621 if (!isImmediateBase(Child, BOR->getDecl()))
1622 SymbolicOffsetBase = R;
1623 }
1624 }
1625 }
1626
1627 // Don't bother calculating precise offsets if we already have a
1628 // symbolic offset somewhere in the chain.
1629 if (SymbolicOffsetBase)
1630 continue;
1631
1632 CharUnits BaseOffset;
1633 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(Child);
1634 if (BOR->isVirtual())
1635 BaseOffset = Layout.getVBaseClassOffset(BOR->getDecl());
1636 else
1637 BaseOffset = Layout.getBaseClassOffset(BOR->getDecl());
1638
1639 // The base offset is in chars, not in bits.
1640 Offset += BaseOffset.getQuantity() * R->getContext().getCharWidth();
1641 break;
1642 }
1643
1644 case MemRegion::CXXDerivedObjectRegionKind: {
1645 // TODO: Store the base type in the CXXDerivedObjectRegion and use it.
1646 goto Finish;
1647 }
1648
1649 case MemRegion::ElementRegionKind: {
1650 const auto *ER = cast<ElementRegion>(R);
1651 R = ER->getSuperRegion();
1652
1653 QualType EleTy = ER->getValueType();
1654 if (EleTy->isIncompleteType()) {
1655 // We cannot compute the offset of the base class.
1656 SymbolicOffsetBase = R;
1657 continue;
1658 }
1659
1660 SVal Index = ER->getIndex();
1661 if (std::optional<nonloc::ConcreteInt> CI =
1662 Index.getAs<nonloc::ConcreteInt>()) {
1663 // Don't bother calculating precise offsets if we already have a
1664 // symbolic offset somewhere in the chain.
1665 if (SymbolicOffsetBase)
1666 continue;
1667
1668 int64_t i = CI->getValue()->getSExtValue();
1669 // This type size is in bits.
1670 Offset += i * R->getContext().getTypeSize(EleTy);
1671 } else {
1672 // We cannot compute offset for non-concrete index.
1673 SymbolicOffsetBase = R;
1674 }
1675 break;
1676 }
1677 case MemRegion::FieldRegionKind: {
1678 const auto *FR = cast<FieldRegion>(R);
1679 R = FR->getSuperRegion();
1680 assert(R);
1681
1682 const RecordDecl *RD = FR->getDecl()->getParent();
1683 if (RD->isUnion() || !RD->isCompleteDefinition()) {
1684 // We cannot compute offset for incomplete type.
1685 // For unions, we could treat everything as offset 0, but we'd rather
1686 // treat each field as a symbolic offset so they aren't stored on top
1687 // of each other, since we depend on things in typed regions actually
1688 // matching their types.
1689 SymbolicOffsetBase = R;
1690 }
1691
1692 // Don't bother calculating precise offsets if we already have a
1693 // symbolic offset somewhere in the chain.
1694 if (SymbolicOffsetBase)
1695 continue;
1696
1697 // Get the field number.
1698 unsigned idx = 0;
1699 for (RecordDecl::field_iterator FI = RD->field_begin(),
1700 FE = RD->field_end(); FI != FE; ++FI, ++idx) {
1701 if (FR->getDecl() == *FI)
1702 break;
1703 }
1704 const ASTRecordLayout &Layout = R->getContext().getASTRecordLayout(RD);
1705 // This is offset in bits.
1706 Offset += Layout.getFieldOffset(idx);
1707 break;
1708 }
1709 }
1710 }
1711
1712 Finish:
1713 if (SymbolicOffsetBase)
1714 return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic);
1715 return RegionOffset(R, Offset);
1716 }
1717
getAsOffset() const1718 RegionOffset MemRegion::getAsOffset() const {
1719 if (!cachedOffset)
1720 cachedOffset = calculateOffset(this);
1721 return *cachedOffset;
1722 }
1723
1724 //===----------------------------------------------------------------------===//
1725 // BlockDataRegion
1726 //===----------------------------------------------------------------------===//
1727
1728 std::pair<const VarRegion *, const VarRegion *>
getCaptureRegions(const VarDecl * VD)1729 BlockDataRegion::getCaptureRegions(const VarDecl *VD) {
1730 MemRegionManager &MemMgr = getMemRegionManager();
1731 const VarRegion *VR = nullptr;
1732 const VarRegion *OriginalVR = nullptr;
1733
1734 if (!VD->hasAttr<BlocksAttr>() && VD->hasLocalStorage()) {
1735 VR = MemMgr.getNonParamVarRegion(VD, this);
1736 OriginalVR = MemMgr.getVarRegion(VD, LC);
1737 }
1738 else {
1739 if (LC) {
1740 VR = MemMgr.getVarRegion(VD, LC);
1741 OriginalVR = VR;
1742 }
1743 else {
1744 VR = MemMgr.getNonParamVarRegion(VD, MemMgr.getUnknownRegion());
1745 OriginalVR = MemMgr.getVarRegion(VD, LC);
1746 }
1747 }
1748 return std::make_pair(VR, OriginalVR);
1749 }
1750
LazyInitializeReferencedVars()1751 void BlockDataRegion::LazyInitializeReferencedVars() {
1752 if (ReferencedVars)
1753 return;
1754
1755 AnalysisDeclContext *AC = getCodeRegion()->getAnalysisDeclContext();
1756 const auto &ReferencedBlockVars = AC->getReferencedBlockVars(BC->getDecl());
1757 auto NumBlockVars =
1758 std::distance(ReferencedBlockVars.begin(), ReferencedBlockVars.end());
1759
1760 if (NumBlockVars == 0) {
1761 ReferencedVars = (void*) 0x1;
1762 return;
1763 }
1764
1765 MemRegionManager &MemMgr = getMemRegionManager();
1766 llvm::BumpPtrAllocator &A = MemMgr.getAllocator();
1767 BumpVectorContext BC(A);
1768
1769 using VarVec = BumpVector<const MemRegion *>;
1770
1771 auto *BV = new (A) VarVec(BC, NumBlockVars);
1772 auto *BVOriginal = new (A) VarVec(BC, NumBlockVars);
1773
1774 for (const auto *VD : ReferencedBlockVars) {
1775 const VarRegion *VR = nullptr;
1776 const VarRegion *OriginalVR = nullptr;
1777 std::tie(VR, OriginalVR) = getCaptureRegions(VD);
1778 assert(VR);
1779 assert(OriginalVR);
1780 BV->push_back(VR, BC);
1781 BVOriginal->push_back(OriginalVR, BC);
1782 }
1783
1784 ReferencedVars = BV;
1785 OriginalVars = BVOriginal;
1786 }
1787
1788 BlockDataRegion::referenced_vars_iterator
referenced_vars_begin() const1789 BlockDataRegion::referenced_vars_begin() const {
1790 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
1791
1792 auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
1793
1794 if (Vec == (void*) 0x1)
1795 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
1796
1797 auto *VecOriginal =
1798 static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
1799
1800 return BlockDataRegion::referenced_vars_iterator(Vec->begin(),
1801 VecOriginal->begin());
1802 }
1803
1804 BlockDataRegion::referenced_vars_iterator
referenced_vars_end() const1805 BlockDataRegion::referenced_vars_end() const {
1806 const_cast<BlockDataRegion*>(this)->LazyInitializeReferencedVars();
1807
1808 auto *Vec = static_cast<BumpVector<const MemRegion *> *>(ReferencedVars);
1809
1810 if (Vec == (void*) 0x1)
1811 return BlockDataRegion::referenced_vars_iterator(nullptr, nullptr);
1812
1813 auto *VecOriginal =
1814 static_cast<BumpVector<const MemRegion *> *>(OriginalVars);
1815
1816 return BlockDataRegion::referenced_vars_iterator(Vec->end(),
1817 VecOriginal->end());
1818 }
1819
1820 llvm::iterator_range<BlockDataRegion::referenced_vars_iterator>
referenced_vars() const1821 BlockDataRegion::referenced_vars() const {
1822 return llvm::make_range(referenced_vars_begin(), referenced_vars_end());
1823 }
1824
getOriginalRegion(const VarRegion * R) const1825 const VarRegion *BlockDataRegion::getOriginalRegion(const VarRegion *R) const {
1826 for (const auto &I : referenced_vars()) {
1827 if (I.getCapturedRegion() == R)
1828 return I.getOriginalRegion();
1829 }
1830 return nullptr;
1831 }
1832
1833 //===----------------------------------------------------------------------===//
1834 // RegionAndSymbolInvalidationTraits
1835 //===----------------------------------------------------------------------===//
1836
setTrait(SymbolRef Sym,InvalidationKinds IK)1837 void RegionAndSymbolInvalidationTraits::setTrait(SymbolRef Sym,
1838 InvalidationKinds IK) {
1839 SymTraitsMap[Sym] |= IK;
1840 }
1841
setTrait(const MemRegion * MR,InvalidationKinds IK)1842 void RegionAndSymbolInvalidationTraits::setTrait(const MemRegion *MR,
1843 InvalidationKinds IK) {
1844 assert(MR);
1845 if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
1846 setTrait(SR->getSymbol(), IK);
1847 else
1848 MRTraitsMap[MR] |= IK;
1849 }
1850
hasTrait(SymbolRef Sym,InvalidationKinds IK) const1851 bool RegionAndSymbolInvalidationTraits::hasTrait(SymbolRef Sym,
1852 InvalidationKinds IK) const {
1853 const_symbol_iterator I = SymTraitsMap.find(Sym);
1854 if (I != SymTraitsMap.end())
1855 return I->second & IK;
1856
1857 return false;
1858 }
1859
hasTrait(const MemRegion * MR,InvalidationKinds IK) const1860 bool RegionAndSymbolInvalidationTraits::hasTrait(const MemRegion *MR,
1861 InvalidationKinds IK) const {
1862 if (!MR)
1863 return false;
1864
1865 if (const auto *SR = dyn_cast<SymbolicRegion>(MR))
1866 return hasTrait(SR->getSymbol(), IK);
1867
1868 const_region_iterator I = MRTraitsMap.find(MR);
1869 if (I != MRTraitsMap.end())
1870 return I->second & IK;
1871
1872 return false;
1873 }
1874