]> granicus.if.org Git - clang/commitdiff
[analyzer] Properly handle the ternary operator in trackNullOrUndefValue
authorAnna Zaks <ganna@apple.com>
Wed, 3 Apr 2013 19:28:12 +0000 (19:28 +0000)
committerAnna Zaks <ganna@apple.com>
Wed, 3 Apr 2013 19:28:12 +0000 (19:28 +0000)
1) Look for the node where the condition expression is live when checking if
it is constrained to true or false.

2) Fix a bug in ProgramState::isNull, which was masking the problem. When
the expression is not a symbol (,which is the case when it is Unknown) return
unconstrained value, instead of value constrained to “false”!
(Thankfully other callers of isNull have not been effected by the bug.)

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178684 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/BugReporterVisitors.cpp
lib/StaticAnalyzer/Core/ProgramState.cpp
test/Analysis/inlining/false-positive-suppression.c

index 5f364304e8d949ae4ab67ea18f35b1f4f0eec0d5..7f71b8e81ed5b7047f4424bab776eb14a62c241b 100644 (file)
@@ -800,14 +800,22 @@ static const Expr *peelOffOuterExpr(const Stmt *S,
 
     // Peel off the ternary operator.
     if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
-      ProgramStateRef State = N->getState();
-      SVal CondVal = State->getSVal(CO->getCond(), N->getLocationContext());
-      if (State->isNull(CondVal).isConstrainedTrue()) {
-        return CO->getTrueExpr();
-      } else {
-        assert(State->isNull(CondVal).isConstrainedFalse());
-        return CO->getFalseExpr();
-      }
+      const Expr *CondEx = CO->getCond();
+
+      // Find a node where the value of the condition is known.
+      do {
+        ProgramStateRef State = N->getState();
+        SVal CondVal = State->getSVal(CondEx, N->getLocationContext());
+        ConditionTruthVal CondEvaluated = State->isNull(CondVal);
+        if (CondEvaluated.isConstrained()) {
+          if (CondEvaluated.isConstrainedTrue())
+            return CO->getFalseExpr();
+          else
+            return CO->getTrueExpr();
+        }
+        N = N->getFirstPred();
+      } while (N);
+      
     }
   }
   return 0;
@@ -820,9 +828,8 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
   if (!S || !N)
     return false;
 
-  if (const Expr *Ex = peelOffOuterExpr(S, N)) {
+  if (const Expr *Ex = peelOffOuterExpr(S, N))
     S = Ex;
-  }
 
   const Expr *Inner = 0;
   if (const Expr *Ex = dyn_cast<Expr>(S)) {
index f3e80f19c923136cbc7c2ed09f54eed3f4eb7e7b..bff2242925e5ccc7731dc53aa91d87c6247c6f29 100644 (file)
@@ -380,9 +380,13 @@ ConditionTruthVal ProgramState::isNull(SVal V) const {
   if (V.isZeroConstant())
     return true;
 
+  if (V.isConstant())
+    return false;
+  
   SymbolRef Sym = V.getAsSymbol();
   if (!Sym)
-    return false;
+    return ConditionTruthVal();
+  
   return getStateManager().ConstraintMgr->isNull(this, Sym);
 }
 
index 31ad8917621689ab27ac0f0aaf9d08314644abd1..e12612d8c4b49966a99421ff551d3f7b8f3ccdef 100644 (file)
@@ -9,6 +9,8 @@ int *getNull() {
   return 0;
 }
 
+int* getPtr();
+
 int *dynCastToInt(void *ptr) {
   if (opaquePropertyCheck(ptr))
     return (int *)ptr;
@@ -219,9 +221,10 @@ int derefAssignment(int *p) {
   // expected-warning@-2 {{Dereference of null pointer}}
 #endif
 }
+
 void ternaryAssignment(char cond) {
   static int x;
-  int *p = cond ? &x : getNull();
+  int *p = cond ? getNull() : getPtr();
   derefAssignment(p);
 }