summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-07-20 22:58:02 +0000
committerTed Kremenek <kremenek@apple.com>2009-07-20 22:58:02 +0000
commit834e2f69da6154e6360f69243a76ede0bf5263f6 (patch)
tree4c145fd65a5f31c3f70662712e0ba97fed71c31e
parentd231d78f3f8094c42fd15e52583ceba856364853 (diff)
downloadbcm5719-llvm-834e2f69da6154e6360f69243a76ede0bf5263f6.tar.gz
bcm5719-llvm-834e2f69da6154e6360f69243a76ede0bf5263f6.zip
Enhanced IsReinterpreted() (RegionStore.cpp) to reason about higher-order
pointers. Enhanced RegionStoreManager::Retrieve() to handle automatic casts when the loaded value is different from the requested value. This should be refined over time, but essentially we should always symbolicate locations as locations, and convert them to non-locations on demand. These changes now cause 'misc-ps.m' to pass again. llvm-svn: 76497
-rw-r--r--clang/lib/Analysis/RegionStore.cpp61
-rw-r--r--clang/test/Analysis/misc-ps.m1
2 files changed, 48 insertions, 14 deletions
diff --git a/clang/lib/Analysis/RegionStore.cpp b/clang/lib/Analysis/RegionStore.cpp
index 0d2467f55e0..247c6040c81 100644
--- a/clang/lib/Analysis/RegionStore.cpp
+++ b/clang/lib/Analysis/RegionStore.cpp
@@ -286,6 +286,10 @@ public:
SVal RetrieveField(const GRState *state, const FieldRegion *R);
SVal RetrieveObjCIvar(const GRState *state, const ObjCIvarRegion *R);
+
+ SVal RetrieveLazySymbol(const GRState *state, const TypedRegion *R);
+
+ SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy);
/// Retrieve the values in a struct and return a CompoundVal, used when doing
/// struct copy:
@@ -758,7 +762,20 @@ static bool IsReinterpreted(QualType RTy, QualType UsedTy, ASTContext &Ctx) {
if (RTy == UsedTy)
return false;
- return !(Loc::IsLocType(RTy) && Loc::IsLocType(UsedTy));
+
+ // Recursively check the types. We basically want to see if a pointer value
+ // is ever reinterpreted as a non-pointer, e.g. void** and intptr_t*
+ // represents a reinterpretation.
+ if (Loc::IsLocType(RTy) && Loc::IsLocType(UsedTy)) {
+ const PointerType *PRTy = RTy->getAsPointerType();
+ const PointerType *PUsedTy = UsedTy->getAsPointerType();
+
+ return PUsedTy && PRTy &&
+ IsReinterpreted(PRTy->getPointeeType(),
+ PUsedTy->getPointeeType(), Ctx);
+ }
+
+ return true;
}
SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
@@ -823,11 +840,14 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
return UnknownVal();
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
- return RetrieveField(state, FR);
+ return CastRetrievedVal(RetrieveField(state, FR), FR, T);
if (const ElementRegion* ER = dyn_cast<ElementRegion>(R))
- return RetrieveElement(state, ER);
+ return CastRetrievedVal(RetrieveElement(state, ER), ER, T);
+ if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R))
+ return CastRetrievedVal(RetrieveObjCIvar(state, IVR), IVR, T);
+
RegionBindingsTy B = GetRegionBindings(state->getStore());
RegionBindingsTy::data_type* V = B.lookup(R);
@@ -835,9 +855,6 @@ SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
if (V)
return *V;
- if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R))
- return RetrieveObjCIvar(state, IVR);
-
// The location does not have a bound value. This means that it has
// the value it had upon its creation and/or entry to the analyzed
// function/method. These are either symbolic values or 'undefined'.
@@ -986,8 +1003,6 @@ SVal RegionStoreManager::RetrieveField(const GRState* state,
SVal RegionStoreManager::RetrieveObjCIvar(const GRState* state,
const ObjCIvarRegion* R) {
- QualType Ty = R->getValueType(getContext());
-
// Check if the region has a binding.
RegionBindingsTy B = GetRegionBindings(state->getStore());
@@ -1005,18 +1020,29 @@ SVal RegionStoreManager::RetrieveObjCIvar(const GRState* state,
return UnknownVal();
}
+ return RetrieveLazySymbol(state, R);
+}
+
+SVal RegionStoreManager::RetrieveLazySymbol(const GRState *state,
+ const TypedRegion *R) {
+
+ QualType valTy = R->getValueType(getContext());
+
// If the region is already cast to another type, use that type to create the
// symbol value.
- if (const QualType *p = state->get<RegionCasts>(R)) {
- QualType tmp = *p;
- Ty = tmp->getAsPointerType()->getPointeeType();
+ if (const QualType *ty = state->get<RegionCasts>(R)) {
+ if (const PointerType *PT = (*ty)->getAsPointerType()) {
+ QualType castTy = PT->getPointeeType();
+
+ if (!IsReinterpreted(valTy, castTy, getContext()))
+ valTy = castTy;
+ }
}
// All other values are symbolic.
- return ValMgr.getRegionValueSymbolValOrUnknown(R, Ty);
+ return ValMgr.getRegionValueSymbolValOrUnknown(R, valTy);
}
-
SVal RegionStoreManager::RetrieveStruct(const GRState *state,
const TypedRegion* R){
QualType T = R->getValueType(getContext());
@@ -1064,6 +1090,15 @@ SVal RegionStoreManager::RetrieveArray(const GRState *state,
return ValMgr.makeCompoundVal(T, ArrayVal);
}
+SVal RegionStoreManager::CastRetrievedVal(SVal V, const TypedRegion *R,
+ QualType castTy) {
+
+ if (castTy.isNull() || R->getValueType(getContext()) == castTy)
+ return V;
+
+ return ValMgr.getSValuator().EvalCast(V, castTy);
+}
+
//===----------------------------------------------------------------------===//
// Binding values to regions.
//===----------------------------------------------------------------------===//
diff --git a/clang/test/Analysis/misc-ps.m b/clang/test/Analysis/misc-ps.m
index dfae22b37a6..4f97464830b 100644
--- a/clang/test/Analysis/misc-ps.m
+++ b/clang/test/Analysis/misc-ps.m
@@ -4,7 +4,6 @@
// RUN: clang-cc -analyze -checker-cfref --analyzer-store=basic-old-cast -analyzer-constraints=range --verify -fblocks %s &&
// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=basic --verify -fblocks %s &&
// RUN: clang-cc -analyze -checker-cfref --analyzer-store=region -analyzer-constraints=range --verify -fblocks %s
-// XFAIL
typedef struct objc_selector *SEL;
typedef signed char BOOL;
OpenPOWER on IntegriCloud