re PR c++/20008 (internal compiler error: in expand_case, at stmt.c:2397)
authorAlexandre Oliva <aoliva@redhat.com>
Fri, 18 Feb 2005 12:20:49 +0000 (12:20 +0000)
committerAlexandre Oliva <aoliva@gcc.gnu.org>
Fri, 18 Feb 2005 12:20:49 +0000 (12:20 +0000)
gcc/ChangeLog:
PR c++/20008
* stmt.c (expand_case): Don't assume cleanup_tree_cfg will remove
cases that are out-of-range for the index type.
gcc/testsuite/ChangeLog:
PR c++/20008
* g++.dg/opt/switch4.C: New.

From-SVN: r95225

gcc/ChangeLog
gcc/stmt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/opt/switch4.C [new file with mode: 0644]

index ca5a33b871ca6a5add257309371105f3e5a31a7c..61ea0ad332c03504fbad122b480eb73a8e5228a6 100644 (file)
@@ -1,3 +1,9 @@
+2005-02-18  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR c++/20008
+       * stmt.c (expand_case): Don't assume cleanup_tree_cfg will remove
+       cases that are out-of-range for the index type.
+
 2005-02-18  James A. Morrison  <phython@gcc.gnu.org>
 
        * stmt.c (emit_case_bit_tests): Call fold_convert instead of convert.
index a438532b11bb3f0242102e85747b96658dde0463..64e070b5a0a707bf5d578cd0c3a0455500e445a5 100644 (file)
@@ -2394,8 +2394,14 @@ expand_case (tree exp)
       BITMAP_FREE (label_bitmap);
 
       /* cleanup_tree_cfg removes all SWITCH_EXPR with a single
-        destination, such as one with a default case only.  */
-      gcc_assert (count != 0);
+        destination, such as one with a default case only.  However,
+        it doesn't remove cases that are out of range for the switch
+        type, so we may still get a zero here.  */
+      if (count == 0)
+       {
+         emit_jump (default_label);
+         return;
+       }
 
       /* Compute span of values.  */
       range = fold (build2 (MINUS_EXPR, index_type, maxval, minval));
index 668d6e471c3531b39b09c71d2c15c02c9262c759..7d653eca38b69a325cf6b4536422d52ca1d905d0 100644 (file)
@@ -1,3 +1,8 @@
+2005-02-18  Alexandre Oliva  <aoliva@redhat.com>
+
+       PR c++/20008
+       * g++.dg/opt/switch4.C: New.
+
 2005-02-18  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/20023
diff --git a/gcc/testsuite/g++.dg/opt/switch4.C b/gcc/testsuite/g++.dg/opt/switch4.C
new file mode 100644 (file)
index 0000000..231929f
--- /dev/null
@@ -0,0 +1,30 @@
+// { dg-do compile }
+
+// PR c++/20008
+
+// We failed to compile this because CFG cleanup left the switch
+// statement intact, whereas expand_case expected at least one
+// in-range case to remain.
+
+typedef enum _SECStatus {
+  SECWouldBlock = -2,
+  SECFailure = -1,
+  SECSuccess = 0
+} SECStatus;
+
+typedef enum {
+  SEC_ERROR_BAD_SIGNATURE = (-0x2000) + 10
+} SECErrorCodes;
+
+void g(void);
+void f(SECStatus status)
+{
+  switch( status )
+    {
+    case SEC_ERROR_BAD_SIGNATURE :
+      // This case can be optimized away in C++ (but apparently not in
+      // C), because the enum type is defined with a narrow range.
+      g();
+      break ;
+    }
+}