1 //==- MemRegion.h - Abstract memory regions for static analysis -*- C++ -*--==//
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 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
16 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
17
18 #include "clang/AST/ASTContext.h"
19 #include "clang/AST/CharUnits.h"
20 #include "clang/AST/Decl.h"
21 #include "clang/AST/DeclObjC.h"
22 #include "clang/AST/DeclarationName.h"
23 #include "clang/AST/Expr.h"
24 #include "clang/AST/ExprObjC.h"
25 #include "clang/AST/Type.h"
26 #include "clang/Analysis/AnalysisDeclContext.h"
27 #include "clang/Basic/LLVM.h"
28 #include "clang/Basic/SourceLocation.h"
29 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
30 #include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
31 #include "llvm/ADT/DenseMap.h"
32 #include "llvm/ADT/FoldingSet.h"
33 #include "llvm/ADT/Optional.h"
34 #include "llvm/ADT/PointerIntPair.h"
35 #include "llvm/Support/Allocator.h"
36 #include "llvm/Support/Casting.h"
37 #include <cassert>
38 #include <cstdint>
39 #include <limits>
40 #include <string>
41 #include <utility>
42
43 namespace clang {
44
45 class AnalysisDeclContext;
46 class CXXRecordDecl;
47 class Decl;
48 class LocationContext;
49 class StackFrameContext;
50
51 namespace ento {
52
53 class CodeTextRegion;
54 class MemRegion;
55 class MemRegionManager;
56 class MemSpaceRegion;
57 class SValBuilder;
58 class SymbolicRegion;
59 class VarRegion;
60
61 /// Represent a region's offset within the top level base region.
62 class RegionOffset {
63 /// The base region.
64 const MemRegion *R = nullptr;
65
66 /// The bit offset within the base region. Can be negative.
67 int64_t Offset;
68
69 public:
70 // We're using a const instead of an enumeration due to the size required;
71 // Visual Studio will only create enumerations of size int, not long long.
72 static const int64_t Symbolic = std::numeric_limits<int64_t>::max();
73
74 RegionOffset() = default;
RegionOffset(const MemRegion * r,int64_t off)75 RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
76
77 /// It might return null.
getRegion()78 const MemRegion *getRegion() const { return R; }
79
hasSymbolicOffset()80 bool hasSymbolicOffset() const { return Offset == Symbolic; }
81
getOffset()82 int64_t getOffset() const {
83 assert(!hasSymbolicOffset());
84 return Offset;
85 }
86
isValid()87 bool isValid() const { return R; }
88 };
89
90 //===----------------------------------------------------------------------===//
91 // Base region classes.
92 //===----------------------------------------------------------------------===//
93
94 /// MemRegion - The root abstract class for all memory regions.
95 class MemRegion : public llvm::FoldingSetNode {
96 public:
97 enum Kind {
98 #define REGION(Id, Parent) Id ## Kind,
99 #define REGION_RANGE(Id, First, Last) BEGIN_##Id = First, END_##Id = Last,
100 #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def"
101 };
102
103 private:
104 const Kind kind;
105 mutable Optional<RegionOffset> cachedOffset;
106
107 protected:
MemRegion(Kind k)108 MemRegion(Kind k) : kind(k) {}
109 virtual ~MemRegion();
110
111 public:
112 ASTContext &getContext() const;
113
114 virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
115
116 virtual MemRegionManager &getMemRegionManager() const = 0;
117
118 LLVM_ATTRIBUTE_RETURNS_NONNULL const MemSpaceRegion *getMemorySpace() const;
119
120 LLVM_ATTRIBUTE_RETURNS_NONNULL const MemRegion *getBaseRegion() const;
121
122 /// Recursively retrieve the region of the most derived class instance of
123 /// regions of C++ base class instances.
124 LLVM_ATTRIBUTE_RETURNS_NONNULL
125 const MemRegion *getMostDerivedObjectRegion() const;
126
127 /// Check if the region is a subregion of the given region.
128 /// Each region is a subregion of itself.
129 virtual bool isSubRegionOf(const MemRegion *R) const;
130
131 LLVM_ATTRIBUTE_RETURNS_NONNULL
132 const MemRegion *StripCasts(bool StripBaseAndDerivedCasts = true) const;
133
134 /// If this is a symbolic region, returns the region. Otherwise,
135 /// goes up the base chain looking for the first symbolic base region.
136 /// It might return null.
137 const SymbolicRegion *getSymbolicBase() const;
138
139 bool hasGlobalsOrParametersStorage() const;
140
141 bool hasStackStorage() const;
142
143 bool hasStackNonParametersStorage() const;
144
145 bool hasStackParametersStorage() const;
146
147 /// Compute the offset within the top level memory object.
148 RegionOffset getAsOffset() const;
149
150 /// Get a string representation of a region for debug use.
151 std::string getString() const;
152
153 virtual void dumpToStream(raw_ostream &os) const;
154
155 void dump() const;
156
157 /// Returns true if this region can be printed in a user-friendly way.
158 virtual bool canPrintPretty() const;
159
160 /// Print the region for use in diagnostics.
161 virtual void printPretty(raw_ostream &os) const;
162
163 /// Returns true if this region's textual representation can be used
164 /// as part of a larger expression.
165 virtual bool canPrintPrettyAsExpr() const;
166
167 /// Print the region as expression.
168 ///
169 /// When this region represents a subexpression, the method is for printing
170 /// an expression containing it.
171 virtual void printPrettyAsExpr(raw_ostream &os) const;
172
getKind()173 Kind getKind() const { return kind; }
174
175 template<typename RegionTy> const RegionTy* getAs() const;
176 template <typename RegionTy>
177 LLVM_ATTRIBUTE_RETURNS_NONNULL const RegionTy *castAs() const;
178
isBoundable()179 virtual bool isBoundable() const { return false; }
180
181 /// Get descriptive name for memory region. The name is obtained from
182 /// the variable/field declaration retrieved from the memory region.
183 /// Regions that point to an element of an array are returned as: "arr[0]".
184 /// Regions that point to a struct are returned as: "st.var".
185 //
186 /// \param UseQuotes Set if the name should be quoted.
187 ///
188 /// \returns variable name for memory region
189 std::string getDescriptiveName(bool UseQuotes = true) const;
190
191 /// Retrieve source range from memory region. The range retrieval
192 /// is based on the decl obtained from the memory region.
193 /// For a VarRegion the range of the base region is returned.
194 /// For a FieldRegion the range of the field is returned.
195 /// If no declaration is found, an empty source range is returned.
196 /// The client is responsible for checking if the returned range is valid.
197 ///
198 /// \returns source range for declaration retrieved from memory region
199 SourceRange sourceRange() const;
200 };
201
202 /// MemSpaceRegion - A memory region that represents a "memory space";
203 /// for example, the set of global variables, the stack frame, etc.
204 class MemSpaceRegion : public MemRegion {
205 protected:
206 MemRegionManager &Mgr;
207
MemSpaceRegion(MemRegionManager & mgr,Kind k)208 MemSpaceRegion(MemRegionManager &mgr, Kind k) : MemRegion(k), Mgr(mgr) {
209 assert(classof(this));
210 }
211
getMemRegionManager()212 MemRegionManager &getMemRegionManager() const override { return Mgr; }
213
214 public:
isBoundable()215 bool isBoundable() const override { return false; }
216
217 void Profile(llvm::FoldingSetNodeID &ID) const override;
218
classof(const MemRegion * R)219 static bool classof(const MemRegion *R) {
220 Kind k = R->getKind();
221 return k >= BEGIN_MEMSPACES && k <= END_MEMSPACES;
222 }
223 };
224
225 /// CodeSpaceRegion - The memory space that holds the executable code of
226 /// functions and blocks.
227 class CodeSpaceRegion : public MemSpaceRegion {
228 friend class MemRegionManager;
229
CodeSpaceRegion(MemRegionManager & mgr)230 CodeSpaceRegion(MemRegionManager &mgr)
231 : MemSpaceRegion(mgr, CodeSpaceRegionKind) {}
232
233 public:
234 void dumpToStream(raw_ostream &os) const override;
235
classof(const MemRegion * R)236 static bool classof(const MemRegion *R) {
237 return R->getKind() == CodeSpaceRegionKind;
238 }
239 };
240
241 class GlobalsSpaceRegion : public MemSpaceRegion {
242 virtual void anchor();
243
244 protected:
GlobalsSpaceRegion(MemRegionManager & mgr,Kind k)245 GlobalsSpaceRegion(MemRegionManager &mgr, Kind k) : MemSpaceRegion(mgr, k) {
246 assert(classof(this));
247 }
248
249 public:
classof(const MemRegion * R)250 static bool classof(const MemRegion *R) {
251 Kind k = R->getKind();
252 return k >= BEGIN_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
253 }
254 };
255
256 /// The region of the static variables within the current CodeTextRegion
257 /// scope.
258 ///
259 /// Currently, only the static locals are placed there, so we know that these
260 /// variables do not get invalidated by calls to other functions.
261 class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
262 friend class MemRegionManager;
263
264 const CodeTextRegion *CR;
265
StaticGlobalSpaceRegion(MemRegionManager & mgr,const CodeTextRegion * cr)266 StaticGlobalSpaceRegion(MemRegionManager &mgr, const CodeTextRegion *cr)
267 : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {
268 assert(cr);
269 }
270
271 public:
272 void Profile(llvm::FoldingSetNodeID &ID) const override;
273
274 void dumpToStream(raw_ostream &os) const override;
275
276 LLVM_ATTRIBUTE_RETURNS_NONNULL
getCodeRegion()277 const CodeTextRegion *getCodeRegion() const { return CR; }
278
classof(const MemRegion * R)279 static bool classof(const MemRegion *R) {
280 return R->getKind() == StaticGlobalSpaceRegionKind;
281 }
282 };
283
284 /// The region for all the non-static global variables.
285 ///
286 /// This class is further split into subclasses for efficient implementation of
287 /// invalidating a set of related global values as is done in
288 /// RegionStoreManager::invalidateRegions (instead of finding all the dependent
289 /// globals, we invalidate the whole parent region).
290 class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
291 void anchor() override;
292
293 protected:
NonStaticGlobalSpaceRegion(MemRegionManager & mgr,Kind k)294 NonStaticGlobalSpaceRegion(MemRegionManager &mgr, Kind k)
295 : GlobalsSpaceRegion(mgr, k) {
296 assert(classof(this));
297 }
298
299 public:
classof(const MemRegion * R)300 static bool classof(const MemRegion *R) {
301 Kind k = R->getKind();
302 return k >= BEGIN_NON_STATIC_GLOBAL_MEMSPACES &&
303 k <= END_NON_STATIC_GLOBAL_MEMSPACES;
304 }
305 };
306
307 /// The region containing globals which are defined in system/external
308 /// headers and are considered modifiable by system calls (ex: errno).
309 class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion {
310 friend class MemRegionManager;
311
GlobalSystemSpaceRegion(MemRegionManager & mgr)312 GlobalSystemSpaceRegion(MemRegionManager &mgr)
313 : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {}
314
315 public:
316 void dumpToStream(raw_ostream &os) const override;
317
classof(const MemRegion * R)318 static bool classof(const MemRegion *R) {
319 return R->getKind() == GlobalSystemSpaceRegionKind;
320 }
321 };
322
323 /// The region containing globals which are considered not to be modified
324 /// or point to data which could be modified as a result of a function call
325 /// (system or internal). Ex: Const global scalars would be modeled as part of
326 /// this region. This region also includes most system globals since they have
327 /// low chance of being modified.
328 class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion {
329 friend class MemRegionManager;
330
GlobalImmutableSpaceRegion(MemRegionManager & mgr)331 GlobalImmutableSpaceRegion(MemRegionManager &mgr)
332 : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {}
333
334 public:
335 void dumpToStream(raw_ostream &os) const override;
336
classof(const MemRegion * R)337 static bool classof(const MemRegion *R) {
338 return R->getKind() == GlobalImmutableSpaceRegionKind;
339 }
340 };
341
342 /// The region containing globals which can be modified by calls to
343 /// "internally" defined functions - (for now just) functions other then system
344 /// calls.
345 class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
346 friend class MemRegionManager;
347
GlobalInternalSpaceRegion(MemRegionManager & mgr)348 GlobalInternalSpaceRegion(MemRegionManager &mgr)
349 : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {}
350
351 public:
352 void dumpToStream(raw_ostream &os) const override;
353
classof(const MemRegion * R)354 static bool classof(const MemRegion *R) {
355 return R->getKind() == GlobalInternalSpaceRegionKind;
356 }
357 };
358
359 class HeapSpaceRegion : public MemSpaceRegion {
360 friend class MemRegionManager;
361
HeapSpaceRegion(MemRegionManager & mgr)362 HeapSpaceRegion(MemRegionManager &mgr)
363 : MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
364
365 public:
366 void dumpToStream(raw_ostream &os) const override;
367
classof(const MemRegion * R)368 static bool classof(const MemRegion *R) {
369 return R->getKind() == HeapSpaceRegionKind;
370 }
371 };
372
373 class UnknownSpaceRegion : public MemSpaceRegion {
374 friend class MemRegionManager;
375
UnknownSpaceRegion(MemRegionManager & mgr)376 UnknownSpaceRegion(MemRegionManager &mgr)
377 : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
378
379 public:
380 void dumpToStream(raw_ostream &os) const override;
381
classof(const MemRegion * R)382 static bool classof(const MemRegion *R) {
383 return R->getKind() == UnknownSpaceRegionKind;
384 }
385 };
386
387 class StackSpaceRegion : public MemSpaceRegion {
388 virtual void anchor();
389
390 const StackFrameContext *SFC;
391
392 protected:
StackSpaceRegion(MemRegionManager & mgr,Kind k,const StackFrameContext * sfc)393 StackSpaceRegion(MemRegionManager &mgr, Kind k, const StackFrameContext *sfc)
394 : MemSpaceRegion(mgr, k), SFC(sfc) {
395 assert(classof(this));
396 assert(sfc);
397 }
398
399 public:
400 LLVM_ATTRIBUTE_RETURNS_NONNULL
getStackFrame()401 const StackFrameContext *getStackFrame() const { return SFC; }
402
403 void Profile(llvm::FoldingSetNodeID &ID) const override;
404
classof(const MemRegion * R)405 static bool classof(const MemRegion *R) {
406 Kind k = R->getKind();
407 return k >= BEGIN_STACK_MEMSPACES && k <= END_STACK_MEMSPACES;
408 }
409 };
410
411 class StackLocalsSpaceRegion : public StackSpaceRegion {
412 friend class MemRegionManager;
413
StackLocalsSpaceRegion(MemRegionManager & mgr,const StackFrameContext * sfc)414 StackLocalsSpaceRegion(MemRegionManager &mgr, const StackFrameContext *sfc)
415 : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
416
417 public:
418 void dumpToStream(raw_ostream &os) const override;
419
classof(const MemRegion * R)420 static bool classof(const MemRegion *R) {
421 return R->getKind() == StackLocalsSpaceRegionKind;
422 }
423 };
424
425 class StackArgumentsSpaceRegion : public StackSpaceRegion {
426 private:
427 friend class MemRegionManager;
428
StackArgumentsSpaceRegion(MemRegionManager & mgr,const StackFrameContext * sfc)429 StackArgumentsSpaceRegion(MemRegionManager &mgr, const StackFrameContext *sfc)
430 : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
431
432 public:
433 void dumpToStream(raw_ostream &os) const override;
434
classof(const MemRegion * R)435 static bool classof(const MemRegion *R) {
436 return R->getKind() == StackArgumentsSpaceRegionKind;
437 }
438 };
439
440 /// SubRegion - A region that subsets another larger region. Most regions
441 /// are subclasses of SubRegion.
442 class SubRegion : public MemRegion {
443 virtual void anchor();
444
445 protected:
446 const MemRegion* superRegion;
447
SubRegion(const MemRegion * sReg,Kind k)448 SubRegion(const MemRegion *sReg, Kind k) : MemRegion(k), superRegion(sReg) {
449 assert(classof(this));
450 assert(sReg);
451 }
452
453 public:
454 LLVM_ATTRIBUTE_RETURNS_NONNULL
getSuperRegion()455 const MemRegion* getSuperRegion() const {
456 return superRegion;
457 }
458
459 MemRegionManager &getMemRegionManager() const override;
460
461 bool isSubRegionOf(const MemRegion* R) const override;
462
classof(const MemRegion * R)463 static bool classof(const MemRegion* R) {
464 return R->getKind() > END_MEMSPACES;
465 }
466 };
467
468 //===----------------------------------------------------------------------===//
469 // MemRegion subclasses.
470 //===----------------------------------------------------------------------===//
471
472 /// AllocaRegion - A region that represents an untyped blob of bytes created
473 /// by a call to 'alloca'.
474 class AllocaRegion : public SubRegion {
475 friend class MemRegionManager;
476
477 // Block counter. Used to distinguish different pieces of memory allocated by
478 // alloca at the same call site.
479 unsigned Cnt;
480
481 const Expr *Ex;
482
AllocaRegion(const Expr * ex,unsigned cnt,const MemSpaceRegion * superRegion)483 AllocaRegion(const Expr *ex, unsigned cnt, const MemSpaceRegion *superRegion)
484 : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {
485 assert(Ex);
486 }
487
488 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex,
489 unsigned Cnt, const MemRegion *superRegion);
490
491 public:
492 LLVM_ATTRIBUTE_RETURNS_NONNULL
getExpr()493 const Expr *getExpr() const { return Ex; }
494
isBoundable()495 bool isBoundable() const override { return true; }
496
497 void Profile(llvm::FoldingSetNodeID& ID) const override;
498
499 void dumpToStream(raw_ostream &os) const override;
500
classof(const MemRegion * R)501 static bool classof(const MemRegion* R) {
502 return R->getKind() == AllocaRegionKind;
503 }
504 };
505
506 /// TypedRegion - An abstract class representing regions that are typed.
507 class TypedRegion : public SubRegion {
508 void anchor() override;
509
510 protected:
TypedRegion(const MemRegion * sReg,Kind k)511 TypedRegion(const MemRegion *sReg, Kind k) : SubRegion(sReg, k) {
512 assert(classof(this));
513 }
514
515 public:
516 virtual QualType getLocationType() const = 0;
517
getDesugaredLocationType(ASTContext & Context)518 QualType getDesugaredLocationType(ASTContext &Context) const {
519 return getLocationType().getDesugaredType(Context);
520 }
521
isBoundable()522 bool isBoundable() const override { return true; }
523
classof(const MemRegion * R)524 static bool classof(const MemRegion* R) {
525 unsigned k = R->getKind();
526 return k >= BEGIN_TYPED_REGIONS && k <= END_TYPED_REGIONS;
527 }
528 };
529
530 /// TypedValueRegion - An abstract class representing regions having a typed value.
531 class TypedValueRegion : public TypedRegion {
532 void anchor() override;
533
534 protected:
TypedValueRegion(const MemRegion * sReg,Kind k)535 TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {
536 assert(classof(this));
537 }
538
539 public:
540 virtual QualType getValueType() const = 0;
541
getLocationType()542 QualType getLocationType() const override {
543 // FIXME: We can possibly optimize this later to cache this value.
544 QualType T = getValueType();
545 ASTContext &ctx = getContext();
546 if (T->getAs<ObjCObjectType>())
547 return ctx.getObjCObjectPointerType(T);
548 return ctx.getPointerType(getValueType());
549 }
550
getDesugaredValueType(ASTContext & Context)551 QualType getDesugaredValueType(ASTContext &Context) const {
552 QualType T = getValueType();
553 return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
554 }
555
classof(const MemRegion * R)556 static bool classof(const MemRegion* R) {
557 unsigned k = R->getKind();
558 return k >= BEGIN_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
559 }
560 };
561
562 class CodeTextRegion : public TypedRegion {
563 void anchor() override;
564
565 protected:
CodeTextRegion(const MemSpaceRegion * sreg,Kind k)566 CodeTextRegion(const MemSpaceRegion *sreg, Kind k) : TypedRegion(sreg, k) {
567 assert(classof(this));
568 }
569
570 public:
isBoundable()571 bool isBoundable() const override { return false; }
572
classof(const MemRegion * R)573 static bool classof(const MemRegion* R) {
574 Kind k = R->getKind();
575 return k >= BEGIN_CODE_TEXT_REGIONS && k <= END_CODE_TEXT_REGIONS;
576 }
577 };
578
579 /// FunctionCodeRegion - A region that represents code texts of function.
580 class FunctionCodeRegion : public CodeTextRegion {
581 friend class MemRegionManager;
582
583 const NamedDecl *FD;
584
FunctionCodeRegion(const NamedDecl * fd,const CodeSpaceRegion * sreg)585 FunctionCodeRegion(const NamedDecl *fd, const CodeSpaceRegion* sreg)
586 : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) {
587 assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
588 }
589
590 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD,
591 const MemRegion*);
592
593 public:
getLocationType()594 QualType getLocationType() const override {
595 const ASTContext &Ctx = getContext();
596 if (const auto *D = dyn_cast<FunctionDecl>(FD)) {
597 return Ctx.getPointerType(D->getType());
598 }
599
600 assert(isa<ObjCMethodDecl>(FD));
601 assert(false && "Getting the type of ObjCMethod is not supported yet");
602
603 // TODO: We might want to return a different type here (ex: id (*ty)(...))
604 // depending on how it is used.
605 return {};
606 }
607
getDecl()608 const NamedDecl *getDecl() const {
609 return FD;
610 }
611
612 void dumpToStream(raw_ostream &os) const override;
613
614 void Profile(llvm::FoldingSetNodeID& ID) const override;
615
classof(const MemRegion * R)616 static bool classof(const MemRegion* R) {
617 return R->getKind() == FunctionCodeRegionKind;
618 }
619 };
620
621 /// BlockCodeRegion - A region that represents code texts of blocks (closures).
622 /// Blocks are represented with two kinds of regions. BlockCodeRegions
623 /// represent the "code", while BlockDataRegions represent instances of blocks,
624 /// which correspond to "code+data". The distinction is important, because
625 /// like a closure a block captures the values of externally referenced
626 /// variables.
627 class BlockCodeRegion : public CodeTextRegion {
628 friend class MemRegionManager;
629
630 const BlockDecl *BD;
631 AnalysisDeclContext *AC;
632 CanQualType locTy;
633
BlockCodeRegion(const BlockDecl * bd,CanQualType lTy,AnalysisDeclContext * ac,const CodeSpaceRegion * sreg)634 BlockCodeRegion(const BlockDecl *bd, CanQualType lTy,
635 AnalysisDeclContext *ac, const CodeSpaceRegion* sreg)
636 : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {
637 assert(bd);
638 assert(ac);
639 assert(lTy->getTypePtr()->isBlockPointerType());
640 }
641
642 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
643 CanQualType, const AnalysisDeclContext*,
644 const MemRegion*);
645
646 public:
getLocationType()647 QualType getLocationType() const override {
648 return locTy;
649 }
650
651 LLVM_ATTRIBUTE_RETURNS_NONNULL
getDecl()652 const BlockDecl *getDecl() const {
653 return BD;
654 }
655
656 LLVM_ATTRIBUTE_RETURNS_NONNULL
getAnalysisDeclContext()657 AnalysisDeclContext *getAnalysisDeclContext() const { return AC; }
658
659 void dumpToStream(raw_ostream &os) const override;
660
661 void Profile(llvm::FoldingSetNodeID& ID) const override;
662
classof(const MemRegion * R)663 static bool classof(const MemRegion* R) {
664 return R->getKind() == BlockCodeRegionKind;
665 }
666 };
667
668 /// BlockDataRegion - A region that represents a block instance.
669 /// Blocks are represented with two kinds of regions. BlockCodeRegions
670 /// represent the "code", while BlockDataRegions represent instances of blocks,
671 /// which correspond to "code+data". The distinction is important, because
672 /// like a closure a block captures the values of externally referenced
673 /// variables.
674 class BlockDataRegion : public TypedRegion {
675 friend class MemRegionManager;
676
677 const BlockCodeRegion *BC;
678 const LocationContext *LC; // Can be null
679 unsigned BlockCount;
680 void *ReferencedVars = nullptr;
681 void *OriginalVars = nullptr;
682
BlockDataRegion(const BlockCodeRegion * bc,const LocationContext * lc,unsigned count,const MemSpaceRegion * sreg)683 BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc,
684 unsigned count, const MemSpaceRegion *sreg)
685 : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
686 BlockCount(count) {
687 assert(bc);
688 assert(bc->getDecl());
689 assert(lc);
690 assert(isa<GlobalImmutableSpaceRegion>(sreg) ||
691 isa<StackLocalsSpaceRegion>(sreg) ||
692 isa<UnknownSpaceRegion>(sreg));
693 }
694
695 static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *,
696 const LocationContext *, unsigned,
697 const MemRegion *);
698
699 public:
700 LLVM_ATTRIBUTE_RETURNS_NONNULL
getCodeRegion()701 const BlockCodeRegion *getCodeRegion() const { return BC; }
702
703 LLVM_ATTRIBUTE_RETURNS_NONNULL
getDecl()704 const BlockDecl *getDecl() const { return BC->getDecl(); }
705
getLocationType()706 QualType getLocationType() const override { return BC->getLocationType(); }
707
708 class referenced_vars_iterator {
709 const MemRegion * const *R;
710 const MemRegion * const *OriginalR;
711
712 public:
referenced_vars_iterator(const MemRegion * const * r,const MemRegion * const * originalR)713 explicit referenced_vars_iterator(const MemRegion * const *r,
714 const MemRegion * const *originalR)
715 : R(r), OriginalR(originalR) {}
716
717 LLVM_ATTRIBUTE_RETURNS_NONNULL
getCapturedRegion()718 const VarRegion *getCapturedRegion() const {
719 return cast<VarRegion>(*R);
720 }
721
722 LLVM_ATTRIBUTE_RETURNS_NONNULL
getOriginalRegion()723 const VarRegion *getOriginalRegion() const {
724 return cast<VarRegion>(*OriginalR);
725 }
726
727 bool operator==(const referenced_vars_iterator &I) const {
728 assert((R == nullptr) == (I.R == nullptr));
729 return I.R == R;
730 }
731
732 bool operator!=(const referenced_vars_iterator &I) const {
733 assert((R == nullptr) == (I.R == nullptr));
734 return I.R != R;
735 }
736
737 referenced_vars_iterator &operator++() {
738 ++R;
739 ++OriginalR;
740 return *this;
741 }
742 };
743
744 /// Return the original region for a captured region, if
745 /// one exists. It might return null.
746 const VarRegion *getOriginalRegion(const VarRegion *VR) const;
747
748 referenced_vars_iterator referenced_vars_begin() const;
749 referenced_vars_iterator referenced_vars_end() const;
750
751 void dumpToStream(raw_ostream &os) const override;
752
753 void Profile(llvm::FoldingSetNodeID& ID) const override;
754
classof(const MemRegion * R)755 static bool classof(const MemRegion* R) {
756 return R->getKind() == BlockDataRegionKind;
757 }
758
759 private:
760 void LazyInitializeReferencedVars();
761 std::pair<const VarRegion *, const VarRegion *>
762 getCaptureRegions(const VarDecl *VD);
763 };
764
765 /// SymbolicRegion - A special, "non-concrete" region. Unlike other region
766 /// classes, SymbolicRegion represents a region that serves as an alias for
767 /// either a real region, a NULL pointer, etc. It essentially is used to
768 /// map the concept of symbolic values into the domain of regions. Symbolic
769 /// regions do not need to be typed.
770 class SymbolicRegion : public SubRegion {
771 friend class MemRegionManager;
772
773 const SymbolRef sym;
774
SymbolicRegion(const SymbolRef s,const MemSpaceRegion * sreg)775 SymbolicRegion(const SymbolRef s, const MemSpaceRegion *sreg)
776 : SubRegion(sreg, SymbolicRegionKind), sym(s) {
777 // Because pointer arithmetic is represented by ElementRegion layers,
778 // the base symbol here should not contain any arithmetic.
779 assert(s && isa<SymbolData>(s));
780 assert(s->getType()->isAnyPointerType() ||
781 s->getType()->isReferenceType() ||
782 s->getType()->isBlockPointerType());
783 assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg) ||
784 isa<GlobalSystemSpaceRegion>(sreg));
785 }
786
787 public:
788 /// It might return null.
getSymbol()789 SymbolRef getSymbol() const { return sym; }
790
isBoundable()791 bool isBoundable() const override { return true; }
792
793 void Profile(llvm::FoldingSetNodeID& ID) const override;
794
795 static void ProfileRegion(llvm::FoldingSetNodeID& ID,
796 SymbolRef sym,
797 const MemRegion* superRegion);
798
799 void dumpToStream(raw_ostream &os) const override;
800
classof(const MemRegion * R)801 static bool classof(const MemRegion* R) {
802 return R->getKind() == SymbolicRegionKind;
803 }
804 };
805
806 /// StringRegion - Region associated with a StringLiteral.
807 class StringRegion : public TypedValueRegion {
808 friend class MemRegionManager;
809
810 const StringLiteral *Str;
811
StringRegion(const StringLiteral * str,const GlobalInternalSpaceRegion * sreg)812 StringRegion(const StringLiteral *str, const GlobalInternalSpaceRegion *sreg)
813 : TypedValueRegion(sreg, StringRegionKind), Str(str) {
814 assert(str);
815 }
816
817 static void ProfileRegion(llvm::FoldingSetNodeID &ID,
818 const StringLiteral *Str,
819 const MemRegion *superRegion);
820
821 public:
822 LLVM_ATTRIBUTE_RETURNS_NONNULL
getStringLiteral()823 const StringLiteral *getStringLiteral() const { return Str; }
824
getValueType()825 QualType getValueType() const override { return Str->getType(); }
826
isBoundable()827 bool isBoundable() const override { return false; }
828
Profile(llvm::FoldingSetNodeID & ID)829 void Profile(llvm::FoldingSetNodeID& ID) const override {
830 ProfileRegion(ID, Str, superRegion);
831 }
832
833 void dumpToStream(raw_ostream &os) const override;
834
classof(const MemRegion * R)835 static bool classof(const MemRegion* R) {
836 return R->getKind() == StringRegionKind;
837 }
838 };
839
840 /// The region associated with an ObjCStringLiteral.
841 class ObjCStringRegion : public TypedValueRegion {
842 friend class MemRegionManager;
843
844 const ObjCStringLiteral *Str;
845
ObjCStringRegion(const ObjCStringLiteral * str,const GlobalInternalSpaceRegion * sreg)846 ObjCStringRegion(const ObjCStringLiteral *str,
847 const GlobalInternalSpaceRegion *sreg)
848 : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {
849 assert(str);
850 }
851
852 static void ProfileRegion(llvm::FoldingSetNodeID &ID,
853 const ObjCStringLiteral *Str,
854 const MemRegion *superRegion);
855
856 public:
857 LLVM_ATTRIBUTE_RETURNS_NONNULL
getObjCStringLiteral()858 const ObjCStringLiteral *getObjCStringLiteral() const { return Str; }
859
getValueType()860 QualType getValueType() const override { return Str->getType(); }
861
isBoundable()862 bool isBoundable() const override { return false; }
863
Profile(llvm::FoldingSetNodeID & ID)864 void Profile(llvm::FoldingSetNodeID& ID) const override {
865 ProfileRegion(ID, Str, superRegion);
866 }
867
868 void dumpToStream(raw_ostream &os) const override;
869
classof(const MemRegion * R)870 static bool classof(const MemRegion* R) {
871 return R->getKind() == ObjCStringRegionKind;
872 }
873 };
874
875 /// CompoundLiteralRegion - A memory region representing a compound literal.
876 /// Compound literals are essentially temporaries that are stack allocated
877 /// or in the global constant pool.
878 class CompoundLiteralRegion : public TypedValueRegion {
879 friend class MemRegionManager;
880
881 const CompoundLiteralExpr *CL;
882
CompoundLiteralRegion(const CompoundLiteralExpr * cl,const MemSpaceRegion * sReg)883 CompoundLiteralRegion(const CompoundLiteralExpr *cl,
884 const MemSpaceRegion *sReg)
885 : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {
886 assert(cl);
887 assert(isa<GlobalInternalSpaceRegion>(sReg) ||
888 isa<StackLocalsSpaceRegion>(sReg));
889 }
890
891 static void ProfileRegion(llvm::FoldingSetNodeID& ID,
892 const CompoundLiteralExpr *CL,
893 const MemRegion* superRegion);
894
895 public:
getValueType()896 QualType getValueType() const override { return CL->getType(); }
897
isBoundable()898 bool isBoundable() const override { return !CL->isFileScope(); }
899
900 void Profile(llvm::FoldingSetNodeID& ID) const override;
901
902 void dumpToStream(raw_ostream &os) const override;
903
904 LLVM_ATTRIBUTE_RETURNS_NONNULL
getLiteralExpr()905 const CompoundLiteralExpr *getLiteralExpr() const { return CL; }
906
classof(const MemRegion * R)907 static bool classof(const MemRegion* R) {
908 return R->getKind() == CompoundLiteralRegionKind;
909 }
910 };
911
912 class DeclRegion : public TypedValueRegion {
913 protected:
DeclRegion(const MemRegion * sReg,Kind k)914 DeclRegion(const MemRegion *sReg, Kind k) : TypedValueRegion(sReg, k) {
915 assert(classof(this));
916 }
917
918 public:
919 // TODO what does this return?
920 virtual const ValueDecl *getDecl() const = 0;
921
classof(const MemRegion * R)922 static bool classof(const MemRegion* R) {
923 unsigned k = R->getKind();
924 return k >= BEGIN_DECL_REGIONS && k <= END_DECL_REGIONS;
925 }
926 };
927
928 class VarRegion : public DeclRegion {
929 friend class MemRegionManager;
930
931 protected:
932 // Constructors and protected methods.
VarRegion(const MemRegion * sReg,Kind k)933 VarRegion(const MemRegion *sReg, Kind k) : DeclRegion(sReg, k) {
934 // VarRegion appears in unknown space when it's a block variable as seen
935 // from a block using it, when this block is analyzed at top-level.
936 // Other block variables appear within block data regions,
937 // which, unlike everything else on this list, are not memory spaces.
938 assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) ||
939 isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg));
940 }
941
942 public:
943 // TODO what does this return?
944 const VarDecl *getDecl() const override = 0;
945
946 /// It might return null.
947 const StackFrameContext *getStackFrame() const;
948
getValueType()949 QualType getValueType() const override {
950 // FIXME: We can cache this if needed.
951 return getDecl()->getType();
952 }
953
classof(const MemRegion * R)954 static bool classof(const MemRegion *R) {
955 unsigned k = R->getKind();
956 return k >= BEGIN_VAR_REGIONS && k <= END_VAR_REGIONS;
957 }
958 };
959
960 class NonParamVarRegion : public VarRegion {
961 friend class MemRegionManager;
962
963 const VarDecl *VD;
964
965 // Constructors and private methods.
NonParamVarRegion(const VarDecl * vd,const MemRegion * sReg)966 NonParamVarRegion(const VarDecl *vd, const MemRegion *sReg)
967 : VarRegion(sReg, NonParamVarRegionKind), VD(vd) {
968 // VarRegion appears in unknown space when it's a block variable as seen
969 // from a block using it, when this block is analyzed at top-level.
970 // Other block variables appear within block data regions,
971 // which, unlike everything else on this list, are not memory spaces.
972 assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) ||
973 isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg));
974 assert(vd);
975 }
976
977 static void ProfileRegion(llvm::FoldingSetNodeID &ID, const VarDecl *VD,
978 const MemRegion *superRegion);
979
980 public:
981 void Profile(llvm::FoldingSetNodeID &ID) const override;
982
983 LLVM_ATTRIBUTE_RETURNS_NONNULL
getDecl()984 const VarDecl *getDecl() const override { return VD; }
985
getValueType()986 QualType getValueType() const override {
987 // FIXME: We can cache this if needed.
988 return getDecl()->getType();
989 }
990
991 void dumpToStream(raw_ostream &os) const override;
992
993 bool canPrintPrettyAsExpr() const override;
994
995 void printPrettyAsExpr(raw_ostream &os) const override;
996
classof(const MemRegion * R)997 static bool classof(const MemRegion* R) {
998 return R->getKind() == NonParamVarRegionKind;
999 }
1000 };
1001
1002 /// ParamVarRegion - Represents a region for paremters. Only parameters of the
1003 /// function in the current stack frame are represented as `ParamVarRegion`s.
1004 /// Parameters of top-level analyzed functions as well as captured paremeters
1005 /// by lambdas and blocks are repesented as `VarRegion`s.
1006
1007 // FIXME: `ParamVarRegion` only supports parameters of functions, C++
1008 // constructors, blocks and Objective-C methods with existing `Decl`. Upon
1009 // implementing stack frame creations for functions without decl (functions
1010 // passed by unknown function pointer) methods of `ParamVarRegion` must be
1011 // updated.
1012 class ParamVarRegion : public VarRegion {
1013 friend class MemRegionManager;
1014
1015 const Expr *OriginExpr;
1016 unsigned Index;
1017
ParamVarRegion(const Expr * OE,unsigned Idx,const MemRegion * SReg)1018 ParamVarRegion(const Expr *OE, unsigned Idx, const MemRegion *SReg)
1019 : VarRegion(SReg, ParamVarRegionKind), OriginExpr(OE), Index(Idx) {
1020 assert(!cast<StackSpaceRegion>(SReg)->getStackFrame()->inTopFrame());
1021 assert(OriginExpr);
1022 }
1023
1024 static void ProfileRegion(llvm::FoldingSetNodeID &ID, const Expr *OE,
1025 unsigned Idx, const MemRegion *SReg);
1026
1027 public:
1028 LLVM_ATTRIBUTE_RETURNS_NONNULL
getOriginExpr()1029 const Expr *getOriginExpr() const { return OriginExpr; }
getIndex()1030 unsigned getIndex() const { return Index; }
1031
1032 void Profile(llvm::FoldingSetNodeID& ID) const override;
1033
1034 void dumpToStream(raw_ostream &os) const override;
1035
1036 QualType getValueType() const override;
1037
1038 /// TODO: What does this return?
1039 const ParmVarDecl *getDecl() const override;
1040
1041 bool canPrintPrettyAsExpr() const override;
1042 void printPrettyAsExpr(raw_ostream &os) const override;
1043
classof(const MemRegion * R)1044 static bool classof(const MemRegion *R) {
1045 return R->getKind() == ParamVarRegionKind;
1046 }
1047 };
1048
1049 /// CXXThisRegion - Represents the region for the implicit 'this' parameter
1050 /// in a call to a C++ method. This region doesn't represent the object
1051 /// referred to by 'this', but rather 'this' itself.
1052 class CXXThisRegion : public TypedValueRegion {
1053 friend class MemRegionManager;
1054
CXXThisRegion(const PointerType * thisPointerTy,const StackArgumentsSpaceRegion * sReg)1055 CXXThisRegion(const PointerType *thisPointerTy,
1056 const StackArgumentsSpaceRegion *sReg)
1057 : TypedValueRegion(sReg, CXXThisRegionKind),
1058 ThisPointerTy(thisPointerTy) {
1059 assert(ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() &&
1060 "Invalid region type!");
1061 }
1062
1063 static void ProfileRegion(llvm::FoldingSetNodeID &ID,
1064 const PointerType *PT,
1065 const MemRegion *sReg);
1066
1067 public:
1068 void Profile(llvm::FoldingSetNodeID &ID) const override;
1069
getValueType()1070 QualType getValueType() const override {
1071 return QualType(ThisPointerTy, 0);
1072 }
1073
1074 void dumpToStream(raw_ostream &os) const override;
1075
classof(const MemRegion * R)1076 static bool classof(const MemRegion* R) {
1077 return R->getKind() == CXXThisRegionKind;
1078 }
1079
1080 private:
1081 const PointerType *ThisPointerTy;
1082 };
1083
1084 class FieldRegion : public DeclRegion {
1085 friend class MemRegionManager;
1086
1087 const FieldDecl *FD;
1088
FieldRegion(const FieldDecl * fd,const SubRegion * sReg)1089 FieldRegion(const FieldDecl *fd, const SubRegion *sReg)
1090 : DeclRegion(sReg, FieldRegionKind), FD(fd) {
1091 assert(FD);
1092 }
1093
ProfileRegion(llvm::FoldingSetNodeID & ID,const FieldDecl * FD,const MemRegion * superRegion)1094 static void ProfileRegion(llvm::FoldingSetNodeID &ID, const FieldDecl *FD,
1095 const MemRegion* superRegion) {
1096 ID.AddInteger(static_cast<unsigned>(FieldRegionKind));
1097 ID.AddPointer(FD);
1098 ID.AddPointer(superRegion);
1099 }
1100
1101 public:
1102 LLVM_ATTRIBUTE_RETURNS_NONNULL
getDecl()1103 const FieldDecl *getDecl() const override { return FD; }
1104
1105 void Profile(llvm::FoldingSetNodeID &ID) const override;
1106
getValueType()1107 QualType getValueType() const override {
1108 // FIXME: We can cache this if needed.
1109 return getDecl()->getType();
1110 }
1111
1112 void dumpToStream(raw_ostream &os) const override;
1113
1114 bool canPrintPretty() const override;
1115 void printPretty(raw_ostream &os) const override;
1116 bool canPrintPrettyAsExpr() const override;
1117 void printPrettyAsExpr(raw_ostream &os) const override;
1118
classof(const MemRegion * R)1119 static bool classof(const MemRegion* R) {
1120 return R->getKind() == FieldRegionKind;
1121 }
1122 };
1123
1124 class ObjCIvarRegion : public DeclRegion {
1125 friend class MemRegionManager;
1126
1127 const ObjCIvarDecl *IVD;
1128
1129 ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg);
1130
1131 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd,
1132 const MemRegion* superRegion);
1133
1134 public:
1135 LLVM_ATTRIBUTE_RETURNS_NONNULL
1136 const ObjCIvarDecl *getDecl() const override;
1137
1138 void Profile(llvm::FoldingSetNodeID& ID) const override;
1139
1140 QualType getValueType() const override;
1141
1142 bool canPrintPrettyAsExpr() const override;
1143 void printPrettyAsExpr(raw_ostream &os) const override;
1144
1145 void dumpToStream(raw_ostream &os) const override;
1146
classof(const MemRegion * R)1147 static bool classof(const MemRegion* R) {
1148 return R->getKind() == ObjCIvarRegionKind;
1149 }
1150 };
1151
1152 //===----------------------------------------------------------------------===//
1153 // Auxiliary data classes for use with MemRegions.
1154 //===----------------------------------------------------------------------===//
1155
1156 class RegionRawOffset {
1157 friend class ElementRegion;
1158
1159 const MemRegion *Region;
1160 CharUnits Offset;
1161
1162 RegionRawOffset(const MemRegion* reg, CharUnits offset = CharUnits::Zero())
Region(reg)1163 : Region(reg), Offset(offset) {}
1164
1165 public:
1166 // FIXME: Eventually support symbolic offsets.
getOffset()1167 CharUnits getOffset() const { return Offset; }
1168
1169 // It might return null.
getRegion()1170 const MemRegion *getRegion() const { return Region; }
1171
1172 void dumpToStream(raw_ostream &os) const;
1173 void dump() const;
1174 };
1175
1176 /// ElementRegion is used to represent both array elements and casts.
1177 class ElementRegion : public TypedValueRegion {
1178 friend class MemRegionManager;
1179
1180 QualType ElementType;
1181 NonLoc Index;
1182
ElementRegion(QualType elementType,NonLoc Idx,const SubRegion * sReg)1183 ElementRegion(QualType elementType, NonLoc Idx, const SubRegion *sReg)
1184 : TypedValueRegion(sReg, ElementRegionKind), ElementType(elementType),
1185 Index(Idx) {
1186 assert((!isa<nonloc::ConcreteInt>(Idx) ||
1187 Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) &&
1188 "The index must be signed");
1189 assert(!elementType.isNull() && !elementType->isVoidType() &&
1190 "Invalid region type!");
1191 }
1192
1193 static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType,
1194 SVal Idx, const MemRegion* superRegion);
1195
1196 public:
getIndex()1197 NonLoc getIndex() const { return Index; }
1198
getValueType()1199 QualType getValueType() const override { return ElementType; }
1200
getElementType()1201 QualType getElementType() const { return ElementType; }
1202
1203 /// Compute the offset within the array. The array might also be a subobject.
1204 RegionRawOffset getAsArrayOffset() const;
1205
1206 void dumpToStream(raw_ostream &os) const override;
1207
1208 void Profile(llvm::FoldingSetNodeID& ID) const override;
1209
classof(const MemRegion * R)1210 static bool classof(const MemRegion* R) {
1211 return R->getKind() == ElementRegionKind;
1212 }
1213 };
1214
1215 // C++ temporary object associated with an expression.
1216 class CXXTempObjectRegion : public TypedValueRegion {
1217 friend class MemRegionManager;
1218
1219 Expr const *Ex;
1220
CXXTempObjectRegion(Expr const * E,MemSpaceRegion const * sReg)1221 CXXTempObjectRegion(Expr const *E, MemSpaceRegion const *sReg)
1222 : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {
1223 assert(E);
1224 assert(isa<StackLocalsSpaceRegion>(sReg) ||
1225 isa<GlobalInternalSpaceRegion>(sReg));
1226 }
1227
1228 static void ProfileRegion(llvm::FoldingSetNodeID &ID,
1229 Expr const *E, const MemRegion *sReg);
1230
1231 public:
1232 LLVM_ATTRIBUTE_RETURNS_NONNULL
getExpr()1233 const Expr *getExpr() const { return Ex; }
1234
getValueType()1235 QualType getValueType() const override { return Ex->getType(); }
1236
1237 void dumpToStream(raw_ostream &os) const override;
1238
1239 void Profile(llvm::FoldingSetNodeID &ID) const override;
1240
classof(const MemRegion * R)1241 static bool classof(const MemRegion* R) {
1242 return R->getKind() == CXXTempObjectRegionKind;
1243 }
1244 };
1245
1246 // CXXBaseObjectRegion represents a base object within a C++ object. It is
1247 // identified by the base class declaration and the region of its parent object.
1248 class CXXBaseObjectRegion : public TypedValueRegion {
1249 friend class MemRegionManager;
1250
1251 llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data;
1252
CXXBaseObjectRegion(const CXXRecordDecl * RD,bool IsVirtual,const SubRegion * SReg)1253 CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual,
1254 const SubRegion *SReg)
1255 : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {
1256 assert(RD);
1257 }
1258
1259 static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
1260 bool IsVirtual, const MemRegion *SReg);
1261
1262 public:
1263 LLVM_ATTRIBUTE_RETURNS_NONNULL
getDecl()1264 const CXXRecordDecl *getDecl() const { return Data.getPointer(); }
isVirtual()1265 bool isVirtual() const { return Data.getInt(); }
1266
1267 QualType getValueType() const override;
1268
1269 void dumpToStream(raw_ostream &os) const override;
1270
1271 void Profile(llvm::FoldingSetNodeID &ID) const override;
1272
1273 bool canPrintPrettyAsExpr() const override;
1274
1275 void printPrettyAsExpr(raw_ostream &os) const override;
1276
classof(const MemRegion * region)1277 static bool classof(const MemRegion *region) {
1278 return region->getKind() == CXXBaseObjectRegionKind;
1279 }
1280 };
1281
1282 // CXXDerivedObjectRegion represents a derived-class object that surrounds
1283 // a C++ object. It is identified by the derived class declaration and the
1284 // region of its parent object. It is a bit counter-intuitive (but not otherwise
1285 // unseen) that this region represents a larger segment of memory that its
1286 // super-region.
1287 class CXXDerivedObjectRegion : public TypedValueRegion {
1288 friend class MemRegionManager;
1289
1290 const CXXRecordDecl *DerivedD;
1291
CXXDerivedObjectRegion(const CXXRecordDecl * DerivedD,const SubRegion * SReg)1292 CXXDerivedObjectRegion(const CXXRecordDecl *DerivedD, const SubRegion *SReg)
1293 : TypedValueRegion(SReg, CXXDerivedObjectRegionKind), DerivedD(DerivedD) {
1294 assert(DerivedD);
1295 // In case of a concrete region, it should always be possible to model
1296 // the base-to-derived cast by undoing a previous derived-to-base cast,
1297 // otherwise the cast is most likely ill-formed.
1298 assert(SReg->getSymbolicBase() &&
1299 "Should have unwrapped a base region instead!");
1300 }
1301
1302 static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
1303 const MemRegion *SReg);
1304
1305 public:
1306 LLVM_ATTRIBUTE_RETURNS_NONNULL
getDecl()1307 const CXXRecordDecl *getDecl() const { return DerivedD; }
1308
1309 QualType getValueType() const override;
1310
1311 void dumpToStream(raw_ostream &os) const override;
1312
1313 void Profile(llvm::FoldingSetNodeID &ID) const override;
1314
1315 bool canPrintPrettyAsExpr() const override;
1316
1317 void printPrettyAsExpr(raw_ostream &os) const override;
1318
classof(const MemRegion * region)1319 static bool classof(const MemRegion *region) {
1320 return region->getKind() == CXXDerivedObjectRegionKind;
1321 }
1322 };
1323
1324 template<typename RegionTy>
getAs()1325 const RegionTy* MemRegion::getAs() const {
1326 if (const auto *RT = dyn_cast<RegionTy>(this))
1327 return RT;
1328
1329 return nullptr;
1330 }
1331
1332 template <typename RegionTy>
castAs()1333 LLVM_ATTRIBUTE_RETURNS_NONNULL const RegionTy *MemRegion::castAs() const {
1334 return cast<RegionTy>(this);
1335 }
1336
1337 //===----------------------------------------------------------------------===//
1338 // MemRegionManager - Factory object for creating regions.
1339 //===----------------------------------------------------------------------===//
1340
1341 class MemRegionManager {
1342 ASTContext &Ctx;
1343 llvm::BumpPtrAllocator& A;
1344
1345 llvm::FoldingSet<MemRegion> Regions;
1346
1347 GlobalInternalSpaceRegion *InternalGlobals = nullptr;
1348 GlobalSystemSpaceRegion *SystemGlobals = nullptr;
1349 GlobalImmutableSpaceRegion *ImmutableGlobals = nullptr;
1350
1351 llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>
1352 StackLocalsSpaceRegions;
1353 llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>
1354 StackArgumentsSpaceRegions;
1355 llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *>
1356 StaticsGlobalSpaceRegions;
1357
1358 HeapSpaceRegion *heap = nullptr;
1359 UnknownSpaceRegion *unknown = nullptr;
1360 CodeSpaceRegion *code = nullptr;
1361
1362 public:
MemRegionManager(ASTContext & c,llvm::BumpPtrAllocator & a)1363 MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) : Ctx(c), A(a) {}
1364 ~MemRegionManager();
1365
getContext()1366 ASTContext &getContext() { return Ctx; }
getContext()1367 const ASTContext &getContext() const { return Ctx; }
1368
getAllocator()1369 llvm::BumpPtrAllocator &getAllocator() { return A; }
1370
1371 /// \returns The static size in bytes of the region \p MR.
1372 /// \note The region \p MR must be a 'SubRegion'.
1373 DefinedOrUnknownSVal getStaticSize(const MemRegion *MR,
1374 SValBuilder &SVB) const;
1375
1376 /// getStackLocalsRegion - Retrieve the memory region associated with the
1377 /// specified stack frame.
1378 const StackLocalsSpaceRegion *
1379 getStackLocalsRegion(const StackFrameContext *STC);
1380
1381 /// getStackArgumentsRegion - Retrieve the memory region associated with
1382 /// function/method arguments of the specified stack frame.
1383 const StackArgumentsSpaceRegion *
1384 getStackArgumentsRegion(const StackFrameContext *STC);
1385
1386 /// getGlobalsRegion - Retrieve the memory region associated with
1387 /// global variables.
1388 const GlobalsSpaceRegion *getGlobalsRegion(
1389 MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind,
1390 const CodeTextRegion *R = nullptr);
1391
1392 /// getHeapRegion - Retrieve the memory region associated with the
1393 /// generic "heap".
1394 const HeapSpaceRegion *getHeapRegion();
1395
1396 /// getUnknownRegion - Retrieve the memory region associated with unknown
1397 /// memory space.
1398 const UnknownSpaceRegion *getUnknownRegion();
1399
1400 const CodeSpaceRegion *getCodeRegion();
1401
1402 /// getAllocaRegion - Retrieve a region associated with a call to alloca().
1403 const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt,
1404 const LocationContext *LC);
1405
1406 /// getCompoundLiteralRegion - Retrieve the region associated with a
1407 /// given CompoundLiteral.
1408 const CompoundLiteralRegion*
1409 getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
1410 const LocationContext *LC);
1411
1412 /// getCXXThisRegion - Retrieve the [artificial] region associated with the
1413 /// parameter 'this'.
1414 const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
1415 const LocationContext *LC);
1416
1417 /// Retrieve or create a "symbolic" memory region.
1418 /// If no memory space is specified, `UnknownSpaceRegion` will be used.
1419 const SymbolicRegion *
1420 getSymbolicRegion(SymbolRef Sym, const MemSpaceRegion *MemSpace = nullptr);
1421
1422 /// Return a unique symbolic region belonging to heap memory space.
1423 const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym);
1424
1425 const StringRegion *getStringRegion(const StringLiteral *Str);
1426
1427 const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str);
1428
1429 /// getVarRegion - Retrieve or create the memory region associated with
1430 /// a specified VarDecl and LocationContext.
1431 const VarRegion *getVarRegion(const VarDecl *VD, const LocationContext *LC);
1432
1433 /// getVarRegion - Retrieve or create the memory region associated with
1434 /// a specified VarDecl and LocationContext.
1435 const NonParamVarRegion *getNonParamVarRegion(const VarDecl *VD,
1436 const MemRegion *superR);
1437
1438 /// getParamVarRegion - Retrieve or create the memory region
1439 /// associated with a specified CallExpr, Index and LocationContext.
1440 const ParamVarRegion *getParamVarRegion(const Expr *OriginExpr,
1441 unsigned Index,
1442 const LocationContext *LC);
1443
1444 /// getElementRegion - Retrieve the memory region associated with the
1445 /// associated element type, index, and super region.
1446 const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx,
1447 const SubRegion *superRegion,
1448 ASTContext &Ctx);
1449
getElementRegionWithSuper(const ElementRegion * ER,const SubRegion * superRegion)1450 const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
1451 const SubRegion *superRegion) {
1452 return getElementRegion(ER->getElementType(), ER->getIndex(),
1453 superRegion, ER->getContext());
1454 }
1455
1456 /// getFieldRegion - Retrieve or create the memory region associated with
1457 /// a specified FieldDecl. 'superRegion' corresponds to the containing
1458 /// memory region (which typically represents the memory representing
1459 /// a structure or class).
1460 const FieldRegion *getFieldRegion(const FieldDecl *fd,
1461 const SubRegion* superRegion);
1462
getFieldRegionWithSuper(const FieldRegion * FR,const SubRegion * superRegion)1463 const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR,
1464 const SubRegion *superRegion) {
1465 return getFieldRegion(FR->getDecl(), superRegion);
1466 }
1467
1468 /// getObjCIvarRegion - Retrieve or create the memory region associated with
1469 /// a specified Objective-c instance variable. 'superRegion' corresponds
1470 /// to the containing region (which typically represents the Objective-C
1471 /// object).
1472 const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl *ivd,
1473 const SubRegion* superRegion);
1474
1475 const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
1476 LocationContext const *LC);
1477
1478 /// Create a CXXBaseObjectRegion with the given base class for region
1479 /// \p Super.
1480 ///
1481 /// The type of \p Super is assumed be a class deriving from \p BaseClass.
1482 const CXXBaseObjectRegion *
1483 getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super,
1484 bool IsVirtual);
1485
1486 /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
1487 /// super region.
1488 const CXXBaseObjectRegion *
getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion * baseReg,const SubRegion * superRegion)1489 getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
1490 const SubRegion *superRegion) {
1491 return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion,
1492 baseReg->isVirtual());
1493 }
1494
1495 /// Create a CXXDerivedObjectRegion with the given derived class for region
1496 /// \p Super. This should not be used for casting an existing
1497 /// CXXBaseObjectRegion back to the derived type; instead, CXXBaseObjectRegion
1498 /// should be removed.
1499 const CXXDerivedObjectRegion *
1500 getCXXDerivedObjectRegion(const CXXRecordDecl *BaseClass,
1501 const SubRegion *Super);
1502
1503 const FunctionCodeRegion *getFunctionCodeRegion(const NamedDecl *FD);
1504 const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD,
1505 CanQualType locTy,
1506 AnalysisDeclContext *AC);
1507
1508 /// getBlockDataRegion - Get the memory region associated with an instance
1509 /// of a block. Unlike many other MemRegions, the LocationContext*
1510 /// argument is allowed to be NULL for cases where we have no known
1511 /// context.
1512 const BlockDataRegion *getBlockDataRegion(const BlockCodeRegion *bc,
1513 const LocationContext *lc,
1514 unsigned blockCount);
1515
1516 /// Create a CXXTempObjectRegion for temporaries which are lifetime-extended
1517 /// by static references. This differs from getCXXTempObjectRegion in the
1518 /// super-region used.
1519 const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
1520
1521 private:
1522 template <typename RegionTy, typename SuperTy,
1523 typename Arg1Ty>
1524 RegionTy* getSubRegion(const Arg1Ty arg1,
1525 const SuperTy* superRegion);
1526
1527 template <typename RegionTy, typename SuperTy,
1528 typename Arg1Ty, typename Arg2Ty>
1529 RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
1530 const SuperTy* superRegion);
1531
1532 template <typename RegionTy, typename SuperTy,
1533 typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
1534 RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
1535 const Arg3Ty arg3,
1536 const SuperTy* superRegion);
1537
1538 template <typename REG>
1539 const REG* LazyAllocate(REG*& region);
1540
1541 template <typename REG, typename ARG>
1542 const REG* LazyAllocate(REG*& region, ARG a);
1543 };
1544
1545 //===----------------------------------------------------------------------===//
1546 // Out-of-line member definitions.
1547 //===----------------------------------------------------------------------===//
1548
getContext()1549 inline ASTContext &MemRegion::getContext() const {
1550 return getMemRegionManager().getContext();
1551 }
1552
1553 //===----------------------------------------------------------------------===//
1554 // Means for storing region/symbol handling traits.
1555 //===----------------------------------------------------------------------===//
1556
1557 /// Information about invalidation for a particular region/symbol.
1558 class RegionAndSymbolInvalidationTraits {
1559 using StorageTypeForKinds = unsigned char;
1560
1561 llvm::DenseMap<const MemRegion *, StorageTypeForKinds> MRTraitsMap;
1562 llvm::DenseMap<SymbolRef, StorageTypeForKinds> SymTraitsMap;
1563
1564 using const_region_iterator =
1565 llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator;
1566 using const_symbol_iterator =
1567 llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator;
1568
1569 public:
1570 /// Describes different invalidation traits.
1571 enum InvalidationKinds {
1572 /// Tells that a region's contents is not changed.
1573 TK_PreserveContents = 0x1,
1574
1575 /// Suppress pointer-escaping of a region.
1576 TK_SuppressEscape = 0x2,
1577
1578 // Do not invalidate super region.
1579 TK_DoNotInvalidateSuperRegion = 0x4,
1580
1581 /// When applied to a MemSpaceRegion, indicates the entire memory space
1582 /// should be invalidated.
1583 TK_EntireMemSpace = 0x8
1584
1585 // Do not forget to extend StorageTypeForKinds if number of traits exceed
1586 // the number of bits StorageTypeForKinds can store.
1587 };
1588
1589 void setTrait(SymbolRef Sym, InvalidationKinds IK);
1590 void setTrait(const MemRegion *MR, InvalidationKinds IK);
1591 bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const;
1592 bool hasTrait(const MemRegion *MR, InvalidationKinds IK) const;
1593 };
1594
1595 //===----------------------------------------------------------------------===//
1596 // Pretty-printing regions.
1597 //===----------------------------------------------------------------------===//
1598 inline raw_ostream &operator<<(raw_ostream &os, const MemRegion *R) {
1599 R->dumpToStream(os);
1600 return os;
1601 }
1602
1603 } // namespace ento
1604
1605 } // namespace clang
1606
1607 #endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
1608