https://gcc.gnu.org/g:daa2e7c7ffe49b788357f7f2c9ef1c9b125c1f8c
commit r14-9758-gdaa2e7c7ffe49b788357f7f2c9ef1c9b125c1f8c Author: Marek Polacek <pola...@redhat.com> Date: Fri Mar 29 16:59:37 2024 -0400 c++: ICE with scoped enum in switch condition [PR103825] 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. Diff: --- gcc/cp/typeck.cc | 1 + gcc/testsuite/g++.dg/cpp0x/enum44.C | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/gcc/cp/typeck.cc b/gcc/cp/typeck.cc index 88ed38e4f30..e5a52dc2b39 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; + } +}