re PR c++/20008 (internal compiler error: in expand_case, at stmt.c:2397)
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
This commit is contained in:
parent
aeba6c285a
commit
2aabee29e1
4 changed files with 49 additions and 2 deletions
|
@ -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.
|
||||
|
|
10
gcc/stmt.c
10
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));
|
||||
|
|
|
@ -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
|
||||
|
|
30
gcc/testsuite/g++.dg/opt/switch4.C
Normal file
30
gcc/testsuite/g++.dg/opt/switch4.C
Normal file
|
@ -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 ;
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue