Message ID | 20240329223101.421760-1-polacek@redhat.com |
---|---|
State | New |
Headers | show |
Series | c++: ICE with scoped enum in switch condition [PR114451] | expand |
On 3/29/24 18:31, Marek Polacek wrote: > Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/13? OK. > -- >8 -- > Here we ICE when gimplifying > > enum class Type { Pawn }; > struct Piece { > Type type : 4; > }; > void foo() { > switch (Piece().type) > case Type::Pawn:; > } > > because we ended up with TYPE_PRECISION (cond) < TYPE_PRECISION (case). > That's because the case expr type here is the unlowered type Type, > whereas the conditional's type is the lowered <unnamed-signed:4>. This > is not supposed to happen: see the comment in pop_switch around the > is_bitfield_expr_with_lowered_type check. > > But here we did not revert to the lowered SWITCH_STMT_TYPE, because > the conditional contains a TARGET_EXPR, which has side-effects, which > means that finish_switch_cond -> maybe_cleanup_point_expr wraps it > in a CLEANUP_POINT_EXPR. And is_bitfield_expr_with_lowered_type does > not see through those. > > PR c++/103825 > > gcc/cp/ChangeLog: > > * typeck.cc (is_bitfield_expr_with_lowered_type): Handle > CLEANUP_POINT_EXPR. > > gcc/testsuite/ChangeLog: > > * g++.dg/cpp0x/enum44.C: New test. > --- > gcc/cp/typeck.cc | 1 + > gcc/testsuite/g++.dg/cpp0x/enum44.C | 30 +++++++++++++++++++++++++++++ > 2 files changed, 31 insertions(+) > create mode 100644 gcc/testsuite/g++.dg/cpp0x/enum44.C > > diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc > index f5a0a2273be..9a096b51d55 100644 > --- a/gcc/cp/typeck.cc > +++ b/gcc/cp/typeck.cc > @@ -2400,6 +2400,7 @@ is_bitfield_expr_with_lowered_type (const_tree exp) > case NEGATE_EXPR: > case NON_LVALUE_EXPR: > case BIT_NOT_EXPR: > + case CLEANUP_POINT_EXPR: > return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); > > case COMPONENT_REF: > diff --git a/gcc/testsuite/g++.dg/cpp0x/enum44.C b/gcc/testsuite/g++.dg/cpp0x/enum44.C > new file mode 100644 > index 00000000000..92408c92217 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/cpp0x/enum44.C > @@ -0,0 +1,30 @@ > +// PR c++/103825 > +// { dg-do compile { target c++11 } } > + > +enum class Type { Pawn }; > +struct Piece { > + Type type : 4; > +}; > + > +void > +foo () > +{ > + switch (Piece().type) > + case Type::Pawn:; > + > + auto x = Piece().type; > + switch (x) > + case Type::Pawn:; > +} > + > +enum class En {A}; > +struct St {En field :1;}; > + > +void > +bar () > +{ > + volatile St s = {En::A}; > + switch(s.field) { > + case En::A : break; > + } > +} > > base-commit: 4c18ace1cb69a31af4ac719850a66de79ed12e93
diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index f5a0a2273be..9a096b51d55 100644 --- a/gcc/cp/typeck.cc +++ b/gcc/cp/typeck.cc @@ -2400,6 +2400,7 @@ is_bitfield_expr_with_lowered_type (const_tree exp) case NEGATE_EXPR: case NON_LVALUE_EXPR: case BIT_NOT_EXPR: + case CLEANUP_POINT_EXPR: return is_bitfield_expr_with_lowered_type (TREE_OPERAND (exp, 0)); case COMPONENT_REF: diff --git a/gcc/testsuite/g++.dg/cpp0x/enum44.C b/gcc/testsuite/g++.dg/cpp0x/enum44.C new file mode 100644 index 00000000000..92408c92217 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/enum44.C @@ -0,0 +1,30 @@ +// PR c++/103825 +// { dg-do compile { target c++11 } } + +enum class Type { Pawn }; +struct Piece { + Type type : 4; +}; + +void +foo () +{ + switch (Piece().type) + case Type::Pawn:; + + auto x = Piece().type; + switch (x) + case Type::Pawn:; +} + +enum class En {A}; +struct St {En field :1;}; + +void +bar () +{ + volatile St s = {En::A}; + switch(s.field) { + case En::A : break; + } +}