From c6c0fc9164c05979b2791791936aaedf28e90c6d Mon Sep 17 00:00:00 2001 From: Jordy Rose Date: Mon, 9 Aug 2010 20:31:57 +0000 Subject: [PATCH] Allow EvalBinOpNN to handle expressions of the form $a+$b if $b can be reduced to a constant. llvm-svn: 110592 --- clang/lib/Checker/SimpleSValuator.cpp | 23 +++++++++++++++++++---- clang/test/Analysis/misc-ps.m | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/clang/lib/Checker/SimpleSValuator.cpp b/clang/lib/Checker/SimpleSValuator.cpp index 48c8b9a81bdd..433c3654fada 100644 --- a/clang/lib/Checker/SimpleSValuator.cpp +++ b/clang/lib/Checker/SimpleSValuator.cpp @@ -461,10 +461,12 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state, case nonloc::SymbolValKind: { nonloc::SymbolVal *slhs = cast(&lhs); SymbolRef Sym = slhs->getSymbol(); - + + ASTContext& Ctx = ValMgr.getContext(); + // Does the symbol simplify to a constant? If so, "fold" the constant // by setting 'lhs' to a ConcreteInt and try again. - if (Sym->getType(ValMgr.getContext())->isIntegerType()) + if (Sym->getType(Ctx)->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. @@ -474,7 +476,7 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state, // Also promote the RHS (if necessary). - // For shifts, it necessary promote the RHS to the result type. + // For shifts, it is not necessary to promote the RHS. if (BinaryOperator::isShiftOp(op)) continue; @@ -486,7 +488,20 @@ SVal SimpleSValuator::EvalBinOpNN(const GRState *state, continue; } - + + // Is the RHS a symbol we can simplify? + if (const nonloc::SymbolVal *srhs = dyn_cast(&rhs)) { + SymbolRef RSym = srhs->getSymbol(); + if (RSym->getType(Ctx)->isIntegerType()) { + if (const llvm::APSInt *Constant = state->getSymVal(RSym)) { + // The symbol evaluates to a constant. + BasicValueFactory &BVF = ValMgr.getBasicValueFactory(); + const llvm::APSInt &rhs_I = BVF.Convert(resultTy, *Constant); + rhs = nonloc::ConcreteInt(rhs_I); + } + } + } + if (isa(rhs)) { return MakeSymIntVal(slhs->getSymbol(), op, cast(rhs).getValue(), diff --git a/clang/test/Analysis/misc-ps.m b/clang/test/Analysis/misc-ps.m index a36221104924..f6a92831d739 100644 --- a/clang/test/Analysis/misc-ps.m +++ b/clang/test/Analysis/misc-ps.m @@ -1027,3 +1027,21 @@ float f0(_Complex float x) { return __real l0 + __imag l0; } + +//===----------------------------------------------------------------------=== +// Test that we can reduce symbols to constants whether they are on the left +// or right side of an expression. +//===----------------------------------------------------------------------=== + +void reduce_to_constant(int x, int y) { + if (x != 20) + return; + + int a = x + y; + int b = y + x; + + if (y == -20 && a != 0) + (void)*(char*)0; // no-warning + if (y == -20 && b != 0) + (void)*(char*)0; // no-warning +}