mirror of
https://github.com/intel/llvm.git
synced 2026-01-27 06:06:34 +08:00
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:
@@ -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));
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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)));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user