1 //== MemRegion.h - Abstract memory regions for static analysis --*- C++ -*--==//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file defines MemRegion and its subclasses. MemRegion defines a
11 // partially-typed abstraction of memory useful for path-sensitive dataflow
14 //===----------------------------------------------------------------------===//
16 #ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
17 #define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
19 #include "clang/AST/ASTContext.h"
20 #include "clang/AST/CharUnits.h"
21 #include "clang/AST/Decl.h"
22 #include "clang/AST/DeclCXX.h"
23 #include "clang/AST/ExprObjC.h"
24 #include "clang/Analysis/AnalysisDeclContext.h"
25 #include "clang/Basic/LLVM.h"
26 #include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
27 #include "llvm/ADT/FoldingSet.h"
28 #include "llvm/Support/Allocator.h"
29 #include "llvm/Support/ErrorHandling.h"
34 class LocationContext;
35 class StackFrameContext;
40 class MemRegionManager;
46 /// Represent a region's offset within the top level base region.
51 /// The bit offset within the base region. Can be negative.
55 // We're using a const instead of an enumeration due to the size required;
56 // Visual Studio will only create enumerations of size int, not long long.
57 static const int64_t Symbolic = INT64_MAX;
59 RegionOffset() : R(nullptr) {}
60 RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
62 const MemRegion *getRegion() const { return R; }
64 bool hasSymbolicOffset() const { return Offset == Symbolic; }
66 int64_t getOffset() const {
67 assert(!hasSymbolicOffset());
71 bool isValid() const { return R; }
74 //===----------------------------------------------------------------------===//
75 // Base region classes.
76 //===----------------------------------------------------------------------===//
78 /// MemRegion - The root abstract class for all memory regions.
79 class MemRegion : public llvm::FoldingSetNode {
82 #define REGION(Id, Parent) Id ## Kind,
83 #define REGION_RANGE(Id, First, Last) BEGIN_##Id = First, END_##Id = Last,
84 #include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def"
91 MemRegion(Kind k) : kind(k) {}
95 ASTContext &getContext() const;
97 virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
99 virtual MemRegionManager* getMemRegionManager() const = 0;
101 const MemSpaceRegion *getMemorySpace() const;
103 const MemRegion *getBaseRegion() const;
105 /// Check if the region is a subregion of the given region.
106 virtual bool isSubRegionOf(const MemRegion *R) const;
108 const MemRegion *StripCasts(bool StripBaseCasts = true) const;
110 /// \brief If this is a symbolic region, returns the region. Otherwise,
111 /// goes up the base chain looking for the first symbolic base region.
112 const SymbolicRegion *getSymbolicBase() const;
114 bool hasGlobalsOrParametersStorage() const;
116 bool hasStackStorage() const;
118 bool hasStackNonParametersStorage() const;
120 bool hasStackParametersStorage() const;
122 /// Compute the offset within the top level memory object.
123 RegionOffset getAsOffset() const;
125 /// \brief Get a string representation of a region for debug use.
126 std::string getString() const;
128 virtual void dumpToStream(raw_ostream &os) const;
132 /// \brief Returns true if this region can be printed in a user-friendly way.
133 virtual bool canPrintPretty() const;
135 /// \brief Print the region for use in diagnostics.
136 virtual void printPretty(raw_ostream &os) const;
138 /// \brief Returns true if this region's textual representation can be used
139 /// as part of a larger expression.
140 virtual bool canPrintPrettyAsExpr() const;
142 /// \brief Print the region as expression.
144 /// When this region represents a subexpression, the method is for printing
145 /// an expression containing it.
146 virtual void printPrettyAsExpr(raw_ostream &os) const;
148 Kind getKind() const { return kind; }
150 template<typename RegionTy> const RegionTy* getAs() const;
152 virtual bool isBoundable() const { return false; }
155 /// Get descriptive name for memory region. The name is obtained from
156 /// the variable/field declaration retrieved from the memory region.
157 /// Regions that point to an element of an array are returned as: "arr[0]".
158 /// Regions that point to a struct are returned as: "st.var".
160 /// \param UseQuotes Set if the name should be quoted.
162 /// \returns variable name for memory region
163 std::string getDescriptiveName(bool UseQuotes = true) const;
166 /// Retrieve source range from memory region. The range retrieval
167 /// is based on the decl obtained from the memory region.
168 /// For a VarRegion the range of the base region is returned.
169 /// For a FieldRegion the range of the field is returned.
170 /// If no declaration is found, an empty source range is returned.
171 /// The client is responsible for checking if the returned range is valid.
173 /// \returns source range for declaration retrieved from memory region
174 clang::SourceRange sourceRange() const;
177 /// MemSpaceRegion - A memory region that represents a "memory space";
178 /// for example, the set of global variables, the stack frame, etc.
179 class MemSpaceRegion : public MemRegion {
181 MemRegionManager *Mgr;
183 MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) {
184 assert(classof(this));
188 MemRegionManager* getMemRegionManager() const override { return Mgr; }
191 bool isBoundable() const override { return false; }
193 void Profile(llvm::FoldingSetNodeID &ID) const override;
195 static bool classof(const MemRegion *R) {
196 Kind k = R->getKind();
197 return k >= BEGIN_MEMSPACES && k <= END_MEMSPACES;
201 /// CodeSpaceRegion - The memory space that holds the executable code of
202 /// functions and blocks.
203 class CodeSpaceRegion : public MemSpaceRegion {
204 friend class MemRegionManager;
206 CodeSpaceRegion(MemRegionManager *mgr)
207 : MemSpaceRegion(mgr, CodeSpaceRegionKind) {}
210 void dumpToStream(raw_ostream &os) const override;
212 static bool classof(const MemRegion *R) {
213 return R->getKind() == CodeSpaceRegionKind;
217 class GlobalsSpaceRegion : public MemSpaceRegion {
218 virtual void anchor();
221 GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) : MemSpaceRegion(mgr, k) {
222 assert(classof(this));
226 static bool classof(const MemRegion *R) {
227 Kind k = R->getKind();
228 return k >= BEGIN_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
232 /// \brief The region of the static variables within the current CodeTextRegion
235 /// Currently, only the static locals are placed there, so we know that these
236 /// variables do not get invalidated by calls to other functions.
237 class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
238 friend class MemRegionManager;
240 const CodeTextRegion *CR;
242 StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr)
243 : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {
248 void Profile(llvm::FoldingSetNodeID &ID) const override;
250 void dumpToStream(raw_ostream &os) const override;
252 const CodeTextRegion *getCodeRegion() const { return CR; }
254 static bool classof(const MemRegion *R) {
255 return R->getKind() == StaticGlobalSpaceRegionKind;
259 /// \brief The region for all the non-static global variables.
261 /// This class is further split into subclasses for efficient implementation of
262 /// invalidating a set of related global values as is done in
263 /// RegionStoreManager::invalidateRegions (instead of finding all the dependent
264 /// globals, we invalidate the whole parent region).
265 class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
266 virtual void anchor() override;
269 NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
270 : GlobalsSpaceRegion(mgr, k) {
271 assert(classof(this));
276 static bool classof(const MemRegion *R) {
277 Kind k = R->getKind();
278 return k >= BEGIN_NON_STATIC_GLOBAL_MEMSPACES &&
279 k <= END_NON_STATIC_GLOBAL_MEMSPACES;
283 /// \brief The region containing globals which are defined in system/external
284 /// headers and are considered modifiable by system calls (ex: errno).
285 class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion {
286 friend class MemRegionManager;
288 GlobalSystemSpaceRegion(MemRegionManager *mgr)
289 : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {}
293 void dumpToStream(raw_ostream &os) const override;
295 static bool classof(const MemRegion *R) {
296 return R->getKind() == GlobalSystemSpaceRegionKind;
300 /// \brief The region containing globals which are considered not to be modified
301 /// or point to data which could be modified as a result of a function call
302 /// (system or internal). Ex: Const global scalars would be modeled as part of
303 /// this region. This region also includes most system globals since they have
304 /// low chance of being modified.
305 class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion {
306 friend class MemRegionManager;
308 GlobalImmutableSpaceRegion(MemRegionManager *mgr)
309 : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {}
313 void dumpToStream(raw_ostream &os) const override;
315 static bool classof(const MemRegion *R) {
316 return R->getKind() == GlobalImmutableSpaceRegionKind;
320 /// \brief The region containing globals which can be modified by calls to
321 /// "internally" defined functions - (for now just) functions other then system
323 class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
324 friend class MemRegionManager;
326 GlobalInternalSpaceRegion(MemRegionManager *mgr)
327 : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {}
331 void dumpToStream(raw_ostream &os) const override;
333 static bool classof(const MemRegion *R) {
334 return R->getKind() == GlobalInternalSpaceRegionKind;
338 class HeapSpaceRegion : public MemSpaceRegion {
339 friend class MemRegionManager;
341 HeapSpaceRegion(MemRegionManager *mgr)
342 : MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
345 void dumpToStream(raw_ostream &os) const override;
347 static bool classof(const MemRegion *R) {
348 return R->getKind() == HeapSpaceRegionKind;
352 class UnknownSpaceRegion : public MemSpaceRegion {
353 friend class MemRegionManager;
354 UnknownSpaceRegion(MemRegionManager *mgr)
355 : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
359 void dumpToStream(raw_ostream &os) const override;
361 static bool classof(const MemRegion *R) {
362 return R->getKind() == UnknownSpaceRegionKind;
366 class StackSpaceRegion : public MemSpaceRegion {
367 virtual void anchor();
369 const StackFrameContext *SFC;
372 StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
373 : MemSpaceRegion(mgr, k), SFC(sfc) {
374 assert(classof(this));
379 const StackFrameContext *getStackFrame() const { return SFC; }
381 void Profile(llvm::FoldingSetNodeID &ID) const override;
383 static bool classof(const MemRegion *R) {
384 Kind k = R->getKind();
385 return k >= BEGIN_STACK_MEMSPACES && k <= END_STACK_MEMSPACES;
389 class StackLocalsSpaceRegion : public StackSpaceRegion {
390 friend class MemRegionManager;
391 StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
392 : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
395 void dumpToStream(raw_ostream &os) const override;
397 static bool classof(const MemRegion *R) {
398 return R->getKind() == StackLocalsSpaceRegionKind;
402 class StackArgumentsSpaceRegion : public StackSpaceRegion {
404 friend class MemRegionManager;
405 StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
406 : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
409 void dumpToStream(raw_ostream &os) const override;
411 static bool classof(const MemRegion *R) {
412 return R->getKind() == StackArgumentsSpaceRegionKind;
417 /// SubRegion - A region that subsets another larger region. Most regions
418 /// are subclasses of SubRegion.
419 class SubRegion : public MemRegion {
420 virtual void anchor();
423 const MemRegion* superRegion;
424 SubRegion(const MemRegion *sReg, Kind k) : MemRegion(k), superRegion(sReg) {
425 assert(classof(this));
430 const MemRegion* getSuperRegion() const {
434 /// getExtent - Returns the size of the region in bytes.
435 virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const {
439 MemRegionManager* getMemRegionManager() const override;
441 bool isSubRegionOf(const MemRegion* R) const override;
443 static bool classof(const MemRegion* R) {
444 return R->getKind() > END_MEMSPACES;
448 //===----------------------------------------------------------------------===//
449 // MemRegion subclasses.
450 //===----------------------------------------------------------------------===//
452 /// AllocaRegion - A region that represents an untyped blob of bytes created
453 /// by a call to 'alloca'.
454 class AllocaRegion : public SubRegion {
455 friend class MemRegionManager;
457 unsigned Cnt; // Block counter. Used to distinguish different pieces of
458 // memory allocated by alloca at the same call site.
461 AllocaRegion(const Expr *ex, unsigned cnt, const MemSpaceRegion *superRegion)
462 : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {
466 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex,
467 unsigned Cnt, const MemRegion *superRegion);
471 const Expr *getExpr() const { return Ex; }
473 bool isBoundable() const override { return true; }
475 DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
477 void Profile(llvm::FoldingSetNodeID& ID) const override;
479 void dumpToStream(raw_ostream &os) const override;
481 static bool classof(const MemRegion* R) {
482 return R->getKind() == AllocaRegionKind;
486 /// TypedRegion - An abstract class representing regions that are typed.
487 class TypedRegion : public SubRegion {
488 virtual void anchor() override;
491 TypedRegion(const MemRegion *sReg, Kind k) : SubRegion(sReg, k) {
492 assert(classof(this));
496 virtual QualType getLocationType() const = 0;
498 QualType getDesugaredLocationType(ASTContext &Context) const {
499 return getLocationType().getDesugaredType(Context);
502 bool isBoundable() const override { return true; }
504 static bool classof(const MemRegion* R) {
505 unsigned k = R->getKind();
506 return k >= BEGIN_TYPED_REGIONS && k <= END_TYPED_REGIONS;
510 /// TypedValueRegion - An abstract class representing regions having a typed value.
511 class TypedValueRegion : public TypedRegion {
512 virtual void anchor() override;
515 TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {
516 assert(classof(this));
520 virtual QualType getValueType() const = 0;
522 QualType getLocationType() const override {
523 // FIXME: We can possibly optimize this later to cache this value.
524 QualType T = getValueType();
525 ASTContext &ctx = getContext();
526 if (T->getAs<ObjCObjectType>())
527 return ctx.getObjCObjectPointerType(T);
528 return ctx.getPointerType(getValueType());
531 QualType getDesugaredValueType(ASTContext &Context) const {
532 QualType T = getValueType();
533 return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
536 DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
538 static bool classof(const MemRegion* R) {
539 unsigned k = R->getKind();
540 return k >= BEGIN_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
545 class CodeTextRegion : public TypedRegion {
546 virtual void anchor() override;
549 CodeTextRegion(const MemSpaceRegion *sreg, Kind k) : TypedRegion(sreg, k) {
550 assert(classof(this));
554 bool isBoundable() const override { return false; }
556 static bool classof(const MemRegion* R) {
557 Kind k = R->getKind();
558 return k >= BEGIN_CODE_TEXT_REGIONS && k <= END_CODE_TEXT_REGIONS;
562 /// FunctionCodeRegion - A region that represents code texts of function.
563 class FunctionCodeRegion : public CodeTextRegion {
564 friend class MemRegionManager;
568 FunctionCodeRegion(const NamedDecl *fd, const CodeSpaceRegion* sreg)
569 : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) {
570 assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
573 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD,
577 QualType getLocationType() const override {
578 const ASTContext &Ctx = getContext();
579 if (const FunctionDecl *D = dyn_cast<FunctionDecl>(FD)) {
580 return Ctx.getPointerType(D->getType());
583 assert(isa<ObjCMethodDecl>(FD));
584 assert(false && "Getting the type of ObjCMethod is not supported yet");
586 // TODO: We might want to return a different type here (ex: id (*ty)(...))
587 // depending on how it is used.
591 const NamedDecl *getDecl() const {
595 void dumpToStream(raw_ostream &os) const override;
597 void Profile(llvm::FoldingSetNodeID& ID) const override;
599 static bool classof(const MemRegion* R) {
600 return R->getKind() == FunctionCodeRegionKind;
605 /// BlockCodeRegion - A region that represents code texts of blocks (closures).
606 /// Blocks are represented with two kinds of regions. BlockCodeRegions
607 /// represent the "code", while BlockDataRegions represent instances of blocks,
608 /// which correspond to "code+data". The distinction is important, because
609 /// like a closure a block captures the values of externally referenced
611 class BlockCodeRegion : public CodeTextRegion {
612 friend class MemRegionManager;
615 AnalysisDeclContext *AC;
618 BlockCodeRegion(const BlockDecl *bd, CanQualType lTy,
619 AnalysisDeclContext *ac, const CodeSpaceRegion* sreg)
620 : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {
623 assert(lTy->getTypePtr()->isBlockPointerType());
626 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
627 CanQualType, const AnalysisDeclContext*,
631 QualType getLocationType() const override {
635 const BlockDecl *getDecl() const {
639 AnalysisDeclContext *getAnalysisDeclContext() const { return AC; }
641 void dumpToStream(raw_ostream &os) const override;
643 void Profile(llvm::FoldingSetNodeID& ID) const override;
645 static bool classof(const MemRegion* R) {
646 return R->getKind() == BlockCodeRegionKind;
650 /// BlockDataRegion - A region that represents a block instance.
651 /// Blocks are represented with two kinds of regions. BlockCodeRegions
652 /// represent the "code", while BlockDataRegions represent instances of blocks,
653 /// which correspond to "code+data". The distinction is important, because
654 /// like a closure a block captures the values of externally referenced
656 class BlockDataRegion : public TypedRegion {
657 friend class MemRegionManager;
659 const BlockCodeRegion *BC;
660 const LocationContext *LC; // Can be null */
662 void *ReferencedVars;
665 BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc,
666 unsigned count, const MemSpaceRegion *sreg)
667 : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
668 BlockCount(count), ReferencedVars(nullptr), OriginalVars(nullptr) {
671 assert(isa<GlobalImmutableSpaceRegion>(sreg) ||
672 isa<StackLocalsSpaceRegion>(sreg) ||
673 isa<UnknownSpaceRegion>(sreg));
676 static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *,
677 const LocationContext *, unsigned,
681 const BlockCodeRegion *getCodeRegion() const { return BC; }
683 const BlockDecl *getDecl() const { return BC->getDecl(); }
685 QualType getLocationType() const override { return BC->getLocationType(); }
687 class referenced_vars_iterator {
688 const MemRegion * const *R;
689 const MemRegion * const *OriginalR;
691 explicit referenced_vars_iterator(const MemRegion * const *r,
692 const MemRegion * const *originalR)
693 : R(r), OriginalR(originalR) {}
695 const VarRegion *getCapturedRegion() const {
696 return cast<VarRegion>(*R);
698 const VarRegion *getOriginalRegion() const {
699 return cast<VarRegion>(*OriginalR);
702 bool operator==(const referenced_vars_iterator &I) const {
703 assert((R == nullptr) == (I.R == nullptr));
706 bool operator!=(const referenced_vars_iterator &I) const {
707 assert((R == nullptr) == (I.R == nullptr));
710 referenced_vars_iterator &operator++() {
717 /// Return the original region for a captured region, if
719 const VarRegion *getOriginalRegion(const VarRegion *VR) const;
721 referenced_vars_iterator referenced_vars_begin() const;
722 referenced_vars_iterator referenced_vars_end() const;
724 void dumpToStream(raw_ostream &os) const override;
726 void Profile(llvm::FoldingSetNodeID& ID) const override;
728 static bool classof(const MemRegion* R) {
729 return R->getKind() == BlockDataRegionKind;
732 void LazyInitializeReferencedVars();
733 std::pair<const VarRegion *, const VarRegion *>
734 getCaptureRegions(const VarDecl *VD);
737 /// SymbolicRegion - A special, "non-concrete" region. Unlike other region
738 /// classes, SymbolicRegion represents a region that serves as an alias for
739 /// either a real region, a NULL pointer, etc. It essentially is used to
740 /// map the concept of symbolic values into the domain of regions. Symbolic
741 /// regions do not need to be typed.
742 class SymbolicRegion : public SubRegion {
743 friend class MemRegionManager;
747 SymbolicRegion(const SymbolRef s, const MemSpaceRegion *sreg)
748 : SubRegion(sreg, SymbolicRegionKind), sym(s) {
750 assert(s->getType()->isAnyPointerType() ||
751 s->getType()->isReferenceType() ||
752 s->getType()->isBlockPointerType());
753 assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg));
757 SymbolRef getSymbol() const {
761 bool isBoundable() const override { return true; }
763 DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
765 void Profile(llvm::FoldingSetNodeID& ID) const override;
767 static void ProfileRegion(llvm::FoldingSetNodeID& ID,
769 const MemRegion* superRegion);
771 void dumpToStream(raw_ostream &os) const override;
773 static bool classof(const MemRegion* R) {
774 return R->getKind() == SymbolicRegionKind;
778 /// StringRegion - Region associated with a StringLiteral.
779 class StringRegion : public TypedValueRegion {
780 friend class MemRegionManager;
782 const StringLiteral* Str;
784 StringRegion(const StringLiteral *str, const GlobalInternalSpaceRegion *sreg)
785 : TypedValueRegion(sreg, StringRegionKind), Str(str) {
789 static void ProfileRegion(llvm::FoldingSetNodeID& ID,
790 const StringLiteral* Str,
791 const MemRegion* superRegion);
795 const StringLiteral* getStringLiteral() const { return Str; }
797 QualType getValueType() const override {
798 return Str->getType();
801 DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
803 bool isBoundable() const override { return false; }
805 void Profile(llvm::FoldingSetNodeID& ID) const override {
806 ProfileRegion(ID, Str, superRegion);
809 void dumpToStream(raw_ostream &os) const override;
811 static bool classof(const MemRegion* R) {
812 return R->getKind() == StringRegionKind;
816 /// The region associated with an ObjCStringLiteral.
817 class ObjCStringRegion : public TypedValueRegion {
818 friend class MemRegionManager;
820 const ObjCStringLiteral* Str;
822 ObjCStringRegion(const ObjCStringLiteral *str,
823 const GlobalInternalSpaceRegion *sreg)
824 : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {
828 static void ProfileRegion(llvm::FoldingSetNodeID& ID,
829 const ObjCStringLiteral* Str,
830 const MemRegion* superRegion);
834 const ObjCStringLiteral* getObjCStringLiteral() const { return Str; }
836 QualType getValueType() const override {
837 return Str->getType();
840 bool isBoundable() const override { return false; }
842 void Profile(llvm::FoldingSetNodeID& ID) const override {
843 ProfileRegion(ID, Str, superRegion);
846 void dumpToStream(raw_ostream &os) const override;
848 static bool classof(const MemRegion* R) {
849 return R->getKind() == ObjCStringRegionKind;
853 /// CompoundLiteralRegion - A memory region representing a compound literal.
854 /// Compound literals are essentially temporaries that are stack allocated
855 /// or in the global constant pool.
856 class CompoundLiteralRegion : public TypedValueRegion {
857 friend class MemRegionManager;
859 const CompoundLiteralExpr *CL;
861 CompoundLiteralRegion(const CompoundLiteralExpr *cl,
862 const MemSpaceRegion *sReg)
863 : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {
865 assert(isa<GlobalInternalSpaceRegion>(sReg) ||
866 isa<StackLocalsSpaceRegion>(sReg));
869 static void ProfileRegion(llvm::FoldingSetNodeID& ID,
870 const CompoundLiteralExpr *CL,
871 const MemRegion* superRegion);
873 QualType getValueType() const override {
874 return CL->getType();
877 bool isBoundable() const override { return !CL->isFileScope(); }
879 void Profile(llvm::FoldingSetNodeID& ID) const override;
881 void dumpToStream(raw_ostream &os) const override;
883 const CompoundLiteralExpr *getLiteralExpr() const { return CL; }
885 static bool classof(const MemRegion* R) {
886 return R->getKind() == CompoundLiteralRegionKind;
890 class DeclRegion : public TypedValueRegion {
894 DeclRegion(const Decl *d, const MemRegion *sReg, Kind k)
895 : TypedValueRegion(sReg, k), D(d) {
896 assert(classof(this));
900 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D,
901 const MemRegion* superRegion, Kind k);
904 const Decl *getDecl() const { return D; }
905 void Profile(llvm::FoldingSetNodeID& ID) const override;
907 static bool classof(const MemRegion* R) {
908 unsigned k = R->getKind();
909 return k >= BEGIN_DECL_REGIONS && k <= END_DECL_REGIONS;
913 class VarRegion : public DeclRegion {
914 friend class MemRegionManager;
916 // Constructors and private methods.
917 VarRegion(const VarDecl *vd, const MemRegion *sReg)
918 : DeclRegion(vd, sReg, VarRegionKind) {
919 // VarRegion appears in unknown space when it's a block variable as seen
920 // from a block using it, when this block is analyzed at top-level.
921 // Other block variables appear within block data regions,
922 // which, unlike everything else on this list, are not memory spaces.
923 assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) ||
924 isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg));
927 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD,
928 const MemRegion *superRegion) {
929 DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
933 void Profile(llvm::FoldingSetNodeID& ID) const override;
935 const VarDecl *getDecl() const { return cast<VarDecl>(D); }
937 const StackFrameContext *getStackFrame() const;
939 QualType getValueType() const override {
940 // FIXME: We can cache this if needed.
941 return getDecl()->getType();
944 void dumpToStream(raw_ostream &os) const override;
946 static bool classof(const MemRegion* R) {
947 return R->getKind() == VarRegionKind;
950 bool canPrintPrettyAsExpr() const override;
952 void printPrettyAsExpr(raw_ostream &os) const override;
955 /// CXXThisRegion - Represents the region for the implicit 'this' parameter
956 /// in a call to a C++ method. This region doesn't represent the object
957 /// referred to by 'this', but rather 'this' itself.
958 class CXXThisRegion : public TypedValueRegion {
959 friend class MemRegionManager;
961 CXXThisRegion(const PointerType *thisPointerTy,
962 const StackArgumentsSpaceRegion *sReg)
963 : TypedValueRegion(sReg, CXXThisRegionKind),
964 ThisPointerTy(thisPointerTy) {}
966 static void ProfileRegion(llvm::FoldingSetNodeID &ID,
967 const PointerType *PT,
968 const MemRegion *sReg);
971 void Profile(llvm::FoldingSetNodeID &ID) const override;
973 QualType getValueType() const override {
974 return QualType(ThisPointerTy, 0);
977 void dumpToStream(raw_ostream &os) const override;
979 static bool classof(const MemRegion* R) {
980 return R->getKind() == CXXThisRegionKind;
984 const PointerType *ThisPointerTy;
987 class FieldRegion : public DeclRegion {
988 friend class MemRegionManager;
990 FieldRegion(const FieldDecl *fd, const SubRegion* sReg)
991 : DeclRegion(fd, sReg, FieldRegionKind) {}
993 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD,
994 const MemRegion* superRegion) {
995 DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
999 const FieldDecl *getDecl() const { return cast<FieldDecl>(D); }
1001 QualType getValueType() const override {
1002 // FIXME: We can cache this if needed.
1003 return getDecl()->getType();
1006 DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
1008 static bool classof(const MemRegion* R) {
1009 return R->getKind() == FieldRegionKind;
1012 void dumpToStream(raw_ostream &os) const override;
1014 bool canPrintPretty() const override;
1015 void printPretty(raw_ostream &os) const override;
1016 bool canPrintPrettyAsExpr() const override;
1017 void printPrettyAsExpr(raw_ostream &os) const override;
1020 class ObjCIvarRegion : public DeclRegion {
1021 friend class MemRegionManager;
1023 ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg);
1025 static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd,
1026 const MemRegion* superRegion);
1029 const ObjCIvarDecl *getDecl() const;
1030 QualType getValueType() const override;
1032 bool canPrintPrettyAsExpr() const override;
1033 void printPrettyAsExpr(raw_ostream &os) const override;
1035 void dumpToStream(raw_ostream &os) const override;
1037 static bool classof(const MemRegion* R) {
1038 return R->getKind() == ObjCIvarRegionKind;
1041 //===----------------------------------------------------------------------===//
1042 // Auxiliary data classes for use with MemRegions.
1043 //===----------------------------------------------------------------------===//
1045 class ElementRegion;
1047 class RegionRawOffset {
1048 friend class ElementRegion;
1050 const MemRegion *Region;
1053 RegionRawOffset(const MemRegion* reg, CharUnits offset = CharUnits::Zero())
1054 : Region(reg), Offset(offset) {}
1057 // FIXME: Eventually support symbolic offsets.
1058 CharUnits getOffset() const { return Offset; }
1059 const MemRegion *getRegion() const { return Region; }
1061 void dumpToStream(raw_ostream &os) const;
1065 /// \brief ElementRegin is used to represent both array elements and casts.
1066 class ElementRegion : public TypedValueRegion {
1067 friend class MemRegionManager;
1069 QualType ElementType;
1072 ElementRegion(QualType elementType, NonLoc Idx, const SubRegion *sReg)
1073 : TypedValueRegion(sReg, ElementRegionKind),
1074 ElementType(elementType), Index(Idx) {
1075 assert((!Idx.getAs<nonloc::ConcreteInt>() ||
1076 Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) &&
1077 "The index must be signed");
1080 static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType,
1081 SVal Idx, const MemRegion* superRegion);
1085 NonLoc getIndex() const { return Index; }
1087 QualType getValueType() const override {
1091 QualType getElementType() const {
1094 /// Compute the offset within the array. The array might also be a subobject.
1095 RegionRawOffset getAsArrayOffset() const;
1097 void dumpToStream(raw_ostream &os) const override;
1099 void Profile(llvm::FoldingSetNodeID& ID) const override;
1101 static bool classof(const MemRegion* R) {
1102 return R->getKind() == ElementRegionKind;
1106 // C++ temporary object associated with an expression.
1107 class CXXTempObjectRegion : public TypedValueRegion {
1108 friend class MemRegionManager;
1112 CXXTempObjectRegion(Expr const *E, MemSpaceRegion const *sReg)
1113 : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {
1115 assert(isa<StackLocalsSpaceRegion>(sReg) ||
1116 isa<GlobalInternalSpaceRegion>(sReg));
1119 static void ProfileRegion(llvm::FoldingSetNodeID &ID,
1120 Expr const *E, const MemRegion *sReg);
1123 const Expr *getExpr() const { return Ex; }
1125 QualType getValueType() const override {
1126 return Ex->getType();
1129 void dumpToStream(raw_ostream &os) const override;
1131 void Profile(llvm::FoldingSetNodeID &ID) const override;
1133 static bool classof(const MemRegion* R) {
1134 return R->getKind() == CXXTempObjectRegionKind;
1138 // CXXBaseObjectRegion represents a base object within a C++ object. It is
1139 // identified by the base class declaration and the region of its parent object.
1140 class CXXBaseObjectRegion : public TypedValueRegion {
1141 friend class MemRegionManager;
1143 llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data;
1145 CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual,
1146 const SubRegion *SReg)
1147 : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {
1151 static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
1152 bool IsVirtual, const MemRegion *SReg);
1155 const CXXRecordDecl *getDecl() const { return Data.getPointer(); }
1156 bool isVirtual() const { return Data.getInt(); }
1158 QualType getValueType() const override;
1160 void dumpToStream(raw_ostream &os) const override;
1162 void Profile(llvm::FoldingSetNodeID &ID) const override;
1164 static bool classof(const MemRegion *region) {
1165 return region->getKind() == CXXBaseObjectRegionKind;
1168 bool canPrintPrettyAsExpr() const override;
1170 void printPrettyAsExpr(raw_ostream &os) const override;
1173 template<typename RegionTy>
1174 const RegionTy* MemRegion::getAs() const {
1175 if (const RegionTy* RT = dyn_cast<RegionTy>(this))
1181 //===----------------------------------------------------------------------===//
1182 // MemRegionManager - Factory object for creating regions.
1183 //===----------------------------------------------------------------------===//
1185 class MemRegionManager {
1187 llvm::BumpPtrAllocator& A;
1188 llvm::FoldingSet<MemRegion> Regions;
1190 GlobalInternalSpaceRegion *InternalGlobals;
1191 GlobalSystemSpaceRegion *SystemGlobals;
1192 GlobalImmutableSpaceRegion *ImmutableGlobals;
1195 llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>
1196 StackLocalsSpaceRegions;
1197 llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>
1198 StackArgumentsSpaceRegions;
1199 llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *>
1200 StaticsGlobalSpaceRegions;
1202 HeapSpaceRegion *heap;
1203 UnknownSpaceRegion *unknown;
1204 CodeSpaceRegion *code;
1207 MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a)
1208 : C(c), A(a), InternalGlobals(nullptr), SystemGlobals(nullptr),
1209 ImmutableGlobals(nullptr), heap(nullptr), unknown(nullptr),
1212 ~MemRegionManager();
1214 ASTContext &getContext() { return C; }
1216 llvm::BumpPtrAllocator &getAllocator() { return A; }
1218 /// getStackLocalsRegion - Retrieve the memory region associated with the
1219 /// specified stack frame.
1220 const StackLocalsSpaceRegion *
1221 getStackLocalsRegion(const StackFrameContext *STC);
1223 /// getStackArgumentsRegion - Retrieve the memory region associated with
1224 /// function/method arguments of the specified stack frame.
1225 const StackArgumentsSpaceRegion *
1226 getStackArgumentsRegion(const StackFrameContext *STC);
1228 /// getGlobalsRegion - Retrieve the memory region associated with
1229 /// global variables.
1230 const GlobalsSpaceRegion *getGlobalsRegion(
1231 MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind,
1232 const CodeTextRegion *R = nullptr);
1234 /// getHeapRegion - Retrieve the memory region associated with the
1236 const HeapSpaceRegion *getHeapRegion();
1238 /// getUnknownRegion - Retrieve the memory region associated with unknown
1240 const UnknownSpaceRegion *getUnknownRegion();
1242 const CodeSpaceRegion *getCodeRegion();
1244 /// getAllocaRegion - Retrieve a region associated with a call to alloca().
1245 const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt,
1246 const LocationContext *LC);
1248 /// getCompoundLiteralRegion - Retrieve the region associated with a
1249 /// given CompoundLiteral.
1250 const CompoundLiteralRegion*
1251 getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
1252 const LocationContext *LC);
1254 /// getCXXThisRegion - Retrieve the [artificial] region associated with the
1255 /// parameter 'this'.
1256 const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
1257 const LocationContext *LC);
1259 /// \brief Retrieve or create a "symbolic" memory region.
1260 const SymbolicRegion* getSymbolicRegion(SymbolRef Sym);
1262 /// \brief Return a unique symbolic region belonging to heap memory space.
1263 const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym);
1265 const StringRegion *getStringRegion(const StringLiteral* Str);
1267 const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str);
1269 /// getVarRegion - Retrieve or create the memory region associated with
1270 /// a specified VarDecl and LocationContext.
1271 const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC);
1273 /// getVarRegion - Retrieve or create the memory region associated with
1274 /// a specified VarDecl and super region.
1275 const VarRegion *getVarRegion(const VarDecl *D, const MemRegion *superR);
1277 /// getElementRegion - Retrieve the memory region associated with the
1278 /// associated element type, index, and super region.
1279 const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx,
1280 const SubRegion *superRegion,
1283 const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
1284 const SubRegion *superRegion) {
1285 return getElementRegion(ER->getElementType(), ER->getIndex(),
1286 superRegion, ER->getContext());
1289 /// getFieldRegion - Retrieve or create the memory region associated with
1290 /// a specified FieldDecl. 'superRegion' corresponds to the containing
1291 /// memory region (which typically represents the memory representing
1292 /// a structure or class).
1293 const FieldRegion *getFieldRegion(const FieldDecl *fd,
1294 const SubRegion* superRegion);
1296 const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR,
1297 const SubRegion *superRegion) {
1298 return getFieldRegion(FR->getDecl(), superRegion);
1301 /// getObjCIvarRegion - Retrieve or create the memory region associated with
1302 /// a specified Objective-c instance variable. 'superRegion' corresponds
1303 /// to the containing region (which typically represents the Objective-C
1305 const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl *ivd,
1306 const SubRegion* superRegion);
1308 const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
1309 LocationContext const *LC);
1311 /// Create a CXXBaseObjectRegion with the given base class for region
1314 /// The type of \p Super is assumed be a class deriving from \p BaseClass.
1315 const CXXBaseObjectRegion *
1316 getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super,
1319 /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
1321 const CXXBaseObjectRegion *
1322 getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
1323 const SubRegion *superRegion) {
1324 return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion,
1325 baseReg->isVirtual());
1328 const FunctionCodeRegion *getFunctionCodeRegion(const NamedDecl *FD);
1329 const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD,
1331 AnalysisDeclContext *AC);
1333 /// getBlockDataRegion - Get the memory region associated with an instance
1334 /// of a block. Unlike many other MemRegions, the LocationContext*
1335 /// argument is allowed to be NULL for cases where we have no known
1337 const BlockDataRegion *getBlockDataRegion(const BlockCodeRegion *bc,
1338 const LocationContext *lc,
1339 unsigned blockCount);
1341 /// Create a CXXTempObjectRegion for temporaries which are lifetime-extended
1342 /// by static references. This differs from getCXXTempObjectRegion in the
1343 /// super-region used.
1344 const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
1347 template <typename RegionTy, typename SuperTy,
1349 RegionTy* getSubRegion(const Arg1Ty arg1,
1350 const SuperTy* superRegion);
1352 template <typename RegionTy, typename SuperTy,
1353 typename Arg1Ty, typename Arg2Ty>
1354 RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
1355 const SuperTy* superRegion);
1357 template <typename RegionTy, typename SuperTy,
1358 typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
1359 RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
1361 const SuperTy* superRegion);
1363 template <typename REG>
1364 const REG* LazyAllocate(REG*& region);
1366 template <typename REG, typename ARG>
1367 const REG* LazyAllocate(REG*& region, ARG a);
1370 //===----------------------------------------------------------------------===//
1371 // Out-of-line member definitions.
1372 //===----------------------------------------------------------------------===//
1374 inline ASTContext &MemRegion::getContext() const {
1375 return getMemRegionManager()->getContext();
1378 //===----------------------------------------------------------------------===//
1379 // Means for storing region/symbol handling traits.
1380 //===----------------------------------------------------------------------===//
1382 /// Information about invalidation for a particular region/symbol.
1383 class RegionAndSymbolInvalidationTraits {
1384 typedef unsigned char StorageTypeForKinds;
1385 llvm::DenseMap<const MemRegion *, StorageTypeForKinds> MRTraitsMap;
1386 llvm::DenseMap<SymbolRef, StorageTypeForKinds> SymTraitsMap;
1388 typedef llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator
1389 const_region_iterator;
1390 typedef llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator
1391 const_symbol_iterator;
1394 /// \brief Describes different invalidation traits.
1395 enum InvalidationKinds {
1396 /// Tells that a region's contents is not changed.
1397 TK_PreserveContents = 0x1,
1398 /// Suppress pointer-escaping of a region.
1399 TK_SuppressEscape = 0x2,
1400 // Do not invalidate super region.
1401 TK_DoNotInvalidateSuperRegion = 0x4,
1402 /// When applied to a MemSpaceRegion, indicates the entire memory space
1403 /// should be invalidated.
1404 TK_EntireMemSpace = 0x8
1406 // Do not forget to extend StorageTypeForKinds if number of traits exceed
1407 // the number of bits StorageTypeForKinds can store.
1410 void setTrait(SymbolRef Sym, InvalidationKinds IK);
1411 void setTrait(const MemRegion *MR, InvalidationKinds IK);
1412 bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const;
1413 bool hasTrait(const MemRegion *MR, InvalidationKinds IK) const;
1416 //===----------------------------------------------------------------------===//
1417 // Pretty-printing regions.
1418 //===----------------------------------------------------------------------===//
1419 inline raw_ostream &operator<<(raw_ostream &os,
1420 const clang::ento::MemRegion *R) {
1421 R->dumpToStream(os);
1427 } // namespace clang