aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
diff options
context:
space:
mode:
authorJordy Rose <jediknil@belkadan.com>2011-06-15 04:55:49 +0000
committerJordy Rose <jediknil@belkadan.com>2011-06-15 04:55:49 +0000
commita9af8e71bba24d2a1d1827972ef4cd856c179e56 (patch)
treebc7778864266ee56d81eca499ab2731a21771d68 /lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
parent55080a78c81733021b45fc3a47541619e4470883 (diff)
[analyzer] When performing a binary operation on symbolic operands, we convert the symbol values to a common type. But in a relational operation, the result is an 'int' or 'bool', which may not be the appropriate type to convert the operands to. In these cases, use the left-hand operand's type as the conversion type.
There's no associated test for this because fully-constrained symbolic values are evaluated ahead of time in normal expressions. This can only come up in checker-constructed expressions (like the ones in an upcoming patch to CStringChecker). git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@133041 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp36
1 files changed, 32 insertions, 4 deletions
diff --git a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
index 197442b157..80c18a335f 100644
--- a/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
+++ b/lib/StaticAnalyzer/Core/SimpleSValBuilder.cpp
@@ -415,6 +415,24 @@ SVal SimpleSValBuilder::evalBinOpNN(const GRState *state,
case nonloc::ConcreteIntKind: {
const nonloc::ConcreteInt& lhsInt = cast<nonloc::ConcreteInt>(lhs);
+ // Is the RHS a symbol we can simplify?
+ // FIXME: This was mostly copy/pasted from the LHS-is-a-symbol case.
+ if (const nonloc::SymbolVal *srhs = dyn_cast<nonloc::SymbolVal>(&rhs)) {
+ SymbolRef RSym = srhs->getSymbol();
+ if (RSym->getType(Context)->isIntegerType()) {
+ if (const llvm::APSInt *Constant = state->getSymVal(RSym)) {
+ // The symbol evaluates to a constant.
+ const llvm::APSInt *rhs_I;
+ if (BinaryOperator::isRelationalOp(op))
+ rhs_I = &BasicVals.Convert(lhsInt.getValue(), *Constant);
+ else
+ rhs_I = &BasicVals.Convert(resultTy, *Constant);
+
+ rhs = nonloc::ConcreteInt(*rhs_I);
+ }
+ }
+ }
+
if (isa<nonloc::ConcreteInt>(rhs)) {
return lhsInt.evalBinOp(*this, op, cast<nonloc::ConcreteInt>(rhs));
} else {
@@ -461,13 +479,22 @@ SVal SimpleSValBuilder::evalBinOpNN(const GRState *state,
case nonloc::SymbolValKind: {
nonloc::SymbolVal *slhs = cast<nonloc::SymbolVal>(&lhs);
SymbolRef Sym = slhs->getSymbol();
+ QualType lhsType = Sym->getType(Context);
+
+ // The conversion type is usually the result type, but not in the case
+ // of relational expressions.
+ QualType conversionType = resultTy;
+ if (BinaryOperator::isRelationalOp(op))
+ conversionType = lhsType;
+
// Does the symbol simplify to a constant? If so, "fold" the constant
// by setting 'lhs' to a ConcreteInt and try again.
- if (Sym->getType(Context)->isIntegerType())
+ 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(resultTy, *Constant);
+ const llvm::APSInt &lhs_I = BasicVals.Convert(conversionType,
+ *Constant);
lhs = nonloc::ConcreteInt(lhs_I);
// Also promote the RHS (if necessary).
@@ -479,7 +506,7 @@ SVal SimpleSValBuilder::evalBinOpNN(const GRState *state,
// 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(resultTy,
+ rhs = nonloc::ConcreteInt(BasicVals.Convert(conversionType,
rhs_I->getValue()));
}
@@ -492,7 +519,8 @@ SVal SimpleSValBuilder::evalBinOpNN(const GRState *state,
if (RSym->getType(Context)->isIntegerType()) {
if (const llvm::APSInt *Constant = state->getSymVal(RSym)) {
// The symbol evaluates to a constant.
- const llvm::APSInt &rhs_I = BasicVals.Convert(resultTy, *Constant);
+ const llvm::APSInt &rhs_I = BasicVals.Convert(conversionType,
+ *Constant);
rhs = nonloc::ConcreteInt(rhs_I);
}
}