]> granicus.if.org Git - clang/commitdiff
[analyzer] make peelOffOuterExpr in BugReporterVisitors recursively peel off select...
authorAnna Zaks <ganna@apple.com>
Wed, 3 Apr 2013 19:28:15 +0000 (19:28 +0000)
committerAnna Zaks <ganna@apple.com>
Wed, 3 Apr 2013 19:28:15 +0000 (19:28 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@178685 91177308-0d34-0410-b5e6-96231b3b80d8

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

index 7f71b8e81ed5b7047f4424bab776eb14a62c241b..60a7e65254dce8d10048331b877f11cc40268c0b 100644 (file)
@@ -789,36 +789,33 @@ static const MemRegion *getLocationRegionIfReference(const Expr *E,
   return 0;
 }
 
-static const Expr *peelOffOuterExpr(const Stmt *S,
+static const Expr *peelOffOuterExpr(const Expr *Ex,
                                     const ExplodedNode *N) {
-  if (const Expr *Ex = dyn_cast<Expr>(S)) {
-    Ex = Ex->IgnoreParenCasts();
-    if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex))
-      return EWC->getSubExpr();
-    if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex))
-      return OVE->getSourceExpr();
-
-    // Peel off the ternary operator.
-    if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
-      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);
-      
-    }
+  Ex = Ex->IgnoreParenCasts();
+  if (const ExprWithCleanups *EWC = dyn_cast<ExprWithCleanups>(Ex))
+    return peelOffOuterExpr(EWC->getSubExpr(), N);
+  if (const OpaqueValueExpr *OVE = dyn_cast<OpaqueValueExpr>(Ex))
+    return peelOffOuterExpr(OVE->getSourceExpr(), N);
+
+  // Peel off the ternary operator.
+  if (const ConditionalOperator *CO = dyn_cast<ConditionalOperator>(Ex)) {
+    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 peelOffOuterExpr(CO->getFalseExpr(), N);
+        else
+          return peelOffOuterExpr(CO->getTrueExpr(), N);
+      }
+      N = N->getFirstPred();
+    } while (N);
   }
-  return 0;
+  return Ex;
 }
 
 bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
@@ -828,8 +825,12 @@ bool bugreporter::trackNullOrUndefValue(const ExplodedNode *N,
   if (!S || !N)
     return false;
 
-  if (const Expr *Ex = peelOffOuterExpr(S, N))
-    S = Ex;
+  if (const Expr *Ex = dyn_cast<Expr>(S)) {
+    Ex = Ex->IgnoreParenCasts();
+    const Expr *PeeledEx = peelOffOuterExpr(Ex, N);
+    if (Ex != PeeledEx)
+      S = PeeledEx;
+  }
 
   const Expr *Inner = 0;
   if (const Expr *Ex = dyn_cast<Expr>(S)) {
index e12612d8c4b49966a99421ff551d3f7b8f3ccdef..248d854dbc29b98b4035e11516c31d266f4a9287 100644 (file)
@@ -240,4 +240,29 @@ int ternaryRetNull(char cond) {
 #endif
 }
 
+// Test suppression of nested conditional operators.
+int testConditionalOperatorSuppress(int x) {
+  return *(x ? getNull() : getPtr());
+#ifndef SUPPRESSED
+  // expected-warning@-2 {{Dereference of null pointer}}
+#endif
+}
+int testNestedConditionalOperatorSuppress(int x) {
+  return *(x ? (x ? getNull() : getPtr()) : getPtr());
+#ifndef SUPPRESSED
+  // expected-warning@-2 {{Dereference of null pointer}}
+#endif
+}
+int testConditionalOperator(int x) {
+  return *(x ? 0 : getPtr()); // expected-warning {{Dereference of null pointer}}
+}
+int testNestedConditionalOperator(int x) {
+  return *(x ? (x ? 0 : getPtr()) : getPtr()); // expected-warning {{Dereference of null pointer}}
+}
+
+// False Positve - we are unable to suppress this case because the condition is
+// float.
+int testConditionalOperatorSuppressFloatCond(float x) {
+  return *(x ? getNull() : getPtr()); // expected-warning {{Dereference of null pointer}}
+}