2009-02-15 01:08:39 +08:00
|
|
|
//== SimpleConstraintManager.cpp --------------------------------*- 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 SimpleConstraintManager, a class that holds code shared
|
|
|
|
// between BasicConstraintManager and RangeConstraintManager.
|
|
|
|
//
|
|
|
|
//===----------------------------------------------------------------------===//
|
|
|
|
|
|
|
|
#include "SimpleConstraintManager.h"
|
2012-05-08 11:27:16 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/APSIntType.h"
|
2011-02-10 09:03:03 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/ExprEngine.h"
|
2011-08-16 06:09:50 +08:00
|
|
|
#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h"
|
2009-02-15 01:08:39 +08:00
|
|
|
|
|
|
|
namespace clang {
|
|
|
|
|
2010-12-23 15:20:52 +08:00
|
|
|
namespace ento {
|
2010-12-23 02:53:20 +08:00
|
|
|
|
2015-10-20 21:23:58 +08:00
|
|
|
SimpleConstraintManager::~SimpleConstraintManager() {}
|
2009-02-15 01:08:39 +08:00
|
|
|
|
2009-03-11 10:22:59 +08:00
|
|
|
bool SimpleConstraintManager::canReasonAbout(SVal X) const {
|
2013-02-21 06:23:23 +08:00
|
|
|
Optional<nonloc::SymbolVal> SymVal = X.getAs<nonloc::SymbolVal>();
|
2011-12-06 02:58:30 +08:00
|
|
|
if (SymVal && SymVal->isExpression()) {
|
|
|
|
const SymExpr *SE = SymVal->getSymbol();
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2009-03-26 11:35:11 +08:00
|
|
|
if (const SymIntExpr *SIE = dyn_cast<SymIntExpr>(SE)) {
|
|
|
|
switch (SIE->getOpcode()) {
|
|
|
|
// We don't reason yet about bitwise-constraints on symbolic values.
|
2010-08-25 19:45:40 +08:00
|
|
|
case BO_And:
|
|
|
|
case BO_Or:
|
|
|
|
case BO_Xor:
|
2009-03-26 11:35:11 +08:00
|
|
|
return false;
|
2010-06-19 06:49:11 +08:00
|
|
|
// We don't reason yet about these arithmetic constraints on
|
|
|
|
// symbolic values.
|
2010-08-25 19:45:40 +08:00
|
|
|
case BO_Mul:
|
|
|
|
case BO_Div:
|
|
|
|
case BO_Rem:
|
|
|
|
case BO_Shl:
|
|
|
|
case BO_Shr:
|
2009-03-26 11:35:11 +08:00
|
|
|
return false;
|
|
|
|
// All other cases.
|
|
|
|
default:
|
|
|
|
return true;
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-03-26 11:35:11 +08:00
|
|
|
}
|
|
|
|
|
2013-03-23 09:21:16 +08:00
|
|
|
if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(SE)) {
|
2013-03-25 04:25:22 +08:00
|
|
|
if (BinaryOperator::isComparisonOp(SSE->getOpcode())) {
|
|
|
|
// We handle Loc <> Loc comparisons, but not (yet) NonLoc <> NonLoc.
|
|
|
|
if (Loc::isLocType(SSE->getLHS()->getType())) {
|
|
|
|
assert(Loc::isLocType(SSE->getRHS()->getType()));
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2013-03-23 09:21:16 +08:00
|
|
|
}
|
|
|
|
|
2009-03-26 11:35:11 +08:00
|
|
|
return false;
|
2009-03-11 10:29:48 +08:00
|
|
|
}
|
|
|
|
|
2009-03-11 10:22:59 +08:00
|
|
|
return true;
|
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2012-01-27 05:29:00 +08:00
|
|
|
ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
|
2009-09-12 06:07:28 +08:00
|
|
|
DefinedSVal Cond,
|
|
|
|
bool Assumption) {
|
[analyzer] Add support for testing the presence of weak functions.
When casting the address of a FunctionTextRegion to bool, or when adding
constraints to such an address, use a stand-in symbol to represent the
presence or absence of the function if the function is weakly linked.
This is groundwork for possible simple availability testing checks, and
can already catch mistakes involving inverted null checks for
weakly-linked functions.
Currently, the implementation reuses the "extent" symbols, originally created
for tracking the size of a malloc region. Since FunctionTextRegions cannot
be dereferenced, the extent symbol will never be used for anything else.
Still, this probably deserves a refactoring in the future.
This patch does not attempt to support testing the presence of weak
/variables/ (global variables), which would likely require much more of
a change and a generalization of "region structure metadata", like the
current "extents", vs. "region contents metadata", like CStringChecker's
"string length".
Patch by Richard <tarka.t.otter@googlemail.com>!
llvm-svn: 189492
2013-08-29 01:07:04 +08:00
|
|
|
// If we have a Loc value, cast it to a bool NonLoc first.
|
|
|
|
if (Optional<Loc> LV = Cond.getAs<Loc>()) {
|
|
|
|
SValBuilder &SVB = state->getStateManager().getSValBuilder();
|
|
|
|
QualType T;
|
|
|
|
const MemRegion *MR = LV->getAsRegion();
|
|
|
|
if (const TypedRegion *TR = dyn_cast_or_null<TypedRegion>(MR))
|
|
|
|
T = TR->getLocationType();
|
|
|
|
else
|
|
|
|
T = SVB.getContext().VoidPtrTy;
|
|
|
|
|
|
|
|
Cond = SVB.evalCast(*LV, SVB.getContext().BoolTy, T).castAs<DefinedSVal>();
|
2009-02-15 01:08:39 +08:00
|
|
|
}
|
2009-09-09 23:08:12 +08:00
|
|
|
|
[analyzer] Add support for testing the presence of weak functions.
When casting the address of a FunctionTextRegion to bool, or when adding
constraints to such an address, use a stand-in symbol to represent the
presence or absence of the function if the function is weakly linked.
This is groundwork for possible simple availability testing checks, and
can already catch mistakes involving inverted null checks for
weakly-linked functions.
Currently, the implementation reuses the "extent" symbols, originally created
for tracking the size of a malloc region. Since FunctionTextRegions cannot
be dereferenced, the extent symbol will never be used for anything else.
Still, this probably deserves a refactoring in the future.
This patch does not attempt to support testing the presence of weak
/variables/ (global variables), which would likely require much more of
a change and a generalization of "region structure metadata", like the
current "extents", vs. "region contents metadata", like CStringChecker's
"string length".
Patch by Richard <tarka.t.otter@googlemail.com>!
llvm-svn: 189492
2013-08-29 01:07:04 +08:00
|
|
|
return assume(state, Cond.castAs<NonLoc>(), Assumption);
|
2009-02-15 01:08:39 +08:00
|
|
|
}
|
|
|
|
|
2012-01-27 05:29:00 +08:00
|
|
|
ProgramStateRef SimpleConstraintManager::assume(ProgramStateRef state,
|
2010-01-05 08:15:18 +08:00
|
|
|
NonLoc cond,
|
|
|
|
bool assumption) {
|
2010-12-02 06:16:56 +08:00
|
|
|
state = assumeAux(state, cond, assumption);
|
2012-10-02 00:53:40 +08:00
|
|
|
if (NotifyAssumeClients && SU)
|
|
|
|
return SU->processAssume(state, cond, assumption);
|
2012-09-25 01:43:41 +08:00
|
|
|
return state;
|
2009-02-15 01:08:39 +08:00
|
|
|
}
|
|
|
|
|
2011-12-06 02:58:19 +08:00
|
|
|
|
2012-05-08 11:27:16 +08:00
|
|
|
ProgramStateRef
|
|
|
|
SimpleConstraintManager::assumeAuxForSymbol(ProgramStateRef State,
|
|
|
|
SymbolRef Sym, bool Assumption) {
|
|
|
|
BasicValueFactory &BVF = getBasicVals();
|
2012-09-26 14:00:14 +08:00
|
|
|
QualType T = Sym->getType();
|
2012-05-11 05:49:52 +08:00
|
|
|
|
2012-08-23 03:58:20 +08:00
|
|
|
// None of the constraint solvers currently support non-integer types.
|
2013-04-09 10:30:33 +08:00
|
|
|
if (!T->isIntegralOrEnumerationType())
|
2012-05-11 05:49:52 +08:00
|
|
|
return State;
|
|
|
|
|
2012-05-08 11:27:16 +08:00
|
|
|
const llvm::APSInt &zero = BVF.getValue(0, T);
|
2011-12-06 02:58:19 +08:00
|
|
|
if (Assumption)
|
|
|
|
return assumeSymNE(State, Sym, zero, zero);
|
|
|
|
else
|
|
|
|
return assumeSymEQ(State, Sym, zero, zero);
|
|
|
|
}
|
|
|
|
|
2012-01-27 05:29:00 +08:00
|
|
|
ProgramStateRef SimpleConstraintManager::assumeAux(ProgramStateRef state,
|
2009-06-19 06:57:13 +08:00
|
|
|
NonLoc Cond,
|
|
|
|
bool Assumption) {
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2011-12-06 02:58:19 +08:00
|
|
|
// We cannot reason about SymSymExprs, and can only reason about some
|
|
|
|
// SymIntExprs.
|
2009-03-25 13:58:37 +08:00
|
|
|
if (!canReasonAbout(Cond)) {
|
2011-12-06 02:58:19 +08:00
|
|
|
// Just add the constraint to the expression without trying to simplify.
|
|
|
|
SymbolRef sym = Cond.getAsSymExpr();
|
|
|
|
return assumeAuxForSymbol(state, sym, Assumption);
|
2009-09-09 23:08:12 +08:00
|
|
|
}
|
2009-03-25 13:58:37 +08:00
|
|
|
|
2009-02-15 01:08:39 +08:00
|
|
|
switch (Cond.getSubKind()) {
|
|
|
|
default:
|
2011-09-23 13:06:16 +08:00
|
|
|
llvm_unreachable("'Assume' not implemented for this NonLoc");
|
2009-02-15 01:08:39 +08:00
|
|
|
|
|
|
|
case nonloc::SymbolValKind: {
|
2013-02-20 13:52:05 +08:00
|
|
|
nonloc::SymbolVal SV = Cond.castAs<nonloc::SymbolVal>();
|
2009-02-15 01:08:39 +08:00
|
|
|
SymbolRef sym = SV.getSymbol();
|
2011-12-06 02:58:19 +08:00
|
|
|
assert(sym);
|
|
|
|
|
2011-12-06 02:58:30 +08:00
|
|
|
// Handle SymbolData.
|
|
|
|
if (!SV.isExpression()) {
|
2011-12-06 02:58:19 +08:00
|
|
|
return assumeAuxForSymbol(state, sym, Assumption);
|
2010-06-19 06:49:11 +08:00
|
|
|
|
2011-12-06 02:58:30 +08:00
|
|
|
// Handle symbolic expression.
|
2013-03-23 09:21:16 +08:00
|
|
|
} else if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(sym)) {
|
2011-12-06 02:58:30 +08:00
|
|
|
// We can only simplify expressions whose RHS is an integer.
|
|
|
|
|
|
|
|
BinaryOperator::Opcode op = SE->getOpcode();
|
2013-03-23 09:21:16 +08:00
|
|
|
if (BinaryOperator::isComparisonOp(op)) {
|
|
|
|
if (!Assumption)
|
2013-03-23 09:21:20 +08:00
|
|
|
op = BinaryOperator::negateComparisonOp(op);
|
2013-03-23 09:21:16 +08:00
|
|
|
|
|
|
|
return assumeSymRel(state, SE->getLHS(), op, SE->getRHS());
|
2012-08-23 03:58:20 +08:00
|
|
|
}
|
2010-06-19 06:49:11 +08:00
|
|
|
|
2013-03-23 09:21:16 +08:00
|
|
|
} else if (const SymSymExpr *SSE = dyn_cast<SymSymExpr>(sym)) {
|
|
|
|
// Translate "a != b" to "(b - a) != 0".
|
|
|
|
// We invert the order of the operands as a heuristic for how loop
|
|
|
|
// conditions are usually written ("begin != end") as compared to length
|
|
|
|
// calculations ("end - begin"). The more correct thing to do would be to
|
|
|
|
// canonicalize "a - b" and "b - a", which would allow us to treat
|
|
|
|
// "a != b" and "b != a" the same.
|
2013-03-23 09:21:23 +08:00
|
|
|
SymbolManager &SymMgr = getSymbolManager();
|
|
|
|
BinaryOperator::Opcode Op = SSE->getOpcode();
|
|
|
|
assert(BinaryOperator::isComparisonOp(Op));
|
|
|
|
|
|
|
|
// For now, we only support comparing pointers.
|
|
|
|
assert(Loc::isLocType(SSE->getLHS()->getType()));
|
|
|
|
assert(Loc::isLocType(SSE->getRHS()->getType()));
|
|
|
|
QualType DiffTy = SymMgr.getContext().getPointerDiffType();
|
|
|
|
SymbolRef Subtraction = SymMgr.getSymSymExpr(SSE->getRHS(), BO_Sub,
|
|
|
|
SSE->getLHS(), DiffTy);
|
|
|
|
|
|
|
|
const llvm::APSInt &Zero = getBasicVals().getValue(0, DiffTy);
|
|
|
|
Op = BinaryOperator::reverseComparisonOp(Op);
|
|
|
|
if (!Assumption)
|
|
|
|
Op = BinaryOperator::negateComparisonOp(Op);
|
|
|
|
return assumeSymRel(state, Subtraction, Op, Zero);
|
2011-12-06 02:58:30 +08:00
|
|
|
}
|
2013-03-23 09:21:16 +08:00
|
|
|
|
|
|
|
// If we get here, there's nothing else we can do but treat the symbol as
|
|
|
|
// opaque.
|
|
|
|
return assumeAuxForSymbol(state, sym, Assumption);
|
2009-03-26 11:35:11 +08:00
|
|
|
}
|
2009-02-15 01:08:39 +08:00
|
|
|
|
|
|
|
case nonloc::ConcreteIntKind: {
|
2013-02-20 13:52:05 +08:00
|
|
|
bool b = Cond.castAs<nonloc::ConcreteInt>().getValue() != 0;
|
2009-06-19 06:57:13 +08:00
|
|
|
bool isFeasible = b ? Assumption : !Assumption;
|
2014-05-27 10:45:47 +08:00
|
|
|
return isFeasible ? state : nullptr;
|
2009-02-15 01:08:39 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
case nonloc::LocAsIntegerKind:
|
[analyzer] Add support for testing the presence of weak functions.
When casting the address of a FunctionTextRegion to bool, or when adding
constraints to such an address, use a stand-in symbol to represent the
presence or absence of the function if the function is weakly linked.
This is groundwork for possible simple availability testing checks, and
can already catch mistakes involving inverted null checks for
weakly-linked functions.
Currently, the implementation reuses the "extent" symbols, originally created
for tracking the size of a malloc region. Since FunctionTextRegions cannot
be dereferenced, the extent symbol will never be used for anything else.
Still, this probably deserves a refactoring in the future.
This patch does not attempt to support testing the presence of weak
/variables/ (global variables), which would likely require much more of
a change and a generalization of "region structure metadata", like the
current "extents", vs. "region contents metadata", like CStringChecker's
"string length".
Patch by Richard <tarka.t.otter@googlemail.com>!
llvm-svn: 189492
2013-08-29 01:07:04 +08:00
|
|
|
return assume(state, Cond.castAs<nonloc::LocAsInteger>().getLoc(),
|
|
|
|
Assumption);
|
2009-02-15 01:08:39 +08:00
|
|
|
} // end switch
|
|
|
|
}
|
|
|
|
|
2015-09-23 04:31:19 +08:00
|
|
|
ProgramStateRef SimpleConstraintManager::assumeWithinInclusiveRange(
|
|
|
|
ProgramStateRef State, NonLoc Value, const llvm::APSInt &From,
|
|
|
|
const llvm::APSInt &To, bool InRange) {
|
|
|
|
|
|
|
|
assert(From.isUnsigned() == To.isUnsigned() &&
|
|
|
|
From.getBitWidth() == To.getBitWidth() &&
|
|
|
|
"Values should have same types!");
|
|
|
|
|
|
|
|
if (!canReasonAbout(Value)) {
|
|
|
|
// Just add the constraint to the expression without trying to simplify.
|
|
|
|
SymbolRef Sym = Value.getAsSymExpr();
|
|
|
|
assert(Sym);
|
|
|
|
return assumeSymWithinInclusiveRange(State, Sym, From, To, InRange);
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (Value.getSubKind()) {
|
|
|
|
default:
|
|
|
|
llvm_unreachable("'assumeWithinInclusiveRange' is not implemented"
|
|
|
|
"for this NonLoc");
|
|
|
|
|
|
|
|
case nonloc::LocAsIntegerKind:
|
|
|
|
case nonloc::SymbolValKind: {
|
|
|
|
if (SymbolRef Sym = Value.getAsSymbol())
|
|
|
|
return assumeSymWithinInclusiveRange(State, Sym, From, To, InRange);
|
|
|
|
return State;
|
|
|
|
} // end switch
|
|
|
|
|
|
|
|
case nonloc::ConcreteIntKind: {
|
|
|
|
const llvm::APSInt &IntVal = Value.castAs<nonloc::ConcreteInt>().getValue();
|
|
|
|
bool IsInRange = IntVal >= From && IntVal <= To;
|
|
|
|
bool isFeasible = (IsInRange == InRange);
|
|
|
|
return isFeasible ? State : nullptr;
|
|
|
|
}
|
|
|
|
} // end switch
|
|
|
|
}
|
|
|
|
|
2012-05-08 11:27:16 +08:00
|
|
|
static void computeAdjustment(SymbolRef &Sym, llvm::APSInt &Adjustment) {
|
|
|
|
// Is it a "($sym+constant1)" expression?
|
|
|
|
if (const SymIntExpr *SE = dyn_cast<SymIntExpr>(Sym)) {
|
|
|
|
BinaryOperator::Opcode Op = SE->getOpcode();
|
|
|
|
if (Op == BO_Add || Op == BO_Sub) {
|
|
|
|
Sym = SE->getLHS();
|
|
|
|
Adjustment = APSIntType(Adjustment).convert(SE->getRHS());
|
|
|
|
|
|
|
|
// Don't forget to negate the adjustment if it's being subtracted.
|
|
|
|
// This should happen /after/ promotion, in case the value being
|
|
|
|
// subtracted is, say, CHAR_MIN, and the promoted type is 'int'.
|
|
|
|
if (Op == BO_Sub)
|
|
|
|
Adjustment = -Adjustment;
|
|
|
|
}
|
2011-12-06 02:58:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-27 05:29:00 +08:00
|
|
|
ProgramStateRef SimpleConstraintManager::assumeSymRel(ProgramStateRef state,
|
2010-06-19 06:49:11 +08:00
|
|
|
const SymExpr *LHS,
|
|
|
|
BinaryOperator::Opcode op,
|
|
|
|
const llvm::APSInt& Int) {
|
|
|
|
assert(BinaryOperator::isComparisonOp(op) &&
|
|
|
|
"Non-comparison ops should be rewritten as comparisons to zero.");
|
|
|
|
|
2012-05-08 11:27:16 +08:00
|
|
|
// Get the type used for calculating wraparound.
|
2012-09-26 14:00:14 +08:00
|
|
|
BasicValueFactory &BVF = getBasicVals();
|
|
|
|
APSIntType WraparoundType = BVF.getAPSIntType(LHS->getType());
|
2012-05-08 11:27:16 +08:00
|
|
|
|
2011-12-06 02:58:25 +08:00
|
|
|
// We only handle simple comparisons of the form "$sym == constant"
|
|
|
|
// or "($sym+constant1) == constant2".
|
|
|
|
// The adjustment is "constant1" in the above expression. It's used to
|
|
|
|
// "slide" the solution range around for modular arithmetic. For example,
|
|
|
|
// x < 4 has the solution [0, 3]. x+2 < 4 has the solution [0-2, 3-2], which
|
|
|
|
// in modular arithmetic is [0, 1] U [UINT_MAX-1, UINT_MAX]. It's up to
|
|
|
|
// the subclasses of SimpleConstraintManager to handle the adjustment.
|
|
|
|
SymbolRef Sym = LHS;
|
2012-05-08 11:27:16 +08:00
|
|
|
llvm::APSInt Adjustment = WraparoundType.getZeroValue();
|
|
|
|
computeAdjustment(Sym, Adjustment);
|
|
|
|
|
|
|
|
// Convert the right-hand side integer as necessary.
|
|
|
|
APSIntType ComparisonType = std::max(WraparoundType, APSIntType(Int));
|
|
|
|
llvm::APSInt ConvertedInt = ComparisonType.convert(Int);
|
2010-06-22 04:15:15 +08:00
|
|
|
|
2013-03-23 09:21:33 +08:00
|
|
|
// Prefer unsigned comparisons.
|
|
|
|
if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() &&
|
|
|
|
ComparisonType.isUnsigned() && !WraparoundType.isUnsigned())
|
|
|
|
Adjustment.setIsSigned(false);
|
|
|
|
|
2010-06-19 06:49:11 +08:00
|
|
|
switch (op) {
|
2009-02-15 01:08:39 +08:00
|
|
|
default:
|
2013-03-23 09:21:33 +08:00
|
|
|
llvm_unreachable("invalid operation not caught by assertion above");
|
2009-02-15 01:08:39 +08:00
|
|
|
|
2010-08-25 19:45:40 +08:00
|
|
|
case BO_EQ:
|
2010-12-02 06:16:56 +08:00
|
|
|
return assumeSymEQ(state, Sym, ConvertedInt, Adjustment);
|
2009-02-15 01:08:39 +08:00
|
|
|
|
2010-08-25 19:45:40 +08:00
|
|
|
case BO_NE:
|
2010-12-02 06:16:56 +08:00
|
|
|
return assumeSymNE(state, Sym, ConvertedInt, Adjustment);
|
2010-06-19 06:49:11 +08:00
|
|
|
|
2010-08-25 19:45:40 +08:00
|
|
|
case BO_GT:
|
2010-12-02 06:16:56 +08:00
|
|
|
return assumeSymGT(state, Sym, ConvertedInt, Adjustment);
|
2009-02-15 01:08:39 +08:00
|
|
|
|
2010-08-25 19:45:40 +08:00
|
|
|
case BO_GE:
|
2010-12-02 06:16:56 +08:00
|
|
|
return assumeSymGE(state, Sym, ConvertedInt, Adjustment);
|
2009-02-15 01:08:39 +08:00
|
|
|
|
2010-08-25 19:45:40 +08:00
|
|
|
case BO_LT:
|
2010-12-02 06:16:56 +08:00
|
|
|
return assumeSymLT(state, Sym, ConvertedInt, Adjustment);
|
2009-09-09 23:08:12 +08:00
|
|
|
|
2010-08-25 19:45:40 +08:00
|
|
|
case BO_LE:
|
2010-12-02 06:16:56 +08:00
|
|
|
return assumeSymLE(state, Sym, ConvertedInt, Adjustment);
|
2009-02-15 01:08:39 +08:00
|
|
|
} // end switch
|
|
|
|
}
|
|
|
|
|
2015-09-23 04:31:19 +08:00
|
|
|
ProgramStateRef
|
|
|
|
SimpleConstraintManager::assumeSymWithinInclusiveRange(ProgramStateRef State,
|
|
|
|
SymbolRef Sym,
|
|
|
|
const llvm::APSInt &From,
|
|
|
|
const llvm::APSInt &To,
|
|
|
|
bool InRange) {
|
|
|
|
// Get the type used for calculating wraparound.
|
|
|
|
BasicValueFactory &BVF = getBasicVals();
|
|
|
|
APSIntType WraparoundType = BVF.getAPSIntType(Sym->getType());
|
|
|
|
|
|
|
|
llvm::APSInt Adjustment = WraparoundType.getZeroValue();
|
|
|
|
SymbolRef AdjustedSym = Sym;
|
|
|
|
computeAdjustment(AdjustedSym, Adjustment);
|
|
|
|
|
|
|
|
// Convert the right-hand side integer as necessary.
|
|
|
|
APSIntType ComparisonType = std::max(WraparoundType, APSIntType(From));
|
|
|
|
llvm::APSInt ConvertedFrom = ComparisonType.convert(From);
|
|
|
|
llvm::APSInt ConvertedTo = ComparisonType.convert(To);
|
|
|
|
|
|
|
|
// Prefer unsigned comparisons.
|
|
|
|
if (ComparisonType.getBitWidth() == WraparoundType.getBitWidth() &&
|
|
|
|
ComparisonType.isUnsigned() && !WraparoundType.isUnsigned())
|
|
|
|
Adjustment.setIsSigned(false);
|
|
|
|
|
|
|
|
if (InRange)
|
|
|
|
return assumeSymbolWithinInclusiveRange(State, AdjustedSym, ConvertedFrom,
|
|
|
|
ConvertedTo, Adjustment);
|
|
|
|
return assumeSymbolOutOfInclusiveRange(State, AdjustedSym, ConvertedFrom,
|
|
|
|
ConvertedTo, Adjustment);
|
|
|
|
}
|
|
|
|
|
2010-12-23 15:20:52 +08:00
|
|
|
} // end of namespace ento
|
2010-12-23 02:53:20 +08:00
|
|
|
|
|
|
|
} // end of namespace clang
|