From 8c30a5105f004e885ae81edbf9c1607547bd4ace Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Mon, 9 Mar 2009 20:34:10 +0100 Subject: [PATCH] re PR c++/39371 (Incorrectly rejects switch((unsigned int)boolvar)) PR c++/39371 * semantics.c (finish_switch_cond): Don't call get_unwidened. * decl.c (finish_case_label): Pass SWITCH_STMT_TYPE as 3rd argument instead of TREE_TYPE (cond). * g++.dg/opt/switch2.C: Add -w to dg-options. * g++.dg/warn/Wswitch-1.C: Adjust expected warnings. * g++.dg/warn/switch1.C: New test. * g++.dg/other/switch3.C: New test. From-SVN: r144732 --- gcc/cp/ChangeLog | 7 +++++++ gcc/cp/decl.c | 3 ++- gcc/cp/semantics.c | 14 -------------- gcc/testsuite/ChangeLog | 6 ++++++ gcc/testsuite/g++.dg/opt/switch2.C | 2 +- gcc/testsuite/g++.dg/other/switch3.C | 25 +++++++++++++++++++++++++ gcc/testsuite/g++.dg/warn/Wswitch-1.C | 6 +++--- gcc/testsuite/g++.dg/warn/switch1.C | 15 +++++++++++++++ 8 files changed, 59 insertions(+), 19 deletions(-) create mode 100644 gcc/testsuite/g++.dg/other/switch3.C create mode 100644 gcc/testsuite/g++.dg/warn/switch1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c4b151b79a8..e4161c504cb 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2009-03-09 Jakub Jelinek + + PR c++/39371 + * semantics.c (finish_switch_cond): Don't call get_unwidened. + * decl.c (finish_case_label): Pass SWITCH_STMT_TYPE as 3rd argument + instead of TREE_TYPE (cond). + 2009-03-08 H.J. Lu PR c++/39060 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 4ed342514b8..03e65d0f9db 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2806,7 +2806,8 @@ finish_case_label (tree low_value, tree high_value) if (!check_switch_goto (switch_stack->level)) return error_mark_node; - r = c_add_case_label (switch_stack->cases, cond, TREE_TYPE (cond), + r = c_add_case_label (switch_stack->cases, cond, + SWITCH_STMT_TYPE (switch_stack->switch_stmt), low_value, high_value); /* After labels, make any new cleanups in the function go into their diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 5f01a83c463..eb5d25ae80a 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -945,8 +945,6 @@ finish_switch_cond (tree cond, tree switch_stmt) tree orig_type = NULL; if (!processing_template_decl) { - tree index; - /* Convert the condition to an integer or enumeration type. */ cond = build_expr_type_conversion (WANT_INT | WANT_ENUM, cond, true); if (cond == NULL_TREE) @@ -963,18 +961,6 @@ finish_switch_cond (tree cond, tree switch_stmt) cond = perform_integral_promotions (cond); cond = maybe_cleanup_point_expr (cond); } - - if (cond != error_mark_node) - { - index = get_unwidened (cond, NULL_TREE); - /* We can't strip a conversion from a signed type to an unsigned, - because if we did, int_fits_type_p would do the wrong thing - when checking case values for being in range, - and it's too hard to do the right thing. */ - if (TYPE_UNSIGNED (TREE_TYPE (cond)) - == TYPE_UNSIGNED (TREE_TYPE (index))) - cond = index; - } } if (check_for_bare_parameter_packs (cond)) cond = error_mark_node; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 5329e909d54..60f2f92d3e9 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,11 @@ 2009-03-09 Jakub Jelinek + PR c++/39371 + * g++.dg/opt/switch2.C: Add -w to dg-options. + * g++.dg/warn/Wswitch-1.C: Adjust expected warnings. + * g++.dg/warn/switch1.C: New test. + * g++.dg/other/switch3.C: New test. + PR tree-optimization/39394 * gcc.c-torture/compile/pr39394.c: New test. diff --git a/gcc/testsuite/g++.dg/opt/switch2.C b/gcc/testsuite/g++.dg/opt/switch2.C index 2590273c5d9..f7374cb7474 100644 --- a/gcc/testsuite/g++.dg/opt/switch2.C +++ b/gcc/testsuite/g++.dg/opt/switch2.C @@ -1,5 +1,5 @@ // { dg-do compile } -// { dg-options "-O2" } +// { dg-options "-O2 -w" } extern int foo (int); diff --git a/gcc/testsuite/g++.dg/other/switch3.C b/gcc/testsuite/g++.dg/other/switch3.C new file mode 100644 index 00000000000..4f9b5485ef9 --- /dev/null +++ b/gcc/testsuite/g++.dg/other/switch3.C @@ -0,0 +1,25 @@ +// PR c++/39371 +// { dg-do compile } + +void +foo (bool b) +{ + switch ((unsigned int) b) + { + case 1: + case 2: + break; + } +} + +void +bar (unsigned char b) +{ + switch ((unsigned int) b) + { + case 1: + case 257: + case 513: + break; + } +} diff --git a/gcc/testsuite/g++.dg/warn/Wswitch-1.C b/gcc/testsuite/g++.dg/warn/Wswitch-1.C index 9b05cd16c5d..6a2094466cf 100644 --- a/gcc/testsuite/g++.dg/warn/Wswitch-1.C +++ b/gcc/testsuite/g++.dg/warn/Wswitch-1.C @@ -50,14 +50,14 @@ foo (int i, int j, enum e ei, enum e ej, enum e ek, enum e el, { case e1: return 1; case e2: return 2; - case 3: return 3; /* { dg-warning "case value '3' not in enumerated type 'e'" "excess 3" } */ + case 3: return 3; /* { dg-warning "exceeds maximum value" } */ } switch (ep) { case e1: return 1; case e2: return 2; - case 3: return 3; + case 3: return 3; /* { dg-warning "exceeds maximum value" } */ default: break; - } /* Since there is a default, no warning about ``case 3'' */ + } return 0; } diff --git a/gcc/testsuite/g++.dg/warn/switch1.C b/gcc/testsuite/g++.dg/warn/switch1.C new file mode 100644 index 00000000000..49c17e9120c --- /dev/null +++ b/gcc/testsuite/g++.dg/warn/switch1.C @@ -0,0 +1,15 @@ +// { dg-do compile { target { int32plus } } } + +signed char sc; + +void +foo (void) +{ + switch (sc) + { + case 1: + case 2 * __SCHAR_MAX__ + 3: // { dg-warning "case label value exceeds maximum" } + case - 2 * __SCHAR_MAX__ - 1: // { dg-warning "case label value is less than minimum" } + break; + } +}