2008-10-08 10:50:44 +08:00
|
|
|
//== 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"
|
2008-11-16 12:07:26 +08:00
|
|
|
#include "clang/Analysis/PathSensitive/GRStateTrait.h"
|
2008-10-08 10:50:44 +08:00
|
|
|
#include "clang/Analysis/Analyses/LiveVariables.h"
|
|
|
|
|
|
|
|
#include "llvm/ADT/ImmutableMap.h"
|
2008-11-16 12:07:26 +08:00
|
|
|
#include "llvm/ADT/ImmutableList.h"
|
2008-10-24 14:01:33 +08:00
|
|
|
#include "llvm/Support/raw_ostream.h"
|
2008-10-08 10:50:44 +08:00
|
|
|
#include "llvm/Support/Compiler.h"
|
|
|
|
|
|
|
|
using namespace clang;
|
|
|
|
|
2008-11-24 17:44:56 +08:00
|
|
|
// Actual Store type.
|
2008-10-17 13:57:07 +08:00
|
|
|
typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
|
2008-11-24 17:44:56 +08:00
|
|
|
|
|
|
|
// RegionView GDM stuff.
|
2008-11-16 12:07:26 +08:00
|
|
|
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; }
|
|
|
|
};
|
|
|
|
}
|
2008-10-08 10:50:44 +08:00
|
|
|
|
2008-11-24 17:44:56 +08:00
|
|
|
// 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; }
|
|
|
|
};
|
|
|
|
}
|
|
|
|
|
2008-12-04 10:08:27 +08:00
|
|
|
// KillSet GDM stuff.
|
2008-12-05 08:47:52 +08:00
|
|
|
typedef llvm::ImmutableSet<const MemRegion*> RegionKills;
|
|
|
|
static int RegionKillsIndex = 0;
|
2008-12-04 10:08:27 +08:00
|
|
|
namespace clang {
|
2008-12-05 08:47:52 +08:00
|
|
|
template<> struct GRStateTrait<RegionKills>
|
|
|
|
: public GRStatePartialTrait<RegionKills> {
|
|
|
|
static void* GDMIndex() { return &RegionKillsIndex; }
|
2008-12-04 10:08:27 +08:00
|
|
|
};
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-10-08 10:50:44 +08:00
|
|
|
namespace {
|
|
|
|
|
|
|
|
class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
|
|
|
|
RegionBindingsTy::Factory RBFactory;
|
2008-11-16 12:07:26 +08:00
|
|
|
RegionViewTy::Factory RVFactory;
|
|
|
|
|
2008-10-08 10:50:44 +08:00
|
|
|
GRStateManager& StateMgr;
|
|
|
|
MemRegionManager MRMgr;
|
|
|
|
|
|
|
|
public:
|
|
|
|
RegionStoreManager(GRStateManager& mgr)
|
2008-11-16 12:07:26 +08:00
|
|
|
: RBFactory(mgr.getAllocator()),
|
|
|
|
RVFactory(mgr.getAllocator()),
|
|
|
|
StateMgr(mgr),
|
|
|
|
MRMgr(StateMgr.getAllocator()) {}
|
2008-10-08 10:50:44 +08:00
|
|
|
|
|
|
|
virtual ~RegionStoreManager() {}
|
|
|
|
|
2008-10-24 09:38:55 +08:00
|
|
|
MemRegionManager& getRegionManager() { return MRMgr; }
|
2008-10-28 05:54:31 +08:00
|
|
|
|
2008-11-07 18:38:33 +08:00
|
|
|
Store BindCompoundLiteral(Store store, const CompoundLiteralExpr* CL, SVal V);
|
2008-10-24 09:38:55 +08:00
|
|
|
|
2008-10-25 22:18:57 +08:00
|
|
|
SVal getLValueString(const GRState* St, const StringLiteral* S);
|
|
|
|
|
2008-11-07 18:38:33 +08:00
|
|
|
SVal getLValueCompoundLiteral(const GRState* St, const CompoundLiteralExpr*);
|
|
|
|
|
2008-10-22 21:44:38 +08:00
|
|
|
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);
|
|
|
|
|
2008-10-24 09:09:32 +08:00
|
|
|
SVal getLValueElement(const GRState* St, SVal Base, SVal Offset);
|
|
|
|
|
2008-11-22 21:21:46 +08:00
|
|
|
SVal getSizeInElements(const GRState* St, const MemRegion* R);
|
|
|
|
|
2008-10-24 09:09:32 +08:00
|
|
|
SVal ArrayToPointer(SVal Array);
|
|
|
|
|
2008-11-16 15:06:26 +08:00
|
|
|
std::pair<const GRState*, SVal>
|
|
|
|
CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy, Stmt* CastE);
|
2008-11-16 12:07:26 +08:00
|
|
|
|
2008-12-05 08:47:52 +08:00
|
|
|
SVal Retrieve(const GRState* state, Loc L, QualType T = QualType());
|
2008-10-22 21:44:38 +08:00
|
|
|
|
2008-10-21 14:27:32 +08:00
|
|
|
Store Bind(Store St, Loc LV, SVal V);
|
2008-10-08 10:50:44 +08:00
|
|
|
|
2008-10-24 09:38:55 +08:00
|
|
|
Store Remove(Store store, Loc LV) {
|
|
|
|
// FIXME: Implement.
|
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
2008-10-08 10:50:44 +08:00
|
|
|
Store getInitialStore();
|
2008-10-25 04:32:16 +08:00
|
|
|
|
|
|
|
/// 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;
|
|
|
|
}
|
2008-12-04 10:08:27 +08:00
|
|
|
|
2008-12-05 08:47:52 +08:00
|
|
|
/// 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,
|
2008-10-24 09:38:55 +08:00
|
|
|
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
|
2008-11-10 17:39:04 +08:00
|
|
|
LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols);
|
2008-12-05 08:47:52 +08:00
|
|
|
|
2008-12-04 10:08:27 +08:00
|
|
|
void UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols);
|
2008-10-24 09:38:55 +08:00
|
|
|
|
2008-11-13 03:18:35 +08:00
|
|
|
Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, unsigned Count);
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2008-11-24 17:44:56 +08:00
|
|
|
const GRState* setExtent(const GRState* St, const MemRegion* R, SVal Extent);
|
|
|
|
|
2008-10-08 10:50:44 +08:00
|
|
|
static inline RegionBindingsTy GetRegionBindings(Store store) {
|
2008-12-05 08:47:52 +08:00
|
|
|
return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store));
|
2008-10-08 10:50:44 +08:00
|
|
|
}
|
2008-10-24 09:38:55 +08:00
|
|
|
|
2008-10-24 12:33:15 +08:00
|
|
|
void print(Store store, std::ostream& Out, const char* nl, const char *sep);
|
2008-10-24 09:38:55 +08:00
|
|
|
|
|
|
|
void iterBindings(Store store, BindingsHandler& f) {
|
|
|
|
// FIXME: Implement.
|
|
|
|
}
|
2008-10-24 16:42:28 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
Loc getVarLoc(const VarDecl* VD) {
|
|
|
|
return loc::MemRegionVal(MRMgr.getVarRegion(VD));
|
|
|
|
}
|
|
|
|
|
2008-11-02 20:13:30 +08:00
|
|
|
Store InitializeArray(Store store, const TypedRegion* R, SVal Init);
|
|
|
|
Store BindArrayToVal(Store store, const TypedRegion* BaseR, SVal V);
|
2008-11-19 19:06:24 +08:00
|
|
|
Store BindArrayToSymVal(Store store, const TypedRegion* BaseR);
|
|
|
|
|
2008-11-02 20:13:30 +08:00
|
|
|
Store InitializeStruct(Store store, const TypedRegion* R, SVal Init);
|
|
|
|
Store BindStructToVal(Store store, const TypedRegion* BaseR, SVal V);
|
2008-11-19 19:06:24 +08:00
|
|
|
Store BindStructToSymVal(Store store, const TypedRegion* BaseR);
|
2008-10-31 15:16:08 +08:00
|
|
|
|
2008-12-04 09:12:41 +08: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.
|
2008-10-31 15:16:08 +08:00
|
|
|
SVal RetrieveStruct(Store store, const TypedRegion* R);
|
2008-12-04 09:12:41 +08:00
|
|
|
|
2008-10-31 16:10:01 +08:00
|
|
|
Store BindStruct(Store store, const TypedRegion* R, SVal V);
|
2008-11-23 12:30:35 +08:00
|
|
|
|
2008-10-31 15:16:08 +08:00
|
|
|
// Utility methods.
|
|
|
|
BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
|
|
|
|
ASTContext& getContext() { return StateMgr.getContext(); }
|
2008-11-23 12:30:35 +08:00
|
|
|
SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); }
|
2008-11-16 12:07:26 +08:00
|
|
|
|
|
|
|
const GRState* AddRegionView(const GRState* St,
|
|
|
|
const MemRegion* View, const MemRegion* Base);
|
2008-10-08 10:50:44 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
} // end anonymous namespace
|
|
|
|
|
2008-10-24 09:04:59 +08:00
|
|
|
StoreManager* clang::CreateRegionStoreManager(GRStateManager& StMgr) {
|
2008-10-24 09:38:55 +08:00
|
|
|
return new RegionStoreManager(StMgr);
|
2008-10-24 09:04:59 +08:00
|
|
|
}
|
|
|
|
|
2008-10-25 22:18:57 +08:00
|
|
|
SVal RegionStoreManager::getLValueString(const GRState* St,
|
|
|
|
const StringLiteral* S) {
|
|
|
|
return loc::MemRegionVal(MRMgr.getStringRegion(S));
|
|
|
|
}
|
|
|
|
|
2008-10-22 21:44:38 +08:00
|
|
|
SVal RegionStoreManager::getLValueVar(const GRState* St, const VarDecl* VD) {
|
|
|
|
return loc::MemRegionVal(MRMgr.getVarRegion(VD));
|
|
|
|
}
|
2008-11-07 18:38:33 +08:00
|
|
|
|
|
|
|
SVal RegionStoreManager::getLValueCompoundLiteral(const GRState* St,
|
|
|
|
const CompoundLiteralExpr* CL) {
|
|
|
|
return loc::MemRegionVal(MRMgr.getCompoundLiteralRegion(CL));
|
|
|
|
}
|
|
|
|
|
2008-10-22 21:44:38 +08:00
|
|
|
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:
|
2008-11-07 16:57:30 +08:00
|
|
|
assert(0 && "Unhandled Base.");
|
2008-10-22 21:44:38 +08:00
|
|
|
return Base;
|
|
|
|
}
|
|
|
|
|
|
|
|
return loc::MemRegionVal(MRMgr.getFieldRegion(D, BaseR));
|
|
|
|
}
|
|
|
|
|
2008-10-24 09:09:32 +08:00
|
|
|
SVal RegionStoreManager::getLValueElement(const GRState* St,
|
|
|
|
SVal Base, SVal Offset) {
|
|
|
|
if (Base.isUnknownOrUndef())
|
|
|
|
return Base;
|
|
|
|
|
2008-10-27 20:23:17 +08:00
|
|
|
if (isa<loc::SymbolVal>(Base))
|
|
|
|
return Base;
|
|
|
|
|
2008-10-24 09:09:32 +08:00
|
|
|
loc::MemRegionVal& BaseL = cast<loc::MemRegionVal>(Base);
|
|
|
|
|
2008-11-13 17:48:44 +08:00
|
|
|
// 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();
|
|
|
|
}
|
|
|
|
|
2008-10-24 09:09:32 +08:00
|
|
|
// 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))) {
|
2008-11-13 17:15:14 +08:00
|
|
|
|
2008-11-25 03:35:33 +08:00
|
|
|
// Temporary SVal to hold a potential signed and extended APSInt.
|
2008-11-13 17:15:14 +08:00
|
|
|
SVal SignedInt;
|
|
|
|
|
2008-11-25 03:35:33 +08:00
|
|
|
// 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()) {
|
2008-11-13 17:15:14 +08:00
|
|
|
llvm::APSInt SI = CI2->getValue();
|
2008-11-25 03:39:40 +08:00
|
|
|
if (CI2->getValue().getBitWidth() < CI1->getValue().getBitWidth())
|
|
|
|
SI.extend(CI1->getValue().getBitWidth());
|
2008-11-13 17:15:14 +08:00
|
|
|
SI.setIsSigned(true);
|
|
|
|
SignedInt = nonloc::ConcreteInt(getBasicVals().getValue(SI));
|
|
|
|
CI2 = cast<nonloc::ConcreteInt>(&SignedInt);
|
|
|
|
}
|
|
|
|
|
2008-11-23 12:30:35 +08:00
|
|
|
SVal NewIdx = CI1->EvalBinOp(getBasicVals(), BinaryOperator::Add, *CI2);
|
2008-10-24 09:09:32 +08:00
|
|
|
return loc::MemRegionVal(MRMgr.getElementRegion(NewIdx,
|
|
|
|
ElemR->getSuperRegion()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
|
|
|
|
2008-11-22 21:21:46 +08:00
|
|
|
SVal RegionStoreManager::getSizeInElements(const GRState* St,
|
|
|
|
const MemRegion* R) {
|
|
|
|
if (const VarRegion* VR = dyn_cast<VarRegion>(R)) {
|
|
|
|
// Get the type of the variable.
|
|
|
|
QualType T = VR->getType(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)) {
|
2008-11-24 10:18:56 +08:00
|
|
|
const StringLiteral* Str = SR->getStringLiteral();
|
2008-11-24 10:30:48 +08:00
|
|
|
// We intentionally made the size value signed because it participates in
|
|
|
|
// operations with signed indices.
|
2008-11-24 13:16:01 +08:00
|
|
|
return NonLoc::MakeVal(getBasicVals(), Str->getByteLength() + 1, false);
|
2008-11-22 21:21:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (const AnonTypedRegion* ATR = dyn_cast<AnonTypedRegion>(R)) {
|
2008-11-24 17:44:56 +08:00
|
|
|
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.
|
|
|
|
QualType ElemTy = cast<PointerType>(ATR->getType(getContext()).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);
|
2008-11-22 21:21:46 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R)) {
|
|
|
|
// FIXME: Unsupported yet.
|
|
|
|
FR = 0;
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
2008-11-22 21:23:00 +08:00
|
|
|
|
2008-11-22 21:21:46 +08:00
|
|
|
assert(0 && "Other regions are not supported yet.");
|
|
|
|
}
|
|
|
|
|
2008-10-24 09:09:32 +08:00
|
|
|
// Cast 'pointer to array' to 'pointer to the first element of array'.
|
|
|
|
|
|
|
|
SVal RegionStoreManager::ArrayToPointer(SVal Array) {
|
|
|
|
const MemRegion* ArrayR = cast<loc::MemRegionVal>(&Array)->getRegion();
|
2008-10-25 22:18:57 +08:00
|
|
|
|
2008-11-23 12:30:35 +08:00
|
|
|
nonloc::ConcreteInt Idx(getBasicVals().getZeroWithPtrWidth(false));
|
2008-10-26 10:23:57 +08:00
|
|
|
ElementRegion* ER = MRMgr.getElementRegion(Idx, ArrayR);
|
|
|
|
|
|
|
|
return loc::MemRegionVal(ER);
|
2008-10-24 09:09:32 +08:00
|
|
|
}
|
|
|
|
|
2008-11-16 15:06:26 +08:00
|
|
|
std::pair<const GRState*, SVal>
|
|
|
|
RegionStoreManager::CastRegion(const GRState* St, SVal VoidPtr,
|
|
|
|
QualType CastToTy, Stmt* CastE) {
|
2008-11-16 12:07:26 +08:00
|
|
|
if (const AllocaRegion* AR =
|
|
|
|
dyn_cast<AllocaRegion>(cast<loc::MemRegionVal>(VoidPtr).getRegion())) {
|
|
|
|
|
|
|
|
// Create a new region to attach type information to it.
|
|
|
|
const AnonTypedRegion* TR = MRMgr.getAnonTypedRegion(CastToTy, AR);
|
|
|
|
|
|
|
|
// Get the pointer to the first element.
|
|
|
|
nonloc::ConcreteInt Idx(getBasicVals().getZeroWithPtrWidth(false));
|
|
|
|
const ElementRegion* ER = MRMgr.getElementRegion(Idx, TR);
|
|
|
|
|
|
|
|
// Add a RegionView to base region.
|
2008-11-28 11:55:52 +08:00
|
|
|
return std::make_pair(AddRegionView(St, TR, AR), loc::MemRegionVal(ER));
|
2008-11-16 12:07:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Default case.
|
2008-11-28 11:55:52 +08:00
|
|
|
return std::make_pair(St, UnknownVal());
|
2008-11-16 12:07:26 +08:00
|
|
|
}
|
|
|
|
|
2008-12-05 08:47:52 +08:00
|
|
|
SVal RegionStoreManager::Retrieve(const GRState* state, Loc L, QualType T) {
|
2008-10-21 13:29:26 +08:00
|
|
|
assert(!isa<UnknownVal>(L) && "location unknown");
|
|
|
|
assert(!isa<UndefinedVal>(L) && "location undefined");
|
2008-12-05 08:47:52 +08:00
|
|
|
Store S = state->getStore();
|
2008-10-21 13:29:26 +08:00
|
|
|
|
|
|
|
switch (L.getSubKind()) {
|
|
|
|
case loc::MemRegionKind: {
|
|
|
|
const MemRegion* R = cast<loc::MemRegionVal>(L).getRegion();
|
|
|
|
assert(R && "bad region");
|
|
|
|
|
2008-10-31 15:16:08 +08:00
|
|
|
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
|
|
|
|
if (TR->getType(getContext())->isStructureType())
|
|
|
|
return RetrieveStruct(S, TR);
|
|
|
|
|
2008-10-21 13:29:26 +08:00
|
|
|
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");
|
2008-11-19 08:27:37 +08:00
|
|
|
return L;
|
2008-10-21 13:29:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2008-10-31 15:16:08 +08:00
|
|
|
SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
|
|
|
|
QualType T = R->getType(getContext());
|
|
|
|
assert(T->isStructureType());
|
|
|
|
|
|
|
|
const RecordType* RT = cast<RecordType>(T.getTypePtr());
|
|
|
|
RecordDecl* RD = RT->getDecl();
|
|
|
|
assert(RD->isDefinition());
|
|
|
|
|
|
|
|
llvm::ImmutableList<SVal> StructVal = getBasicVals().getEmptySValList();
|
|
|
|
|
|
|
|
for (int i = RD->getNumMembers() - 1; i >= 0; --i) {
|
|
|
|
FieldRegion* FR = MRMgr.getFieldRegion(RD->getMember(i), R);
|
|
|
|
RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(store));
|
2008-10-31 16:10:01 +08:00
|
|
|
RegionBindingsTy::data_type* data = B.lookup(FR);
|
2008-10-31 15:16:08 +08:00
|
|
|
|
|
|
|
SVal FieldValue = data ? *data : UnknownVal();
|
|
|
|
|
|
|
|
StructVal = getBasicVals().consVals(FieldValue, StructVal);
|
|
|
|
}
|
|
|
|
|
|
|
|
return NonLoc::MakeCompoundVal(T, StructVal, getBasicVals());
|
|
|
|
}
|
|
|
|
|
2008-10-21 14:27:32 +08:00
|
|
|
Store RegionStoreManager::Bind(Store store, Loc LV, SVal V) {
|
2008-10-27 17:24:07 +08:00
|
|
|
if (LV.getSubKind() == loc::SymbolValKind)
|
|
|
|
return store;
|
|
|
|
|
2008-10-17 13:57:07 +08:00
|
|
|
assert(LV.getSubKind() == loc::MemRegionKind);
|
2008-10-08 10:50:44 +08:00
|
|
|
|
2008-10-18 04:28:54 +08:00
|
|
|
const MemRegion* R = cast<loc::MemRegionVal>(LV).getRegion();
|
2008-10-08 10:50:44 +08:00
|
|
|
|
2008-10-31 16:10:01 +08:00
|
|
|
assert(R);
|
|
|
|
|
|
|
|
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
|
|
|
|
if (TR->getType(getContext())->isStructureType())
|
|
|
|
return BindStruct(store, TR, V);
|
2008-10-08 10:50:44 +08:00
|
|
|
|
|
|
|
RegionBindingsTy B = GetRegionBindings(store);
|
|
|
|
return V.isUnknown()
|
|
|
|
? RBFactory.Remove(B, R).getRoot()
|
|
|
|
: RBFactory.Add(B, R, V).getRoot();
|
|
|
|
}
|
|
|
|
|
2008-10-31 16:10:01 +08:00
|
|
|
Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R, SVal V){
|
|
|
|
QualType T = R->getType(getContext());
|
|
|
|
assert(T->isStructureType());
|
|
|
|
|
|
|
|
const RecordType* RT = cast<RecordType>(T.getTypePtr());
|
|
|
|
RecordDecl* RD = RT->getDecl();
|
2008-11-13 16:41:36 +08:00
|
|
|
|
|
|
|
if (!RD->isDefinition()) {
|
2008-11-19 19:06:24 +08:00
|
|
|
// This can only occur when a pointer of incomplete struct type is used as a
|
2008-11-13 16:41:36 +08:00
|
|
|
// function argument.
|
|
|
|
assert(V.isUnknown());
|
|
|
|
return store;
|
|
|
|
}
|
2008-10-31 16:10:01 +08:00
|
|
|
|
|
|
|
RegionBindingsTy B = GetRegionBindings(store);
|
|
|
|
|
2008-11-02 20:13:30 +08:00
|
|
|
if (isa<UnknownVal>(V))
|
|
|
|
return BindStructToVal(store, R, UnknownVal());
|
|
|
|
|
2008-10-31 16:10:01 +08:00
|
|
|
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();
|
|
|
|
}
|
|
|
|
|
2008-10-08 10:50:44 +08:00
|
|
|
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) {
|
2008-10-22 00:13:35 +08:00
|
|
|
NamedDecl* ND = const_cast<NamedDecl*>(I->first);
|
2008-10-08 10:50:44 +08:00
|
|
|
|
2008-10-22 00:13:35 +08:00
|
|
|
if (VarDecl* VD = dyn_cast<VarDecl>(ND)) {
|
2008-10-08 10:50:44 +08:00
|
|
|
// Punt on static variables for now.
|
|
|
|
if (VD->getStorageClass() == VarDecl::Static)
|
|
|
|
continue;
|
|
|
|
|
2008-11-19 19:06:24 +08:00
|
|
|
VarRegion* VR = MRMgr.getVarRegion(VD);
|
|
|
|
|
2008-10-08 10:50:44 +08:00
|
|
|
QualType T = VD->getType();
|
|
|
|
// Only handle pointers and integers for now.
|
2008-10-17 13:57:07 +08:00
|
|
|
if (Loc::IsLocType(T) || T->isIntegerType()) {
|
2008-10-08 10:50:44 +08:00
|
|
|
// Initialize globals and parameters to symbolic values.
|
|
|
|
// Initialize local variables to undefined.
|
2008-10-17 13:57:07 +08:00
|
|
|
SVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
|
2008-10-08 10:50:44 +08:00
|
|
|
isa<ImplicitParamDecl>(VD))
|
2008-11-23 12:30:35 +08:00
|
|
|
? SVal::GetSymbolValue(getSymbolManager(), VD)
|
2008-10-08 10:50:44 +08:00
|
|
|
: UndefinedVal();
|
|
|
|
|
2008-10-21 14:27:32 +08:00
|
|
|
St = Bind(St, getVarLoc(VD), X);
|
2008-11-19 19:06:24 +08:00
|
|
|
}
|
|
|
|
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());
|
2008-10-08 10:50:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return St;
|
|
|
|
}
|
2008-10-21 13:29:26 +08:00
|
|
|
|
2008-11-13 03:18:35 +08:00
|
|
|
Store RegionStoreManager::BindDecl(Store store, const VarDecl* VD,
|
|
|
|
SVal* InitVal, unsigned Count) {
|
|
|
|
|
2008-10-21 13:29:26 +08:00
|
|
|
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) {
|
2008-11-13 03:18:35 +08:00
|
|
|
if (!InitVal) {
|
2008-10-21 13:29:26 +08:00
|
|
|
// Only handle pointer and integer static variables.
|
|
|
|
|
|
|
|
QualType T = VD->getType();
|
|
|
|
|
|
|
|
if (Loc::IsLocType(T))
|
2008-10-21 14:27:32 +08:00
|
|
|
store = Bind(store, getVarLoc(VD),
|
2008-11-23 12:30:35 +08:00
|
|
|
loc::ConcreteInt(getBasicVals().getValue(0, T)));
|
2008-10-21 13:29:26 +08:00
|
|
|
|
|
|
|
else if (T->isIntegerType())
|
2008-10-21 14:27:32 +08:00
|
|
|
store = Bind(store, getVarLoc(VD),
|
2008-11-23 12:30:35 +08:00
|
|
|
loc::ConcreteInt(getBasicVals().getValue(0, T)));
|
2008-10-31 18:24:47 +08:00
|
|
|
|
|
|
|
// Other types of static local variables are not handled yet.
|
2008-10-21 13:29:26 +08:00
|
|
|
} else {
|
2008-11-13 03:18:35 +08:00
|
|
|
store = Bind(store, getVarLoc(VD), *InitVal);
|
2008-10-21 13:29:26 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Process local variables.
|
|
|
|
|
|
|
|
QualType T = VD->getType();
|
|
|
|
|
2008-10-24 16:42:28 +08:00
|
|
|
VarRegion* VR = MRMgr.getVarRegion(VD);
|
|
|
|
|
2008-10-21 13:29:26 +08:00
|
|
|
if (Loc::IsLocType(T) || T->isIntegerType()) {
|
2008-11-13 03:18:35 +08:00
|
|
|
SVal V = InitVal ? *InitVal : UndefinedVal();
|
2008-10-24 16:42:28 +08:00
|
|
|
store = Bind(store, loc::MemRegionVal(VR), V);
|
2008-11-13 03:18:35 +08:00
|
|
|
}
|
|
|
|
else if (T->isArrayType()) {
|
|
|
|
if (!InitVal)
|
2008-11-02 20:13:30 +08:00
|
|
|
store = BindArrayToVal(store, VR, UndefinedVal());
|
2008-10-31 18:24:47 +08:00
|
|
|
else
|
2008-11-13 03:18:35 +08:00
|
|
|
store = InitializeArray(store, VR, *InitVal);
|
|
|
|
}
|
|
|
|
else if (T->isStructureType()) {
|
|
|
|
if (!InitVal)
|
2008-11-02 20:13:30 +08:00
|
|
|
store = BindStructToVal(store, VR, UndefinedVal());
|
2008-10-31 18:53:01 +08:00
|
|
|
else
|
2008-11-13 03:18:35 +08:00
|
|
|
store = InitializeStruct(store, VR, *InitVal);
|
2008-10-21 13:29:26 +08:00
|
|
|
}
|
2008-10-31 18:24:47 +08:00
|
|
|
|
|
|
|
// Other types of local variables are not handled yet.
|
2008-10-21 13:29:26 +08:00
|
|
|
}
|
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
2008-11-07 18:38:33 +08:00
|
|
|
Store RegionStoreManager::BindCompoundLiteral(Store store,
|
|
|
|
const CompoundLiteralExpr* CL,
|
|
|
|
SVal V) {
|
|
|
|
CompoundLiteralRegion* R = MRMgr.getCompoundLiteralRegion(CL);
|
|
|
|
store = Bind(store, loc::MemRegionVal(R), V);
|
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
2008-11-24 17:44:56 +08:00
|
|
|
const GRState* RegionStoreManager::setExtent(const GRState* St,
|
|
|
|
const MemRegion* R, SVal Extent) {
|
|
|
|
GRStateRef state(St, StateMgr);
|
|
|
|
return state.set<RegionExtentsTy>(R, Extent);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2008-12-04 10:08:27 +08:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2008-12-05 08:47:52 +08:00
|
|
|
Store RegionStoreManager::RemoveDeadBindings(const GRState* state, Stmt* Loc,
|
2008-11-10 17:39:04 +08:00
|
|
|
const LiveVariables& Live,
|
|
|
|
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
|
|
|
|
LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) {
|
|
|
|
|
2008-12-05 08:47:52 +08:00
|
|
|
Store store = state->getStore();
|
2008-11-10 17:39:04 +08:00
|
|
|
RegionBindingsTy B = GetRegionBindings(store);
|
2008-12-04 10:08:27 +08:00
|
|
|
|
|
|
|
// 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.
|
2008-11-10 17:39:04 +08:00
|
|
|
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
2008-12-04 10:08:27 +08:00
|
|
|
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);
|
2008-11-10 17:39:04 +08:00
|
|
|
}
|
2008-12-04 10:08:27 +08:00
|
|
|
|
|
|
|
// 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::MemRegionVal(R));
|
|
|
|
|
|
|
|
// Mark all non-live symbols that this region references as dead.
|
|
|
|
if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) {
|
2008-12-05 10:27:51 +08:00
|
|
|
SymbolRef Sym = SymR->getSymbol();
|
2008-12-04 10:08:27 +08:00
|
|
|
if (!LSymbols.count(Sym)) DSymbols.insert(Sym);
|
|
|
|
}
|
2008-11-10 17:39:04 +08:00
|
|
|
|
2008-12-04 10:08:27 +08:00
|
|
|
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); }
|
|
|
|
}
|
|
|
|
|
2008-11-10 17:39:04 +08:00
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
2008-10-24 14:01:33 +08:00
|
|
|
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 12:33:15 +08:00
|
|
|
}
|
2008-10-24 16:42:28 +08:00
|
|
|
|
2008-11-02 20:13:30 +08:00
|
|
|
Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R,
|
2008-10-31 18:24:47 +08:00
|
|
|
SVal Init) {
|
|
|
|
QualType T = R->getType(getContext());
|
|
|
|
assert(T->isArrayType());
|
|
|
|
|
|
|
|
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
|
|
|
|
|
2008-11-30 13:49:49 +08:00
|
|
|
llvm::APSInt Size(CAT->getSize(), false);
|
|
|
|
|
2008-12-03 00:47:35 +08:00
|
|
|
llvm::APSInt i = getBasicVals().getValue(0, Size.getBitWidth(),
|
|
|
|
Size.isUnsigned());
|
2008-11-30 13:49:49 +08:00
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
2008-10-31 18:24:47 +08:00
|
|
|
|
|
|
|
|
|
|
|
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
|
|
|
|
|
|
|
|
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
|
|
|
|
2008-11-30 13:49:49 +08:00
|
|
|
for (; i < Size; ++i) {
|
|
|
|
SVal Idx = NonLoc::MakeVal(getBasicVals(), i);
|
2008-10-31 18:24:47 +08:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-11-02 20:13:30 +08:00
|
|
|
// Bind all elements of the array to some value.
|
|
|
|
Store RegionStoreManager::BindArrayToVal(Store store, const TypedRegion* BaseR,
|
|
|
|
SVal V){
|
2008-10-31 19:02:48 +08:00
|
|
|
QualType T = BaseR->getType(getContext());
|
2008-10-24 16:42:28 +08:00
|
|
|
assert(T->isArrayType());
|
|
|
|
|
|
|
|
// Only handle constant size array for now.
|
|
|
|
if (ConstantArrayType* CAT=dyn_cast<ConstantArrayType>(T.getTypePtr())) {
|
|
|
|
|
|
|
|
llvm::APInt Size = CAT->getSize();
|
2008-10-31 18:24:47 +08:00
|
|
|
llvm::APInt i = llvm::APInt::getNullValue(Size.getBitWidth());
|
2008-11-28 16:41:39 +08:00
|
|
|
|
2008-10-31 18:24:47 +08:00
|
|
|
for (; i != Size; ++i) {
|
2008-11-28 16:41:39 +08:00
|
|
|
nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(i, false)));
|
2008-10-24 16:42:28 +08:00
|
|
|
|
|
|
|
ElementRegion* ER = MRMgr.getElementRegion(Idx, BaseR);
|
|
|
|
|
2008-11-18 21:11:04 +08:00
|
|
|
if (CAT->getElementType()->isStructureType())
|
|
|
|
store = BindStructToVal(store, ER, V);
|
|
|
|
else
|
|
|
|
store = Bind(store, loc::MemRegionVal(ER), V);
|
2008-10-24 16:42:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
2008-11-19 19:06:24 +08:00
|
|
|
Store RegionStoreManager::BindArrayToSymVal(Store store,
|
|
|
|
const TypedRegion* BaseR) {
|
|
|
|
QualType T = BaseR->getType(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) {
|
2008-11-28 16:41:39 +08:00
|
|
|
nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(i, false)));
|
2008-11-19 19:06:24 +08:00
|
|
|
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2008-11-02 20:13:30 +08:00
|
|
|
Store RegionStoreManager::InitializeStruct(Store store, const TypedRegion* R,
|
2008-10-31 19:02:48 +08:00
|
|
|
SVal Init) {
|
2008-10-31 18:53:01 +08:00
|
|
|
QualType T = R->getType(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
|
2008-11-02 20:13:30 +08:00
|
|
|
store = BindArrayToVal(store, FR, UndefinedVal());
|
2008-10-31 18:53:01 +08:00
|
|
|
}
|
|
|
|
else if (FTy->isStructureType()) {
|
|
|
|
if (VI != VE) {
|
|
|
|
store = InitializeStruct(store, FR, *VI);
|
|
|
|
++VI;
|
|
|
|
} else
|
2008-11-02 20:13:30 +08:00
|
|
|
store = BindStructToVal(store, FR, UndefinedVal());
|
2008-10-31 18:53:01 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return store;
|
|
|
|
}
|
|
|
|
|
2008-11-02 20:13:30 +08:00
|
|
|
// Bind all fields of the struct to some value.
|
|
|
|
Store RegionStoreManager::BindStructToVal(Store store, const TypedRegion* BaseR,
|
|
|
|
SVal V) {
|
2008-10-31 19:02:48 +08:00
|
|
|
QualType T = BaseR->getType(getContext());
|
|
|
|
assert(T->isStructureType());
|
|
|
|
|
|
|
|
const RecordType* RT = cast<RecordType>(T.getTypePtr());
|
2008-10-24 16:42:28 +08:00
|
|
|
RecordDecl* RD = RT->getDecl();
|
|
|
|
assert(RD->isDefinition());
|
2008-10-31 19:02:48 +08:00
|
|
|
|
|
|
|
RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
|
|
|
|
|
|
|
|
for (; I != E; ++I) {
|
2008-10-24 16:42:28 +08:00
|
|
|
|
|
|
|
QualType FTy = (*I)->getType();
|
|
|
|
FieldRegion* FR = MRMgr.getFieldRegion(*I, BaseR);
|
|
|
|
|
|
|
|
if (Loc::IsLocType(FTy) || FTy->isIntegerType()) {
|
2008-11-02 20:13:30 +08:00
|
|
|
store = Bind(store, loc::MemRegionVal(FR), V);
|
2008-10-24 16:42:28 +08:00
|
|
|
|
|
|
|
} else if (FTy->isArrayType()) {
|
2008-11-02 20:13:30 +08:00
|
|
|
store = BindArrayToVal(store, FR, V);
|
2008-10-24 16:42:28 +08:00
|
|
|
|
|
|
|
} else if (FTy->isStructureType()) {
|
2008-11-02 20:13:30 +08:00
|
|
|
store = BindStructToVal(store, FR, V);
|
2008-10-24 16:42:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return store;
|
|
|
|
}
|
2008-11-16 12:07:26 +08:00
|
|
|
|
2008-11-19 19:06:24 +08:00
|
|
|
Store RegionStoreManager::BindStructToSymVal(Store store,
|
|
|
|
const TypedRegion* BaseR) {
|
|
|
|
QualType T = BaseR->getType(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;
|
|
|
|
}
|
|
|
|
|
2008-11-16 12:07:26 +08:00
|
|
|
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);
|
|
|
|
}
|