aboutsummaryrefslogtreecommitdiff
path: root/lib/Analysis/BasicStore.cpp
diff options
context:
space:
mode:
authorTed Kremenek <kremenek@apple.com>2009-04-29 16:03:27 +0000
committerTed Kremenek <kremenek@apple.com>2009-04-29 16:03:27 +0000
commit5fa93d5285ed68a0819521f4681755ae696b996f (patch)
treeb907cbacd13d6a1b66ae35b04df8e6820b515546 /lib/Analysis/BasicStore.cpp
parent82539b09e33914861a60f0947500741ace409eb5 (diff)
Add corner case logic to BasicStoreManager and GRSimpleVals::EvalBinOp to enable
reasoning about OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier. Essentially the address of reference to a region (pointer-to-pointer) can be casted to (int32_t*), and we need to handle the logic to convert the involved locations back and forth from nonloc::LocAsInteger, nonloc::ConcreteInt, to Loc and loc::ConcreteInt respectively. This adds some potentially suspect logic to BasicStoreManager that allows the analyzer to reason about abuses of the C type system. This should probably be refined, be ported over to RegionStoreManager, and extended with "path-sensitive type checking" to flag bugs in clearly incoherent code. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@70382 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Analysis/BasicStore.cpp')
-rw-r--r--lib/Analysis/BasicStore.cpp41
1 files changed, 36 insertions, 5 deletions
diff --git a/lib/Analysis/BasicStore.cpp b/lib/Analysis/BasicStore.cpp
index 616c4b5135..c9bf9ea566 100644
--- a/lib/Analysis/BasicStore.cpp
+++ b/lib/Analysis/BasicStore.cpp
@@ -251,7 +251,7 @@ SVal BasicStoreManager::getLValueElement(const GRState* St, SVal Base,
return UnknownVal();
}
-static bool isHigherOrderVoidPtr(QualType T, ASTContext &C) {
+static bool isHigherOrderRawPtr(QualType T, ASTContext &C) {
bool foundPointer = false;
while (1) {
const PointerType *PT = T->getAsPointerType();
@@ -259,6 +259,10 @@ static bool isHigherOrderVoidPtr(QualType T, ASTContext &C) {
if (!foundPointer)
return false;
+ // intptr_t* or intptr_t**, etc?
+ if (T->isIntegerType() && C.getTypeSize(T) == C.getTypeSize(C.VoidPtrTy))
+ return true;
+
QualType X = C.getCanonicalType(T).getUnqualifiedType();
return X == C.VoidTy;
}
@@ -267,7 +271,7 @@ static bool isHigherOrderVoidPtr(QualType T, ASTContext &C) {
T = PT->getPointeeType();
}
}
-
+
SVal BasicStoreManager::Retrieve(const GRState* state, Loc loc, QualType T) {
if (isa<UnknownVal>(loc))
@@ -281,12 +285,12 @@ SVal BasicStoreManager::Retrieve(const GRState* state, Loc loc, QualType T) {
const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
if (const TypedViewRegion *TR = dyn_cast<TypedViewRegion>(R)) {
- // Just support void**, void***, etc., for now. This is needed
- // to handle OSCompareAndSwapPtr().
+ // Just support void**, void***, intptr_t*, intptr_t**, etc., for now.
+ // This is needed to handle OSCompareAndSwapPtr() and friends.
ASTContext &Ctx = StateMgr.getContext();
QualType T = TR->getLValueType(Ctx);
- if (!isHigherOrderVoidPtr(T, Ctx))
+ if (!isHigherOrderRawPtr(T, Ctx))
return UnknownVal();
// Otherwise, strip the views.
@@ -321,6 +325,33 @@ Store BasicStoreManager::BindInternal(Store store, Loc loc, SVal V) {
case loc::MemRegionKind: {
const MemRegion* R = cast<loc::MemRegionVal>(loc).getRegion();
+ // Special case: handle store of pointer values (Loc) to pointers via
+ // a cast to intXX_t*, void*, etc. This is needed to handle
+ // OSCompareAndSwap32Barrier/OSCompareAndSwap64Barrier.
+ if (isa<Loc>(V) || isa<nonloc::LocAsInteger>(V))
+ if (const TypedViewRegion *TR = dyn_cast<TypedViewRegion>(R)) {
+ ASTContext &C = StateMgr.getContext();
+ QualType T = TR->getLValueType(C);
+
+ if (isHigherOrderRawPtr(T, C)) {
+ R = TR->removeViews();
+
+ if (nonloc::LocAsInteger *X = dyn_cast<nonloc::LocAsInteger>(&V)) {
+ // Only convert 'V' to a location iff the underlying region type
+ // is a location as well.
+ // FIXME: We are allowing a store of an arbitrary location to
+ // a pointer. We may wish to flag a type error here if the types
+ // are incompatible. This may also cause lots of breakage
+ // elsewhere. Food for thought.
+ if (const TypedRegion *TyR = dyn_cast<TypedRegion>(R)) {
+ if (TyR->isBoundable(C) &&
+ Loc::IsLocType(TyR->getRValueType(C)))
+ V = X->getLoc();
+ }
+ }
+ }
+ }
+
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
return store;