aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Analysis')
-rw-r--r--lib/Analysis/BasicObjCFoundationChecks.cpp9
-rw-r--r--lib/Analysis/BasicStore.cpp29
-rw-r--r--lib/Analysis/CFRefCount.cpp2
-rw-r--r--lib/Analysis/GRExprEngine.cpp25
-rw-r--r--lib/Analysis/MemRegion.cpp46
-rw-r--r--lib/Analysis/RegionStore.cpp81
6 files changed, 107 insertions, 85 deletions
diff --git a/lib/Analysis/BasicObjCFoundationChecks.cpp b/lib/Analysis/BasicObjCFoundationChecks.cpp
index d81b3343c9..be729bee6c 100644
--- a/lib/Analysis/BasicObjCFoundationChecks.cpp
+++ b/lib/Analysis/BasicObjCFoundationChecks.cpp
@@ -504,11 +504,14 @@ bool AuditCFNumberCreate::Audit(ExplodedNode<GRState>* N,GRStateManager&){
return false;
const TypedRegion* R = dyn_cast<TypedRegion>(LV->getRegion());
- if (!R)
- return false;
+ if (!R) return false;
+ while (const AnonTypedRegion* ATR = dyn_cast<AnonTypedRegion>(R)) {
+ R = dyn_cast<TypedRegion>(ATR->getSuperRegion());
+ if (!R) return false;
+ }
- QualType T = Ctx.getCanonicalType(R->getType(Ctx));
+ QualType T = Ctx.getCanonicalType(R->getRValueType(Ctx));
// FIXME: If the pointee isn't an integer type, should we flag a warning?
// People can do weird stuff with pointers.
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 91d85c4c2b..1febba675d 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -66,11 +66,11 @@ public:
/// conversions between arrays and pointers.
SVal ArrayToPointer(SVal Array) { return Array; }
- std::pair<const GRState*, SVal>
- CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy, Stmt* CastE) {
- return std::make_pair(St, UnknownVal());
- }
-
+ /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+ /// a MemRegion* to a specific location type. 'R' is the region being
+ /// casted and 'CastToTy' the result type of the cast.
+ CastResult CastRegion(const GRState* state, const MemRegion* R,
+ QualType CastToTy);
/// getSelfRegion - Returns the region for the 'self' (Objective-C) or
/// 'this' object (C++). When used when analyzing a normal function this
@@ -124,6 +124,25 @@ SVal BasicStoreManager::getLValueIvar(const GRState* St, const ObjCIvarDecl* D,
return UnknownVal();
}
+/// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+/// a MemRegion* to a specific location type. 'R' is the region being
+/// casted and 'CastToTy' the result type of the cast.
+StoreManager::CastResult
+BasicStoreManager::CastRegion(const GRState* state, const MemRegion* R,
+ QualType CastToTy) {
+
+ // Return the same region if the region types are compatible.
+ if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
+ ASTContext& Ctx = StateMgr.getContext();
+ QualType Ta = Ctx.getCanonicalType(TR->getLValueType(Ctx));
+ QualType Tb = Ctx.getCanonicalType(CastToTy);
+
+ if (Ta == Tb)
+ return CastResult(state, R);
+ }
+
+ return CastResult(state, MRMgr.getAnonTypedRegion(CastToTy, R));
+}
SVal BasicStoreManager::getLValueField(const GRState* St, SVal Base,
const FieldDecl* D) {
diff --git a/lib/Analysis/CFRefCount.cpp b/lib/Analysis/CFRefCount.cpp
index cb0cbd1681..e044d1d789 100644
--- a/lib/Analysis/CFRefCount.cpp
+++ b/lib/Analysis/CFRefCount.cpp
@@ -1602,7 +1602,7 @@ void CFRefCount::EvalSummary(ExplodedNodeSet<GRState>& Dst,
if (R) {
// Set the value of the variable to be a conjured symbol.
unsigned Count = Builder.getCurrentBlockCount();
- QualType T = R->getType(Ctx);
+ QualType T = R->getRValueType(Ctx);
// FIXME: handle structs.
if (Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType())) {
diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp
index 74e1a07631..d6b15b1e2c 100644
--- a/lib/Analysis/GRExprEngine.cpp
+++ b/lib/Analysis/GRExprEngine.cpp
@@ -1465,7 +1465,7 @@ void GRExprEngine::VisitObjCForCollectionStmtAux(ObjCForCollectionStmt* S,
// FIXME: The proper thing to do is to really iterate over the
// container. We will do this with dispatch logic to the store.
// For now, just 'conjure' up a symbolic value.
- QualType T = R->getType(getContext());
+ QualType T = R->getRValueType(getContext());
assert (Loc::IsLocType(T));
unsigned Count = Builder->getCurrentBlockCount();
loc::SymbolVal SymV(SymMgr.getConjuredSymbol(elem, T, Count));
@@ -1731,16 +1731,25 @@ void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
continue;
}
- // Check for casts from a pointer to a region to typed pointer.
- if (isa<loc::MemRegionVal>(V)) {
+ // Check for casts from a region to a specific type.
+ if (loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(&V)) {
assert(Loc::IsLocType(T));
assert(Loc::IsLocType(ExTy));
- // Delegate to store manager.
- std::pair<const GRState*, SVal> Res =
- getStoreManager().CastRegion(St, V, T, CastE);
-
- MakeNode(Dst, CastE, N, BindExpr(Res.first, CastE, Res.second));
+ const MemRegion* R = RV->getRegion();
+ StoreManager& StoreMgr = getStoreManager();
+
+ // Delegate to store manager to get the result of casting a region
+ // to a different type.
+ const StoreManager::CastResult& Res = StoreMgr.CastRegion(St, R, T);
+
+ // Inspect the result. If the MemRegion* returned is NULL, this
+ // expression evaluates to UnknownVal.
+ R = Res.getRegion();
+ if (R) { V = loc::MemRegionVal(R); } else { V = UnknownVal(); }
+
+ // Generate the new node in the ExplodedGraph.
+ MakeNode(Dst, CastE, N, BindExpr(Res.getState(), CastE, V));
continue;
}
diff --git a/lib/Analysis/MemRegion.cpp b/lib/Analysis/MemRegion.cpp
index 94ffb3f152..898aff031f 100644
--- a/lib/Analysis/MemRegion.cpp
+++ b/lib/Analysis/MemRegion.cpp
@@ -51,18 +51,6 @@ void AnonTypedRegion::ProfileRegion(llvm::FoldingSetNodeID& ID, QualType T,
ID.AddPointer(superRegion);
}
-QualType AnonPointeeRegion::getType(ASTContext& C) const {
- return C.getCanonicalType(T);
-}
-
-void AnonPointeeRegion::ProfileRegion(llvm::FoldingSetNodeID& ID,
- SymbolRef Sym,
- const MemRegion* superRegion) {
- ID.AddInteger((unsigned) AnonPointeeRegionKind);
- Sym.Profile(ID);
- ID.AddPointer(superRegion);
-}
-
void CompoundLiteralRegion::Profile(llvm::FoldingSetNodeID& ID) const {
CompoundLiteralRegion::ProfileRegion(ID, CL, superRegion);
}
@@ -106,9 +94,9 @@ void ElementRegion::Profile(llvm::FoldingSetNodeID& ID) const {
ElementRegion::ProfileRegion(ID, Index, superRegion);
}
-QualType ElementRegion::getType(ASTContext& C) const {
- QualType T = getArrayRegion()->getType(C);
-
+QualType ElementRegion::getRValueType(ASTContext& C) const {
+ QualType T = getArrayRegion()->getLValueType(C);
+ // FIXME: Should ArrayType be considered an LValue or RValue type?
if (isa<ArrayType>(T.getTypePtr())) {
ArrayType* AT = cast<ArrayType>(T.getTypePtr());
return AT->getElementType();
@@ -121,6 +109,14 @@ QualType ElementRegion::getType(ASTContext& C) const {
}
//===----------------------------------------------------------------------===//
+// getLValueType() and getRValueType()
+//===----------------------------------------------------------------------===//
+
+QualType StringRegion::getRValueType(ASTContext& C) const {
+ return Str->getType();
+}
+
+//===----------------------------------------------------------------------===//
// Region pretty-printing.
//===----------------------------------------------------------------------===//
@@ -390,26 +386,6 @@ MemRegionManager::getAnonTypedRegion(QualType t, const MemRegion* superRegion) {
return R;
}
-AnonPointeeRegion* MemRegionManager::getAnonPointeeRegion(SymbolRef Sym,
- QualType T) {
- llvm::FoldingSetNodeID ID;
- MemRegion* superRegion = getUnknownRegion();
-
- AnonPointeeRegion::ProfileRegion(ID, Sym, 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(Sym, T, superRegion);
- Regions.InsertNode(R, InsertPos);
- }
-
- return R;
-}
-
AllocaRegion* MemRegionManager::getAllocaRegion(const Expr* E, unsigned cnt) {
llvm::FoldingSetNodeID ID;
AllocaRegion::ProfileRegion(ID, E, cnt);
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp
index defa80f324..af1bebff80 100644
--- a/lib/Analysis/RegionStore.cpp
+++ b/lib/Analysis/RegionStore.cpp
@@ -101,8 +101,11 @@ public:
SVal ArrayToPointer(SVal Array);
- std::pair<const GRState*, SVal>
- CastRegion(const GRState* St, SVal VoidPtr, QualType CastToTy, Stmt* CastE);
+ /// CastRegion - Used by GRExprEngine::VisitCast to handle casts from
+ /// a MemRegion* to a specific location type. 'R' is the region being
+ /// casted and 'CastToTy' the result type of the cast.
+ CastResult CastRegion(const GRState* state, const MemRegion* R,
+ QualType CastToTy);
SVal Retrieve(const GRState* state, Loc L, QualType T = QualType());
@@ -297,7 +300,7 @@ 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());
+ QualType T = VR->getRValueType(getContext());
// It must be of array type.
const ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
@@ -326,8 +329,8 @@ SVal RegionStoreManager::getSizeInElements(const GRState* St,
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();
+ QualType LvT = ATR->getLValueType(getContext());
+ QualType ElemTy = cast<PointerType>(LvT.getTypePtr())->getPointeeType();
uint64_t X = getContext().getTypeSize(ElemTy);
@@ -378,25 +381,22 @@ SVal RegionStoreManager::ArrayToPointer(SVal Array) {
return loc::MemRegionVal(ER);
}
-std::pair<const GRState*, SVal>
-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);
-
- // Add a RegionView to base region.
- return std::make_pair(AddRegionView(St, TR, AR), loc::MemRegionVal(ER));
+StoreManager::CastResult
+RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R,
+ QualType CastToTy) {
+
+ // Return the same region if the region types are compatible.
+ if (const TypedRegion* TR = dyn_cast<TypedRegion>(R)) {
+ ASTContext& Ctx = StateMgr.getContext();
+ QualType Ta = Ctx.getCanonicalType(TR->getLValueType(Ctx));
+ QualType Tb = Ctx.getCanonicalType(CastToTy);
+
+ if (Ta == Tb)
+ return CastResult(state, R);
}
-
- // Default case.
- return std::make_pair(St, UnknownVal());
+
+ const MemRegion* ViewR = MRMgr.getAnonTypedRegion(CastToTy, R);
+ return CastResult(AddRegionView(state, ViewR, R), ViewR);
}
SVal RegionStoreManager::Retrieve(const GRState* state, Loc L, QualType T) {
@@ -410,7 +410,7 @@ SVal RegionStoreManager::Retrieve(const GRState* state, Loc L, QualType T) {
assert(R && "bad region");
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
- if (TR->getType(getContext())->isStructureType())
+ if (TR->getRValueType(getContext())->isStructureType())
return RetrieveStruct(S, TR);
RegionBindingsTy B(static_cast<const RegionBindingsTy::TreeTy*>(S));
@@ -434,7 +434,8 @@ SVal RegionStoreManager::Retrieve(const GRState* state, Loc L, QualType T) {
}
SVal RegionStoreManager::RetrieveStruct(Store store, const TypedRegion* R) {
- QualType T = R->getType(getContext());
+ // FIXME: Verify we want getRValueType instead of getLValueType.
+ QualType T = R->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
@@ -471,7 +472,8 @@ Store RegionStoreManager::Bind(Store store, Loc LV, SVal V) {
assert(R);
if (const TypedRegion* TR = dyn_cast<TypedRegion>(R))
- if (TR->getType(getContext())->isStructureType())
+ // FIXME: Verify we want getRValueType().
+ if (TR->getRValueType(getContext())->isStructureType())
return BindStruct(store, TR, V);
RegionBindingsTy B = GetRegionBindings(store);
@@ -481,7 +483,8 @@ Store RegionStoreManager::Bind(Store store, Loc LV, SVal V) {
}
Store RegionStoreManager::BindStruct(Store store, const TypedRegion* R, SVal V){
- QualType T = R->getType(getContext());
+ // Verify we want getRValueType.
+ QualType T = R->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
@@ -774,7 +777,9 @@ void RegionStoreManager::print(Store store, std::ostream& Out,
Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R,
SVal Init) {
- QualType T = R->getType(getContext());
+
+ // FIXME: Verify we should use getLValueType or getRValueType.
+ QualType T = R->getLValueType(getContext());
assert(T->isArrayType());
ConstantArrayType* CAT = cast<ConstantArrayType>(T.getTypePtr());
@@ -829,7 +834,9 @@ Store RegionStoreManager::InitializeArray(Store store, const TypedRegion* R,
// Bind all elements of the array to some value.
Store RegionStoreManager::BindArrayToVal(Store store, const TypedRegion* BaseR,
SVal V){
- QualType T = BaseR->getType(getContext());
+
+ // FIXME: Verify we want getRValueType.
+ QualType T = BaseR->getRValueType(getContext());
assert(T->isArrayType());
// Only handle constant size array for now.
@@ -855,7 +862,9 @@ Store RegionStoreManager::BindArrayToVal(Store store, const TypedRegion* BaseR,
Store RegionStoreManager::BindArrayToSymVal(Store store,
const TypedRegion* BaseR) {
- QualType T = BaseR->getType(getContext());
+
+ // FIXME: Verify we want getRValueType.
+ QualType T = BaseR->getRValueType(getContext());
assert(T->isArrayType());
if (ConstantArrayType* CAT = dyn_cast<ConstantArrayType>(T.getTypePtr())) {
@@ -882,7 +891,9 @@ Store RegionStoreManager::BindArrayToSymVal(Store store,
Store RegionStoreManager::InitializeStruct(Store store, const TypedRegion* R,
SVal Init) {
- QualType T = R->getType(getContext());
+
+ // FIXME: Verify that we should use getRValueType or getLValueType.
+ QualType T = R->getRValueType(getContext());
assert(T->isStructureType());
RecordType* RT = cast<RecordType>(T.getTypePtr());
@@ -925,7 +936,9 @@ Store RegionStoreManager::InitializeStruct(Store store, const TypedRegion* R,
// Bind all fields of the struct to some value.
Store RegionStoreManager::BindStructToVal(Store store, const TypedRegion* BaseR,
SVal V) {
- QualType T = BaseR->getType(getContext());
+
+ // FIXME: Verify that we should use getLValueType or getRValueType.
+ QualType T = BaseR->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());
@@ -955,7 +968,9 @@ Store RegionStoreManager::BindStructToVal(Store store, const TypedRegion* BaseR,
Store RegionStoreManager::BindStructToSymVal(Store store,
const TypedRegion* BaseR) {
- QualType T = BaseR->getType(getContext());
+
+ // FIXME: Verify that we should use getLValueType or getRValueType
+ QualType T = BaseR->getRValueType(getContext());
assert(T->isStructureType());
const RecordType* RT = cast<RecordType>(T.getTypePtr());