Implement FIXME in GRExprEngine::VisitUnaryOperator() to handle implicit conversions caused by the '!' operator. This required adding some logic to GRSimpleVals to reason about nonloc::LocAsInteger SVals. This code appears to work fine, but it should eventually be cleaned up.

llvm-svn: 59335
This commit is contained in:
Ted Kremenek
2008-11-15 00:20:05 +00:00
parent 7eee049eea
commit 1ca3346b19
6 changed files with 61 additions and 21 deletions

View File

@@ -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));
}

View File

@@ -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);

View File

@@ -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);
}
//===----------------------------------------------------------------------===//

View File

@@ -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?

View File

@@ -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);

View File

@@ -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)));
}