[cfe-commits] r162209 - in /cfe/trunk: lib/StaticAnalyzer/Core/ExprEngineC.cpp test/Analysis/logical-ops.c
Jordan Rose
jordan_rose at apple.com
Mon Aug 20 10:04:46 PDT 2012
Author: jrose
Date: Mon Aug 20 12:04:45 2012
New Revision: 162209
URL: http://llvm.org/viewvc/llvm-project?rev=162209&view=rev
Log:
[analyzer] The result of && or || is always a 1 or 0.
Forgetting to at least cast the result was giving us Loc/NonLoc problems
in SValBuilder (hitting an assertion). But the standard (both C and C++)
does actually guarantee that && and || will result in the actual values
1 and 0, typed as 'int' in C and 'bool' in C++, and we can easily model that.
PR13461
Added:
cfe/trunk/test/Analysis/logical-ops.c
Modified:
cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
Modified: cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp?rev=162209&r1=162208&r2=162209&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ExprEngineC.cpp Mon Aug 20 12:04:45 2012
@@ -531,10 +531,28 @@
else {
// If there is no terminator, by construction the last statement
// in SrcBlock is the value of the enclosing expression.
+ // However, we still need to constrain that value to be 0 or 1.
assert(!SrcBlock->empty());
CFGStmt Elem = cast<CFGStmt>(*SrcBlock->rbegin());
- const Stmt *S = Elem.getStmt();
- X = N->getState()->getSVal(S, Pred->getLocationContext());
+ const Expr *RHS = cast<Expr>(Elem.getStmt());
+ SVal RHSVal = N->getState()->getSVal(RHS, Pred->getLocationContext());
+
+ DefinedOrUnknownSVal DefinedRHS = cast<DefinedOrUnknownSVal>(RHSVal);
+ ProgramStateRef StTrue, StFalse;
+ llvm::tie(StTrue, StFalse) = N->getState()->assume(DefinedRHS);
+ if (StTrue) {
+ if (StFalse) {
+ // We can't constrain the value to 0 or 1; the best we can do is a cast.
+ X = getSValBuilder().evalCast(RHSVal, B->getType(), RHS->getType());
+ } else {
+ // The value is known to be true.
+ X = getSValBuilder().makeIntVal(1, B->getType());
+ }
+ } else {
+ // The value is known to be false.
+ assert(StFalse && "Infeasible path!");
+ X = getSValBuilder().makeIntVal(0, B->getType());
+ }
}
Bldr.generateNode(B, Pred, state->BindExpr(B, Pred->getLocationContext(), X));
Added: cfe/trunk/test/Analysis/logical-ops.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/logical-ops.c?rev=162209&view=auto
==============================================================================
--- cfe/trunk/test/Analysis/logical-ops.c (added)
+++ cfe/trunk/test/Analysis/logical-ops.c Mon Aug 20 12:04:45 2012
@@ -0,0 +1,27 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,debug.ExprInspection -verify %s
+
+void clang_analyzer_eval(int);
+
+void testAnd(int i, int *p) {
+ int *nullP = 0;
+ int *knownP = &i;
+ clang_analyzer_eval((knownP && knownP) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval((knownP && nullP) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval((knownP && p) == 1); // expected-warning{{UNKNOWN}}
+}
+
+void testOr(int i, int *p) {
+ int *nullP = 0;
+ int *knownP = &i;
+ clang_analyzer_eval((nullP || knownP) == 1); // expected-warning{{TRUE}}
+ clang_analyzer_eval((nullP || nullP) == 0); // expected-warning{{TRUE}}
+ clang_analyzer_eval((nullP || p) == 1); // expected-warning{{UNKNOWN}}
+}
+
+
+// PR13461
+int testTypeIsInt(int i, void *p) {
+ if (i | (p && p))
+ return 1;
+ return 0;
+}
More information about the cfe-commits
mailing list