Message ID | 4DDA743A.7000604@redhat.com |
---|---|
State | New |
Headers | show |
On Mon, May 23, 2011 at 4:50 PM, Jason Merrill <jason@redhat.com> wrote: > C++0x scoped enums don't implicitly convert to an integral type, so we need > to be careful about throwing away explicit conversions. In this case, the > static_cast<int>(e) creates a NOP_EXPR which get_narrower throws away, but > 'e' itself is not a valid argument for &, so we need to replace the NOP_EXPR > with a different one. > > Tested x86_64-pc-linux-gnu. OK for trunk? Ok. Though I wonder where you enter folding before you check semantic validity. Thanks, Richard.
On 05/23/2011 11:01 AM, Richard Guenther wrote: > Ok. Though I wonder where you enter folding before you check semantic > validity. The problem is in c-common:shorten_binary_op, which uses get_narrower and then calls common_type on the types of the results. There is no common type between a scoped enum and char, so common_type returns NULL_TREE, so we get a SEGV in c_common_signed_or_unsigned_type. Do you think I should change shorten_binary_op instead? Jason
On Mon, May 23, 2011 at 5:38 PM, Jason Merrill <jason@redhat.com> wrote: > On 05/23/2011 11:01 AM, Richard Guenther wrote: >> >> Ok. Though I wonder where you enter folding before you check semantic >> validity. > > The problem is in c-common:shorten_binary_op, which uses get_narrower and > then calls common_type on the types of the results. There is no common type > between a scoped enum and char, so common_type returns NULL_TREE, so we get > a SEGV in c_common_signed_or_unsigned_type. > > Do you think I should change shorten_binary_op instead? Yeah, that might constrain it to C family languages. shorten_binary_op is one of our premature optimization things anyway, best to slowly go away ... Richard. > Jason >
commit 8f9cf5d22de2418bdb2ab9cb79ae878f809299ec Author: Jason Merrill <jason@redhat.com> Date: Sun May 22 15:21:19 2011 -0400 PR c++/48106 * tree.c (get_narrower): Handle scoped enum. diff --git a/gcc/testsuite/g++.dg/cpp0x/enum14.C b/gcc/testsuite/g++.dg/cpp0x/enum14.C new file mode 100644 index 0000000..709b201 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/enum14.C @@ -0,0 +1,12 @@ +// PR c++/48106 +// { dg-options -std=c++0x } + +enum class E : char +{ + e +}; + +bool operator&(E e, char m) +{ + return static_cast<int>(e) & m; +} diff --git a/gcc/tree.c b/gcc/tree.c index 3357d84..99402e8 100644 --- a/gcc/tree.c +++ b/gcc/tree.c @@ -8117,6 +8117,17 @@ get_narrower (tree op, int *unsignedp_ptr) win = fold_convert (type, op); } } + else if (TREE_CODE (TREE_TYPE (op)) == ENUMERAL_TYPE + && ENUM_IS_SCOPED (TREE_TYPE (op))) + { + /* C++0x scoped enumerations don't implicitly convert to integral + type, so if we stripped an explicit conversion to a larger type we + need to replace it. */ + tree type = (lang_hooks.types.type_for_size + (TYPE_PRECISION (TREE_TYPE (op)), + TYPE_UNSIGNED (TREE_TYPE (op)))); + win = fold_convert (type, op); + } *unsignedp_ptr = uns; return win;