diff options
-rw-r--r-- | gcc/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/stmt.c | 10 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/opt/switch4.C | 30 |
4 files changed, 49 insertions, 2 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ca5a33b871c..61ea0ad332c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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. diff --git a/gcc/stmt.c b/gcc/stmt.c index a438532b11b..64e070b5a0a 100644 --- a/gcc/stmt.c +++ b/gcc/stmt.c @@ -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)); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 668d6e471c3..7d653eca38b 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 index 00000000000..231929fdf3d --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/switch4.C @@ -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 ; + } +} |