diff options
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRExprEngine.h | 6 | ||||
-rw-r--r-- | include/clang/Analysis/PathSensitive/GRTransferFuncs.h | 6 | ||||
-rw-r--r-- | lib/Analysis/GRExprEngine.cpp | 16 | ||||
-rw-r--r-- | lib/Analysis/GRSimpleVals.cpp | 48 | ||||
-rw-r--r-- | lib/Analysis/GRSimpleVals.h | 2 | ||||
-rw-r--r-- | lib/Analysis/GRTransferFuncs.cpp | 4 |
6 files changed, 61 insertions, 21 deletions
diff --git a/include/clang/Analysis/PathSensitive/GRExprEngine.h b/include/clang/Analysis/PathSensitive/GRExprEngine.h index c67ca38540..9ab4f4fddc 100644 --- a/include/clang/Analysis/PathSensitive/GRExprEngine.h +++ b/include/clang/Analysis/PathSensitive/GRExprEngine.h @@ -592,12 +592,12 @@ protected: } SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, NonLoc R) { - return R.isValid() ? getTF().DetermEvalBinOpNN(getStateManager(), Op, L, R) + return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, R) : R; } SVal EvalBinOp(BinaryOperator::Opcode Op, NonLoc L, SVal R) { - return R.isValid() ? getTF().DetermEvalBinOpNN(getStateManager(), Op, L, + return R.isValid() ? getTF().DetermEvalBinOpNN(*this, Op, L, cast<NonLoc>(R)) : R; } @@ -634,7 +634,7 @@ protected: cast<NonLoc>(L)); } else - return getTF().DetermEvalBinOpNN(getStateManager(), Op, cast<NonLoc>(L), + return getTF().DetermEvalBinOpNN(*this, Op, cast<NonLoc>(L), cast<NonLoc>(R)); } diff --git a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h index ab58d56300..8f6a75a8ab 100644 --- a/include/clang/Analysis/PathSensitive/GRTransferFuncs.h +++ b/include/clang/Analysis/PathSensitive/GRTransferFuncs.h @@ -32,7 +32,7 @@ class GRTransferFuncs { protected: - virtual SVal DetermEvalBinOpNN(GRStateManager& StateMgr, + virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng, BinaryOperator::Opcode Op, NonLoc L, NonLoc R) { return UnknownVal(); @@ -58,7 +58,9 @@ public: virtual SVal EvalComplement(GRExprEngine& Engine, NonLoc X) = 0; // Binary Operators. - virtual void EvalBinOpNN(GRStateSet& OStates, GRStateManager& StateMgr, + // FIXME: We're moving back towards using GREXprEngine directly. No need + // for OStates + virtual void EvalBinOpNN(GRStateSet& OStates, GRExprEngine& Eng, const GRState* St, Expr* Ex, BinaryOperator::Opcode Op, NonLoc L, NonLoc R); diff --git a/lib/Analysis/GRExprEngine.cpp b/lib/Analysis/GRExprEngine.cpp index 6b53f1ec2d..137a31ed9c 100644 --- a/lib/Analysis/GRExprEngine.cpp +++ b/lib/Analysis/GRExprEngine.cpp @@ -2044,10 +2044,16 @@ void GRExprEngine::VisitUnaryOperator(UnaryOperator* U, NodeTy* Pred, // Get the value of the subexpression. SVal V = GetSVal(St, Ex); - // Perform promotions. - // FIXME: This is the right thing to do, but it currently breaks - // a bunch of tests. - // V = EvalCast(V, U->getType()); + if (V.isUnknownOrUndef()) { + MakeNode(Dst, U, *I, BindExpr(St, U, V)); + continue; + } + + QualType DstT = getContext().getCanonicalType(U->getType()); + QualType SrcT = getContext().getCanonicalType(Ex->getType()); + + if (DstT != SrcT) // Perform promotions. + V = EvalCast(V, DstT); if (V.isUnknownOrUndef()) { MakeNode(Dst, U, *I, BindExpr(St, U, V)); @@ -2551,7 +2557,7 @@ void GRExprEngine::EvalBinOp(GRStateSet& OStates, const GRState* St, NonLoc L, NonLoc R) { GRStateSet::AutoPopulate AP(OStates, St); - if (R.isValid()) getTF().EvalBinOpNN(OStates, StateMgr, St, Ex, Op, L, R); + if (R.isValid()) getTF().EvalBinOpNN(OStates, *this, St, Ex, Op, L, R); } //===----------------------------------------------------------------------===// diff --git a/lib/Analysis/GRSimpleVals.cpp b/lib/Analysis/GRSimpleVals.cpp index 4deef68a6a..783bccc7d7 100644 --- a/lib/Analysis/GRSimpleVals.cpp +++ b/lib/Analysis/GRSimpleVals.cpp @@ -69,20 +69,21 @@ SVal GRSimpleVals::EvalCast(GRExprEngine& Eng, Loc X, QualType T) { // can be introduced by the frontend for corner cases, e.g // casting from va_list* to __builtin_va_list&. // + assert (!X.isUnknownOrUndef()); + if (Loc::IsLocType(T) || T->isReferenceType()) return X; assert (T->isIntegerType()); - - if (!isa<loc::ConcreteInt>(X)) - return UnknownVal(); - BasicValueFactory& BasicVals = Eng.getBasicVals(); + unsigned BitWidth = Eng.getContext().getTypeSize(T); + + if (!isa<loc::ConcreteInt>(X)) + return nonloc::LocAsInteger::Make(BasicVals, X, BitWidth); llvm::APSInt V = cast<loc::ConcreteInt>(X).getValue(); V.setIsUnsigned(T->isUnsignedIntegerType() || Loc::IsLocType(T)); - V.extOrTrunc(Eng.getContext().getTypeSize(T)); - + V.extOrTrunc(BitWidth); return nonloc::ConcreteInt(BasicVals.getValue(V)); } @@ -123,11 +124,11 @@ static unsigned char LNotOpMap[] = { (unsigned char) BinaryOperator::EQ /* NE => EQ */ }; -SVal GRSimpleVals::DetermEvalBinOpNN(GRStateManager& StateMgr, +SVal GRSimpleVals::DetermEvalBinOpNN(GRExprEngine& Eng, BinaryOperator::Opcode Op, NonLoc L, NonLoc R) { - BasicValueFactory& BasicVals = StateMgr.getBasicVals(); + BasicValueFactory& BasicVals = Eng.getBasicVals(); unsigned subkind = L.getSubKind(); while (1) { @@ -136,6 +137,37 @@ SVal GRSimpleVals::DetermEvalBinOpNN(GRStateManager& StateMgr, default: return UnknownVal(); + case nonloc::LocAsIntegerKind: { + Loc LL = cast<nonloc::LocAsInteger>(L).getLoc(); + + switch (R.getSubKind()) { + case nonloc::LocAsIntegerKind: + return EvalBinOp(Eng, Op, LL, + cast<nonloc::LocAsInteger>(R).getLoc()); + + case nonloc::ConcreteIntKind: { + // Transform the integer into a location and compare. + ASTContext& Ctx = Eng.getContext(); + llvm::APSInt V = cast<nonloc::ConcreteInt>(R).getValue(); + V.setIsUnsigned(true); + V.extOrTrunc(Ctx.getTypeSize(Ctx.VoidPtrTy)); + return EvalBinOp(Eng, Op, LL, + loc::ConcreteInt(BasicVals.getValue(V))); + } + + default: + switch (Op) { + case BinaryOperator::EQ: + return NonLoc::MakeIntTruthVal(BasicVals, false); + case BinaryOperator::NE: + return NonLoc::MakeIntTruthVal(BasicVals, true); + default: + // This case also handles pointer arithmetic. + return UnknownVal(); + } + } + } + case nonloc::SymIntConstraintValKind: { // Logical not? diff --git a/lib/Analysis/GRSimpleVals.h b/lib/Analysis/GRSimpleVals.h index ee32e8a99d..6848ced2be 100644 --- a/lib/Analysis/GRSimpleVals.h +++ b/lib/Analysis/GRSimpleVals.h @@ -27,7 +27,7 @@ class ASTContext; class GRSimpleVals : public GRTransferFuncs { protected: - virtual SVal DetermEvalBinOpNN(GRStateManager& StateMgr, + virtual SVal DetermEvalBinOpNN(GRExprEngine& Eng, BinaryOperator::Opcode Op, NonLoc L, NonLoc R); diff --git a/lib/Analysis/GRTransferFuncs.cpp b/lib/Analysis/GRTransferFuncs.cpp index ca169d5aaf..16d083c50f 100644 --- a/lib/Analysis/GRTransferFuncs.cpp +++ b/lib/Analysis/GRTransferFuncs.cpp @@ -39,10 +39,10 @@ void GRTransferFuncs::EvalStore(ExplodedNodeSet<GRState>& Dst, } void GRTransferFuncs::EvalBinOpNN(GRStateSet& OStates, - GRStateManager& StateMgr, + GRExprEngine& Eng, const GRState *St, Expr* Ex, BinaryOperator::Opcode Op, NonLoc L, NonLoc R) { - OStates.Add(StateMgr.BindExpr(St, Ex, DetermEvalBinOpNN(StateMgr, Op, L, R))); + OStates.Add(Eng.getStateManager().BindExpr(St, Ex, DetermEvalBinOpNN(Eng, Op, L, R))); } |