llvm-project/clang/lib/Analysis/RegionStore.cpp

1022 lines
34 KiB
C++
Raw Normal View History

//== RegionStore.cpp - Field-sensitive store model --------------*- C++ -*--==//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file defines a basic region store model. In this model, we do have field
// sensitivity. But we assume nothing about the heap shape. So recursive data
// structures are largely ignored. Basically we do 1-limiting analysis.
// Parameter pointers are assumed with no aliasing. Pointee objects of
// parameters are created lazily.
//
//===----------------------------------------------------------------------===//
#include "clang/Analysis/PathSensitive/MemRegion.h"
#include "clang/Analysis/PathSensitive/GRState.h"
#include "clang/Analysis/PathSensitive/GRStateTrait.h"
#include "clang/Analysis/Analyses/LiveVariables.h"
#include "llvm/ADT/ImmutableMap.h"
#include "llvm/ADT/ImmutableList.h"
#include "llvm/Support/raw_ostream.h"
#include "llvm/Support/Compiler.h"
using namespace clang;
// Actual Store type.
typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
// RegionView GDM stuff.
typedef llvm::ImmutableList<const MemRegion*> RegionViewTy;
typedef llvm::ImmutableMap<const MemRegion*, RegionViewTy> RegionViewMapTy;
static int RegionViewMapTyIndex = 0;
namespace clang {
template<> struct GRStateTrait<RegionViewMapTy>
: public GRStatePartialTrait<RegionViewMapTy> {
static void* GDMIndex() { return &RegionViewMapTyIndex; }
};
}
// RegionExtents GDM stuff.
// Currently RegionExtents are in bytes. We can change this representation when
// there are real requirements.
typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionExtentsTy;
static int RegionExtentsTyIndex = 0;
namespace clang {
template<> struct GRStateTrait<RegionExtentsTy>
: public GRStatePartialTrait<RegionExtentsTy> {
static void* GDMIndex() { return &RegionExtentsTyIndex; }
};
}
// KillSet GDM stuff.
typedef llvm::ImmutableSet<const MemRegion*> RegionKills;
static int RegionKillsIndex = 0;
namespace clang {
template<> struct GRStateTrait<RegionKills>
: public GRStatePartialTrait<RegionKills> {
static void* GDMIndex() { return &RegionKillsIndex; }
};
}
namespace {
class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
RegionBindingsTy::Factory RBFactory;
RegionViewTy::Factory RVFactory;
GRStateManager& StateMgr;
MemRegionManager MRMgr;
public:
RegionStoreManager(GRStateManager& mgr)
: RBFactory(mgr.getAllocator()),
RVFactory(mgr.getAllocator()),
StateMgr(mgr),
MRMgr(StateMgr.getAllocator()) {}
virtual ~RegionStoreManager() {}
MemRegionManager& getRegionManager() { return MRMgr; }
Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* CL, SVal V);
SVal getLValueString(const GRState* St, const StringLiteral* S);
SVal getLValueCompoundLiteral(const GRState* St, const CompoundLiteralExpr*);
SVal getLValueVar(const GRState* St, const VarDecl* VD);
SVal getLValueIvar(const GRState* St, const ObjCIvarDecl* D, SVal Base);
SVal getLValueField(const GRState* St, SVal Base, const FieldDecl* D);
SVal getLValueElement(const GRState* St, SVal Base, SVal Offset);
SVal getSizeInElements(const GRState* St, const MemRegion* R);
SVal ArrayToPointer(SVal Array);
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
/// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
/// a MemRegion* to a specific location type. 'R' is the region being
/// casted and 'CastToTy' the result type of the cast.
CastResult CastRegion(const GRState* state, const MemRegion* R,
QualType CastToTy);
SVal Retrieve(const GRState* state, Loc L, QualType T = QualType());
Store Bind(Store St, Loc LV, SVal V);
Store Remove(Store store, Loc LV);
Store getInitialStore();
/// getSelfRegion - Returns the region for the 'self' (Objective-C) or
/// 'this' object (C++). When used when analyzing a normal function this
/// method returns NULL.
const MemRegion* getSelfRegion(Store) {
assert (false && "Not implemented.");
return 0;
}
/// RemoveDeadBindings - Scans the RegionStore of 'state' for dead values.
/// It returns a new Store with these values removed, and populates LSymbols
// and DSymbols with the known set of live and dead symbols respectively.
Store RemoveDeadBindings(const GRState* state, Stmt* Loc,
const LiveVariables& Live,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols);
void UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols);
Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, unsigned Count);
const GRState* setExtent(const GRState* St, const MemRegion* R, SVal Extent);
static inline RegionBindingsTy GetRegionBindings(Store store) {
return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store));
}
2008-10-24 04:33:15 +00:00
void print(Store store, std::ostream& Out, const char* nl, const char *sep);
void iterBindings(Store store, BindingsHandler& f) {
// FIXME: Implement.
}
private:
Loc getVarLoc(const VarDecl* VD) {
return loc::MemRegionVal(MRMgr.getVarRegion(VD));
}
Store InitializeArray(Store store, const TypedRegion* R, SVal Init);
Store BindArrayToVal(Store store, const TypedRegion* BaseR, SVal V);
Store BindArrayToSymVal(Store store, const TypedRegion* BaseR);
Store InitializeStruct(Store store, const TypedRegion* R, SVal Init);
Store BindStructToVal(Store store, const TypedRegion* BaseR, SVal V);
Store BindStructToSymVal(Store store, const TypedRegion* BaseR);
2008-12-04 01:12:41 +00:00
/// Retrieve the values in a struct and return a CompoundVal, used when doing
/// struct copy:
/// struct s x, y;
/// x = y;
/// y's value is retrieved by this method.
SVal RetrieveStruct(Store store, const TypedRegion* R);
2008-12-04 01:12:41 +00:00
Store BindStruct(Store store, const TypedRegion* R, SVal V);
// Utility methods.
BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
ASTContext& getContext() { return StateMgr.getContext(); }
SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); }
const GRState* AddRegionView(const GRState* St,
const MemRegion* View, const MemRegion* Base);
};
} // end anonymous namespace
StoreManager* clang::CreateRegionStoreManager(GRStateManager& StMgr) {
return new RegionStoreManager(StMgr);
}
SVal RegionStoreManager::getLValueString(const GRState* St,
const StringLiteral* S) {
return loc::MemRegionVal(MRMgr.getStringRegion(S));
}
SVal RegionStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
return loc::MemRegionVal(MRMgr.getVarRegion(VD));
}
SVal RegionStoreManager::getLValueCompoundLiteral(const GRState* St,
const CompoundLiteralExpr* CL) {
return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL));
}
SVal RegionStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
SVal Base) {
return UnknownVal();
}
SVal RegionStoreManager::getLValueField(const GRState* St, SVal Base,
const FieldDecl* D) {
if (Base.isUnknownOrUndef())
return Base;
Loc BaseL = cast<Loc>(Base);
const MemRegion* BaseR = 0;
switch (BaseL.getSubKind()) {
case loc::MemRegionKind:
BaseR = cast<loc::MemRegionVal>(BaseL).getRegion();
break;
case loc::SymbolValKind:
BaseR = MRMgr.getSymbolicRegion(cast<loc::SymbolVal>(&BaseL)->getSymbol());
break;
case loc::GotoLabelKind:
case loc::FuncValKind:
// These are anormal cases. Flag an undefined value.
return UndefinedVal();
case loc::ConcreteIntKind:
// 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(0 && "Unhandled Base.");
return Base;
}
return loc::MemRegionVal(MRMgr.getFieldRegion(D, BaseR));
}
SVal RegionStoreManager::getLValueElement(const GRState* St,
SVal Base, SVal Offset) {
if (Base.isUnknownOrUndef())
return Base;
if (isa<loc::SymbolVal>(Base))
return Base;
loc::MemRegionVal& BaseL = cast<loc::MemRegionVal>(Base);
// Pointer of any type can be cast and used as array base. We do not support
// that case yet.
if (!isa<ElementRegion>(BaseL.getRegion())) {
// Record what we have seen in real code.
assert(isa<FieldRegion>(BaseL.getRegion()));
return UnknownVal();
}
// We expect BaseR is an ElementRegion, not a base VarRegion.
const ElementRegion* ElemR = cast<ElementRegion>(BaseL.getRegion());
SVal Idx = ElemR->getIndex();
nonloc::ConcreteInt *CI1, *CI2;
// Only handle integer indices for now.
if ((CI1 = dyn_cast<nonloc::ConcreteInt>(&Idx)) &&
(CI2 = dyn_cast<nonloc::ConcreteInt>(&Offset))) {
// Temporary SVal to hold a potential signed and extended APSInt.
SVal SignedInt;
// Index might be unsigned. We have to convert it to signed. It might also
// be less wide than the size. We have to extend it.
if (CI2->getValue().isUnsigned() ||
CI2->getValue().getBitWidth() < CI1->getValue().getBitWidth()) {
llvm::APSInt SI = CI2->getValue();
if (CI2->getValue().getBitWidth() < CI1->getValue().getBitWidth())
SI.extend(CI1->getValue().getBitWidth());
SI.setIsSigned(true);
SignedInt = nonloc::ConcreteInt(getBasicVals().getValue(SI));
CI2 = cast<nonloc::ConcreteInt>(&SignedInt);
}
SVal NewIdx = CI1->EvalBinOp(getBasicVals(), BinaryOperator::Add, *CI2);
return loc::MemRegionVal(MRMgr.getElementRegion(NewIdx,
ElemR->getArrayRegion()));
}
return UnknownVal();
}
SVal RegionStoreManager::getSizeInElements(const GRState* St,
const MemRegion* R) {
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
// Get the type of the variable.
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
QualType T = VR->getRValueType(getContext());
// It must be of array type.
const ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
// return the size as signed integer.
return NonLoc::MakeVal(getBasicVals(), CAT->getSize(), false);
}
if (const StringRegion* SR = dyn_cast<StringRegion>(R)) {
const StringLiteral* Str = SR->getStringLiteral();
// We intentionally made the size value signed because it participates in
// operations with signed indices.
return NonLoc::MakeVal(getBasicVals(), Str->getByteLength() + 1, false);
}
if (const AnonTypedRegion* ATR = dyn_cast<AnonTypedRegion>(R)) {
GRStateRef state(St, StateMgr);
// Get the size of the super region in bytes.
RegionExtentsTy::data_type* T
= state.get<RegionExtentsTy>(ATR->getSuperRegion());
assert(T && "region extent not exist");
// Assume it's ConcreteInt for now.
llvm::APSInt SSize = cast<nonloc::ConcreteInt>(*T).getValue();
// Get the size of the element in bits.
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
QualType LvT = ATR->getLValueType(getContext());
QualType ElemTy = cast<PointerType>(LvT.getTypePtr())->getPointeeType();
uint64_t X = getContext().getTypeSize(ElemTy);
const llvm::APSInt& ESize = getBasicVals().getValue(X, SSize.getBitWidth(),
false);
// Calculate the number of elements.
// FIXME: What do we do with signed-ness problem? Shall we make all APSInts
// signed?
if (SSize.isUnsigned())
SSize.setIsSigned(true);
// FIXME: move this operation into BasicVals.
const llvm::APSInt S =
(SSize * getBasicVals().getValue(8, SSize.getBitWidth(), false)) / ESize;
return NonLoc::MakeVal(getBasicVals(), S);
}
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R)) {
// FIXME: Unsupported yet.
FR = 0;
return UnknownVal();
}
2008-11-22 13:23:00 +00:00
assert(0 && "Other regions are not supported yet.");
}
// Cast 'pointer to array' to 'pointer to the first element of array'.
SVal RegionStoreManager::ArrayToPointer(SVal Array) {
if (Array.isUnknownOrUndef())
return Array;
if (!isa<loc::MemRegionVal>(Array))
return UnknownVal();
const MemRegion* R = cast<loc::MemRegionVal>(&Array)->getRegion();
const TypedRegion* ArrayR = dyn_cast<TypedRegion>(R);
if (ArrayR)
return UnknownVal();
nonloc::ConcreteInt Idx(getBasicVals().getZeroWithPtrWidth(false));
ElementRegion* ER = MRMgr.getElementRegion(Idx, ArrayR);
return loc::MemRegionVal(ER);
}
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
StoreManager::CastResult
RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
QualType CastToTy) {
// Return the same region if the region types are compatible.
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
ASTContext& Ctx = StateMgr.getContext();
QualType Ta = Ctx.getCanonicalType(TR->getLValueType(Ctx));
QualType Tb = Ctx.getCanonicalType(CastToTy);
if (Ta == Tb)
return CastResult(state, R);
}
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
const MemRegion* ViewR = MRMgr.getAnonTypedRegion(CastToTy, R);
return CastResult(AddRegionView(state, ViewR, R), ViewR);
}
SVal RegionStoreManager::Retrieve(const GRState* state, Loc L, QualType T) {
assert(!isa<UnknownVal>(L) && "location unknown");
assert(!isa<UndefinedVal>(L) && "location undefined");
Store S = state->getStore();
switch (L.getSubKind()) {
case loc::MemRegionKind: {
const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
assert(R && "bad region");
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
if (TR->getRValueType(getContext())->isStructureType())
return RetrieveStruct(S, TR);
RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(S));
RegionBindingsTy::data_type* V = B.lookup(R);
return V ? *V : UnknownVal();
}
case loc::SymbolValKind:
return UnknownVal();
case loc::ConcreteIntKind:
return UndefinedVal(); // As in BasicStoreManager.
case loc::FuncValKind:
return L;
default:
assert(false && "Invalid Location");
return L;
}
}
SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
// FIXME: Verify we want getRValueType instead of getLValueType.
QualType T = R->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
RecordDecl* RD = RT->getDecl();
assert(RD->isDefinition());
llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList();
std::vector<FieldDecl *> Fields(RD->field_begin(), RD->field_end());
for (std::vector<FieldDecl *>::reverse_iterator Field = Fields.rbegin(),
FieldEnd = Fields.rend();
Field != FieldEnd; ++Field) {
FieldRegion* FR = MRMgr.getFieldRegion(*Field, R);
RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(store));
RegionBindingsTy::data_type* data = B.lookup(FR);
SVal FieldValue = data ? *data : UnknownVal();
StructVal = getBasicVals().consVals(FieldValue, StructVal);
}
return NonLoc::MakeCompoundVal(T, StructVal, getBasicVals());
}
Store RegionStoreManager::Bind(Store store, Loc LV, SVal V) {
if (LV.getSubKind() == loc::SymbolValKind)
return store;
assert(LV.getSubKind() == loc::MemRegionKind);
const MemRegion* R = cast<loc::MemRegionVal>(LV).getRegion();
assert(R);
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
// FIXME: Verify we want getRValueType().
if (TR->getRValueType(getContext())->isStructureType())
return BindStruct(store, TR, V);
RegionBindingsTy B = GetRegionBindings(store);
return V.isUnknown()
? RBFactory.Remove(B, R).getRoot()
: RBFactory.Add(B, R, V).getRoot();
}
Store RegionStoreManager::Remove(Store store, Loc L) {
RegionBindingsTy B = GetRegionBindings(store);
const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
assert(R);
return RBFactory.Remove(B, R).getRoot();
}
Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R, SVal V){
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
// Verify we want getRValueType.
QualType T = R->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
RecordDecl* RD = RT->getDecl();
if (!RD->isDefinition()) {
// This can only occur when a pointer of incomplete struct type is used as a
// function argument.
assert(V.isUnknown());
return store;
}
RegionBindingsTy B = GetRegionBindings(store);
if (isa<UnknownVal>(V))
return BindStructToVal(store, R, UnknownVal());
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(V);
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
RecordDecl::field_iterator FI = RD->field_begin(), FE = RD->field_end();
for (; FI != FE; ++FI, ++VI) {
assert(VI != VE);
FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
B = RBFactory.Add(B, FR, *VI);
}
return B.getRoot();
}
Store RegionStoreManager::getInitialStore() {
typedef LiveVariables::AnalysisDataTy LVDataTy;
LVDataTy& D = StateMgr.getLiveVariables().getAnalysisData();
Store St = RBFactory.GetEmptyMap().getRoot();
for (LVDataTy::decl_iterator I=D.begin_decl(), E=D.end_decl(); I != E; ++I) {
NamedDecl* ND = const_cast<NamedDecl*>(I->first);
if (VarDecl* VD = dyn_cast<VarDecl>(ND)) {
// Punt on static variables for now.
if (VD->getStorageClass() == VarDecl::Static)
continue;
VarRegion* VR = MRMgr.getVarRegion(VD);
QualType T = VD->getType();
// Only handle pointers and integers for now.
if (Loc::IsLocType(T) || T->isIntegerType()) {
// Initialize globals and parameters to symbolic values.
// Initialize local variables to undefined.
SVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
isa<ImplicitParamDecl>(VD))
? SVal::GetSymbolValue(getSymbolManager(), VD)
: UndefinedVal();
St = Bind(St, getVarLoc(VD), X);
}
else if (T->isArrayType()) {
if (VD->hasGlobalStorage()) // Params cannot have array type.
St = BindArrayToSymVal(St, VR);
else
St = BindArrayToVal(St, VR, UndefinedVal());
}
else if (T->isStructureType()) {
if (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
isa<ImplicitParamDecl>(VD))
St = BindStructToSymVal(St, VR);
else
St = BindStructToVal(St, VR, UndefinedVal());
}
}
}
return St;
}
Store RegionStoreManager::BindDecl(Store store, const VarDecl* VD,
SVal* InitVal, unsigned Count) {
if (VD->hasGlobalStorage()) {
// Static global variables should not be visited here.
assert(!(VD->getStorageClass() == VarDecl::Static &&
VD->isFileVarDecl()));
// Process static variables.
if (VD->getStorageClass() == VarDecl::Static) {
if (!InitVal) {
// Only handle pointer and integer static variables.
QualType T = VD->getType();
if (Loc::IsLocType(T))
store = Bind(store, getVarLoc(VD),
loc::ConcreteInt(getBasicVals().getValue(0, T)));
else if (T->isIntegerType())
store = Bind(store, getVarLoc(VD),
loc::ConcreteInt(getBasicVals().getValue(0, T)));
// Other types of static local variables are not handled yet.
} else {
store = Bind(store, getVarLoc(VD), *InitVal);
}
}
} else {
// Process local variables.
QualType T = VD->getType();
VarRegion* VR = MRMgr.getVarRegion(VD);
if (Loc::IsLocType(T) || T->isIntegerType()) {
SVal V = InitVal ? *InitVal : UndefinedVal();
store = Bind(store, loc::MemRegionVal(VR), V);
}
else if (T->isArrayType()) {
if (!InitVal)
store = BindArrayToVal(store, VR, UndefinedVal());
else
store = InitializeArray(store, VR, *InitVal);
}
else if (T->isStructureType()) {
if (!InitVal)
store = BindStructToVal(store, VR, UndefinedVal());
else
store = InitializeStruct(store, VR, *InitVal);
}
// Other types of local variables are not handled yet.
}
return store;
}
Store RegionStoreManager::BindCompoundLiteral(Store store,
const CompoundLiteralExpr* CL,
SVal V) {
CompoundLiteralRegion* R = MRMgr.getCompoundLiteralRegion(CL);
store = Bind(store, loc::MemRegionVal(R), V);
return store;
}
const GRState* RegionStoreManager::setExtent(const GRState* St,
const MemRegion* R, SVal Extent) {
GRStateRef state(St, StateMgr);
return state.set<RegionExtentsTy>(R, Extent);
}
void RegionStoreManager::UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols) {
for (SVal::symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end();SI!=SE;++SI)
LSymbols.insert(*SI);
}
Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
const LiveVariables& Live,
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) {
Store store = state->getStore();
RegionBindingsTy B = GetRegionBindings(store);
// Lazily constructed backmap from MemRegions to SubRegions.
typedef llvm::ImmutableSet<const MemRegion*> SubRegionsTy;
typedef llvm::ImmutableMap<const MemRegion*, SubRegionsTy> SubRegionsMapTy;
// FIXME: As a future optimization we can modifiy BumpPtrAllocator to have
// the ability to reuse memory. This way we can keep TmpAlloc around as
// an instance variable of RegionStoreManager (avoiding repeated malloc
// overhead).
llvm::BumpPtrAllocator TmpAlloc;
// Factory objects.
SubRegionsMapTy::Factory SubRegMapF(TmpAlloc);
SubRegionsTy::Factory SubRegF(TmpAlloc);
// The backmap from regions to subregions.
SubRegionsMapTy SubRegMap = SubRegMapF.GetEmptyMap();
// Do a pass over the regions in the store. For VarRegions we check if
// the variable is still live and if so add it to the list of live roots.
// For other regions we populate our region backmap.
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
const MemRegion* R = I.getKey();
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
if (Live.isLive(Loc, VR->getDecl()))
RegionRoots.push_back(VR); // This is a live "root".
}
else {
// Get the super region for R.
const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion();
// Get the current set of subregions for SuperR.
const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR);
SubRegionsTy SR = SRptr ? *SRptr : SubRegF.GetEmptySet();
// Add R to the subregions of SuperR.
SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SR, R));
// Finally, check if SuperR is a VarRegion. We need to do this
// to also mark SuperR as a root (as it may not have a value directly
// bound to it in the store).
if (const VarRegion* VR = dyn_cast<VarRegion>(SuperR)) {
if (Live.isLive(Loc, VR->getDecl()))
RegionRoots.push_back(VR); // This is a live "root".
}
}
}
// Process the worklist of RegionRoots. This performs a "mark-and-sweep"
// of the store. We want to find all live symbols and dead regions.
llvm::SmallPtrSet<const MemRegion*, 10> Marked;
while (!RegionRoots.empty()) {
// Dequeue the next region on the worklist.
const MemRegion* R = RegionRoots.back();
RegionRoots.pop_back();
// Check if we have already processed this region.
if (Marked.count(R)) continue;
// Mark this region as processed. This is needed for termination in case
// a region is referenced more than once.
Marked.insert(R);
// Mark the symbol for any live SymbolicRegion as "live". This means we
// should continue to track that symbol.
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R))
LSymbols.insert(SymR->getSymbol());
// Get the data binding for R (if any).
RegionBindingsTy::data_type* Xptr = B.lookup(R);
if (Xptr) {
SVal X = *Xptr;
UpdateLiveSymbols(X, LSymbols); // Update the set of live symbols.
// If X is a region, then add it the RegionRoots.
if (loc::MemRegionVal* RegionX = dyn_cast<loc::MemRegionVal>(&X))
RegionRoots.push_back(RegionX->getRegion());
}
// Get the subregions of R. These are RegionRoots as well since they
// represent values that are also bound to R.
const SubRegionsTy* SRptr = SubRegMap.lookup(R);
if (!SRptr) continue;
SubRegionsTy SR = *SRptr;
for (SubRegionsTy::iterator I=SR.begin(), E=SR.end(); I!=E; ++I)
RegionRoots.push_back(*I);
}
// We have now scanned the store, marking reachable regions and symbols
// as live. We now remove all the regions that are dead from the store
// as well as update DSymbols with the set symbols that are now dead.
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
const MemRegion* R = I.getKey();
// If this region live? Is so, none of its symbols are dead.
if (Marked.count(R))
continue;
// Remove this dead region from the store.
store = Remove(store, Loc::MakeVal(R));
// Mark all non-live symbols that this region references as dead.
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) {
SymbolRef Sym = SymR->getSymbol();
if (!LSymbols.count(Sym)) DSymbols.insert(Sym);
}
SVal X = I.getData();
SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end();
for (; SI != SE; ++SI) { if (!LSymbols.count(*SI)) DSymbols.insert(*SI); }
}
return store;
}
void RegionStoreManager::print(Store store, std::ostream& Out,
const char* nl, const char *sep) {
llvm::raw_os_ostream OS(Out);
RegionBindingsTy B = GetRegionBindings(store);
OS << "Store:" << nl;
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
OS << ' '; I.getKey()->print(OS); OS << " : ";
I.getData().print(OS); OS << nl;
}
2008-10-24 04:33:15 +00:00
}
Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R,
SVal Init) {
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
// FIXME: Verify we should use getLValueType or getRValueType.
QualType T = R->getRValueType(getContext());
assert(T->isArrayType());
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
llvm::APSInt Size(CAT->getSize(), false);
llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(),
Size.isUnsigned());
// Check if the init expr is a StringLiteral.
if (isa<loc::MemRegionVal>(Init)) {
const MemRegion* InitR = cast<loc::MemRegionVal>(Init).getRegion();
const StringLiteral* S = cast<StringRegion>(InitR)->getStringLiteral();
const char* str = S->getStrData();
unsigned len = S->getByteLength();
unsigned j = 0;
for (; i < Size; ++i, ++j) {
SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
ElementRegion* ER = MRMgr.getElementRegion(Idx, R);
// Copy bytes from the string literal into the target array. Trailing
// bytes in the array that are not covered by the string literal are
// initialized to zero.
SVal V = (j < len)
? NonLoc::MakeVal(getBasicVals(), str[j], sizeof(char)*8, true)
: NonLoc::MakeVal(getBasicVals(), 0, sizeof(char)*8, true);
store = Bind(store, loc::MemRegionVal(ER), V);
}
return store;
}
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
for (; i < Size; ++i) {
SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
ElementRegion* ER = MRMgr.getElementRegion(Idx, R);
store = Bind(store, loc::MemRegionVal(ER), (VI!=VE) ? *VI : UndefinedVal());
// The init list might be shorter than the array decl.
if (VI != VE) ++VI;
}
return store;
}
// Bind all elements of the array to some value.
Store RegionStoreManager::BindArrayToVal(Store store, const TypedRegion* BaseR,
SVal V){
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
// FIXME: Verify we want getRValueType.
QualType T = BaseR->getRValueType(getContext());
assert(T->isArrayType());
// Only handle constant size array for now.
if (ConstantArrayType* CAT=dyn_cast<ConstantArrayType>(T.getTypePtr())) {
llvm::APInt Size = CAT->getSize();
llvm::APInt i = llvm::APInt::getNullValue(Size.getBitWidth());
for (; i != Size; ++i) {
nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(i, false)));
ElementRegion* ER = MRMgr.getElementRegion(Idx, BaseR);
if (CAT->getElementType()->isStructureType())
store = BindStructToVal(store, ER, V);
else
store = Bind(store, loc::MemRegionVal(ER), V);
}
}
return store;
}
Store RegionStoreManager::BindArrayToSymVal(Store store,
const TypedRegion* BaseR) {
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
// FIXME: Verify we want getRValueType.
QualType T = BaseR->getRValueType(getContext());
assert(T->isArrayType());
if (ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(T.getTypePtr())) {
llvm::APInt Size = CAT->getSize();
llvm::APInt i = llvm::APInt::getNullValue(Size.getBitWidth());
for (; i != Size; ++i) {
nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(i, false)));
ElementRegion* ER = MRMgr.getElementRegion(Idx, BaseR);
if (CAT->getElementType()->isStructureType()) {
store = BindStructToSymVal(store, ER);
}
else {
SVal V = SVal::getSymbolValue(getSymbolManager(), BaseR,
&Idx.getValue(), CAT->getElementType());
store = Bind(store, loc::MemRegionVal(ER), V);
}
}
}
return store;
}
Store RegionStoreManager::InitializeStruct(Store store, const TypedRegion* R,
SVal Init) {
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
// FIXME: Verify that we should use getRValueType or getLValueType.
QualType T = R->getRValueType(getContext());
assert(T->isStructureType());
RecordType* RT = cast<RecordType>(T.getTypePtr());
RecordDecl* RD = RT->getDecl();
assert(RD->isDefinition());
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
RecordDecl::field_iterator FI = RD->field_begin(), FE = RD->field_end();
for (; FI != FE; ++FI) {
QualType FTy = (*FI)->getType();
FieldRegion* FR = MRMgr.getFieldRegion(*FI, R);
if (Loc::IsLocType(FTy) || FTy->isIntegerType()) {
if (VI != VE) {
store = Bind(store, loc::MemRegionVal(FR), *VI);
++VI;
} else
store = Bind(store, loc::MemRegionVal(FR), UndefinedVal());
}
else if (FTy->isArrayType()) {
if (VI != VE) {
store = InitializeArray(store, FR, *VI);
++VI;
} else
store = BindArrayToVal(store, FR, UndefinedVal());
}
else if (FTy->isStructureType()) {
if (VI != VE) {
store = InitializeStruct(store, FR, *VI);
++VI;
} else
store = BindStructToVal(store, FR, UndefinedVal());
}
}
return store;
}
// Bind all fields of the struct to some value.
Store RegionStoreManager::BindStructToVal(Store store, const TypedRegion* BaseR,
SVal V) {
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
// FIXME: Verify that we should use getLValueType or getRValueType.
QualType T = BaseR->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
RecordDecl* RD = RT->getDecl();
assert(RD->isDefinition());
RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
for (; I != E; ++I) {
QualType FTy = (*I)->getType();
FieldRegion* FR = MRMgr.getFieldRegion(*I, BaseR);
if (Loc::IsLocType(FTy) || FTy->isIntegerType()) {
store = Bind(store, loc::MemRegionVal(FR), V);
} else if (FTy->isArrayType()) {
store = BindArrayToVal(store, FR, V);
} else if (FTy->isStructureType()) {
store = BindStructToVal(store, FR, V);
}
}
return store;
}
Store RegionStoreManager::BindStructToSymVal(Store store,
const TypedRegion* BaseR) {
MemRegion: - Overhauled the notion of "types" for TypedRegions. We now distinguish between the "lvalue" of a region (via getLValueRegion()) and the "rvalue" of a region (va getRValueRegion()). Since a region represents a chunk of memory it has both, but we were conflating these concepts in some cases, leading to some insidious bugs. - Removed AnonPointeeType, partially because it is unused and because it doesn't have a clear notion of lvalue vs rvalue type. We can add it back once there is a need for it and we can resolve its role with these concepts. StoreManager: - Overhauled StoreManager::CastRegion. It expects an *lvalue* type for a region. This is actually what motivated the overhaul to the MemRegion type mechanism. It also no longer returns an SVal; we can just return a MemRegion*. - BasicStoreManager::CastRegion now overlays an "AnonTypedRegion" for pointer-pointer casts. This matches with the MemRegion changes. - Similar changes to RegionStore, except I've added a bunch of FIXMEs where it wasn't 100% clear where we should use TypedRegion::getRValueRegion() or TypedRegion::getLValueRegion(). AuditCFNumberCreate check: - Now blasts through AnonTypedRegions that may layer the original memory region, thus checking if the actually memory block is of the appropriate type. This change was needed to work with the changes to StoreManager::CastRegion. GRExprEngine::VisitCast: - Conform to the new interface of StoreManager::CastRegion. Tests: - None of the analysis tests fail now for using the "basic store". - Disabled the tests 'array-struct.c' and 'rdar-6442306-1.m' pending further testing and bug fixing. llvm-svn: 60995
2008-12-13 21:49:13 +00:00
// FIXME: Verify that we should use getLValueType or getRValueType
QualType T = BaseR->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
RecordDecl* RD = RT->getDecl();
assert(RD->isDefinition());
RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
for (; I != E; ++I) {
QualType FTy = (*I)->getType();
FieldRegion* FR = MRMgr.getFieldRegion(*I, BaseR);
if (Loc::IsLocType(FTy) || FTy->isIntegerType()) {
store = Bind(store, loc::MemRegionVal(FR),
SVal::getSymbolValue(getSymbolManager(), BaseR, *I, FTy));
}
else if (FTy->isArrayType()) {
store = BindArrayToSymVal(store, FR);
}
else if (FTy->isStructureType()) {
store = BindStructToSymVal(store, FR);
}
}
return store;
}
const GRState* RegionStoreManager::AddRegionView(const GRState* St,
const MemRegion* View,
const MemRegion* Base) {
GRStateRef state(St, StateMgr);
// First, retrieve the region view of the base region.
RegionViewMapTy::data_type* d = state.get<RegionViewMapTy>(Base);
RegionViewTy L = d ? *d : RVFactory.GetEmptyList();
// Now add View to the region view.
L = RVFactory.Add(View, L);
// Create a new state with the new region view.
return state.set<RegionViewMapTy>(Base, L);
}