mirror of
https://github.com/intel/llvm.git
synced 2026-02-01 08:56:15 +08:00
Enhances SCA to process untyped region to typed region conversion.
- RegionView and RegionViewMap is introduced to assist back-mapping from super region to subregions. - GDM is used to carry RegionView information. - AnonTypedRegion is added to represent a typed region introduced by pointer casting. Later AnonTypedRegion can be used in other similar cases, e.g., malloc()'ed region. - The specific conversion is delegated to store manager. llvm-svn: 59382
This commit is contained in:
@@ -23,6 +23,8 @@
|
||||
#include "clang/AST/ASTContext.h"
|
||||
#include "llvm/Support/Casting.h"
|
||||
#include "llvm/ADT/FoldingSet.h"
|
||||
#include "llvm/ADT/ImmutableList.h"
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
#include "llvm/Support/Allocator.h"
|
||||
#include <string>
|
||||
|
||||
@@ -42,12 +44,13 @@ public:
|
||||
BEG_TYPED_REGIONS,
|
||||
CompoundLiteralRegionKind,
|
||||
StringRegionKind, ElementRegionKind,
|
||||
AnonTypedRegionKind,
|
||||
AnonPointeeRegionKind,
|
||||
// Decl Regions.
|
||||
BEG_DECL_REGIONS,
|
||||
VarRegionKind, FieldRegionKind,
|
||||
ObjCIvarRegionKind, ObjCObjectRegionKind,
|
||||
END_DECL_REGIONS,
|
||||
AnonPointeeRegionKind,
|
||||
END_TYPED_REGIONS };
|
||||
private:
|
||||
const Kind kind;
|
||||
@@ -201,6 +204,32 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
class AnonTypedRegion : public TypedRegion {
|
||||
friend class MemRegionManager;
|
||||
|
||||
QualType T;
|
||||
|
||||
AnonTypedRegion(QualType t, const MemRegion* sreg)
|
||||
: TypedRegion(sreg, AnonTypedRegionKind), T(t) {}
|
||||
|
||||
static void ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
|
||||
const MemRegion* superRegion);
|
||||
|
||||
public:
|
||||
|
||||
QualType getType(ASTContext& C) const {
|
||||
return T;
|
||||
}
|
||||
|
||||
void Profile(llvm::FoldingSetNodeID& ID) const {
|
||||
ProfileRegion(ID, T, superRegion);
|
||||
}
|
||||
|
||||
static bool classof(const MemRegion* R) {
|
||||
return R->getKind() == AnonTypedRegionKind;
|
||||
}
|
||||
};
|
||||
|
||||
/// AnonPointeeRegion - anonymous regions pointed-to by pointer function
|
||||
/// parameters or pointer globals. In RegionStoreManager, we assume pointer
|
||||
/// parameters or globals point at some anonymous region. Such regions are not
|
||||
@@ -494,7 +523,7 @@ class MemRegionManager {
|
||||
MemSpaceRegion* stack;
|
||||
MemSpaceRegion* heap;
|
||||
MemSpaceRegion* unknown;
|
||||
|
||||
|
||||
public:
|
||||
MemRegionManager(llvm::BumpPtrAllocator& a)
|
||||
: A(a), globals(0), stack(0), heap(0) {}
|
||||
@@ -559,10 +588,12 @@ public:
|
||||
ObjCIvarRegion* getObjCIvarRegion(const ObjCIvarDecl* ivd,
|
||||
const MemRegion* superRegion);
|
||||
|
||||
AnonTypedRegion* getAnonTypedRegion(QualType t, const MemRegion* superRegion);
|
||||
|
||||
AnonPointeeRegion* getAnonPointeeRegion(const VarDecl* d);
|
||||
|
||||
bool hasStackStorage(const MemRegion* R);
|
||||
|
||||
|
||||
private:
|
||||
MemSpaceRegion* LazyAllocate(MemSpaceRegion*& region);
|
||||
};
|
||||
|
||||
@@ -80,6 +80,9 @@ public:
|
||||
/// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
|
||||
/// conversions between arrays and pointers.
|
||||
virtual SVal ArrayToPointer(SVal Array) = 0;
|
||||
|
||||
virtual const GRState* CastRegion(const GRState* St, SVal VoidPtr,
|
||||
QualType CastToTy, Stmt* CastE) = 0;
|
||||
|
||||
/// getSelfRegion - Returns the region for the 'self' (Objective-C) or
|
||||
/// 'this' object (C++). When used when analyzing a normal function this
|
||||
|
||||
@@ -65,6 +65,12 @@ public:
|
||||
/// ArrayToPointer - Used by GRExprEngine::VistCast to handle implicit
|
||||
/// conversions between arrays and pointers.
|
||||
SVal ArrayToPointer(SVal Array) { return Array; }
|
||||
|
||||
const GRState* CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy,
|
||||
Stmt* CastE) {
|
||||
return St;
|
||||
}
|
||||
|
||||
|
||||
/// getSelfRegion - Returns the region for the 'self' (Objective-C) or
|
||||
/// 'this' object (C++). When used when analyzing a normal function this
|
||||
|
||||
@@ -1692,6 +1692,21 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
|
||||
continue;
|
||||
}
|
||||
|
||||
// Check for casts from AllocaRegion pointer to typed pointer.
|
||||
if (isa<loc::MemRegionVal>(V)) {
|
||||
assert(Loc::IsLocType(T));
|
||||
assert(Loc::IsLocType(ExTy));
|
||||
|
||||
// Delegate to store manager.
|
||||
const GRState* NewSt = getStoreManager().CastRegion(St, V, T, CastE);
|
||||
|
||||
// If no new region is created, fall through to the default case.
|
||||
if (NewSt != St) {
|
||||
MakeNode(Dst, CastE, N, NewSt);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// All other cases.
|
||||
MakeNode(Dst, CastE, N, BindExpr(St, CastE, EvalCast(V, CastE->getType())));
|
||||
}
|
||||
|
||||
@@ -44,6 +44,13 @@ void AllocaRegion::Profile(llvm::FoldingSetNodeID& ID) const {
|
||||
ProfileRegion(ID, Ex, Cnt);
|
||||
}
|
||||
|
||||
void AnonTypedRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
|
||||
const MemRegion* superRegion) {
|
||||
ID.AddInteger((unsigned) AnonTypedRegionKind);
|
||||
ID.Add(T);
|
||||
ID.AddPointer(superRegion);
|
||||
}
|
||||
|
||||
QualType AnonPointeeRegion::getType(ASTContext& C) const {
|
||||
QualType T = C.getCanonicalType(Pointer->getType());
|
||||
PointerType* PTy = cast<PointerType>(T.getTypePtr());
|
||||
@@ -110,7 +117,7 @@ QualType ElementRegion::getType(ASTContext& C) const {
|
||||
ArrayType* AT = cast<ArrayType>(T.getTypePtr());
|
||||
return AT->getElementType();
|
||||
}
|
||||
else if (isa<AllocaRegion>(superRegion)) {
|
||||
else if (isa<AnonTypedRegion>(superRegion)) {
|
||||
PointerType* PtrT = cast<PointerType>(T.getTypePtr());
|
||||
QualType PTy = PtrT->getPointeeType();
|
||||
return C.getCanonicalType(PTy);
|
||||
@@ -369,6 +376,23 @@ MemRegionManager::getObjCObjectRegion(const ObjCInterfaceDecl* d,
|
||||
return R;
|
||||
}
|
||||
|
||||
AnonTypedRegion*
|
||||
MemRegionManager::getAnonTypedRegion(QualType t, const MemRegion* superRegion) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
AnonTypedRegion::ProfileRegion(ID, t, superRegion);
|
||||
|
||||
void* InsertPos;
|
||||
MemRegion* data = Regions.FindNodeOrInsertPos(ID, InsertPos);
|
||||
AnonTypedRegion* R = cast_or_null<AnonTypedRegion>(data);
|
||||
|
||||
if (!R) {
|
||||
R = (AnonTypedRegion*) A.Allocate<AnonTypedRegion>();
|
||||
new (R) AnonTypedRegion(t, superRegion);
|
||||
Regions.InsertNode(R, InsertPos);
|
||||
}
|
||||
|
||||
return R;
|
||||
}
|
||||
|
||||
AnonPointeeRegion* MemRegionManager::getAnonPointeeRegion(const VarDecl* d) {
|
||||
llvm::FoldingSetNodeID ID;
|
||||
|
||||
@@ -16,26 +16,46 @@
|
||||
//===----------------------------------------------------------------------===//
|
||||
#include "clang/Analysis/PathSensitive/MemRegion.h"
|
||||
#include "clang/Analysis/PathSensitive/GRState.h"
|
||||
#include "clang/Analysis/PathSensitive/GRStateTrait.h"
|
||||
#include "clang/Analysis/Analyses/LiveVariables.h"
|
||||
|
||||
#include "llvm/ADT/ImmutableMap.h"
|
||||
#include "llvm/ADT/ImmutableList.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
|
||||
using namespace clang;
|
||||
|
||||
typedef llvm::ImmutableMap<const MemRegion*, SVal> RegionBindingsTy;
|
||||
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; }
|
||||
};
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager {
|
||||
RegionBindingsTy::Factory RBFactory;
|
||||
RegionViewTy::Factory RVFactory;
|
||||
RegionViewMapTy::Factory RVMFactory;
|
||||
|
||||
GRStateManager& StateMgr;
|
||||
MemRegionManager MRMgr;
|
||||
|
||||
public:
|
||||
RegionStoreManager(GRStateManager& mgr)
|
||||
: StateMgr(mgr), MRMgr(StateMgr.getAllocator()) {}
|
||||
: RBFactory(mgr.getAllocator()),
|
||||
RVFactory(mgr.getAllocator()),
|
||||
RVMFactory(mgr.getAllocator()),
|
||||
StateMgr(mgr),
|
||||
MRMgr(StateMgr.getAllocator()) {}
|
||||
|
||||
virtual ~RegionStoreManager() {}
|
||||
|
||||
@@ -62,6 +82,9 @@ public:
|
||||
|
||||
SVal ArrayToPointer(SVal Array);
|
||||
|
||||
const GRState* CastRegion(const GRState* St, SVal VoidPtr,
|
||||
QualType CastToTy, Stmt* CastE);
|
||||
|
||||
SVal Retrieve(Store S, Loc L, QualType T = QualType());
|
||||
|
||||
Store Bind(Store St, Loc LV, SVal V);
|
||||
@@ -112,6 +135,9 @@ private:
|
||||
// Utility methods.
|
||||
BasicValueFactory& getBasicVals() { return StateMgr.getBasicVals(); }
|
||||
ASTContext& getContext() { return StateMgr.getContext(); }
|
||||
|
||||
const GRState* AddRegionView(const GRState* St,
|
||||
const MemRegion* View, const MemRegion* Base);
|
||||
};
|
||||
|
||||
} // end anonymous namespace
|
||||
@@ -238,6 +264,30 @@ SVal RegionStoreManager::ArrayToPointer(SVal Array) {
|
||||
return loc::MemRegionVal(ER);
|
||||
}
|
||||
|
||||
const GRState* RegionStoreManager::CastRegion(const GRState* St,
|
||||
SVal VoidPtr,
|
||||
QualType CastToTy,
|
||||
Stmt* CastE) {
|
||||
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);
|
||||
|
||||
St = StateMgr.BindExpr(St, CastE, loc::MemRegionVal(ER));
|
||||
|
||||
// Add a RegionView to base region.
|
||||
return AddRegionView(St, TR, AR);
|
||||
}
|
||||
|
||||
// Default case.
|
||||
return St;
|
||||
}
|
||||
|
||||
SVal RegionStoreManager::Retrieve(Store S, Loc L, QualType T) {
|
||||
assert(!isa<UnknownVal>(L) && "location unknown");
|
||||
assert(!isa<UndefinedVal>(L) && "location undefined");
|
||||
@@ -600,3 +650,19 @@ Store RegionStoreManager::BindStructToVal(Store store, const TypedRegion* BaseR,
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
const GRState* RegionStoreManager::AddRegionView(const GRState* St,
|
||||
const MemRegion* View,
|
||||
const MemRegion* Base) {
|
||||
GRStateRef state(St, StateMgr);
|
||||
|
||||
// First, retrieve the region view of the base region.
|
||||
RegionViewMapTy::data_type* d = state.get<RegionViewMapTy>(Base);
|
||||
RegionViewTy L = d ? *d : RVFactory.GetEmptyList();
|
||||
|
||||
// Now add View to the region view.
|
||||
L = RVFactory.Add(View, L);
|
||||
|
||||
// Create a new state with the new region view.
|
||||
return state.set<RegionViewMapTy>(Base, L);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user