[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