[cfe-commits] r57717 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRState.h include/clang/Analysis/PathSensitive/MemRegion.h include/clang/Analysis/PathSensitive/RValues.h include/clang/Analysis/PathSensitive/Store.h lib/Analysis/BasicObjCFoundationChecks.cpp lib/Analysis/BasicStore.cpp lib/Analysis/CFRefCount.cpp lib/Analysis/CheckNSError.cpp lib/Analysis/MemRegion.cpp lib/Analysis/RegionStore.cpp
Ted Kremenek
kremenek at apple.com
Fri Oct 17 13:28:54 PDT 2008
Author: kremenek
Date: Fri Oct 17 15:28:54 2008
New Revision: 57717
URL: http://llvm.org/viewvc/llvm-project?rev=57717&view=rev
Log:
- constify some uses of MemRegion* (MemRegion should be immutable).
- Added new region "SymbolicRegion", which maps symbol values to the region domain.
- Enhanced BasicStore::getFieldLValue() to return a FieldRegion (using SymbolicRegion)
- Added some utility methods to GRState for fetch svals from the store.
- Fixed regression in CheckNSError (we weren't getting the value bound to the parameter)
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h
cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp
cfe/trunk/lib/Analysis/BasicStore.cpp
cfe/trunk/lib/Analysis/CFRefCount.cpp
cfe/trunk/lib/Analysis/CheckNSError.cpp
cfe/trunk/lib/Analysis/MemRegion.cpp
cfe/trunk/lib/Analysis/RegionStore.cpp
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h?rev=57717&r1=57716&r2=57717&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h Fri Oct 17 15:28:54 2008
@@ -425,6 +425,10 @@
return StoreMgr->GetSVal(St->getStore(), LV, T);
}
+ SVal GetSVal(const GRState* St, const MemRegion* R) {
+ return StoreMgr->GetRegionSVal(St->getStore(), R);
+ }
+
void SetSVal(GRState& St, Loc LV, SVal V) {
St.St = StoreMgr->SetSVal(St.St, LV, V);
}
@@ -522,6 +526,10 @@
return Mgr->GetSVal(St, LV, T);
}
+ SVal GetSVal(const MemRegion* R) {
+ return Mgr->GetSVal(St, R);
+ }
+
GRStateRef SetSVal(Expr* Ex, SVal V, bool isBlkExpr, bool Invalidate) {
return GRStateRef(Mgr->SetSVal(St, Ex, V, isBlkExpr, Invalidate), *Mgr);
}
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h?rev=57717&r1=57716&r2=57717&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/MemRegion.h Fri Oct 17 15:28:54 2008
@@ -16,11 +16,12 @@
#ifndef LLVM_CLANG_ANALYSIS_MEMREGION_H
#define LLVM_CLANG_ANALYSIS_MEMREGION_H
+#include "clang/AST/Decl.h"
+#include "clang/AST/DeclObjC.h"
+#include "clang/Analysis/PathSensitive/SymbolManager.h"
#include "llvm/Support/Casting.h"
#include "llvm/ADT/FoldingSet.h"
#include "llvm/Support/Allocator.h"
-#include "clang/AST/Decl.h"
-#include "clang/AST/DeclObjC.h"
#include <string>
namespace llvm { class raw_ostream; }
@@ -33,7 +34,7 @@
/// MemRegion - The root abstract class for all memory regions.
class MemRegion : public llvm::FoldingSetNode {
public:
- enum Kind { MemSpaceRegionKind,
+ enum Kind { MemSpaceRegionKind, SymbolicRegionKind,
// Typed regions.
BEG_TYPED_REGIONS,
VarRegionKind, FieldRegionKind, ObjCIvarRegionKind,
@@ -48,7 +49,6 @@
public:
// virtual MemExtent getExtent(MemRegionManager& mrm) const = 0;
- virtual const MemRegion* getSuperRegion() const = 0;
virtual void Profile(llvm::FoldingSetNodeID& ID) const = 0;
std::string getString() const;
@@ -67,11 +67,6 @@
public:
//RegionExtent getExtent() const { return UndefinedExtent(); }
- const MemRegion* getSuperRegion() const {
- return 0;
- }
-
- //static void ProfileRegion(llvm::FoldingSetNodeID& ID);
void Profile(llvm::FoldingSetNodeID& ID) const;
static bool classof(const MemRegion* R) {
@@ -79,23 +74,58 @@
}
};
-/// TypedRegion - An abstract class representing regions that are typed.
-class TypedRegion : public MemRegion {
+/// SubRegion - A region that subsets another larger region. Most regions
+/// are subclasses of SubRegion.
+class SubRegion : public MemRegion {
protected:
- const MemRegion* superRegion;
-
- TypedRegion(const MemRegion* sReg, Kind k)
- : MemRegion(k), superRegion(sReg) {};
+ const MemRegion* superRegion;
+ SubRegion(const MemRegion* sReg, Kind k) : MemRegion(k), superRegion(sReg) {}
public:
- virtual QualType getType() const = 0;
-
- // MemExtent getExtent(MemRegionManager& mrm) const;
const MemRegion* getSuperRegion() const {
return superRegion;
}
static bool classof(const MemRegion* R) {
+ return R->getKind() > SymbolicRegionKind;
+ }
+};
+
+/// SymbolicRegion - A special, "non-concrete" region. Unlike other region
+/// clases, 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 MemRegion {
+protected:
+ const SymbolID sym;
+
+public:
+ SymbolicRegion(const SymbolID s) : MemRegion(SymbolicRegionKind), sym(s) {}
+
+ SymbolID getSymbol() const {
+ return sym;
+ }
+
+ void Profile(llvm::FoldingSetNodeID& ID) const;
+ static void ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolID sym);
+
+ void print(llvm::raw_ostream& os) const;
+
+ static bool classof(const MemRegion* R) {
+ return R->getKind() == SymbolicRegionKind;
+ }
+};
+
+/// TypedRegion - An abstract class representing regions that are typed.
+class TypedRegion : public SubRegion {
+protected:
+ TypedRegion(const MemRegion* sReg, Kind k) : SubRegion(sReg, k) {}
+
+public:
+ virtual QualType getType() const = 0;
+
+ static bool classof(const MemRegion* R) {
unsigned k = R->getKind();
return k > BEG_TYPED_REGIONS && k < END_TYPED_REGIONS;
}
@@ -152,7 +182,7 @@
protected:
const Decl* D;
- DeclRegion(const Decl* d, MemRegion* sReg, Kind k)
+ DeclRegion(const Decl* d, const MemRegion* sReg, Kind k)
: TypedRegion(sReg, k), D(d) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const Decl* D,
@@ -165,7 +195,7 @@
class VarRegion : public DeclRegion {
friend class MemRegionManager;
- VarRegion(const VarDecl* vd, MemRegion* sReg)
+ VarRegion(const VarDecl* vd, const MemRegion* sReg)
: DeclRegion(vd, sReg, VarRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, VarDecl* VD,
@@ -187,7 +217,7 @@
class FieldRegion : public DeclRegion {
friend class MemRegionManager;
- FieldRegion(const FieldDecl* fd, MemRegion* sReg)
+ FieldRegion(const FieldDecl* fd, const MemRegion* sReg)
: DeclRegion(fd, sReg, FieldRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, FieldDecl* FD,
@@ -208,7 +238,7 @@
friend class MemRegionManager;
- ObjCIvarRegion(const ObjCIvarDecl* ivd, MemRegion* sReg)
+ ObjCIvarRegion(const ObjCIvarDecl* ivd, const MemRegion* sReg)
: DeclRegion(ivd, sReg, ObjCIvarRegionKind) {}
static void ProfileRegion(llvm::FoldingSetNodeID& ID, ObjCIvarDecl* ivd,
@@ -260,10 +290,13 @@
/// memory space.
MemSpaceRegion* getUnknownRegion();
+ /// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
+ SymbolicRegion* getSymbolicRegion(const SymbolID sym);
+
/// getVarRegion - Retrieve or create the memory region associated with
/// a specified VarDecl. 'superRegion' corresponds to the containing
/// memory region, and 'off' is the offset within the containing region.
- VarRegion* getVarRegion(const VarDecl* vd, MemRegion* superRegion);
+ VarRegion* getVarRegion(const VarDecl* vd, const MemRegion* superRegion);
VarRegion* getVarRegion(const VarDecl* vd) {
return getVarRegion(vd, vd->hasLocalStorage() ? getStackRegion()
@@ -274,14 +307,14 @@
/// a specified FieldDecl. 'superRegion' corresponds to the containing
/// memory region (which typically represents the memory representing
/// a structure or class).
- FieldRegion* getFieldRegion(const FieldDecl* fd, MemRegion* superRegion);
+ FieldRegion* getFieldRegion(const FieldDecl* fd, const MemRegion* 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).
ObjCIvarRegion* getObjCIvarRegion(const ObjCIvarDecl* ivd,
- MemRegion* superRegion);
+ const MemRegion* superRegion);
AnonPointeeRegion* getAnonPointeeRegion(const VarDecl* d);
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h?rev=57717&r1=57716&r2=57717&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/RValues.h Fri Oct 17 15:28:54 2008
@@ -331,10 +331,15 @@
public:
MemRegionVal(const MemRegion* r) : Loc(MemRegionKind, r) {}
- MemRegion* getRegion() const {
+ const MemRegion* getRegion() const {
return static_cast<MemRegion*>(Data);
}
+ template <typename REGION>
+ const REGION* getRegionAs() const {
+ return llvm::dyn_cast<REGION>(getRegion());
+ }
+
inline bool operator==(const MemRegionVal& R) const {
return getRegion() == R.getRegion();
}
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Store.h?rev=57717&r1=57716&r2=57717&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Store.h Fri Oct 17 15:28:54 2008
@@ -15,6 +15,7 @@
#define LLVM_CLANG_ANALYSIS_STORE_H
#include "clang/Analysis/PathSensitive/RValues.h"
+#include "clang/Analysis/PathSensitive/MemRegion.h"
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallSet.h"
#include "llvm/ADT/DenseSet.h"
@@ -31,8 +32,6 @@
class Stmt;
class Expr;
class ObjCIvarDecl;
-class MemRegion;
-class MemRegionManager;
class StoreManager {
public:
@@ -40,7 +39,12 @@
typedef llvm::DenseSet<SymbolID> DeadSymbolsTy;
virtual ~StoreManager() {}
- virtual SVal GetSVal(Store St, Loc LV, QualType T = QualType()) = 0;
+ virtual SVal GetSVal(Store St, Loc LV, QualType T = QualType()) = 0;
+
+ virtual SVal GetRegionSVal(Store St, const MemRegion* R) {
+ return GetSVal(St, loc::MemRegionVal(R));
+ }
+
virtual Store SetSVal(Store St, Loc LV, SVal V) = 0;
virtual Store Remove(Store St, Loc LV) = 0;
virtual Store getInitialStore() = 0;
Modified: cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp?rev=57717&r1=57716&r2=57717&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicObjCFoundationChecks.cpp Fri Oct 17 15:28:54 2008
@@ -367,7 +367,7 @@
private:
- void AddError(TypedRegion* R, Expr* Ex, ExplodedNode<GRState> *N,
+ void AddError(const TypedRegion* R, Expr* Ex, ExplodedNode<GRState> *N,
uint64_t SourceSize, uint64_t TargetSize, uint64_t NumberKind);
};
} // end anonymous namespace
@@ -503,7 +503,7 @@
if (!LV)
return false;
- TypedRegion* R = dyn_cast<TypedRegion>(LV->getRegion());
+ const TypedRegion* R = dyn_cast<TypedRegion>(LV->getRegion());
if (!R)
return false;
@@ -530,7 +530,7 @@
return SourceSize < TargetSize;
}
-void AuditCFNumberCreate::AddError(TypedRegion* R, Expr* Ex,
+void AuditCFNumberCreate::AddError(const TypedRegion* R, Expr* Ex,
ExplodedNode<GRState> *N,
uint64_t SourceSize, uint64_t TargetSize,
uint64_t NumberKind) {
Modified: cfe/trunk/lib/Analysis/BasicStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicStore.cpp?rev=57717&r1=57716&r2=57717&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BasicStore.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicStore.cpp Fri Oct 17 15:28:54 2008
@@ -90,7 +90,41 @@
SVal BasicStoreManager::getLValueField(const GRState* St, const FieldDecl* D,
SVal Base) {
- return UnknownVal();
+
+ if (Base.isUnknownOrUndef())
+ return Base;
+
+ Loc BaseL = cast<Loc>(Base);
+ const MemRegion* BaseR = 0;
+
+ switch(BaseL.getSubKind()) {
+ case loc::SymbolValKind:
+ BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol());
+ break;
+
+ case loc::GotoLabelKind:
+ case loc::FuncValKind:
+ // Technically we can get here if people do funny things with casts.
+ return UndefinedVal();
+
+ case loc::MemRegionKind:
+ BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
+ break;
+
+ case loc::ConcreteIntKind:
+ case loc::StringLiteralValKind:
+ // While these seem funny, this can happen through casts.
+ // FIXME: What we should return is the field offset. For example,
+ // add the field offset to the integer value. That way funny things
+ // like this work properly: &(((struct foo *) 0xa)->f)
+ return Base;
+
+ default:
+ assert ("Unhandled Base.");
+ return Base;
+ }
+
+ return loc::MemRegionVal(MRMgr.getFieldRegion(D, BaseR));
}
SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base,
@@ -108,7 +142,7 @@
switch (LV.getSubKind()) {
case loc::MemRegionKind: {
- VarRegion* R =
+ const VarRegion* R =
dyn_cast<VarRegion>(cast<loc::MemRegionVal>(LV).getRegion());
if (!R)
@@ -145,7 +179,7 @@
Store BasicStoreManager::SetSVal(Store store, Loc LV, SVal V) {
switch (LV.getSubKind()) {
case loc::MemRegionKind: {
- VarRegion* R =
+ const VarRegion* R =
dyn_cast<VarRegion>(cast<loc::MemRegionVal>(LV).getRegion());
if (!R)
@@ -165,8 +199,8 @@
Store BasicStoreManager::Remove(Store store, Loc LV) {
switch (LV.getSubKind()) {
case loc::MemRegionKind: {
- VarRegion* R =
- dyn_cast<VarRegion>(cast<loc::MemRegionVal>(LV).getRegion());
+ const VarRegion* R =
+ dyn_cast<VarRegion>(cast<loc::MemRegionVal>(LV).getRegion());
if (!R)
return store;
Modified: cfe/trunk/lib/Analysis/CFRefCount.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CFRefCount.cpp?rev=57717&r1=57716&r2=57717&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CFRefCount.cpp (original)
+++ cfe/trunk/lib/Analysis/CFRefCount.cpp Fri Oct 17 15:28:54 2008
@@ -1513,7 +1513,7 @@
state = state.remove<RefBindings>(Sym);
}
- TypedRegion* R = dyn_cast<TypedRegion>(MR->getRegion());
+ const TypedRegion* R = dyn_cast<TypedRegion>(MR->getRegion());
if (R) {
// Set the value of the variable to be a conjured symbol.
unsigned Count = Builder.getCurrentBlockCount();
@@ -1717,7 +1717,7 @@
if (!isa<loc::MemRegionVal>(TargetLV))
escapes = true;
else {
- MemRegion* R = cast<loc::MemRegionVal>(TargetLV).getRegion();
+ const MemRegion* R = cast<loc::MemRegionVal>(TargetLV).getRegion();
escapes = !Eng.getStateManager().hasStackStorage(R);
}
Modified: cfe/trunk/lib/Analysis/CheckNSError.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CheckNSError.cpp?rev=57717&r1=57716&r2=57717&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CheckNSError.cpp (original)
+++ cfe/trunk/lib/Analysis/CheckNSError.cpp Fri Oct 17 15:28:54 2008
@@ -216,7 +216,11 @@
GRExprEngine& Eng, GRBugReporter& BR,
bool isNSErrorWarning) {
- SVal ParamSVal = rootState.GetLValue(Param);
+ SVal ParamL = rootState.GetLValue(Param);
+ const MemRegion* ParamR = cast<loc::MemRegionVal>(ParamL).getRegionAs<VarRegion>();
+ assert (ParamR && "Parameters always have VarRegions.");
+ SVal ParamSVal = rootState.GetSVal(ParamR);
+
// FIXME: For now assume that ParamSVal is symbolic. We need to generalize
// this later.
Modified: cfe/trunk/lib/Analysis/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/MemRegion.cpp?rev=57717&r1=57716&r2=57717&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/MemRegion.cpp (original)
+++ cfe/trunk/lib/Analysis/MemRegion.cpp Fri Oct 17 15:28:54 2008
@@ -56,6 +56,15 @@
DeclRegion::ProfileRegion(ID, D, superRegion, getKind());
}
+void SymbolicRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, SymbolID sym) {
+ ID.AddInteger((unsigned) MemRegion::SymbolicRegionKind);
+ ID.AddInteger(sym.getNumber());
+}
+
+void SymbolicRegion::Profile(llvm::FoldingSetNodeID& ID) const {
+ SymbolicRegion::ProfileRegion(ID, sym);
+}
+
//===----------------------------------------------------------------------===//
// Region pretty-printing.
//===----------------------------------------------------------------------===//
@@ -75,6 +84,10 @@
os << cast<VarDecl>(D)->getName();
}
+void SymbolicRegion::print(llvm::raw_ostream& os) const {
+ os << "$" << sym.getNumber();
+}
+
//===----------------------------------------------------------------------===//
// MemRegionManager methods.
//===----------------------------------------------------------------------===//
@@ -106,7 +119,7 @@
}
VarRegion* MemRegionManager::getVarRegion(const VarDecl* d,
- MemRegion* superRegion) {
+ const MemRegion* superRegion) {
llvm::FoldingSetNodeID ID;
DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::VarRegionKind);
@@ -123,8 +136,27 @@
return R;
}
+/// getSymbolicRegion - Retrieve or create a "symbolic" memory region.
+SymbolicRegion* MemRegionManager::getSymbolicRegion(const SymbolID sym) {
+
+ llvm::FoldingSetNodeID ID;
+ SymbolicRegion::ProfileRegion(ID, sym);
+
+ void* InsertPos;
+ MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
+ SymbolicRegion* R = cast_or_null<SymbolicRegion>(data);
+
+ if (!R) {
+ R = (SymbolicRegion*) A.Allocate<SymbolicRegion>();
+ new (R) SymbolicRegion(sym);
+ Regions.InsertNode(R, InsertPos);
+ }
+
+ return R;
+}
+
FieldRegion* MemRegionManager::getFieldRegion(const FieldDecl* d,
- MemRegion* superRegion) {
+ const MemRegion* superRegion) {
llvm::FoldingSetNodeID ID;
DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::FieldRegionKind);
@@ -141,8 +173,9 @@
return R;
}
-ObjCIvarRegion* MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
- MemRegion* superRegion) {
+ObjCIvarRegion*
+MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
+ const MemRegion* superRegion) {
llvm::FoldingSetNodeID ID;
DeclRegion::ProfileRegion(ID, d, superRegion, MemRegion::ObjCIvarRegionKind);
@@ -181,11 +214,20 @@
}
bool MemRegionManager::hasStackStorage(const MemRegion* R) {
+ const SubRegion* SR = dyn_cast<SubRegion>(R);
+
+ // Only subregions can have stack storage.
+ if (!SR)
+ return false;
+
MemSpaceRegion* S = getStackRegion();
- while (R) {
- if (R == S) return true;
- R = R->getSuperRegion();
+ while (SR) {
+ R = SR->getSuperRegion();
+ if (R == S)
+ return true;
+
+ SR = dyn_cast<SubRegion>(R);
}
return false;
Modified: cfe/trunk/lib/Analysis/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RegionStore.cpp?rev=57717&r1=57716&r2=57717&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/RegionStore.cpp (original)
+++ cfe/trunk/lib/Analysis/RegionStore.cpp Fri Oct 17 15:28:54 2008
@@ -52,7 +52,7 @@
Store RegionStoreManager::SetSVal(Store store, Loc LV, SVal V) {
assert(LV.getSubKind() == loc::MemRegionKind);
- MemRegion* R = cast<loc::MemRegionVal>(LV).getRegion();
+ const MemRegion* R = cast<loc::MemRegionVal>(LV).getRegion();
if (!R)
return store;
More information about the cfe-commits
mailing list