diff options
author | Jason Merrill <jason@redhat.com> | 2011-05-25 16:02:41 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2011-05-25 16:02:41 -0400 |
commit | de69121325ce8e05adb106c87acaeadf1bba61e0 (patch) | |
tree | f31e62ba5d84a403470febb8740f225d5c3578b9 /gcc | |
parent | f03a54024372021a572dd23893982ef2ba0e941e (diff) | |
download | gcc-de69121325ce8e05adb106c87acaeadf1bba61e0.zip gcc-de69121325ce8e05adb106c87acaeadf1bba61e0.tar.gz gcc-de69121325ce8e05adb106c87acaeadf1bba61e0.tar.bz2 |
re PR c++/44311 ([C++0x] no error with switch over enum class and integer case)
PR c++/44311
* decl.c (case_conversion): New.
(finish_case_label): Use it.
From-SVN: r174231
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/cp/ChangeLog | 4 | ||||
-rw-r--r-- | gcc/cp/decl.c | 34 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 3 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C | 23 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/enum15.C | 20 |
5 files changed, 78 insertions, 6 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index c0677cc..1b61193 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,9 @@ 2011-05-25 Jason Merrill <jason@redhat.com> + PR c++/44311 + * decl.c (case_conversion): New. + (finish_case_label): Use it. + * ptree.c (cxx_print_xnode): Handle ARGUMENT_PACK_SELECT. PR c++/45698 diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 2b6a777..7fc1945 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2957,6 +2957,28 @@ pop_switch (void) free (cs); } +/* Convert a case constant VALUE in a switch to the type TYPE of the switch + condition. Note that if TYPE and VALUE are already integral we don't + really do the conversion because the language-independent + warning/optimization code will work better that way. */ + +static tree +case_conversion (tree type, tree value) +{ + if (value == NULL_TREE) + return value; + + if (cxx_dialect >= cxx0x + && (SCOPED_ENUM_P (type) + || !INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (TREE_TYPE (value)))) + { + if (INTEGRAL_OR_UNSCOPED_ENUMERATION_TYPE_P (type)) + type = type_promotes_to (type); + value = perform_implicit_conversion (type, value, tf_warning_or_error); + } + return cxx_constant_value (value); +} + /* Note that we've seen a definition of a case label, and complain if this is a bad place for one. */ @@ -2965,6 +2987,7 @@ finish_case_label (location_t loc, tree low_value, tree high_value) { tree cond, r; struct cp_binding_level *p; + tree type; if (processing_template_decl) { @@ -2984,13 +3007,12 @@ finish_case_label (location_t loc, tree low_value, tree high_value) if (!check_switch_goto (switch_stack->level)) return error_mark_node; - if (low_value) - low_value = cxx_constant_value (low_value); - if (high_value) - high_value = cxx_constant_value (high_value); + type = SWITCH_STMT_TYPE (switch_stack->switch_stmt); + + low_value = case_conversion (type, low_value); + high_value = case_conversion (type, high_value); - r = c_add_case_label (loc, switch_stack->cases, cond, - SWITCH_STMT_TYPE (switch_stack->switch_stmt), + r = c_add_case_label (loc, switch_stack->cases, cond, type, low_value, high_value); /* After labels, make any new cleanups in the function go into their diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 2a30f6e..e8a335f 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2011-05-25 Jason Merrill <jason@redhat.com> + * g++.dg/cpp0x/enum15.C: New. + * g++.dg/cpp0x/constexpr-switch2.C: New. + * g++.dg/cpp0x/variadic110.C: New. * g++.dg/cpp0x/auto9.C: Add typedef test. diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C new file mode 100644 index 0000000..55cf2ad --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C @@ -0,0 +1,23 @@ +// Test for constexpr conversion in case context +// { dg-options -std=c++0x } + +enum class E { e1, e2 }; + +struct A +{ + E e; + constexpr operator E() { return e; } + constexpr A(E e): e(e) { } +}; + +E e; + +int main() +{ + switch (e) + { + case A(E::e1): + case A(E::e2): + ; + } +} diff --git a/gcc/testsuite/g++.dg/cpp0x/enum15.C b/gcc/testsuite/g++.dg/cpp0x/enum15.C new file mode 100644 index 0000000..d653216 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/enum15.C @@ -0,0 +1,20 @@ +// PR c++/44311 +// { dg-options -std=c++0x } + +enum class A { Val0, Val1 }; + +void foo (A a, int i) +{ + switch (a) + { + case A::Val0: break; + case 1: break; // { dg-error "" } + } + + switch (i) + { + case A::Val0: break; // { dg-error "" } + case 1: break; + case 2.0: break; + } +} |