[cfe-commits] r156089 - in /cfe/trunk: lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp test/Analysis/additive-folding.cpp
Jordy Rose
jediknil at belkadan.com
Thu May 3 12:05:48 PDT 2012
Author: jrose
Date: Thu May 3 14:05:48 2012
New Revision: 156089
URL: http://llvm.org/viewvc/llvm-project?rev=156089&view=rev
Log:
[analyzer] When promoting constant integers in a comparison, use the larger width of the two to avoid truncation.
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
cfe/trunk/test/Analysis/additive-folding.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp?rev=156089&r1=156088&r2=156089&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp Thu May 3 14:05:48 2012
@@ -496,30 +496,48 @@
QualType conversionType = resultTy;
if (BinaryOperator::isComparisonOp(op))
conversionType = lhsType;
+ const llvm::APSInt *conversionPrototype = NULL;
// Does the symbol simplify to a constant? If so, "fold" the constant
// by setting 'lhs' to a ConcreteInt and try again.
if (lhsType->isIntegerType())
if (const llvm::APSInt *Constant = state->getSymVal(Sym)) {
- // The symbol evaluates to a constant. If necessary, promote the
- // folded constant (LHS) to the result type.
- const llvm::APSInt &lhs_I = BasicVals.Convert(conversionType,
- *Constant);
- lhs = nonloc::ConcreteInt(lhs_I);
-
- // Also promote the RHS (if necessary).
-
- // For shifts, it is not necessary to promote the RHS.
- if (BinaryOperator::isShiftOp(op))
- continue;
-
- // Other operators: do an implicit conversion. This shouldn't be
- // necessary once we support truncation/extension of symbolic values.
- if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)){
- rhs = nonloc::ConcreteInt(BasicVals.Convert(conversionType,
- rhs_I->getValue()));
+ // Promote the RHS if necessary. Shift operations do not
+ // need their arguments to match in type, but others do.
+ if (!BinaryOperator::isShiftOp(op)) {
+ // If the RHS is a constant, we need to promote it.
+ if (nonloc::ConcreteInt *rhs_I =
+ dyn_cast<nonloc::ConcreteInt>(&rhs)) {
+ const llvm::APSInt &val = rhs_I->getValue();
+
+ // The RHS may have a better type for performing comparisons.
+ // Consider x == 0xF00, where x is a fully constrained char.
+ if (BinaryOperator::isComparisonOp(op)) {
+ const ASTContext &Ctx = getContext();
+ unsigned width = std::max((unsigned)Ctx.getTypeSize(lhsType),
+ (unsigned)val.getBitWidth());
+
+ // Use the LHS's signedness.
+ bool isUnsigned =
+ lhsType->isUnsignedIntegerOrEnumerationType();
+
+ conversionPrototype = &BasicVals.getValue(val.getSExtValue(),
+ width, isUnsigned);
+ } else {
+ conversionPrototype = &BasicVals.Convert(resultTy, val);
+ }
+
+ // Record the promoted value.
+ rhs = nonloc::ConcreteInt(*conversionPrototype);
+ }
}
+ // Promote the LHS constant to the appropriate type.
+ const llvm::APSInt &lhs_I = conversionPrototype ?
+ BasicVals.Convert(*conversionPrototype, *Constant) :
+ BasicVals.Convert(conversionType, *Constant);
+ lhs = nonloc::ConcreteInt(lhs_I);
+
continue;
}
@@ -529,6 +547,8 @@
if (RSym->getType(Context)->isIntegerType()) {
if (const llvm::APSInt *Constant = state->getSymVal(RSym)) {
// The symbol evaluates to a constant.
+ // FIXME: This may not be the proper conversion type. Consider
+ // x > y, where y is a fully constrained int but x is a char.
const llvm::APSInt &rhs_I = BasicVals.Convert(conversionType,
*Constant);
rhs = nonloc::ConcreteInt(rhs_I);
@@ -536,10 +556,9 @@
}
}
- if (isa<nonloc::ConcreteInt>(rhs)) {
+ if (nonloc::ConcreteInt *rhs_I = dyn_cast<nonloc::ConcreteInt>(&rhs)) {
return MakeSymIntVal(slhs->getSymbol(), op,
- cast<nonloc::ConcreteInt>(rhs).getValue(),
- resultTy);
+ rhs_I->getValue(), resultTy);
}
return makeSymExprValNN(state, op, InputLHS, InputRHS, resultTy);
Modified: cfe/trunk/test/Analysis/additive-folding.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/additive-folding.cpp?rev=156089&r1=156088&r2=156089&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/additive-folding.cpp (original)
+++ cfe/trunk/test/Analysis/additive-folding.cpp Thu May 3 14:05:48 2012
@@ -240,3 +240,31 @@
if (1 == (local + 1))
malloc(1); // expected-warning{{never executed}}
}
+
+void PR12206_truncation(signed char x) {
+ // Build a SymIntExpr, dependent on x.
+ signed char local = x - 1;
+
+ // Constrain the value of x.
+ if (x != 1) return;
+
+ // Constant-folding will turn (local+1) back into the symbol for x.
+ // The point of this dance is to make SValBuilder be responsible for
+ // turning the symbol into a ConcreteInt, rather than ExprEngine.
+
+ // Construct a value that cannot be represented by 'char',
+ // but that has the same lower bits as x.
+ signed int value = 1 + (1 << 8);
+
+ // Test relational operators.
+ if ((local + 1) >= value)
+ malloc(1); // expected-warning{{never executed}}
+ if (value <= (local + 1))
+ malloc(1); // expected-warning{{never executed}}
+
+ // Test equality operators.
+ if ((local + 1) == value)
+ malloc(1); // expected-warning{{never executed}}
+ if (value == (local + 1))
+ malloc(1); // expected-warning{{never executed}}
+}
More information about the cfe-commits
mailing list