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
This commit is contained in:
Jason Merrill 2011-05-25 16:02:41 -04:00 committed by Jason Merrill
parent f03a540243
commit de69121325
5 changed files with 78 additions and 6 deletions

View File

@ -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

View File

@ -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);
r = c_add_case_label (loc, switch_stack->cases, cond,
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, type,
low_value, high_value);
/* After labels, make any new cleanups in the function go into their

View File

@ -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.

View File

@ -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):
;
}
}

View File

@ -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;
}
}