[cfe-commits] r76641 - in /cfe/trunk: include/clang/Analysis/PathSensitive/GRExprEngine.h include/clang/Analysis/PathSensitive/GRState.h include/clang/Analysis/PathSensitive/SValuator.h include/clang/Analysis/PathSensitive/Store.h include/clang/Analysis/PathSensitive/ValueManager.h lib/Analysis/BasicStore.cpp lib/Analysis/CMakeLists.txt lib/Analysis/GRExprEngine.cpp lib/Analysis/RegionStore.cpp lib/Analysis/SValuator.cpp lib/Analysis/SimpleSValuator.cpp lib/Analysis/ValueManager.cpp test/Analysis/misc-ps.m
Ted Kremenek
kremenek at apple.com
Tue Jul 21 14:03:30 PDT 2009
Author: kremenek
Date: Tue Jul 21 16:03:30 2009
New Revision: 76641
URL: http://llvm.org/viewvc/llvm-project?rev=76641&view=rev
Log:
Fix PR 4594 by refactoring almost all casting logic from GRExprEngine::VisitCast
to SValuator::EvalCast. In the process, the StoreManagers now use this new cast
machinery, and the hack in GRExprEngine::EvalBind to handle implicit casts
involving OSAtomicCompareAndSwap and friends has been removed (and replaced with
logic closer to the logic specific to those functions).
Added:
cfe/trunk/lib/Analysis/SValuator.cpp
Modified:
cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
cfe/trunk/include/clang/Analysis/PathSensitive/SValuator.h
cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
cfe/trunk/include/clang/Analysis/PathSensitive/ValueManager.h
cfe/trunk/lib/Analysis/BasicStore.cpp
cfe/trunk/lib/Analysis/CMakeLists.txt
cfe/trunk/lib/Analysis/GRExprEngine.cpp
cfe/trunk/lib/Analysis/RegionStore.cpp
cfe/trunk/lib/Analysis/SimpleSValuator.cpp
cfe/trunk/lib/Analysis/ValueManager.cpp
cfe/trunk/test/Analysis/misc-ps.m
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRExprEngine.h Tue Jul 21 16:03:30 2009
@@ -228,6 +228,8 @@
/// getCFG - Returns the CFG associated with this analysis.
CFG& getCFG() { return G.getCFG(); }
+ SValuator &getSValuator() { return SVator; }
+
GRTransferFuncs& getTF() { return *StateMgr.TF; }
BugReporter& getBugReporter() { return BR; }
@@ -532,11 +534,6 @@
/// VisitCast - Transfer function logic for all casts (implicit and explicit).
void VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst);
- /// VisitCastPointerToInteger - Transfer function (called by VisitCast) that
- /// handles pointer to integer casts and array to integer casts.
- void VisitCastPointerToInteger(SVal V, const GRState* state, QualType PtrTy,
- Expr* CastE, NodeTy* Pred, NodeSet& Dst);
-
/// VisitCompoundLiteralExpr - Transfer function logic for compound literals.
void VisitCompoundLiteralExpr(CompoundLiteralExpr* CL, NodeTy* Pred,
NodeSet& Dst, bool asLValue);
@@ -600,11 +597,7 @@
/// expressions of the form 'x != 0' and generate new nodes (stored in Dst)
/// with those assumptions.
void EvalEagerlyAssume(NodeSet& Dst, NodeSet& Src, Expr *Ex);
-
- SVal EvalCast(SVal X, QualType CastT) {
- return SVator.EvalCast(X, CastT);
- }
-
+
SVal EvalMinus(SVal X) {
return X.isValid() ? SVator.EvalMinus(cast<NonLoc>(X)) : X;
}
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/GRState.h Tue Jul 21 16:03:30 2009
@@ -450,7 +450,7 @@
: EnvMgr(alloc),
ISetFactory(alloc),
GDMFactory(alloc),
- ValueMgr(alloc, Ctx),
+ ValueMgr(alloc, Ctx, *this),
Alloc(alloc),
cfg(c),
codedecl(cd),
@@ -693,11 +693,11 @@
}
inline SVal GRState::getSVal(Loc LV, QualType T) const {
- return Mgr->StoreMgr->Retrieve(this, LV, T);
+ return Mgr->StoreMgr->Retrieve(this, LV, T).getSVal();
}
inline SVal GRState::getSVal(const MemRegion* R) const {
- return Mgr->StoreMgr->Retrieve(this, loc::MemRegionVal(R));
+ return Mgr->StoreMgr->Retrieve(this, loc::MemRegionVal(R)).getSVal();
}
inline BasicValueFactory &GRState::getBasicVals() const {
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/SValuator.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/SValuator.h?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/SValuator.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/SValuator.h Tue Jul 21 16:03:30 2009
@@ -24,24 +24,28 @@
class ValueManager;
class SValuator {
+ friend class ValueManager;
protected:
ValueManager &ValMgr;
+
+ virtual SVal EvalCastNL(NonLoc val, QualType castTy) = 0;
+ virtual SVal EvalCastL(Loc val, QualType castTy) = 0;
+
public:
SValuator(ValueManager &valMgr) : ValMgr(valMgr) {}
virtual ~SValuator() {}
- virtual SVal EvalCastNL(NonLoc val, QualType castTy) = 0;
-
- virtual SVal EvalCastL(Loc val, QualType castTy) = 0;
+ class CastResult : public std::pair<const GRState *, SVal> {
+ public:
+ const GRState *getState() const { return first; }
+ SVal getSVal() const { return second; }
+ CastResult(const GRState *s, SVal v)
+ : std::pair<const GRState*, SVal>(s, v) {}
+ };
- SVal EvalCast(SVal val, QualType castTy) {
- if (val.isUnknownOrUndef())
- return val;
-
- return isa<Loc>(val) ? EvalCastL(cast<Loc>(val), castTy)
- : EvalCastNL(cast<NonLoc>(val), castTy);
- }
+ CastResult EvalCast(SVal val, const GRState *state,
+ QualType castTy, QualType originalType);
virtual SVal EvalMinus(NonLoc val) = 0;
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/Store.h?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/Store.h Tue Jul 21 16:03:30 2009
@@ -61,8 +61,8 @@
/// expected type of the returned value. This is used if the value is
/// lazily computed.
/// \return The value bound to the location \c loc.
- virtual SVal Retrieve(const GRState *state, Loc loc,
- QualType T = QualType()) = 0;
+ virtual SValuator::CastResult Retrieve(const GRState *state, Loc loc,
+ QualType T = QualType()) = 0;
/// Return a state with the specified value bound to the given location.
/// \param[in] state The analysis state.
Modified: cfe/trunk/include/clang/Analysis/PathSensitive/ValueManager.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Analysis/PathSensitive/ValueManager.h?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/include/clang/Analysis/PathSensitive/ValueManager.h (original)
+++ cfe/trunk/include/clang/Analysis/PathSensitive/ValueManager.h Tue Jul 21 16:03:30 2009
@@ -26,6 +26,9 @@
namespace llvm { class BumpPtrAllocator; }
namespace clang {
+
+class GRStateManager;
+
class ValueManager {
ASTContext &Context;
@@ -39,14 +42,17 @@
MemRegionManager MemMgr;
+ GRStateManager &StateMgr;
+
const QualType ArrayIndexTy;
const unsigned ArrayIndexWidth;
public:
- ValueManager(llvm::BumpPtrAllocator &alloc, ASTContext &context)
+ ValueManager(llvm::BumpPtrAllocator &alloc, ASTContext &context,
+ GRStateManager &stateMgr)
: Context(context), BasicVals(Context, alloc),
SymMgr(Context, BasicVals, alloc),
- MemMgr(Context, alloc),
+ MemMgr(Context, alloc), StateMgr(stateMgr),
ArrayIndexTy(Context.IntTy),
ArrayIndexWidth(Context.getTypeSize(ArrayIndexTy))
{
@@ -59,6 +65,8 @@
ASTContext &getContext() { return Context; }
const ASTContext &getContext() const { return Context; }
+ GRStateManager &getStateManager() { return StateMgr; }
+
BasicValueFactory &getBasicValueFactory() { return BasicVals; }
const BasicValueFactory &getBasicValueFactory() const { return BasicVals; }
Modified: cfe/trunk/lib/Analysis/BasicStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/BasicStore.cpp?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/BasicStore.cpp (original)
+++ cfe/trunk/lib/Analysis/BasicStore.cpp Tue Jul 21 16:03:30 2009
@@ -49,7 +49,8 @@
return new BasicStoreSubRegionMap();
}
- SVal Retrieve(const GRState *state, Loc loc, QualType T = QualType());
+ SValuator::CastResult Retrieve(const GRState *state, Loc loc,
+ QualType T = QualType());
const GRState *Bind(const GRState *state, Loc L, SVal V) {
return state->makeWithStore(BindInternal(state->getStore(), L, V));
@@ -269,10 +270,11 @@
}
}
-SVal BasicStoreManager::Retrieve(const GRState *state, Loc loc, QualType T) {
+SValuator::CastResult BasicStoreManager::Retrieve(const GRState *state,
+ Loc loc, QualType T) {
if (isa<UnknownVal>(loc))
- return UnknownVal();
+ return SValuator::CastResult(state, UnknownVal());
assert (!isa<UndefinedVal>(loc));
@@ -288,7 +290,7 @@
QualType T = ER->getLocationType(Ctx);
if (!isHigherOrderRawPtr(T, Ctx))
- return UnknownVal();
+ return SValuator::CastResult(state, UnknownVal());
// FIXME: Should check for element 0.
// Otherwise, strip the element region.
@@ -296,25 +298,25 @@
}
if (!(isa<VarRegion>(R) || isa<ObjCIvarRegion>(R)))
- return UnknownVal();
+ return SValuator::CastResult(state, UnknownVal());
BindingsTy B = GetBindings(state->getStore());
BindingsTy::data_type* T = B.lookup(R);
- return T ? *T : UnknownVal();
+ return SValuator::CastResult(state, T ? *T : UnknownVal());
}
case loc::ConcreteIntKind:
// Some clients may call GetSVal with such an option simply because
// they are doing a quick scan through their Locs (potentially to
// invalidate their bindings). Just return Undefined.
- return UndefinedVal();
+ return SValuator::CastResult(state, UndefinedVal());
default:
assert (false && "Invalid Loc.");
break;
}
- return UnknownVal();
+ return SValuator::CastResult(state, UnknownVal());
}
Store BasicStoreManager::BindInternal(Store store, Loc loc, SVal V) {
@@ -426,8 +428,8 @@
if (Marked.count(MR))
break;
- Marked.insert(MR);
- SVal X = Retrieve(state, loc::MemRegionVal(MR));
+ Marked.insert(MR);
+ SVal X = Retrieve(state, loc::MemRegionVal(MR)).getSVal();
// FIXME: We need to handle symbols nested in region definitions.
for (symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end();SI!=SE;++SI)
Modified: cfe/trunk/lib/Analysis/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/CMakeLists.txt?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/CMakeLists.txt (original)
+++ cfe/trunk/lib/Analysis/CMakeLists.txt Tue Jul 21 16:03:30 2009
@@ -27,6 +27,7 @@
RangeConstraintManager.cpp
RegionStore.cpp
SVals.cpp
+ SValuator.cpp
SimpleConstraintManager.cpp
SimpleSValuator.cpp
Store.cpp
Modified: cfe/trunk/lib/Analysis/GRExprEngine.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/GRExprEngine.cpp?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/GRExprEngine.cpp (original)
+++ cfe/trunk/lib/Analysis/GRExprEngine.cpp Tue Jul 21 16:03:30 2009
@@ -1036,7 +1036,7 @@
/// EvalBind - Handle the semantics of binding a value to a specific location.
/// This method is used by EvalStore and (soon) VisitDeclStmt, and others.
void GRExprEngine::EvalBind(NodeSet& Dst, Expr* Ex, NodeTy* Pred,
- const GRState* state, SVal location, SVal Val) {
+ const GRState* state, SVal location, SVal Val) {
const GRState* newState = 0;
@@ -1049,24 +1049,7 @@
else {
// We are binding to a value other than 'unknown'. Perform the binding
// using the StoreManager.
- Loc L = cast<Loc>(location);
-
- // Handle implicit casts not reflected in the AST. This can be due to
- // custom checker logic such as what handles OSAtomicCompareAndSwap.
- if (!Val.isUnknownOrUndef())
- if (const TypedRegion *R =
- dyn_cast_or_null<TypedRegion>(L.getAsRegion())) {
- assert(R->isBoundable());
- QualType ValTy = R->getValueType(getContext());
- if (Loc::IsLocType(ValTy)) {
- if (!isa<Loc>(Val))
- Val = SVator.EvalCastNL(cast<NonLoc>(Val), ValTy);
- }
- else if (!isa<NonLoc>(Val))
- Val = SVator.EvalCastL(cast<Loc>(Val), ValTy);
- }
-
- newState = state->bindLoc(L, Val);
+ newState = state->bindLoc(cast<Loc>(location), Val);
}
// The next thing to do is check if the GRTransferFuncs object wants to
@@ -1343,8 +1326,18 @@
if (stateEqual) {
// Perform the store.
ExplodedNodeSet<GRState> TmpStore;
+ SVal val = stateEqual->getSVal(newValueExpr);
+
+ // Handle implicit value casts.
+ if (const TypedRegion *R =
+ dyn_cast_or_null<TypedRegion>(location.getAsRegion())) {
+ llvm::tie(state, val) =
+ Engine.getSValuator().EvalCast(val, state, R->getValueType(C),
+ newValueExpr->getType());
+ }
+
Engine.EvalStore(TmpStore, theValueExpr, N, stateEqual, location,
- stateEqual->getSVal(newValueExpr), OSAtomicStoreTag);
+ val, OSAtomicStoreTag);
// Now bind the result of the comparison.
for (ExplodedNodeSet<GRState>::iterator I2 = TmpStore.begin(),
@@ -2034,22 +2027,6 @@
// Transfer functions: Miscellaneous statements.
//===----------------------------------------------------------------------===//
-void GRExprEngine::VisitCastPointerToInteger(SVal V, const GRState* state,
- QualType PtrTy,
- Expr* CastE, NodeTy* Pred,
- NodeSet& Dst) {
- if (!V.isUnknownOrUndef()) {
- // FIXME: Determine if the number of bits of the target type is
- // equal or exceeds the number of bits to store the pointer value.
- // If not, flag an error.
- MakeNode(Dst, CastE, Pred, state->bindExpr(CastE, EvalCast(cast<Loc>(V),
- CastE->getType())));
- }
- else
- MakeNode(Dst, CastE, Pred, state->bindExpr(CastE, V));
-}
-
-
void GRExprEngine::VisitCast(Expr* CastE, Expr* Ex, NodeTy* Pred, NodeSet& Dst){
NodeSet S1;
QualType T = CastE->getType();
@@ -2070,128 +2047,14 @@
return;
}
-
- // FIXME: The rest of this should probably just go into EvalCall, and
- // let the transfer function object be responsible for constructing
- // nodes.
-
+
for (NodeSet::iterator I1 = S1.begin(), E1 = S1.end(); I1 != E1; ++I1) {
NodeTy* N = *I1;
const GRState* state = GetState(N);
SVal V = state->getSVal(Ex);
- ASTContext& C = getContext();
-
- // Unknown?
- if (V.isUnknown()) {
- Dst.Add(N);
- continue;
- }
-
- // Undefined?
- if (V.isUndef())
- goto PassThrough;
-
- // For const casts, just propagate the value.
- if (C.getCanonicalType(T).getUnqualifiedType() ==
- C.getCanonicalType(ExTy).getUnqualifiedType())
- goto PassThrough;
-
- // Check for casts from pointers to integers.
- if (T->isIntegerType() && Loc::IsLocType(ExTy)) {
- VisitCastPointerToInteger(V, state, ExTy, CastE, N, Dst);
- continue;
- }
-
- // Check for casts from integers to pointers.
- if (Loc::IsLocType(T) && ExTy->isIntegerType()) {
- if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&V)) {
- // Just unpackage the lval and return it.
- V = LV->getLoc();
- MakeNode(Dst, CastE, N, state->bindExpr(CastE, V));
- continue;
- }
-
- goto DispatchCast;
- }
-
- // Just pass through function and block pointers.
- if (ExTy->isBlockPointerType() || ExTy->isFunctionPointerType()) {
- assert(Loc::IsLocType(T));
- goto PassThrough;
- }
-
- // Check for casts from array type to another type.
- if (ExTy->isArrayType()) {
- // We will always decay to a pointer.
- V = StateMgr.ArrayToPointer(cast<Loc>(V));
-
- // Are we casting from an array to a pointer? If so just pass on
- // the decayed value.
- if (T->isPointerType())
- goto PassThrough;
-
- // Are we casting from an array to an integer? If so, cast the decayed
- // pointer value to an integer.
- assert(T->isIntegerType());
- QualType ElemTy = cast<ArrayType>(ExTy)->getElementType();
- QualType PointerTy = getContext().getPointerType(ElemTy);
- VisitCastPointerToInteger(V, state, PointerTy, CastE, N, Dst);
- continue;
- }
-
- // Check for casts from a region to a specific type.
- if (loc::MemRegionVal *RV = dyn_cast<loc::MemRegionVal>(&V)) {
- // FIXME: For TypedViewRegions, we should handle the case where the
- // underlying symbolic pointer is a function pointer or
- // block pointer.
-
- // FIXME: We should handle the case where we strip off view layers to get
- // to a desugared type.
-
- assert(Loc::IsLocType(T));
- // We get a symbolic function pointer for a dereference of a function
- // pointer, but it is of function type. Example:
-
- // struct FPRec {
- // void (*my_func)(int * x);
- // };
- //
- // int bar(int x);
- //
- // int f1_a(struct FPRec* foo) {
- // int x;
- // (*foo->my_func)(&x);
- // return bar(x)+1; // no-warning
- // }
-
- assert(Loc::IsLocType(ExTy) || ExTy->isFunctionType());
-
- 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(state, 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, Res.getState()->bindExpr(CastE, V));
- continue;
- }
- // All other cases.
- DispatchCast: {
- MakeNode(Dst, CastE, N, state->bindExpr(CastE,
- EvalCast(V, CastE->getType())));
- continue;
- }
-
- PassThrough: {
- MakeNode(Dst, CastE, N, state->bindExpr(CastE, V));
- }
+ const SValuator::CastResult &Res = SVator.EvalCast(V, state, T, ExTy);
+ state = Res.getState()->bindExpr(CastE, Res.getSVal());
+ MakeNode(Dst, CastE, N, state);
}
}
@@ -3034,17 +2897,19 @@
// The RHS is not Unknown.
// Get the computation type.
- QualType CTy = cast<CompoundAssignOperator>(B)->getComputationResultType();
+ QualType CTy =
+ cast<CompoundAssignOperator>(B)->getComputationResultType();
CTy = getContext().getCanonicalType(CTy);
- QualType CLHSTy = cast<CompoundAssignOperator>(B)->getComputationLHSType();
- CLHSTy = getContext().getCanonicalType(CTy);
+ QualType CLHSTy =
+ cast<CompoundAssignOperator>(B)->getComputationLHSType();
+ CLHSTy = getContext().getCanonicalType(CLHSTy);
QualType LTy = getContext().getCanonicalType(LHS->getType());
QualType RTy = getContext().getCanonicalType(RHS->getType());
// Promote LHS.
- V = EvalCast(V, CLHSTy);
+ llvm::tie(state, V) = SVator.EvalCast(V, state, CLHSTy, LTy);
// Evaluate operands and promote to result type.
if (RightV.isUndef()) {
@@ -3055,8 +2920,10 @@
}
// Compute the result of the operation.
- SVal Result = EvalCast(EvalBinOp(state, Op, V, RightV, CTy),
- B->getType());
+ SVal Result;
+ llvm::tie(state, Result) = SVator.EvalCast(EvalBinOp(state, Op, V,
+ RightV, CTy),
+ state, B->getType(), CTy);
if (Result.isUndef()) {
// The operands were not undefined, but the result is undefined.
@@ -3085,12 +2952,12 @@
LHSVal = ValMgr.getConjuredSymbolVal(B->getRHS(), LTy, Count);
// However, we need to convert the symbol to the computation type.
- Result = (LTy == CTy) ? LHSVal : EvalCast(LHSVal,CTy);
+ llvm::tie(state, Result) = SVator.EvalCast(LHSVal, state, CTy, LTy);
}
else {
// The left-hand side may bind to a different value then the
// computation type.
- LHSVal = (LTy == CTy) ? Result : EvalCast(Result,LTy);
+ llvm::tie(state, LHSVal) = SVator.EvalCast(Result, state, LTy, CTy);
}
EvalStore(Dst, B, LHS, *I3, state->bindExpr(B, Result), location,
Modified: cfe/trunk/lib/Analysis/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/RegionStore.cpp?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/RegionStore.cpp (original)
+++ cfe/trunk/lib/Analysis/RegionStore.cpp Tue Jul 21 16:03:30 2009
@@ -279,7 +279,8 @@
/// return undefined
/// else
/// return symbolic
- SVal Retrieve(const GRState *state, Loc L, QualType T = QualType());
+ SValuator::CastResult Retrieve(const GRState *state, Loc L,
+ QualType T = QualType());
SVal RetrieveElement(const GRState *state, const ElementRegion *R);
@@ -291,7 +292,8 @@
SVal RetrieveLazySymbol(const GRState *state, const TypedRegion *R);
- SVal CastRetrievedVal(SVal val, const TypedRegion *R, QualType castTy);
+ SValuator::CastResult CastRetrievedVal(SVal val, const GRState *state,
+ const TypedRegion *R, QualType castTy);
/// Retrieve the values in a struct and return a CompoundVal, used when doing
/// struct copy:
@@ -780,7 +782,8 @@
return true;
}
-SVal RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
+SValuator::CastResult
+RegionStoreManager::Retrieve(const GRState *state, Loc L, QualType T) {
assert(!isa<UnknownVal>(L) && "location unknown");
assert(!isa<UndefinedVal>(L) && "location undefined");
@@ -788,7 +791,7 @@
// FIXME: Is this even possible? Shouldn't this be treated as a null
// dereference at a higher level?
if (isa<loc::ConcreteInt>(L))
- return UndefinedVal();
+ return SValuator::CastResult(state, UndefinedVal());
const MemRegion *MR = cast<loc::MemRegionVal>(L).getRegion();
@@ -799,7 +802,7 @@
// read(p);
// c = *p;
if (isa<AllocaRegion>(MR))
- return UnknownVal();
+ return SValuator::CastResult(state, UnknownVal());
if (isa<SymbolicRegion>(MR)) {
ASTContext &Ctx = getContext();
@@ -832,33 +835,33 @@
}
if (RTy->isStructureType())
- return RetrieveStruct(state, R);
+ return SValuator::CastResult(state, RetrieveStruct(state, R));
if (RTy->isArrayType())
- return RetrieveArray(state, R);
+ return SValuator::CastResult(state, RetrieveArray(state, R));
// FIXME: handle Vector types.
if (RTy->isVectorType())
- return UnknownVal();
+ return SValuator::CastResult(state, UnknownVal());
if (const FieldRegion* FR = dyn_cast<FieldRegion>(R))
- return CastRetrievedVal(RetrieveField(state, FR), FR, T);
+ return CastRetrievedVal(RetrieveField(state, FR), state, FR, T);
if (const ElementRegion* ER = dyn_cast<ElementRegion>(R))
- return CastRetrievedVal(RetrieveElement(state, ER), ER, T);
+ return CastRetrievedVal(RetrieveElement(state, ER), state, ER, T);
if (const ObjCIvarRegion *IVR = dyn_cast<ObjCIvarRegion>(R))
- return CastRetrievedVal(RetrieveObjCIvar(state, IVR), IVR, T);
+ return CastRetrievedVal(RetrieveObjCIvar(state, IVR), state, IVR, T);
if (const VarRegion *VR = dyn_cast<VarRegion>(R))
- return CastRetrievedVal(RetrieveVar(state, VR), VR, T);
+ return CastRetrievedVal(RetrieveVar(state, VR), state, VR, T);
RegionBindingsTy B = GetRegionBindings(state->getStore());
RegionBindingsTy::data_type* V = B.lookup(R);
// Check if the region has a binding.
if (V)
- return *V;
+ return SValuator::CastResult(state, *V);
// 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
@@ -870,7 +873,7 @@
// upon creation. All heap allocated blocks are considered to
// have undefined values as well unless they are explicitly bound
// to specific values.
- return UndefinedVal();
+ return SValuator::CastResult(state, UndefinedVal());
}
// If the region is already cast to another type, use that type to create the
@@ -881,7 +884,8 @@
}
// All other values are symbolic.
- return ValMgr.getRegionValueSymbolValOrUnknown(R, RTy);
+ return SValuator::CastResult(state,
+ ValMgr.getRegionValueSymbolValOrUnknown(R, RTy));
}
SVal RegionStoreManager::RetrieveElement(const GRState* state,
@@ -1079,7 +1083,7 @@
Field != FieldEnd; ++Field) {
FieldRegion* FR = MRMgr.getFieldRegion(*Field, R);
QualType FTy = (*Field)->getType();
- SVal FieldValue = Retrieve(state, loc::MemRegionVal(FR), FTy);
+ SVal FieldValue = Retrieve(state, loc::MemRegionVal(FR), FTy).getSVal();
StructVal = getBasicVals().consVals(FieldValue, StructVal);
}
@@ -1099,28 +1103,22 @@
ElementRegion* ER = MRMgr.getElementRegion(CAT->getElementType(), Idx, R,
getContext());
QualType ETy = ER->getElementType();
- SVal ElementVal = Retrieve(state, loc::MemRegionVal(ER), ETy);
+ SVal ElementVal = Retrieve(state, loc::MemRegionVal(ER), ETy).getSVal();
ArrayVal = getBasicVals().consVals(ElementVal, ArrayVal);
}
return ValMgr.makeCompoundVal(T, ArrayVal);
}
-SVal RegionStoreManager::CastRetrievedVal(SVal V, const TypedRegion *R,
- QualType castTy) {
-
+SValuator::CastResult RegionStoreManager::CastRetrievedVal(SVal V,
+ const GRState *state,
+ const TypedRegion *R,
+ QualType castTy) {
if (castTy.isNull())
- return V;
+ return SValuator::CastResult(state, V);
ASTContext &Ctx = getContext();
- QualType valTy = R->getValueType(Ctx);
- castTy = Ctx.getCanonicalType(castTy);
-
-
- if (valTy == castTy)
- return V;
-
- return ValMgr.getSValuator().EvalCast(V, castTy);
+ return ValMgr.getSValuator().EvalCast(V, state, castTy, R->getValueType(Ctx));
}
//===----------------------------------------------------------------------===//
Added: cfe/trunk/lib/Analysis/SValuator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/SValuator.cpp?rev=76641&view=auto
==============================================================================
--- cfe/trunk/lib/Analysis/SValuator.cpp (added)
+++ cfe/trunk/lib/Analysis/SValuator.cpp Tue Jul 21 16:03:30 2009
@@ -0,0 +1,123 @@
+// SValuator.cpp - Basic class for all SValuator implementations --*- 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 SValuator, the base class for all (complete) SValuator
+// implementations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "clang/Analysis/PathSensitive/SValuator.h"
+#include "clang/Analysis/PathSensitive/GRState.h"
+
+using namespace clang;
+
+SValuator::CastResult SValuator::EvalCast(SVal val, const GRState *state,
+ QualType castTy, QualType originalTy){
+
+ if (val.isUnknownOrUndef() || castTy == originalTy)
+ return CastResult(state, val);
+
+ ASTContext &C = ValMgr.getContext();
+
+ // For const casts, just propagate the value.
+ if (C.getCanonicalType(castTy).getUnqualifiedType() ==
+ C.getCanonicalType(originalTy).getUnqualifiedType())
+ return CastResult(state, val);
+
+ // Check for casts from pointers to integers.
+ if (castTy->isIntegerType() && Loc::IsLocType(originalTy))
+ return CastResult(state, EvalCastL(cast<Loc>(val), castTy));
+
+ // Check for casts from integers to pointers.
+ if (Loc::IsLocType(castTy) && originalTy->isIntegerType()) {
+ if (nonloc::LocAsInteger *LV = dyn_cast<nonloc::LocAsInteger>(&val)) {
+ // Just unpackage the lval and return it.
+ return CastResult(state, LV->getLoc());
+ }
+
+ goto DispatchCast;
+ }
+
+ // Just pass through function and block pointers.
+ if (originalTy->isBlockPointerType() || originalTy->isFunctionPointerType()) {
+ assert(Loc::IsLocType(castTy));
+ return CastResult(state, val);
+ }
+
+ // Check for casts from array type to another type.
+ if (originalTy->isArrayType()) {
+ // We will always decay to a pointer.
+ val = ValMgr.getStateManager().ArrayToPointer(cast<Loc>(val));
+
+ // Are we casting from an array to a pointer? If so just pass on
+ // the decayed value.
+ if (castTy->isPointerType())
+ return CastResult(state, val);
+
+ // Are we casting from an array to an integer? If so, cast the decayed
+ // pointer value to an integer.
+ assert(castTy->isIntegerType());
+
+ // FIXME: Keep these here for now in case we decide soon that we
+ // need the original decayed type.
+ // QualType elemTy = cast<ArrayType>(originalTy)->getElementType();
+ // QualType pointerTy = C.getPointerType(elemTy);
+ return CastResult(state, EvalCastL(cast<Loc>(val), castTy));
+ }
+
+ // Check for casts from a region to a specific type.
+ if (const MemRegion *R = val.getAsRegion()) {
+ // FIXME: For TypedViewRegions, we should handle the case where the
+ // underlying symbolic pointer is a function pointer or
+ // block pointer.
+
+ // FIXME: We should handle the case where we strip off view layers to get
+ // to a desugared type.
+
+ assert(Loc::IsLocType(castTy));
+ // We get a symbolic function pointer for a dereference of a function
+ // pointer, but it is of function type. Example:
+
+ // struct FPRec {
+ // void (*my_func)(int * x);
+ // };
+ //
+ // int bar(int x);
+ //
+ // int f1_a(struct FPRec* foo) {
+ // int x;
+ // (*foo->my_func)(&x);
+ // return bar(x)+1; // no-warning
+ // }
+
+ assert(Loc::IsLocType(originalTy) || originalTy->isFunctionType() ||
+ originalTy->isBlockPointerType());
+
+ StoreManager &storeMgr = ValMgr.getStateManager().getStoreManager();
+
+ // Delegate to store manager to get the result of casting a region
+ // to a different type.
+ const StoreManager::CastResult& Res = storeMgr.CastRegion(state, R, castTy);
+
+ // Inspect the result. If the MemRegion* returned is NULL, this
+ // expression evaluates to UnknownVal.
+ R = Res.getRegion();
+
+ if (R)
+ return CastResult(Res.getState(), loc::MemRegionVal(R));
+
+ return CastResult(Res.getState(), UnknownVal());
+ }
+
+ // All other cases.
+DispatchCast:
+ return CastResult(state,
+ isa<Loc>(val) ? EvalCastL(cast<Loc>(val), castTy)
+ : EvalCastNL(cast<NonLoc>(val), castTy));
+}
\ No newline at end of file
Modified: cfe/trunk/lib/Analysis/SimpleSValuator.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/SimpleSValuator.cpp?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/SimpleSValuator.cpp (original)
+++ cfe/trunk/lib/Analysis/SimpleSValuator.cpp Tue Jul 21 16:03:30 2009
@@ -19,12 +19,14 @@
namespace {
class VISIBILITY_HIDDEN SimpleSValuator : public SValuator {
+protected:
+ virtual SVal EvalCastNL(NonLoc val, QualType castTy);
+ virtual SVal EvalCastL(Loc val, QualType castTy);
+
public:
SimpleSValuator(ValueManager &valMgr) : SValuator(valMgr) {}
virtual ~SimpleSValuator() {}
- virtual SVal EvalCastNL(NonLoc val, QualType castTy);
- virtual SVal EvalCastL(Loc val, QualType castTy);
virtual SVal EvalMinus(NonLoc val);
virtual SVal EvalComplement(NonLoc val);
virtual SVal EvalBinOpNN(BinaryOperator::Opcode op, NonLoc lhs, NonLoc rhs,
Modified: cfe/trunk/lib/Analysis/ValueManager.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Analysis/ValueManager.cpp?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/lib/Analysis/ValueManager.cpp (original)
+++ cfe/trunk/lib/Analysis/ValueManager.cpp Tue Jul 21 16:03:30 2009
@@ -56,6 +56,9 @@
SVal ValueManager::convertToArrayIndex(SVal V) {
+ if (V.isUnknownOrUndef())
+ return V;
+
// Common case: we have an appropriately sized integer.
if (nonloc::ConcreteInt* CI = dyn_cast<nonloc::ConcreteInt>(&V)) {
const llvm::APSInt& I = CI->getValue();
@@ -63,7 +66,7 @@
return V;
}
- return SVator->EvalCast(V, ArrayIndexTy);
+ return SVator->EvalCastNL(cast<NonLoc>(V), ArrayIndexTy);
}
SVal ValueManager::getRegionValueSymbolVal(const MemRegion* R, QualType T) {
Modified: cfe/trunk/test/Analysis/misc-ps.m
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/misc-ps.m?rev=76641&r1=76640&r2=76641&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/misc-ps.m (original)
+++ cfe/trunk/test/Analysis/misc-ps.m Tue Jul 21 16:03:30 2009
@@ -437,7 +437,6 @@
(void (^)(void *))test_block_cast_aux(); // expected-warning{{expression result unused}}
}
-// ** THIS TEST FAILS **
// Test comparison of 'id' instance variable to a null void* constant after
// performing an OSAtomicCompareAndSwap32Barrier.
// This previously was a crash in RegionStoreManager.
@@ -454,5 +453,9 @@
}
@end
-
-
+// PR 4594 - This was a crash when handling casts in SimpleSValuator.
+void PR4594() {
+ char *buf[1];
+ char **foo = buf;
+ *foo = "test";
+}
More information about the cfe-commits
mailing list