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:
parent
f03a540243
commit
de69121325
@ -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
|
||||
|
@ -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
|
||||
|
@ -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.
|
||||
|
23
gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C
Normal file
23
gcc/testsuite/g++.dg/cpp0x/constexpr-switch2.C
Normal 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):
|
||||
;
|
||||
}
|
||||
}
|
20
gcc/testsuite/g++.dg/cpp0x/enum15.C
Normal file
20
gcc/testsuite/g++.dg/cpp0x/enum15.C
Normal 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;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user