xref: /freebsd/contrib/llvm-project/clang/lib/StaticAnalyzer/Core/MemRegion.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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