mirror of
https://github.com/intel/llvm.git
synced 2026-02-02 02:00:03 +08:00
This is the first step to implement a field-sensitive store model. Other things are simplified: no heap shape assumption, no parameter alias assumption, etc.
llvm-svn: 57285
This commit is contained in:
@@ -37,7 +37,7 @@ public:
|
||||
// Typed regions.
|
||||
BEG_TYPED_REGIONS,
|
||||
VarRegionKind, FieldRegionKind, ObjCIvarRegionKind,
|
||||
AnonTypedRegionKind,
|
||||
AnonTypedRegionKind, AnonPointeeRegionKind,
|
||||
END_TYPED_REGIONS };
|
||||
private:
|
||||
const Kind kind;
|
||||
@@ -104,6 +104,7 @@ public:
|
||||
/// AnonTypedRegion - An "anonymous" region that simply types a chunk
|
||||
/// of memory.
|
||||
class AnonTypedRegion : public TypedRegion {
|
||||
protected:
|
||||
QualType T;
|
||||
|
||||
friend class MemRegionManager;
|
||||
@@ -112,8 +113,8 @@ class AnonTypedRegion : public TypedRegion {
|
||||
: TypedRegion(sreg, AnonTypedRegionKind), T(t) {}
|
||||
|
||||
static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
|
||||
const MemRegion* superRegion);
|
||||
|
||||
const MemRegion* superRegion);
|
||||
|
||||
public:
|
||||
QualType getType() const { return T; }
|
||||
|
||||
@@ -125,6 +126,28 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
/// AnonPointeeRegion - anonymous regions pointed-at by pointer function
|
||||
/// parameters or pointer globals. In RegionStoreManager, we assume pointer
|
||||
/// parameters or globals point at some anonymous region initially. Such
|
||||
/// regions are not the regions associated with the pointers themselves, but
|
||||
/// are identified with the VarDecl of the parameters or globals.
|
||||
class AnonPointeeRegion : public AnonTypedRegion {
|
||||
friend class MemRegionManager;
|
||||
// VD - the pointer variable that points at this region.
|
||||
const VarDecl* VD;
|
||||
|
||||
AnonPointeeRegion(const VarDecl* d, QualType t, MemRegion* sreg)
|
||||
: AnonTypedRegion(t, sreg), VD(d) {}
|
||||
|
||||
public:
|
||||
static void ProfileRegion(llvm::FoldingSetNodeID& ID, const VarDecl* PVD,
|
||||
QualType T, const MemRegion* superRegion);
|
||||
};
|
||||
|
||||
/// AnonHeapRegion - anonymous region created by malloc().
|
||||
class AnonHeapRegion : public AnonTypedRegion {
|
||||
};
|
||||
|
||||
class DeclRegion : public TypedRegion {
|
||||
protected:
|
||||
const Decl* D;
|
||||
@@ -213,6 +236,7 @@ class MemRegionManager {
|
||||
MemSpaceRegion* globals;
|
||||
MemSpaceRegion* stack;
|
||||
MemSpaceRegion* heap;
|
||||
MemSpaceRegion* unknown;
|
||||
|
||||
public:
|
||||
MemRegionManager(llvm::BumpPtrAllocator& a)
|
||||
@@ -231,6 +255,10 @@ public:
|
||||
/// getHeapRegion - Retrieve the memory region associated with the
|
||||
/// generic "heap".
|
||||
MemSpaceRegion* getHeapRegion();
|
||||
|
||||
/// getUnknownRegion - Retrieve the memory region associated with unknown
|
||||
/// memory space.
|
||||
MemSpaceRegion* getUnknownRegion();
|
||||
|
||||
/// getVarRegion - Retrieve or create the memory region associated with
|
||||
/// a specified VarDecl. 'superRegion' corresponds to the containing
|
||||
@@ -254,7 +282,9 @@ public:
|
||||
/// object).
|
||||
ObjCIvarRegion* getObjCIvarRegion(const ObjCIvarDecl* ivd,
|
||||
MemRegion* superRegion);
|
||||
|
||||
|
||||
AnonPointeeRegion* getAnonPointeeRegion(const VarDecl* d);
|
||||
|
||||
bool hasStackStorage(const MemRegion* R);
|
||||
|
||||
private:
|
||||
|
||||
@@ -32,6 +32,15 @@ void AnonTypedRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
|
||||
ID.AddPointer(superRegion);
|
||||
}
|
||||
|
||||
void AnonPointeeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
|
||||
const VarDecl* VD, QualType T,
|
||||
const MemRegion* superRegion) {
|
||||
ID.AddInteger((unsigned) AnonPointeeRegionKind);
|
||||
ID.Add(T);
|
||||
ID.AddPointer(VD);
|
||||
ID.AddPointer(superRegion);
|
||||
}
|
||||
|
||||
void AnonTypedRegion::Profile(llvm::FoldingSetNodeID& ID) const {
|
||||
AnonTypedRegion::ProfileRegion(ID, T, superRegion);
|
||||
}
|
||||
@@ -92,6 +101,10 @@ MemSpaceRegion* MemRegionManager::getHeapRegion() {
|
||||
return LazyAllocate(heap);
|
||||
}
|
||||
|
||||
MemSpaceRegion* MemRegionManager::getUnknownRegion() {
|
||||
return LazyAllocate(unknown);
|
||||
}
|
||||
|
||||
VarRegion* MemRegionManager::getVarRegion(const VarDecl* d,
|
||||
MemRegion* superRegion) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
@@ -146,6 +159,27 @@ ObjCIvarRegion* MemRegionManager::getObjCIvarRegion(const ObjCIvarDecl* d,
|
||||
return R;
|
||||
}
|
||||
|
||||
AnonPointeeRegion* MemRegionManager::getAnonPointeeRegion(const VarDecl* d) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
QualType T = d->getType();
|
||||
QualType PointeeType = cast<PointerType>(T.getTypePtr())->getPointeeType();
|
||||
MemRegion* superRegion = getUnknownRegion();
|
||||
|
||||
AnonPointeeRegion::ProfileRegion(ID, d, PointeeType, superRegion);
|
||||
|
||||
void* InsertPos;
|
||||
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
|
||||
AnonPointeeRegion* R = cast_or_null<AnonPointeeRegion>(data);
|
||||
|
||||
if (!R) {
|
||||
R = (AnonPointeeRegion*) A.Allocate<AnonPointeeRegion>();
|
||||
new (R) AnonPointeeRegion(d, PointeeType, superRegion);
|
||||
Regions.InsertNode(R, InsertPos);
|
||||
}
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
bool MemRegionManager::hasStackStorage(const MemRegion* R) {
|
||||
MemSpaceRegion* S = getStackRegion();
|
||||
|
||||
|
||||
96
clang/lib/Analysis/RegionStore.cpp
Normal file
96
clang/lib/Analysis/RegionStore.cpp
Normal file
@@ -0,0 +1,96 @@
|
||||
//== 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/Analyses/LiveVariables.h"
|
||||
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
typedef llvm::ImmutableMap<const MemRegion*, RVal> RegionBindingsTy;
|
||||
|
||||
namespace {
|
||||
|
||||
class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
|
||||
RegionBindingsTy::Factory RBFactory;
|
||||
GRStateManager& StateMgr;
|
||||
MemRegionManager MRMgr;
|
||||
|
||||
public:
|
||||
RegionStoreManager(GRStateManager& mgr)
|
||||
: StateMgr(mgr), MRMgr(StateMgr.getAllocator()) {}
|
||||
|
||||
virtual ~RegionStoreManager() {}
|
||||
|
||||
Store SetRVal(Store St, LVal LV, RVal V);
|
||||
|
||||
Store getInitialStore();
|
||||
|
||||
static inline RegionBindingsTy GetRegionBindings(Store store) {
|
||||
return RegionBindingsTy(static_cast<const RegionBindingsTy::TreeTy*>(store));
|
||||
}
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
|
||||
Store RegionStoreManager::SetRVal(Store store, LVal LV, RVal V) {
|
||||
assert(LV.getSubKind() == lval::MemRegionKind);
|
||||
|
||||
MemRegion* R = cast<lval::MemRegionVal>(LV).getRegion();
|
||||
|
||||
if (!R)
|
||||
return store;
|
||||
|
||||
RegionBindingsTy B = GetRegionBindings(store);
|
||||
return V.isUnknown()
|
||||
? RBFactory.Remove(B, R).getRoot()
|
||||
: RBFactory.Add(B, R, V).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) {
|
||||
ScopedDecl* SD = const_cast<ScopedDecl*>(I->first);
|
||||
|
||||
if (VarDecl* VD = dyn_cast<VarDecl>(SD)) {
|
||||
// Punt on static variables for now.
|
||||
if (VD->getStorageClass() == VarDecl::Static)
|
||||
continue;
|
||||
|
||||
QualType T = VD->getType();
|
||||
// Only handle pointers and integers for now.
|
||||
if (LVal::IsLValType(T) || T->isIntegerType()) {
|
||||
MemRegion* R = MRMgr.getVarRegion(VD);
|
||||
// Initialize globals and parameters to symbolic values.
|
||||
// Initialize local variables to undefined.
|
||||
RVal X = (VD->hasGlobalStorage() || isa<ParmVarDecl>(VD) ||
|
||||
isa<ImplicitParamDecl>(VD))
|
||||
? RVal::GetSymbolValue(StateMgr.getSymbolManager(), VD)
|
||||
: UndefinedVal();
|
||||
|
||||
St = SetRVal(St, lval::MemRegionVal(R), X);
|
||||
}
|
||||
}
|
||||
}
|
||||
return St;
|
||||
}
|
||||
Reference in New Issue
Block a user