summaryrefslogtreecommitdiff
path: root/clang-r353983/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
diff options
context:
space:
mode:
Diffstat (limited to 'clang-r353983/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h')
-rw-r--r--clang-r353983/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h1488
1 files changed, 1488 insertions, 0 deletions
diff --git a/clang-r353983/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/clang-r353983/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
new file mode 100644
index 00000000..071e3508
--- /dev/null
+++ b/clang-r353983/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
@@ -0,0 +1,1488 @@
+//==- MemRegion.h - Abstract memory regions for static analysis -*- C++ -*--==//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines MemRegion and its subclasses. MemRegion defines a
+// partially-typed abstraction of memory useful for path-sensitive dataflow
+// analyses.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
+#define LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H
+
+#include "clang/AST/ASTContext.h"
+#include "clang/AST/CharUnits.h"
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/AST/DeclarationName.h"
+#include "clang/AST/Expr.h"
+#include "clang/AST/ExprObjC.h"
+#include "clang/AST/Type.h"
+#include "clang/Analysis/AnalysisDeclContext.h"
+#include "clang/Basic/LLVM.h"
+#include "clang/Basic/SourceLocation.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SVals.h"
+#include "clang/StaticAnalyzer/Core/PathSensitive/SymExpr.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/FoldingSet.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/PointerIntPair.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Casting.h"
+#include <cassert>
+#include <cstdint>
+#include <limits>
+#include <string>
+#include <utility>
+
+namespace clang {
+
+class AnalysisDeclContext;
+class CXXRecordDecl;
+class Decl;
+class LocationContext;
+class StackFrameContext;
+
+namespace ento {
+
+class CodeTextRegion;
+class MemRegion;
+class MemRegionManager;
+class MemSpaceRegion;
+class SValBuilder;
+class SymbolicRegion;
+class VarRegion;
+
+/// Represent a region's offset within the top level base region.
+class RegionOffset {
+ /// The base region.
+ const MemRegion *R = nullptr;
+
+ /// The bit offset within the base region. Can be negative.
+ int64_t Offset;
+
+public:
+ // We're using a const instead of an enumeration due to the size required;
+ // Visual Studio will only create enumerations of size int, not long long.
+ static const int64_t Symbolic = std::numeric_limits<int64_t>::max();
+
+ RegionOffset() = default;
+ RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
+
+ const MemRegion *getRegion() const { return R; }
+
+ bool hasSymbolicOffset() const { return Offset == Symbolic; }
+
+ int64_t getOffset() const {
+ assert(!hasSymbolicOffset());
+ return Offset;
+ }
+
+ bool isValid() const { return R; }
+};
+
+//===----------------------------------------------------------------------===//
+// Base region classes.
+//===----------------------------------------------------------------------===//
+
+/// MemRegion - The root abstract class for all memory regions.
+class MemRegion : public llvm::FoldingSetNode {
+public:
+ enum Kind {
+#define REGION(Id, Parent) Id ## Kind,
+#define REGION_RANGE(Id, First, Last) BEGIN_##Id = First, END_##Id = Last,
+#include "clang/StaticAnalyzer/Core/PathSensitive/Regions.def"
+ };
+
+private:
+ const Kind kind;
+ mutable Optional<RegionOffset> cachedOffset;
+
+protected:
+ MemRegion(Kind k) : kind(k) {}
+ virtual ~MemRegion();
+
+public:
+ ASTContext &getContext() const;
+
+ virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
+
+ virtual MemRegionManager* getMemRegionManager() const = 0;
+
+ const MemSpaceRegion *getMemorySpace() const;
+
+ const MemRegion *getBaseRegion() const;
+
+ /// Recursively retrieve the region of the most derived class instance of
+ /// regions of C++ base class instances.
+ const MemRegion *getMostDerivedObjectRegion() const;
+
+ /// Check if the region is a subregion of the given region.
+ /// Each region is a subregion of itself.
+ virtual bool isSubRegionOf(const MemRegion *R) const;
+
+ const MemRegion *StripCasts(bool StripBaseAndDerivedCasts = true) const;
+
+ /// If this is a symbolic region, returns the region. Otherwise,
+ /// goes up the base chain looking for the first symbolic base region.
+ const SymbolicRegion *getSymbolicBase() const;
+
+ bool hasGlobalsOrParametersStorage() const;
+
+ bool hasStackStorage() const;
+
+ bool hasStackNonParametersStorage() const;
+
+ bool hasStackParametersStorage() const;
+
+ /// Compute the offset within the top level memory object.
+ RegionOffset getAsOffset() const;
+
+ /// Get a string representation of a region for debug use.
+ std::string getString() const;
+
+ virtual void dumpToStream(raw_ostream &os) const;
+
+ void dump() const;
+
+ /// Returns true if this region can be printed in a user-friendly way.
+ virtual bool canPrintPretty() const;
+
+ /// Print the region for use in diagnostics.
+ virtual void printPretty(raw_ostream &os) const;
+
+ /// Returns true if this region's textual representation can be used
+ /// as part of a larger expression.
+ virtual bool canPrintPrettyAsExpr() const;
+
+ /// Print the region as expression.
+ ///
+ /// When this region represents a subexpression, the method is for printing
+ /// an expression containing it.
+ virtual void printPrettyAsExpr(raw_ostream &os) const;
+
+ Kind getKind() const { return kind; }
+
+ template<typename RegionTy> const RegionTy* getAs() const;
+
+ virtual bool isBoundable() const { return false; }
+
+ /// Get descriptive name for memory region. The name is obtained from
+ /// the variable/field declaration retrieved from the memory region.
+ /// Regions that point to an element of an array are returned as: "arr[0]".
+ /// Regions that point to a struct are returned as: "st.var".
+ //
+ /// \param UseQuotes Set if the name should be quoted.
+ ///
+ /// \returns variable name for memory region
+ std::string getDescriptiveName(bool UseQuotes = true) const;
+
+ /// Retrieve source range from memory region. The range retrieval
+ /// is based on the decl obtained from the memory region.
+ /// For a VarRegion the range of the base region is returned.
+ /// For a FieldRegion the range of the field is returned.
+ /// If no declaration is found, an empty source range is returned.
+ /// The client is responsible for checking if the returned range is valid.
+ ///
+ /// \returns source range for declaration retrieved from memory region
+ SourceRange sourceRange() const;
+};
+
+/// MemSpaceRegion - A memory region that represents a "memory space";
+/// for example, the set of global variables, the stack frame, etc.
+class MemSpaceRegion : public MemRegion {
+protected:
+ MemRegionManager *Mgr;
+
+ MemSpaceRegion(MemRegionManager *mgr, Kind k) : MemRegion(k), Mgr(mgr) {
+ assert(classof(this));
+ assert(mgr);
+ }
+
+ MemRegionManager* getMemRegionManager() const override { return Mgr; }
+
+public:
+ bool isBoundable() const override { return false; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ static bool classof(const MemRegion *R) {
+ Kind k = R->getKind();
+ return k >= BEGIN_MEMSPACES && k <= END_MEMSPACES;
+ }
+};
+
+/// CodeSpaceRegion - The memory space that holds the executable code of
+/// functions and blocks.
+class CodeSpaceRegion : public MemSpaceRegion {
+ friend class MemRegionManager;
+
+ CodeSpaceRegion(MemRegionManager *mgr)
+ : MemSpaceRegion(mgr, CodeSpaceRegionKind) {}
+
+public:
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == CodeSpaceRegionKind;
+ }
+};
+
+class GlobalsSpaceRegion : public MemSpaceRegion {
+ virtual void anchor();
+
+protected:
+ GlobalsSpaceRegion(MemRegionManager *mgr, Kind k) : MemSpaceRegion(mgr, k) {
+ assert(classof(this));
+ }
+
+public:
+ static bool classof(const MemRegion *R) {
+ Kind k = R->getKind();
+ return k >= BEGIN_GLOBAL_MEMSPACES && k <= END_GLOBAL_MEMSPACES;
+ }
+};
+
+/// The region of the static variables within the current CodeTextRegion
+/// scope.
+///
+/// Currently, only the static locals are placed there, so we know that these
+/// variables do not get invalidated by calls to other functions.
+class StaticGlobalSpaceRegion : public GlobalsSpaceRegion {
+ friend class MemRegionManager;
+
+ const CodeTextRegion *CR;
+
+ StaticGlobalSpaceRegion(MemRegionManager *mgr, const CodeTextRegion *cr)
+ : GlobalsSpaceRegion(mgr, StaticGlobalSpaceRegionKind), CR(cr) {
+ assert(cr);
+ }
+
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ const CodeTextRegion *getCodeRegion() const { return CR; }
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == StaticGlobalSpaceRegionKind;
+ }
+};
+
+/// The region for all the non-static global variables.
+///
+/// This class is further split into subclasses for efficient implementation of
+/// invalidating a set of related global values as is done in
+/// RegionStoreManager::invalidateRegions (instead of finding all the dependent
+/// globals, we invalidate the whole parent region).
+class NonStaticGlobalSpaceRegion : public GlobalsSpaceRegion {
+ void anchor() override;
+
+protected:
+ NonStaticGlobalSpaceRegion(MemRegionManager *mgr, Kind k)
+ : GlobalsSpaceRegion(mgr, k) {
+ assert(classof(this));
+ }
+
+public:
+ static bool classof(const MemRegion *R) {
+ Kind k = R->getKind();
+ return k >= BEGIN_NON_STATIC_GLOBAL_MEMSPACES &&
+ k <= END_NON_STATIC_GLOBAL_MEMSPACES;
+ }
+};
+
+/// The region containing globals which are defined in system/external
+/// headers and are considered modifiable by system calls (ex: errno).
+class GlobalSystemSpaceRegion : public NonStaticGlobalSpaceRegion {
+ friend class MemRegionManager;
+
+ GlobalSystemSpaceRegion(MemRegionManager *mgr)
+ : NonStaticGlobalSpaceRegion(mgr, GlobalSystemSpaceRegionKind) {}
+
+public:
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == GlobalSystemSpaceRegionKind;
+ }
+};
+
+/// The region containing globals which are considered not to be modified
+/// or point to data which could be modified as a result of a function call
+/// (system or internal). Ex: Const global scalars would be modeled as part of
+/// this region. This region also includes most system globals since they have
+/// low chance of being modified.
+class GlobalImmutableSpaceRegion : public NonStaticGlobalSpaceRegion {
+ friend class MemRegionManager;
+
+ GlobalImmutableSpaceRegion(MemRegionManager *mgr)
+ : NonStaticGlobalSpaceRegion(mgr, GlobalImmutableSpaceRegionKind) {}
+
+public:
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == GlobalImmutableSpaceRegionKind;
+ }
+};
+
+/// The region containing globals which can be modified by calls to
+/// "internally" defined functions - (for now just) functions other then system
+/// calls.
+class GlobalInternalSpaceRegion : public NonStaticGlobalSpaceRegion {
+ friend class MemRegionManager;
+
+ GlobalInternalSpaceRegion(MemRegionManager *mgr)
+ : NonStaticGlobalSpaceRegion(mgr, GlobalInternalSpaceRegionKind) {}
+
+public:
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == GlobalInternalSpaceRegionKind;
+ }
+};
+
+class HeapSpaceRegion : public MemSpaceRegion {
+ friend class MemRegionManager;
+
+ HeapSpaceRegion(MemRegionManager *mgr)
+ : MemSpaceRegion(mgr, HeapSpaceRegionKind) {}
+
+public:
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == HeapSpaceRegionKind;
+ }
+};
+
+class UnknownSpaceRegion : public MemSpaceRegion {
+ friend class MemRegionManager;
+
+ UnknownSpaceRegion(MemRegionManager *mgr)
+ : MemSpaceRegion(mgr, UnknownSpaceRegionKind) {}
+
+public:
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == UnknownSpaceRegionKind;
+ }
+};
+
+class StackSpaceRegion : public MemSpaceRegion {
+ virtual void anchor();
+
+ const StackFrameContext *SFC;
+
+protected:
+ StackSpaceRegion(MemRegionManager *mgr, Kind k, const StackFrameContext *sfc)
+ : MemSpaceRegion(mgr, k), SFC(sfc) {
+ assert(classof(this));
+ assert(sfc);
+ }
+
+public:
+ const StackFrameContext *getStackFrame() const { return SFC; }
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ static bool classof(const MemRegion *R) {
+ Kind k = R->getKind();
+ return k >= BEGIN_STACK_MEMSPACES && k <= END_STACK_MEMSPACES;
+ }
+};
+
+class StackLocalsSpaceRegion : public StackSpaceRegion {
+ friend class MemRegionManager;
+
+ StackLocalsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
+ : StackSpaceRegion(mgr, StackLocalsSpaceRegionKind, sfc) {}
+
+public:
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == StackLocalsSpaceRegionKind;
+ }
+};
+
+class StackArgumentsSpaceRegion : public StackSpaceRegion {
+private:
+ friend class MemRegionManager;
+
+ StackArgumentsSpaceRegion(MemRegionManager *mgr, const StackFrameContext *sfc)
+ : StackSpaceRegion(mgr, StackArgumentsSpaceRegionKind, sfc) {}
+
+public:
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *R) {
+ return R->getKind() == StackArgumentsSpaceRegionKind;
+ }
+};
+
+/// SubRegion - A region that subsets another larger region. Most regions
+/// are subclasses of SubRegion.
+class SubRegion : public MemRegion {
+ virtual void anchor();
+
+protected:
+ const MemRegion* superRegion;
+
+ SubRegion(const MemRegion *sReg, Kind k) : MemRegion(k), superRegion(sReg) {
+ assert(classof(this));
+ assert(sReg);
+ }
+
+public:
+ const MemRegion* getSuperRegion() const {
+ return superRegion;
+ }
+
+ /// getExtent - Returns the size of the region in bytes.
+ virtual DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const {
+ return UnknownVal();
+ }
+
+ MemRegionManager* getMemRegionManager() const override;
+
+ bool isSubRegionOf(const MemRegion* R) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() > END_MEMSPACES;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// MemRegion subclasses.
+//===----------------------------------------------------------------------===//
+
+/// AllocaRegion - A region that represents an untyped blob of bytes created
+/// by a call to 'alloca'.
+class AllocaRegion : public SubRegion {
+ friend class MemRegionManager;
+
+ // Block counter. Used to distinguish different pieces of memory allocated by
+ // alloca at the same call site.
+ unsigned Cnt;
+
+ const Expr *Ex;
+
+ AllocaRegion(const Expr *ex, unsigned cnt, const MemSpaceRegion *superRegion)
+ : SubRegion(superRegion, AllocaRegionKind), Cnt(cnt), Ex(ex) {
+ assert(Ex);
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Expr *Ex,
+ unsigned Cnt, const MemRegion *superRegion);
+
+public:
+ const Expr *getExpr() const { return Ex; }
+
+ bool isBoundable() const override { return true; }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == AllocaRegionKind;
+ }
+};
+
+/// TypedRegion - An abstract class representing regions that are typed.
+class TypedRegion : public SubRegion {
+ void anchor() override;
+
+protected:
+ TypedRegion(const MemRegion *sReg, Kind k) : SubRegion(sReg, k) {
+ assert(classof(this));
+ }
+
+public:
+ virtual QualType getLocationType() const = 0;
+
+ QualType getDesugaredLocationType(ASTContext &Context) const {
+ return getLocationType().getDesugaredType(Context);
+ }
+
+ bool isBoundable() const override { return true; }
+
+ static bool classof(const MemRegion* R) {
+ unsigned k = R->getKind();
+ return k >= BEGIN_TYPED_REGIONS && k <= END_TYPED_REGIONS;
+ }
+};
+
+/// TypedValueRegion - An abstract class representing regions having a typed value.
+class TypedValueRegion : public TypedRegion {
+ void anchor() override;
+
+protected:
+ TypedValueRegion(const MemRegion* sReg, Kind k) : TypedRegion(sReg, k) {
+ assert(classof(this));
+ }
+
+public:
+ virtual QualType getValueType() const = 0;
+
+ QualType getLocationType() const override {
+ // FIXME: We can possibly optimize this later to cache this value.
+ QualType T = getValueType();
+ ASTContext &ctx = getContext();
+ if (T->getAs<ObjCObjectType>())
+ return ctx.getObjCObjectPointerType(T);
+ return ctx.getPointerType(getValueType());
+ }
+
+ QualType getDesugaredValueType(ASTContext &Context) const {
+ QualType T = getValueType();
+ return T.getTypePtrOrNull() ? T.getDesugaredType(Context) : T;
+ }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+
+ static bool classof(const MemRegion* R) {
+ unsigned k = R->getKind();
+ return k >= BEGIN_TYPED_VALUE_REGIONS && k <= END_TYPED_VALUE_REGIONS;
+ }
+};
+
+class CodeTextRegion : public TypedRegion {
+ void anchor() override;
+
+protected:
+ CodeTextRegion(const MemSpaceRegion *sreg, Kind k) : TypedRegion(sreg, k) {
+ assert(classof(this));
+ }
+
+public:
+ bool isBoundable() const override { return false; }
+
+ static bool classof(const MemRegion* R) {
+ Kind k = R->getKind();
+ return k >= BEGIN_CODE_TEXT_REGIONS && k <= END_CODE_TEXT_REGIONS;
+ }
+};
+
+/// FunctionCodeRegion - A region that represents code texts of function.
+class FunctionCodeRegion : public CodeTextRegion {
+ friend class MemRegionManager;
+
+ const NamedDecl *FD;
+
+ FunctionCodeRegion(const NamedDecl *fd, const CodeSpaceRegion* sreg)
+ : CodeTextRegion(sreg, FunctionCodeRegionKind), FD(fd) {
+ assert(isa<ObjCMethodDecl>(fd) || isa<FunctionDecl>(fd));
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const NamedDecl *FD,
+ const MemRegion*);
+
+public:
+ QualType getLocationType() const override {
+ const ASTContext &Ctx = getContext();
+ if (const auto *D = dyn_cast<FunctionDecl>(FD)) {
+ return Ctx.getPointerType(D->getType());
+ }
+
+ assert(isa<ObjCMethodDecl>(FD));
+ assert(false && "Getting the type of ObjCMethod is not supported yet");
+
+ // TODO: We might want to return a different type here (ex: id (*ty)(...))
+ // depending on how it is used.
+ return {};
+ }
+
+ const NamedDecl *getDecl() const {
+ return FD;
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == FunctionCodeRegionKind;
+ }
+};
+
+/// BlockCodeRegion - A region that represents code texts of blocks (closures).
+/// Blocks are represented with two kinds of regions. BlockCodeRegions
+/// represent the "code", while BlockDataRegions represent instances of blocks,
+/// which correspond to "code+data". The distinction is important, because
+/// like a closure a block captures the values of externally referenced
+/// variables.
+class BlockCodeRegion : public CodeTextRegion {
+ friend class MemRegionManager;
+
+ const BlockDecl *BD;
+ AnalysisDeclContext *AC;
+ CanQualType locTy;
+
+ BlockCodeRegion(const BlockDecl *bd, CanQualType lTy,
+ AnalysisDeclContext *ac, const CodeSpaceRegion* sreg)
+ : CodeTextRegion(sreg, BlockCodeRegionKind), BD(bd), AC(ac), locTy(lTy) {
+ assert(bd);
+ assert(ac);
+ assert(lTy->getTypePtr()->isBlockPointerType());
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const BlockDecl *BD,
+ CanQualType, const AnalysisDeclContext*,
+ const MemRegion*);
+
+public:
+ QualType getLocationType() const override {
+ return locTy;
+ }
+
+ const BlockDecl *getDecl() const {
+ return BD;
+ }
+
+ AnalysisDeclContext *getAnalysisDeclContext() const { return AC; }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == BlockCodeRegionKind;
+ }
+};
+
+/// BlockDataRegion - A region that represents a block instance.
+/// Blocks are represented with two kinds of regions. BlockCodeRegions
+/// represent the "code", while BlockDataRegions represent instances of blocks,
+/// which correspond to "code+data". The distinction is important, because
+/// like a closure a block captures the values of externally referenced
+/// variables.
+class BlockDataRegion : public TypedRegion {
+ friend class MemRegionManager;
+
+ const BlockCodeRegion *BC;
+ const LocationContext *LC; // Can be null
+ unsigned BlockCount;
+ void *ReferencedVars = nullptr;
+ void *OriginalVars = nullptr;
+
+ BlockDataRegion(const BlockCodeRegion *bc, const LocationContext *lc,
+ unsigned count, const MemSpaceRegion *sreg)
+ : TypedRegion(sreg, BlockDataRegionKind), BC(bc), LC(lc),
+ BlockCount(count) {
+ assert(bc);
+ assert(lc);
+ assert(isa<GlobalImmutableSpaceRegion>(sreg) ||
+ isa<StackLocalsSpaceRegion>(sreg) ||
+ isa<UnknownSpaceRegion>(sreg));
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID&, const BlockCodeRegion *,
+ const LocationContext *, unsigned,
+ const MemRegion *);
+
+public:
+ const BlockCodeRegion *getCodeRegion() const { return BC; }
+
+ const BlockDecl *getDecl() const { return BC->getDecl(); }
+
+ QualType getLocationType() const override { return BC->getLocationType(); }
+
+ class referenced_vars_iterator {
+ const MemRegion * const *R;
+ const MemRegion * const *OriginalR;
+
+ public:
+ explicit referenced_vars_iterator(const MemRegion * const *r,
+ const MemRegion * const *originalR)
+ : R(r), OriginalR(originalR) {}
+
+ const VarRegion *getCapturedRegion() const {
+ return cast<VarRegion>(*R);
+ }
+
+ const VarRegion *getOriginalRegion() const {
+ return cast<VarRegion>(*OriginalR);
+ }
+
+ bool operator==(const referenced_vars_iterator &I) const {
+ assert((R == nullptr) == (I.R == nullptr));
+ return I.R == R;
+ }
+
+ bool operator!=(const referenced_vars_iterator &I) const {
+ assert((R == nullptr) == (I.R == nullptr));
+ return I.R != R;
+ }
+
+ referenced_vars_iterator &operator++() {
+ ++R;
+ ++OriginalR;
+ return *this;
+ }
+ };
+
+ /// Return the original region for a captured region, if
+ /// one exists.
+ const VarRegion *getOriginalRegion(const VarRegion *VR) const;
+
+ referenced_vars_iterator referenced_vars_begin() const;
+ referenced_vars_iterator referenced_vars_end() const;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == BlockDataRegionKind;
+ }
+
+private:
+ void LazyInitializeReferencedVars();
+ std::pair<const VarRegion *, const VarRegion *>
+ getCaptureRegions(const VarDecl *VD);
+};
+
+/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
+/// classes, SymbolicRegion represents a region that serves as an alias for
+/// either a real region, a NULL pointer, etc. It essentially is used to
+/// map the concept of symbolic values into the domain of regions. Symbolic
+/// regions do not need to be typed.
+class SymbolicRegion : public SubRegion {
+ friend class MemRegionManager;
+
+ const SymbolRef sym;
+
+ SymbolicRegion(const SymbolRef s, const MemSpaceRegion *sreg)
+ : SubRegion(sreg, SymbolicRegionKind), sym(s) {
+ // Because pointer arithmetic is represented by ElementRegion layers,
+ // the base symbol here should not contain any arithmetic.
+ assert(s && isa<SymbolData>(s));
+ assert(s->getType()->isAnyPointerType() ||
+ s->getType()->isReferenceType() ||
+ s->getType()->isBlockPointerType());
+ assert(isa<UnknownSpaceRegion>(sreg) || isa<HeapSpaceRegion>(sreg));
+ }
+
+public:
+ SymbolRef getSymbol() const { return sym; }
+
+ bool isBoundable() const override { return true; }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ SymbolRef sym,
+ const MemRegion* superRegion);
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == SymbolicRegionKind;
+ }
+};
+
+/// StringRegion - Region associated with a StringLiteral.
+class StringRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ const StringLiteral *Str;
+
+ StringRegion(const StringLiteral *str, const GlobalInternalSpaceRegion *sreg)
+ : TypedValueRegion(sreg, StringRegionKind), Str(str) {
+ assert(str);
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const StringLiteral *Str,
+ const MemRegion *superRegion);
+
+public:
+ const StringLiteral *getStringLiteral() const { return Str; }
+
+ QualType getValueType() const override { return Str->getType(); }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+
+ bool isBoundable() const override { return false; }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override {
+ ProfileRegion(ID, Str, superRegion);
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == StringRegionKind;
+ }
+};
+
+/// The region associated with an ObjCStringLiteral.
+class ObjCStringRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ const ObjCStringLiteral *Str;
+
+ ObjCStringRegion(const ObjCStringLiteral *str,
+ const GlobalInternalSpaceRegion *sreg)
+ : TypedValueRegion(sreg, ObjCStringRegionKind), Str(str) {
+ assert(str);
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const ObjCStringLiteral *Str,
+ const MemRegion *superRegion);
+
+public:
+ const ObjCStringLiteral *getObjCStringLiteral() const { return Str; }
+
+ QualType getValueType() const override { return Str->getType(); }
+
+ bool isBoundable() const override { return false; }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override {
+ ProfileRegion(ID, Str, superRegion);
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ObjCStringRegionKind;
+ }
+};
+
+/// CompoundLiteralRegion - A memory region representing a compound literal.
+/// Compound literals are essentially temporaries that are stack allocated
+/// or in the global constant pool.
+class CompoundLiteralRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ const CompoundLiteralExpr *CL;
+
+ CompoundLiteralRegion(const CompoundLiteralExpr *cl,
+ const MemSpaceRegion *sReg)
+ : TypedValueRegion(sReg, CompoundLiteralRegionKind), CL(cl) {
+ assert(cl);
+ assert(isa<GlobalInternalSpaceRegion>(sReg) ||
+ isa<StackLocalsSpaceRegion>(sReg));
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID,
+ const CompoundLiteralExpr *CL,
+ const MemRegion* superRegion);
+
+public:
+ QualType getValueType() const override { return CL->getType(); }
+
+ bool isBoundable() const override { return !CL->isFileScope(); }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ const CompoundLiteralExpr *getLiteralExpr() const { return CL; }
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == CompoundLiteralRegionKind;
+ }
+};
+
+class DeclRegion : public TypedValueRegion {
+protected:
+ const ValueDecl *D;
+
+ DeclRegion(const ValueDecl *d, const MemRegion *sReg, Kind k)
+ : TypedValueRegion(sReg, k), D(d) {
+ assert(classof(this));
+ assert(d && d->isCanonicalDecl());
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl *D,
+ const MemRegion* superRegion, Kind k);
+
+public:
+ const ValueDecl *getDecl() const { return D; }
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static bool classof(const MemRegion* R) {
+ unsigned k = R->getKind();
+ return k >= BEGIN_DECL_REGIONS && k <= END_DECL_REGIONS;
+ }
+};
+
+class VarRegion : public DeclRegion {
+ friend class MemRegionManager;
+
+ // Constructors and private methods.
+ VarRegion(const VarDecl *vd, const MemRegion *sReg)
+ : DeclRegion(vd, sReg, VarRegionKind) {
+ // VarRegion appears in unknown space when it's a block variable as seen
+ // from a block using it, when this block is analyzed at top-level.
+ // Other block variables appear within block data regions,
+ // which, unlike everything else on this list, are not memory spaces.
+ assert(isa<GlobalsSpaceRegion>(sReg) || isa<StackSpaceRegion>(sReg) ||
+ isa<BlockDataRegion>(sReg) || isa<UnknownSpaceRegion>(sReg));
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl *VD,
+ const MemRegion *superRegion) {
+ DeclRegion::ProfileRegion(ID, VD, superRegion, VarRegionKind);
+ }
+
+public:
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ const VarDecl *getDecl() const { return cast<VarDecl>(D); }
+
+ const StackFrameContext *getStackFrame() const;
+
+ QualType getValueType() const override {
+ // FIXME: We can cache this if needed.
+ return getDecl()->getType();
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ bool canPrintPrettyAsExpr() const override;
+
+ void printPrettyAsExpr(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == VarRegionKind;
+ }
+};
+
+/// CXXThisRegion - Represents the region for the implicit 'this' parameter
+/// in a call to a C++ method. This region doesn't represent the object
+/// referred to by 'this', but rather 'this' itself.
+class CXXThisRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ CXXThisRegion(const PointerType *thisPointerTy,
+ const StackArgumentsSpaceRegion *sReg)
+ : TypedValueRegion(sReg, CXXThisRegionKind),
+ ThisPointerTy(thisPointerTy) {
+ assert(ThisPointerTy->getPointeeType()->getAsCXXRecordDecl() &&
+ "Invalid region type!");
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ const PointerType *PT,
+ const MemRegion *sReg);
+
+public:
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ QualType getValueType() const override {
+ return QualType(ThisPointerTy, 0);
+ }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == CXXThisRegionKind;
+ }
+
+private:
+ const PointerType *ThisPointerTy;
+};
+
+class FieldRegion : public DeclRegion {
+ friend class MemRegionManager;
+
+ FieldRegion(const FieldDecl *fd, const SubRegion* sReg)
+ : DeclRegion(fd, sReg, FieldRegionKind) {}
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const FieldDecl *FD,
+ const MemRegion* superRegion) {
+ DeclRegion::ProfileRegion(ID, FD, superRegion, FieldRegionKind);
+ }
+
+public:
+ const FieldDecl *getDecl() const { return cast<FieldDecl>(D); }
+
+ QualType getValueType() const override {
+ // FIXME: We can cache this if needed.
+ return getDecl()->getType();
+ }
+
+ DefinedOrUnknownSVal getExtent(SValBuilder &svalBuilder) const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ bool canPrintPretty() const override;
+ void printPretty(raw_ostream &os) const override;
+ bool canPrintPrettyAsExpr() const override;
+ void printPrettyAsExpr(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == FieldRegionKind;
+ }
+};
+
+class ObjCIvarRegion : public DeclRegion {
+ friend class MemRegionManager;
+
+ ObjCIvarRegion(const ObjCIvarDecl *ivd, const SubRegion *sReg);
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, const ObjCIvarDecl *ivd,
+ const MemRegion* superRegion);
+
+public:
+ const ObjCIvarDecl *getDecl() const;
+ QualType getValueType() const override;
+
+ bool canPrintPrettyAsExpr() const override;
+ void printPrettyAsExpr(raw_ostream &os) const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ObjCIvarRegionKind;
+ }
+};
+
+//===----------------------------------------------------------------------===//
+// Auxiliary data classes for use with MemRegions.
+//===----------------------------------------------------------------------===//
+
+class RegionRawOffset {
+ friend class ElementRegion;
+
+ const MemRegion *Region;
+ CharUnits Offset;
+
+ RegionRawOffset(const MemRegion* reg, CharUnits offset = CharUnits::Zero())
+ : Region(reg), Offset(offset) {}
+
+public:
+ // FIXME: Eventually support symbolic offsets.
+ CharUnits getOffset() const { return Offset; }
+ const MemRegion *getRegion() const { return Region; }
+
+ void dumpToStream(raw_ostream &os) const;
+ void dump() const;
+};
+
+/// ElementRegion is used to represent both array elements and casts.
+class ElementRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ QualType ElementType;
+ NonLoc Index;
+
+ ElementRegion(QualType elementType, NonLoc Idx, const SubRegion *sReg)
+ : TypedValueRegion(sReg, ElementRegionKind), ElementType(elementType),
+ Index(Idx) {
+ assert((!Idx.getAs<nonloc::ConcreteInt>() ||
+ Idx.castAs<nonloc::ConcreteInt>().getValue().isSigned()) &&
+ "The index must be signed");
+ assert(!elementType.isNull() && !elementType->isVoidType() &&
+ "Invalid region type!");
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType elementType,
+ SVal Idx, const MemRegion* superRegion);
+
+public:
+ NonLoc getIndex() const { return Index; }
+
+ QualType getValueType() const override { return ElementType; }
+
+ QualType getElementType() const { return ElementType; }
+
+ /// Compute the offset within the array. The array might also be a subobject.
+ RegionRawOffset getAsArrayOffset() const;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID& ID) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == ElementRegionKind;
+ }
+};
+
+// C++ temporary object associated with an expression.
+class CXXTempObjectRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ Expr const *Ex;
+
+ CXXTempObjectRegion(Expr const *E, MemSpaceRegion const *sReg)
+ : TypedValueRegion(sReg, CXXTempObjectRegionKind), Ex(E) {
+ assert(E);
+ assert(isa<StackLocalsSpaceRegion>(sReg) ||
+ isa<GlobalInternalSpaceRegion>(sReg));
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID,
+ Expr const *E, const MemRegion *sReg);
+
+public:
+ const Expr *getExpr() const { return Ex; }
+
+ QualType getValueType() const override { return Ex->getType(); }
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == CXXTempObjectRegionKind;
+ }
+};
+
+// CXXBaseObjectRegion represents a base object within a C++ object. It is
+// identified by the base class declaration and the region of its parent object.
+class CXXBaseObjectRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ llvm::PointerIntPair<const CXXRecordDecl *, 1, bool> Data;
+
+ CXXBaseObjectRegion(const CXXRecordDecl *RD, bool IsVirtual,
+ const SubRegion *SReg)
+ : TypedValueRegion(SReg, CXXBaseObjectRegionKind), Data(RD, IsVirtual) {
+ assert(RD);
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
+ bool IsVirtual, const MemRegion *SReg);
+
+public:
+ const CXXRecordDecl *getDecl() const { return Data.getPointer(); }
+ bool isVirtual() const { return Data.getInt(); }
+
+ QualType getValueType() const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ bool canPrintPrettyAsExpr() const override;
+
+ void printPrettyAsExpr(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *region) {
+ return region->getKind() == CXXBaseObjectRegionKind;
+ }
+};
+
+// CXXDerivedObjectRegion represents a derived-class object that surrounds
+// a C++ object. It is identified by the derived class declaration and the
+// region of its parent object. It is a bit counter-intuitive (but not otherwise
+// unseen) that this region represents a larger segment of memory that its
+// super-region.
+class CXXDerivedObjectRegion : public TypedValueRegion {
+ friend class MemRegionManager;
+
+ const CXXRecordDecl *DerivedD;
+
+ CXXDerivedObjectRegion(const CXXRecordDecl *DerivedD, const SubRegion *SReg)
+ : TypedValueRegion(SReg, CXXDerivedObjectRegionKind), DerivedD(DerivedD) {
+ assert(DerivedD);
+ // In case of a concrete region, it should always be possible to model
+ // the base-to-derived cast by undoing a previous derived-to-base cast,
+ // otherwise the cast is most likely ill-formed.
+ assert(SReg->getSymbolicBase() &&
+ "Should have unwrapped a base region instead!");
+ }
+
+ static void ProfileRegion(llvm::FoldingSetNodeID &ID, const CXXRecordDecl *RD,
+ const MemRegion *SReg);
+
+public:
+ const CXXRecordDecl *getDecl() const { return DerivedD; }
+
+ QualType getValueType() const override;
+
+ void dumpToStream(raw_ostream &os) const override;
+
+ void Profile(llvm::FoldingSetNodeID &ID) const override;
+
+ bool canPrintPrettyAsExpr() const override;
+
+ void printPrettyAsExpr(raw_ostream &os) const override;
+
+ static bool classof(const MemRegion *region) {
+ return region->getKind() == CXXDerivedObjectRegionKind;
+ }
+};
+
+template<typename RegionTy>
+const RegionTy* MemRegion::getAs() const {
+ if (const auto *RT = dyn_cast<RegionTy>(this))
+ return RT;
+
+ return nullptr;
+}
+
+//===----------------------------------------------------------------------===//
+// MemRegionManager - Factory object for creating regions.
+//===----------------------------------------------------------------------===//
+
+class MemRegionManager {
+ ASTContext &C;
+ llvm::BumpPtrAllocator& A;
+ llvm::FoldingSet<MemRegion> Regions;
+
+ GlobalInternalSpaceRegion *InternalGlobals = nullptr;
+ GlobalSystemSpaceRegion *SystemGlobals = nullptr;
+ GlobalImmutableSpaceRegion *ImmutableGlobals = nullptr;
+
+ llvm::DenseMap<const StackFrameContext *, StackLocalsSpaceRegion *>
+ StackLocalsSpaceRegions;
+ llvm::DenseMap<const StackFrameContext *, StackArgumentsSpaceRegion *>
+ StackArgumentsSpaceRegions;
+ llvm::DenseMap<const CodeTextRegion *, StaticGlobalSpaceRegion *>
+ StaticsGlobalSpaceRegions;
+
+ HeapSpaceRegion *heap = nullptr;
+ UnknownSpaceRegion *unknown = nullptr;
+ CodeSpaceRegion *code = nullptr;
+
+public:
+ MemRegionManager(ASTContext &c, llvm::BumpPtrAllocator &a) : C(c), A(a) {}
+ ~MemRegionManager();
+
+ ASTContext &getContext() { return C; }
+
+ llvm::BumpPtrAllocator &getAllocator() { return A; }
+
+ /// getStackLocalsRegion - Retrieve the memory region associated with the
+ /// specified stack frame.
+ const StackLocalsSpaceRegion *
+ getStackLocalsRegion(const StackFrameContext *STC);
+
+ /// getStackArgumentsRegion - Retrieve the memory region associated with
+ /// function/method arguments of the specified stack frame.
+ const StackArgumentsSpaceRegion *
+ getStackArgumentsRegion(const StackFrameContext *STC);
+
+ /// getGlobalsRegion - Retrieve the memory region associated with
+ /// global variables.
+ const GlobalsSpaceRegion *getGlobalsRegion(
+ MemRegion::Kind K = MemRegion::GlobalInternalSpaceRegionKind,
+ const CodeTextRegion *R = nullptr);
+
+ /// getHeapRegion - Retrieve the memory region associated with the
+ /// generic "heap".
+ const HeapSpaceRegion *getHeapRegion();
+
+ /// getUnknownRegion - Retrieve the memory region associated with unknown
+ /// memory space.
+ const UnknownSpaceRegion *getUnknownRegion();
+
+ const CodeSpaceRegion *getCodeRegion();
+
+ /// getAllocaRegion - Retrieve a region associated with a call to alloca().
+ const AllocaRegion *getAllocaRegion(const Expr *Ex, unsigned Cnt,
+ const LocationContext *LC);
+
+ /// getCompoundLiteralRegion - Retrieve the region associated with a
+ /// given CompoundLiteral.
+ const CompoundLiteralRegion*
+ getCompoundLiteralRegion(const CompoundLiteralExpr *CL,
+ const LocationContext *LC);
+
+ /// getCXXThisRegion - Retrieve the [artificial] region associated with the
+ /// parameter 'this'.
+ const CXXThisRegion *getCXXThisRegion(QualType thisPointerTy,
+ const LocationContext *LC);
+
+ /// Retrieve or create a "symbolic" memory region.
+ const SymbolicRegion* getSymbolicRegion(SymbolRef Sym);
+
+ /// Return a unique symbolic region belonging to heap memory space.
+ const SymbolicRegion *getSymbolicHeapRegion(SymbolRef sym);
+
+ const StringRegion *getStringRegion(const StringLiteral *Str);
+
+ const ObjCStringRegion *getObjCStringRegion(const ObjCStringLiteral *Str);
+
+ /// getVarRegion - Retrieve or create the memory region associated with
+ /// a specified VarDecl and LocationContext.
+ const VarRegion* getVarRegion(const VarDecl *D, const LocationContext *LC);
+
+ /// getVarRegion - Retrieve or create the memory region associated with
+ /// a specified VarDecl and super region.
+ const VarRegion *getVarRegion(const VarDecl *D, const MemRegion *superR);
+
+ /// getElementRegion - Retrieve the memory region associated with the
+ /// associated element type, index, and super region.
+ const ElementRegion *getElementRegion(QualType elementType, NonLoc Idx,
+ const SubRegion *superRegion,
+ ASTContext &Ctx);
+
+ const ElementRegion *getElementRegionWithSuper(const ElementRegion *ER,
+ const SubRegion *superRegion) {
+ return getElementRegion(ER->getElementType(), ER->getIndex(),
+ superRegion, ER->getContext());
+ }
+
+ /// getFieldRegion - Retrieve or create the memory region associated with
+ /// a specified FieldDecl. 'superRegion' corresponds to the containing
+ /// memory region (which typically represents the memory representing
+ /// a structure or class).
+ const FieldRegion *getFieldRegion(const FieldDecl *fd,
+ const SubRegion* superRegion);
+
+ const FieldRegion *getFieldRegionWithSuper(const FieldRegion *FR,
+ const SubRegion *superRegion) {
+ return getFieldRegion(FR->getDecl(), superRegion);
+ }
+
+ /// getObjCIvarRegion - Retrieve or create the memory region associated with
+ /// a specified Objective-c instance variable. 'superRegion' corresponds
+ /// to the containing region (which typically represents the Objective-C
+ /// object).
+ const ObjCIvarRegion *getObjCIvarRegion(const ObjCIvarDecl *ivd,
+ const SubRegion* superRegion);
+
+ const CXXTempObjectRegion *getCXXTempObjectRegion(Expr const *Ex,
+ LocationContext const *LC);
+
+ /// Create a CXXBaseObjectRegion with the given base class for region
+ /// \p Super.
+ ///
+ /// The type of \p Super is assumed be a class deriving from \p BaseClass.
+ const CXXBaseObjectRegion *
+ getCXXBaseObjectRegion(const CXXRecordDecl *BaseClass, const SubRegion *Super,
+ bool IsVirtual);
+
+ /// Create a CXXBaseObjectRegion with the same CXXRecordDecl but a different
+ /// super region.
+ const CXXBaseObjectRegion *
+ getCXXBaseObjectRegionWithSuper(const CXXBaseObjectRegion *baseReg,
+ const SubRegion *superRegion) {
+ return getCXXBaseObjectRegion(baseReg->getDecl(), superRegion,
+ baseReg->isVirtual());
+ }
+
+ /// Create a CXXDerivedObjectRegion with the given derived class for region
+ /// \p Super. This should not be used for casting an existing
+ /// CXXBaseObjectRegion back to the derived type; instead, CXXBaseObjectRegion
+ /// should be removed.
+ const CXXDerivedObjectRegion *
+ getCXXDerivedObjectRegion(const CXXRecordDecl *BaseClass,
+ const SubRegion *Super);
+
+ const FunctionCodeRegion *getFunctionCodeRegion(const NamedDecl *FD);
+ const BlockCodeRegion *getBlockCodeRegion(const BlockDecl *BD,
+ CanQualType locTy,
+ AnalysisDeclContext *AC);
+
+ /// getBlockDataRegion - Get the memory region associated with an instance
+ /// of a block. Unlike many other MemRegions, the LocationContext*
+ /// argument is allowed to be NULL for cases where we have no known
+ /// context.
+ const BlockDataRegion *getBlockDataRegion(const BlockCodeRegion *bc,
+ const LocationContext *lc,
+ unsigned blockCount);
+
+ /// Create a CXXTempObjectRegion for temporaries which are lifetime-extended
+ /// by static references. This differs from getCXXTempObjectRegion in the
+ /// super-region used.
+ const CXXTempObjectRegion *getCXXStaticTempObjectRegion(const Expr *Ex);
+
+private:
+ template <typename RegionTy, typename SuperTy,
+ typename Arg1Ty>
+ RegionTy* getSubRegion(const Arg1Ty arg1,
+ const SuperTy* superRegion);
+
+ template <typename RegionTy, typename SuperTy,
+ typename Arg1Ty, typename Arg2Ty>
+ RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
+ const SuperTy* superRegion);
+
+ template <typename RegionTy, typename SuperTy,
+ typename Arg1Ty, typename Arg2Ty, typename Arg3Ty>
+ RegionTy* getSubRegion(const Arg1Ty arg1, const Arg2Ty arg2,
+ const Arg3Ty arg3,
+ const SuperTy* superRegion);
+
+ template <typename REG>
+ const REG* LazyAllocate(REG*& region);
+
+ template <typename REG, typename ARG>
+ const REG* LazyAllocate(REG*& region, ARG a);
+};
+
+//===----------------------------------------------------------------------===//
+// Out-of-line member definitions.
+//===----------------------------------------------------------------------===//
+
+inline ASTContext &MemRegion::getContext() const {
+ return getMemRegionManager()->getContext();
+}
+
+//===----------------------------------------------------------------------===//
+// Means for storing region/symbol handling traits.
+//===----------------------------------------------------------------------===//
+
+/// Information about invalidation for a particular region/symbol.
+class RegionAndSymbolInvalidationTraits {
+ using StorageTypeForKinds = unsigned char;
+
+ llvm::DenseMap<const MemRegion *, StorageTypeForKinds> MRTraitsMap;
+ llvm::DenseMap<SymbolRef, StorageTypeForKinds> SymTraitsMap;
+
+ using const_region_iterator =
+ llvm::DenseMap<const MemRegion *, StorageTypeForKinds>::const_iterator;
+ using const_symbol_iterator =
+ llvm::DenseMap<SymbolRef, StorageTypeForKinds>::const_iterator;
+
+public:
+ /// Describes different invalidation traits.
+ enum InvalidationKinds {
+ /// Tells that a region's contents is not changed.
+ TK_PreserveContents = 0x1,
+
+ /// Suppress pointer-escaping of a region.
+ TK_SuppressEscape = 0x2,
+
+ // Do not invalidate super region.
+ TK_DoNotInvalidateSuperRegion = 0x4,
+
+ /// When applied to a MemSpaceRegion, indicates the entire memory space
+ /// should be invalidated.
+ TK_EntireMemSpace = 0x8
+
+ // Do not forget to extend StorageTypeForKinds if number of traits exceed
+ // the number of bits StorageTypeForKinds can store.
+ };
+
+ void setTrait(SymbolRef Sym, InvalidationKinds IK);
+ void setTrait(const MemRegion *MR, InvalidationKinds IK);
+ bool hasTrait(SymbolRef Sym, InvalidationKinds IK) const;
+ bool hasTrait(const MemRegion *MR, InvalidationKinds IK) const;
+};
+
+//===----------------------------------------------------------------------===//
+// Pretty-printing regions.
+//===----------------------------------------------------------------------===//
+inline raw_ostream &operator<<(raw_ostream &os, const MemRegion *R) {
+ R->dumpToStream(os);
+ return os;
+}
+
+} // namespace ento
+
+} // namespace clang
+
+#endif // LLVM_CLANG_STATICANALYZER_CORE_PATHSENSITIVE_MEMREGION_H