From: Zhongxing Xu Date: Wed, 8 Oct 2008 02:50:44 +0000 (+0000) Subject: This is the first step to implement a field-sensitive store model. Other things are... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=178927517fa09ddbb04dc8ef725b5716c18aae21;p=clang 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. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@57285 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Analysis/PathSensitive/MemRegion.h b/include/clang/Analysis/PathSensitive/MemRegion.h index 79705613ab..a1e02b0e98 100644 --- a/include/clang/Analysis/PathSensitive/MemRegion.h +++ b/include/clang/Analysis/PathSensitive/MemRegion.h @@ -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: diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp index 49c58f6496..747d2f6818 100644 --- a/lib/Analysis/MemRegion.cpp +++ b/lib/Analysis/MemRegion.cpp @@ -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(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(data); + + if (!R) { + R = (AnonPointeeRegion*) A.Allocate(); + new (R) AnonPointeeRegion(d, PointeeType, superRegion); + Regions.InsertNode(R, InsertPos); + } + + return R; +} + bool MemRegionManager::hasStackStorage(const MemRegion* R) { MemSpaceRegion* S = getStackRegion(); diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp new file mode 100644 index 0000000000..7004c5558e --- /dev/null +++ b/lib/Analysis/RegionStore.cpp @@ -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 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(store)); + } +}; + +} // end anonymous namespace + +Store RegionStoreManager::SetRVal(Store store, LVal LV, RVal V) { + assert(LV.getSubKind() == lval::MemRegionKind); + + MemRegion* R = cast(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(I->first); + + if (VarDecl* VD = dyn_cast(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(VD) || + isa(VD)) + ? RVal::GetSymbolValue(StateMgr.getSymbolManager(), VD) + : UndefinedVal(); + + St = SetRVal(St, lval::MemRegionVal(R), X); + } + } + } + return St; +}