]> granicus.if.org Git - clang/commitdiff
Fix handling in GRExprEngine of 'default' branch in switch statements
authorTed Kremenek <kremenek@apple.com>
Fri, 8 Jan 2010 18:54:04 +0000 (18:54 +0000)
committerTed Kremenek <kremenek@apple.com>
Fri, 8 Jan 2010 18:54:04 +0000 (18:54 +0000)
when the default case is winnowed down to be infeasible.  When all
cases were ruled out (and the analysis state for the default case
would be infeasible) we would still consider the default case
possible.  This fixes PR 5969.

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

lib/Analysis/GRExprEngine.cpp
test/Analysis/misc-ps-ranges.m

index 3c2512215a36b740d213243dd5871f5e4ed16733..0336ae5ada3b214188c7bcd18c18ae36313d2792 100644 (file)
@@ -1221,7 +1221,8 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
 
     do {
       nonloc::ConcreteInt CaseVal(getBasicVals().getValue(V1.Val.getInt()));
-      DefinedOrUnknownSVal Res = SVator.EvalEQ(DefaultSt, CondV, CaseVal);
+      DefinedOrUnknownSVal Res = SVator.EvalEQ(DefaultSt ? DefaultSt : state,
+                                               CondV, CaseVal);
             
       // Now "assume" that the case matches.
       if (const GRState* stateNew = state->Assume(Res, true)) {
@@ -1236,11 +1237,17 @@ void GRExprEngine::ProcessSwitch(GRSwitchNodeBuilder& builder) {
 
       // Now "assume" that the case doesn't match.  Add this state
       // to the default state (if it is feasible).
-      if (const GRState *stateNew = DefaultSt->Assume(Res, false)) {
-        defaultIsFeasible = true;
-        DefaultSt = stateNew;
+      if (DefaultSt) {
+        if (const GRState *stateNew = DefaultSt->Assume(Res, false)) {
+          defaultIsFeasible = true;
+          DefaultSt = stateNew;
+        }
+        else {
+          defaultIsFeasible = false;
+          DefaultSt = NULL;
+        }
       }
-
+        
       // Concretize the next value in the range.
       if (V1.Val.getInt() == V2.Val.getInt())
         break;
index 760b4d743357c1c466423554adf88654ff315af3..df7e97c46736060b59e7f47d9cf8a5bfd213133e 100644 (file)
@@ -21,3 +21,40 @@ int main(int argc, char* argv[]) {
 
   return *p; // no-warning
 }
+
+// PR 5969: the comparison of argc < 3 || argc > 4 should constraint the switch
+//  statement from having the 'default' branch taken.  This previously reported a false
+//  positive with the use of 'v'.
+
+int pr5969(int argc, char *argv[]) {
+
+  int v;
+
+  if ((argc < 3) || (argc > 4)) return 0;
+
+  switch(argc) {
+    case 3:
+      v = 33;
+      break;
+    case 4:
+      v = 44;
+      break;
+  }
+
+  return v; // no-warning
+}
+
+int pr5969_positive(int argc, char *argv[]) {
+
+  int v;
+
+  if ((argc < 3) || (argc > 4)) return 0;
+
+  switch(argc) {
+    case 3:
+      v = 33;
+      break;
+  }
+
+  return v; // expected-warning{{Undefined or garbage value returned to caller}}
+}