From 262fd03ee934bebfbbfaabc14744427dd2e7a231 Mon Sep 17 00:00:00 2001 From: Zhongxing Xu Date: Wed, 20 May 2009 09:00:16 +0000 Subject: [PATCH] * API change: we need to pass GRState to GRExprEngine::EvalBinOp() because RegionStore needs to know the type of alloca region. * RegionStoreManager::EvalBinOp() now converts the alloca region to its first element region, as what is done to symbolic region. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@72164 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../Analysis/PathSensitive/GRExprEngine.h | 3 +- .../Analysis/PathSensitive/GRTransferFuncs.h | 4 +-- include/clang/Analysis/PathSensitive/Store.h | 3 +- lib/Analysis/GRExprEngine.cpp | 30 ++++++++++--------- lib/Analysis/GRSimpleVals.cpp | 6 ++-- lib/Analysis/GRSimpleVals.h | 4 +-- lib/Analysis/RegionStore.cpp | 23 ++++++++++---- test/Analysis/array-struct.c | 1 + 8 files changed, 46 insertions(+), 28 deletions(-) diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index d9556a08ac..2068b1beaa 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -693,7 +693,8 @@ public: void EvalBinOp(GRStateSet& OStates, const GRState* St, Expr* Ex, BinaryOperator::Opcode Op, NonLoc L, NonLoc R, QualType T); - SVal EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R, QualType T); + SVal EvalBinOp(const GRState *state, BinaryOperator::Opcode Op, SVal L,SVal R, + QualType T); protected: diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index bee139f968..0f353d0700 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -67,8 +67,8 @@ public: // Pointer arithmetic. - virtual SVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op, - Loc L, NonLoc R) = 0; + virtual SVal EvalBinOp(GRExprEngine& Engine, const GRState *state, + BinaryOperator::Opcode Op, Loc L, NonLoc R) = 0; // Calls. diff --git a/include/clang/Analysis/PathSensitive/Store.h b/include/clang/Analysis/PathSensitive/Store.h index adcb2f76e0..1f081f4eb0 100644 --- a/include/clang/Analysis/PathSensitive/Store.h +++ b/include/clang/Analysis/PathSensitive/Store.h @@ -137,7 +137,8 @@ public: QualType CastToTy); /// EvalBinOp - Perform pointer arithmetic. - virtual SVal EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R) { + virtual SVal EvalBinOp(const GRState *state, + BinaryOperator::Opcode Op, Loc L, NonLoc R) { return UnknownVal(); } diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index bc6a36c747..e8c5be51d6 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -177,7 +177,7 @@ const GRState* GRExprEngine::getInitialState() { if (T->isIntegerType()) if (const MemRegion *R = StateMgr.getRegion(PD)) { SVal V = GetSVal(state, loc::MemRegionVal(R)); - SVal Constraint = EvalBinOp(BinaryOperator::GT, V, + SVal Constraint = EvalBinOp(state, BinaryOperator::GT, V, ValMgr.makeZeroVal(T), getContext().IntTy); bool isFeasible = false; @@ -841,7 +841,7 @@ void GRExprEngine::ProcessSwitch(SwitchNodeBuilder& builder) { do { nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt())); - SVal Res = EvalBinOp(BinaryOperator::EQ, CondV, CaseVal, + SVal Res = EvalBinOp(DefaultSt, BinaryOperator::EQ, CondV, CaseVal, getContext().IntTy); // Now "assume" that the case matches. @@ -1333,7 +1333,8 @@ static bool EvalOSAtomicCompareAndSwap(ExplodedNodeSet& Dst, SVal oldValueVal = StateMgr.GetSVal(stateLoad, oldValueExpr); // Perform the comparison. - SVal Cmp = Engine.EvalBinOp(BinaryOperator::EQ, theValueVal, oldValueVal, + SVal Cmp = Engine.EvalBinOp(stateLoad, + BinaryOperator::EQ, theValueVal, oldValueVal, Engine.getContext().IntTy); bool isFeasible = false; const GRState *stateEqual = StateMgr.Assume(stateLoad, Cmp, true, @@ -2622,7 +2623,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, if (isa(V)) { Loc X = Loc::MakeNull(getBasicVals()); - SVal Result = EvalBinOp(BinaryOperator::EQ, cast(V), X, + SVal Result = EvalBinOp(state,BinaryOperator::EQ, cast(V), X, U->getType()); state = BindExpr(state, U, Result); } @@ -2679,7 +2680,8 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, BinaryOperator::Opcode Op = U->isIncrementOp() ? BinaryOperator::Add : BinaryOperator::Sub; - SVal Result = EvalBinOp(Op, V2, MakeConstantVal(1U, U), U->getType()); + SVal Result = EvalBinOp(state, Op, V2, MakeConstantVal(1U, U), + U->getType()); // Conjure a new symbol if necessary to recover precision. if (Result.isUnknown() || !getConstraintManager().canReasonAbout(Result)){ @@ -2690,7 +2692,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, // non-nullness. Check if the original value was non-null, and if so propagate // that constraint. if (Loc::IsLocType(U->getType())) { - SVal Constraint = EvalBinOp(BinaryOperator::EQ, V2, + SVal Constraint = EvalBinOp(state, BinaryOperator::EQ, V2, ValMgr.makeZeroVal(U->getType()), getContext().IntTy); @@ -2699,7 +2701,7 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, if (!isFeasible) { // It isn't feasible for the original value to be null. // Propagate this constraint. - Constraint = EvalBinOp(BinaryOperator::EQ, Result, + Constraint = EvalBinOp(state, BinaryOperator::EQ, Result, ValMgr.makeZeroVal(U->getType()), getContext().IntTy); @@ -2965,7 +2967,7 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, // Process non-assignements except commas or short-circuited // logical expressions (LAnd and LOr). - SVal Result = EvalBinOp(Op, LeftV, RightV, B->getType()); + SVal Result = EvalBinOp(state, Op, LeftV, RightV, B->getType()); if (Result.isUnknown()) { if (OldSt != state) { @@ -3079,7 +3081,8 @@ void GRExprEngine::VisitBinaryOperator(BinaryOperator* B, } // Compute the result of the operation. - SVal Result = EvalCast(EvalBinOp(Op, V, RightV, CTy), B->getType()); + SVal Result = EvalCast(EvalBinOp(state, Op, V, RightV, CTy), + B->getType()); if (Result.isUndef()) { // The operands were not undefined, but the result is undefined. @@ -3147,8 +3150,8 @@ void GRExprEngine::EvalBinOp(GRStateSet& OStates, const GRState* state, if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, state, Ex, Op, L, R, T); } -SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R, - QualType T) { +SVal GRExprEngine::EvalBinOp(const GRState* state, BinaryOperator::Opcode Op, + SVal L, SVal R, QualType T) { if (L.isUndef() || R.isUndef()) return UndefinedVal(); @@ -3160,7 +3163,7 @@ SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R, if (isa(R)) return getTF().EvalBinOp(*this, Op, cast(L), cast(R)); else - return getTF().EvalBinOp(*this, Op, cast(L), cast(R)); + return getTF().EvalBinOp(*this, state, Op, cast(L), cast(R)); } if (isa(R)) { @@ -3170,8 +3173,7 @@ SVal GRExprEngine::EvalBinOp(BinaryOperator::Opcode Op, SVal L, SVal R, assert (Op == BinaryOperator::Add || Op == BinaryOperator::Sub); // Commute the operands. - return getTF().EvalBinOp(*this, Op, cast(R), - cast(L)); + return getTF().EvalBinOp(*this, state, Op, cast(R), cast(L)); } else return getTF().DetermEvalBinOpNN(*this, Op, cast(L), diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp index 17e3c381dc..e1c4848f45 100644 --- a/lib/Analysis/GRSimpleVals.cpp +++ b/lib/Analysis/GRSimpleVals.cpp @@ -257,8 +257,8 @@ SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op, } } -SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op, - Loc L, NonLoc R) { +SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, const GRState *state, + BinaryOperator::Opcode Op, Loc L, NonLoc R) { // Special case: 'R' is an integer that has the same width as a pointer and // we are using the integer location in a comparison. Normally this cannot be @@ -280,7 +280,7 @@ SVal GRSimpleVals::EvalBinOp(GRExprEngine& Eng, BinaryOperator::Opcode Op, } // Delegate pointer arithmetic to store manager. - return Eng.getStoreManager().EvalBinOp(Op, L, R); + return Eng.getStoreManager().EvalBinOp(state, Op, L, R); } // Equality operators for Locs. diff --git a/lib/Analysis/GRSimpleVals.h b/lib/Analysis/GRSimpleVals.h index 1258cbc1bf..6ef49dcdd2 100644 --- a/lib/Analysis/GRSimpleVals.h +++ b/lib/Analysis/GRSimpleVals.h @@ -53,8 +53,8 @@ public: // Pointer arithmetic. - virtual SVal EvalBinOp(GRExprEngine& Engine, BinaryOperator::Opcode Op, - Loc L, NonLoc R); + virtual SVal EvalBinOp(GRExprEngine& Engine, const GRState *state, + BinaryOperator::Opcode Op, Loc L, NonLoc R); // Calls. diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index e1d875b8f9..be34bd57b8 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -214,7 +214,7 @@ public: CastResult CastRegion(const GRState* state, const MemRegion* R, QualType CastToTy); - SVal EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R); + SVal EvalBinOp(const GRState *state,BinaryOperator::Opcode Op,Loc L,NonLoc R); /// The high level logic for this method is this: /// Retrieve (L) @@ -636,15 +636,17 @@ RegionStoreManager::CastRegion(const GRState* state, const MemRegion* R, return 0; } -SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R) { +SVal RegionStoreManager::EvalBinOp(const GRState *state, + BinaryOperator::Opcode Op, Loc L, NonLoc R) { // Assume the base location is MemRegionVal. if (!isa(L)) return UnknownVal(); const MemRegion* MR = cast(L).getRegion(); const ElementRegion *ER = 0; - // If the operand is a symbolic region, we convert it to the first element - // region implicitly. + + // If the operand is a symbolic or alloca region, create the first element + // region on it. if (const SymbolicRegion *SR = dyn_cast(MR)) { // Get symbol's type. It should be a pointer type. SymbolRef Sym = SR->getSymbol(); @@ -653,7 +655,18 @@ SVal RegionStoreManager::EvalBinOp(BinaryOperator::Opcode Op, Loc L, NonLoc R) { SVal ZeroIdx = ValMgr.makeZeroArrayIndex(); ER = MRMgr.getElementRegion(EleTy, ZeroIdx, SR); - } else + } + else if (const AllocaRegion *AR = dyn_cast(MR)) { + // Get the alloca region's current cast type. + GRStateRef StRef(state, StateMgr); + + GRStateTrait::lookup_type T = StRef.get(AR); + assert(T && "alloca region has no type."); + QualType EleTy = cast(T->getTypePtr())->getPointeeType(); + SVal ZeroIdx = ValMgr.makeZeroArrayIndex(); + ER = MRMgr.getElementRegion(EleTy, ZeroIdx, AR); + } + else ER = cast(MR); SVal Idx = ER->getIndex(); diff --git a/test/Analysis/array-struct.c b/test/Analysis/array-struct.c index 318f92f907..17c0d46cd9 100644 --- a/test/Analysis/array-struct.c +++ b/test/Analysis/array-struct.c @@ -63,6 +63,7 @@ void f6() { char *p; p = __builtin_alloca(10); p[1] = 'a'; + p += 2; } struct s2; -- 2.40.0