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-10-17 13:57:07 +08:00
|
|
|
typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
|
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
|
|
|
|
|
|
|
namespace {
|
|
|
|
|
|
|
|
class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
|
|
|
|
RegionBindingsTy::Factory RBFactory;
|
2008-11-16 12:07:26 +08:00
|
|
|
RegionViewTy::Factory RVFactory;
|
|
|
|
RegionViewMapTy::Factory RVMFactory;
|
|
|
|
|
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()),
|
|
|
|
RVMFactory(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; }
|
|
|
|
|
|
|
|
// FIXME: Is this function necessary?
|
|
|
|
SVal GetRegionSVal(Store St, const MemRegion* R) {
|
|
|
|
return Retrieve(St, loc::MemRegionVal(R));
|
|
|
|
}
|
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);
|
|
|
|
|
|
|
|
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-10-24 09:38:55 +08:00
|
|
|
SVal Retrieve(Store S, 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-10-08 10:50:44 +08:00
|
|
|
|
2008-10-24 09:38:55 +08:00
|
|
|
Store RemoveDeadBindings(Store store, Stmt* Loc, const LiveVariables& Live,
|
|
|
|
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
|
2008-11-10 17:39:04 +08:00
|
|
|
LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols);
|
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-10-08 10:50:44 +08:00
|
|
|
static inline RegionBindingsTy GetRegionBindings(Store store) {
|
|
|
|
return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store));
|
|
|
|
}
|
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-19 19:06:24 +08:00
|
|
|
SymbolManager& getSymbolManager() { return StateMgr.getSymbolManager(); }
|
|
|
|
|
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
|
|
|
|
|
|
|
SVal RetrieveStruct(Store store, const TypedRegion* R);
|
2008-10-31 16:10:01 +08:00
|
|
|
Store BindStruct(Store store, const TypedRegion* R, SVal V);
|
2008-10-31 15:16:08 +08:00
|
|
|
// Utility methods.
|
|
|
|
BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
|
|
|
|
ASTContext& getContext() { return StateMgr.getContext(); }
|
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
|
|
|
|
|
|
|
// Temporary SVal to hold a potential signed APSInt.
|
|
|
|
SVal SignedInt;
|
|
|
|
|
|
|
|
// Index might be unsigned. We have to convert it to signed.
|
|
|
|
if (CI2->getValue().isUnsigned()) {
|
|
|
|
llvm::APSInt SI = CI2->getValue();
|
|
|
|
SI.setIsSigned(true);
|
|
|
|
SignedInt = nonloc::ConcreteInt(getBasicVals().getValue(SI));
|
|
|
|
CI2 = cast<nonloc::ConcreteInt>(&SignedInt);
|
|
|
|
}
|
|
|
|
|
2008-10-24 09:09:32 +08:00
|
|
|
SVal NewIdx = CI1->EvalBinOp(StateMgr.getBasicVals(), BinaryOperator::Add,
|
|
|
|
*CI2);
|
|
|
|
return loc::MemRegionVal(MRMgr.getElementRegion(NewIdx,
|
|
|
|
ElemR->getSuperRegion()));
|
|
|
|
}
|
|
|
|
|
|
|
|
return UnknownVal();
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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
|
|
|
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
|
|
|
|
|
2008-11-15 13:18:50 +08:00
|
|
|
nonloc::ConcreteInt Idx(BasicVals.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-16 15:06:26 +08:00
|
|
|
return std::pair<const GRState*, SVal>(AddRegionView(St, TR, AR),
|
|
|
|
loc::MemRegionVal(ER));
|
2008-11-16 12:07:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Default case.
|
2008-11-16 15:06:26 +08:00
|
|
|
return std::pair<const GRState*, SVal>(St, UnknownVal());
|
2008-11-16 12:07:26 +08:00
|
|
|
}
|
|
|
|
|
2008-10-21 14:27:32 +08:00
|
|
|
SVal RegionStoreManager::Retrieve(Store S, Loc L, QualType T) {
|
2008-10-21 13:29:26 +08:00
|
|
|
assert(!isa<UnknownVal>(L) && "location unknown");
|
|
|
|
assert(!isa<UndefinedVal>(L) && "location undefined");
|
|
|
|
|
|
|
|
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-10-17 13:57:07 +08:00
|
|
|
? SVal::GetSymbolValue(StateMgr.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
|
|
|
BasicValueFactory& BasicVals = StateMgr.getBasicVals();
|
|
|
|
|
|
|
|
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),
|
|
|
|
loc::ConcreteInt(BasicVals.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),
|
|
|
|
loc::ConcreteInt(BasicVals.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-10 17:39:04 +08:00
|
|
|
Store RegionStoreManager::RemoveDeadBindings(Store store, Stmt* Loc,
|
|
|
|
const LiveVariables& Live,
|
|
|
|
llvm::SmallVectorImpl<const MemRegion*>& RegionRoots,
|
|
|
|
LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) {
|
|
|
|
|
|
|
|
RegionBindingsTy B = GetRegionBindings(store);
|
|
|
|
typedef SVal::symbol_iterator symbol_iterator;
|
|
|
|
|
|
|
|
// FIXME: Mark all region binding value's symbol as live. We also omit symbols
|
|
|
|
// in SymbolicRegions.
|
|
|
|
for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) {
|
|
|
|
SVal X = I.getData();
|
|
|
|
for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI)
|
|
|
|
LSymbols.insert(*SI);
|
|
|
|
}
|
|
|
|
|
|
|
|
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());
|
|
|
|
|
|
|
|
llvm::APInt Size = CAT->getSize();
|
|
|
|
|
|
|
|
llvm::APInt i = llvm::APInt::getNullValue(Size.getBitWidth());
|
|
|
|
|
|
|
|
nonloc::CompoundVal& CV = cast<nonloc::CompoundVal>(Init);
|
|
|
|
|
|
|
|
nonloc::CompoundVal::iterator VI = CV.begin(), VE = CV.end();
|
|
|
|
|
|
|
|
for (; i != Size; ++i) {
|
|
|
|
nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(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;
|
|
|
|
}
|
|
|
|
|
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());
|
|
|
|
for (; i != Size; ++i) {
|
2008-10-31 19:02:48 +08:00
|
|
|
nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(i)));
|
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) {
|
|
|
|
nonloc::ConcreteInt Idx(getBasicVals().getValue(llvm::APSInt(i)));
|
|
|
|
|
|
|
|
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);
|
|
|
|
}
|