This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C++ PATCH for c++/65556 (ICE with switch and bit-fields)
- From: "H.J. Lu" <hjl dot tools at gmail dot com>
- To: Marek Polacek <polacek at redhat dot com>
- Cc: GCC Patches <gcc-patches at gcc dot gnu dot org>, Jason Merrill <jason at redhat dot com>
- Date: Fri, 27 Mar 2015 16:24:35 -0700
- Subject: Re: C++ PATCH for c++/65556 (ICE with switch and bit-fields)
- Authentication-results: sourceware.org; auth=none
- References: <20150327143810 dot GC25731 at redhat dot com>
On Fri, Mar 27, 2015 at 7:38 AM, Marek Polacek <polacek@redhat.com> wrote:
> In this testcase we were crashing while trying to gimplify a switch, because
> the types of the switch condition and case constants didn't match. This ICE
> started with my -Wswitch-with-enum-bit-fields fix where I used the unlowered
> type so that we're able to get hold of the enum type. The problem with that
> is with ordinary bit-fields: we'll get the underlying type (e.g. long int),
> but subsequent perform_integral_promotions promotes that to int, see
> cp_perform_integral_promotions. Fixed by using the type of the condition in
> case we're not dealing with an enum bit-field, i.e. do what we've been doing
> before the -Wswitch fix, which ought to make this fix very safe.
>
> Bootstrapped/regtested on x86_64-linux, ok for trunk?
>
> 2015-03-27 Marek Polacek <polacek@redhat.com>
>
> PR c++/65556
> * semantics.c (finish_switch_cond): If the unlowered type is not an
> enum, use the type of the condition.
>
> * c-c++-common/pr65556.c: New test.
>
> diff --git gcc/cp/semantics.c gcc/cp/semantics.c
> index f325e41..74af7e8 100644
> --- gcc/cp/semantics.c
> +++ gcc/cp/semantics.c
> @@ -1165,6 +1165,8 @@ finish_switch_cond (tree cond, tree switch_stmt)
> }
> /* We want unlowered type here to handle enum bit-fields. */
> orig_type = unlowered_expr_type (cond);
> + if (TREE_CODE (orig_type) != ENUMERAL_TYPE)
> + orig_type = TREE_TYPE (cond);
> if (cond != error_mark_node)
> {
> /* Warn if the condition has boolean value. */
> diff --git gcc/testsuite/c-c++-common/pr65556.c gcc/testsuite/c-c++-common/pr65556.c
> index e69de29..c6729a1 100644
> --- gcc/testsuite/c-c++-common/pr65556.c
> +++ gcc/testsuite/c-c++-common/pr65556.c
> @@ -0,0 +1,23 @@
> +/* PR c++/65556 */
> +/* { dg-do compile } */
> +
> +struct S
> +{
> + long l: 1;
> + long l2: 41;
> + unsigned long ul: 1;
> + unsigned long ul2: 41;
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
This won't work with 32-bit long.
--
H.J.