Created attachment 49640 [details] Preprocessed source code Compiling the following code crashes g++-10 and g++-11, but not g++-9: // g++ -std=c++2a -o /tmp/example.cpp.o -c example.cpp enum class MyEnumClass { A }; struct MyClass { MyEnumClass foobar : 8 { MyEnumClass::A }; }; bool some_function(MyClass x) { switch (x.foobar) { case MyEnumClass::A: return false; } } See at the bottom the exact invocation, error messages, and g++ versions. The enum-class, bit-packing, the seemingly incomplete switch-case, non-constant switch-argument, all seem to be necessary to trigger the bug. This bug seems very similar to https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97634 , but it's a different platform. Feel free to merge if it's the same bug. * What was the outcome of this action? Compiler crash (error message see below) * What outcome did you expect instead? Either a successful compilation, or a compilation error; but not a compiler crash. Full error message and versions: $ /usr/bin/g++-9 --version g++-9 (Debian 9.3.0-18) 9.3.0 Copyright (C) 2019 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ /usr/bin/g++-9 -std=c++2a -o /tmp/example.cpp.o -c example.cpp example.cpp: In function ‘bool some_function(MyClass)’: example.cpp:12:1: warning: control reaches end of non-void function [-Wreturn- type] 12 | } | ^ $ /usr/bin/g++-10 --version g++-10 (Debian 10.2.0-16) 10.2.0 Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ /usr/bin/g++-10 -std=c++2a -o /tmp/example.cpp.o -c example.cpp example.cpp: In function ‘bool some_function(MyClass)’: example.cpp:6:6: error: type precision mismatch in switch statement 6 | bool some_function(MyClass x) | ^~~~~~~~~~~~~ switch (_1) <default: <D.2095>, case 0: <D.2092>> example.cpp:6:6: internal compiler error: ‘verify_gimple’ failed 0x128422d verify_gimple_in_seq(gimple*) ../../src/gcc/tree-cfg.c:5144 0xf85436 gimplify_body(tree_node*, bool) ../../src/gcc/gimplify.c:14888 0xf856a3 gimplify_function_tree(tree_node*) ../../src/gcc/gimplify.c:14978 0xdbbe27 cgraph_node::analyze() ../../src/gcc/cgraphunit.c:670 0xdbee27 analyze_functions ../../src/gcc/cgraphunit.c:1227 0xdbf9f2 symbol_table::finalize_compilation_unit() ../../src/gcc/cgraphunit.c:2986 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <file:///usr/share/doc/gcc-10/README.Bugs> for instructions. $ /usr/lib/gcc-snapshot/bin/g++ --version g++ (Debian 20201127-1) 11.0.0 20201127 (experimental) [master revision 3493b0c3281:5c47353bc97:5e9f814d754be790aec5b69a95699a8af2654058] Copyright (C) 2020 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. $ /usr/lib/gcc-snapshot/bin/g++ -std=c++2a -o /tmp/example.cpp.o -c example.cpp example.cpp: In function 'bool some_function(MyClass)': example.cpp:6:6: error: type precision mismatch in switch statement 6 | bool some_function(MyClass x) | ^~~~~~~~~~~~~ switch (_1) <default: <D.2107>, case 0: <D.2104>> example.cpp:6:6: internal compiler error: 'verify_gimple' failed 0x12f35bd verify_gimple_in_seq(gimple*) ../../src/gcc/tree-cfg.c:5119 0x1006b66 gimplify_body(tree_node*, bool) ../../src/gcc/gimplify.c:15329 0x1006ced gimplify_function_tree(tree_node*) ../../src/gcc/gimplify.c:15400 0xe37367 cgraph_node::analyze() ../../src/gcc/cgraphunit.c:670 0xe39e27 analyze_functions ../../src/gcc/cgraphunit.c:1235 0xe3aa1d symbol_table::finalize_compilation_unit() ../../src/gcc/cgraphunit.c:2513 Please submit a full bug report, with preprocessed source if appropriate. Please include the complete backtrace with any bug report. See <file:///usr/share/doc/gcc-snapshot/README.Bugs> for instructions. Downstream ticket: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=976024 Your bugs page says you also want a preprocessed source – I don't see how it's useful, but sure: Please find attached the preprocessed file "example.ii". Cheers, Ben
Started with Jakub's revision.
The ICE is much older is you remove the for the ICE unnecessary C++20 initializer of the bitfield. enum class B { A }; struct C { B c : 8; }; bool foo (C x) { switch (x.c) { case B::A: return false; default: return true; } }
Mine then.
Candidate fix: --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -3711,6 +3711,10 @@ pop_switch (void) SWITCH_STMT_ALL_CASES_P (cs->switch_stmt) = 1; if (!cs->break_stmt_seen_p) SWITCH_STMT_NO_BREAK_P (cs->switch_stmt) = 1; + if (SWITCH_STMT_TYPE (cs->switch_stmt) + && SCOPED_ENUM_P (SWITCH_STMT_TYPE (cs->switch_stmt))) + SWITCH_STMT_TYPE (cs->switch_stmt) + = TREE_TYPE (SWITCH_STMT_COND (cs->switch_stmt)); gcc_assert (!cs->in_loop_body_p); splay_tree_delete (cs->cases); switch_stack = switch_stack->next;
The master branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:7482d5a3acb7a8a5564f5cddc4f9d2ebbaea75e4 commit r11-5829-g7482d5a3acb7a8a5564f5cddc4f9d2ebbaea75e4 Author: Marek Polacek <polacek@redhat.com> Date: Wed Dec 2 10:47:49 2020 -0500 c++: ICE with switch and scoped enum bit-fields [PR98043] In this testcase we are crashing trying to gimplify a switch, because the types of the switch condition and case constants have different TYPE_PRECISIONs. This started with my r5-3726 fix: SWITCH_STMT_TYPE is supposed to be the original type of the switch condition before any conversions, so in the C++ FE we need to use unlowered_expr_type to get the unlowered type of enum bit-fields. Normally, the switch type is subject to integral promotions, but here we have a scoped enum type and those don't promote: enum class B { A }; struct C { B c : 8; }; switch (x.c) // type B case B::A: // type int, will be converted to B Here TREE_TYPE is "signed char" but SWITCH_STMT_TYPE is "B". When gimplifying this in gimplify_switch_expr, the index type is "B" and we convert all the case values to "B" in preprocess_case_label_vec, but SWITCH_COND is of type "signed char": gimple_switch_index should be the (possibly promoted) type, not the original type, so we gimplify the "x.c" SWITCH_COND to a SSA_NAME of type "signed char". And then we crash because the precision of the index type doesn't match the precision of the case value type. I think it makes sense to do the following; at the end of pop_switch we've already issued the switch warnings, and since scoped enums don't promote, it should be okay to use the type of SWITCH_STMT_COND. The r5-3726 change was about giving warnings for enum bit-fields anyway. gcc/cp/ChangeLog: PR c++/98043 * decl.c (pop_switch): If SWITCH_STMT_TYPE is a scoped enum type, set it to the type of SWITCH_STMT_COND. gcc/testsuite/ChangeLog: PR c++/98043 * g++.dg/cpp0x/enum41.C: New test.
Fixed on trunk thus far.
A testcase got added in PR 98043. Yay! The testcase contains a `default:` in the switch-case statement. Wasn't it the case that the bug got triggered by a *lack* of `default:` case?
(In reply to Ben Wiederhake from comment #7) > A testcase got added in PR 98043. Yay! > > The testcase contains a `default:` in the switch-case statement. Wasn't it > the case that the bug got triggered by a *lack* of `default:` case? No, it was about a type mismatch between the type of the controlling expression, and the type of the case value. Thanks for reporting this issue.
I totally forgot to say it: Thanks for fixing it so quickly! :D When I saw https://gcc.gnu.org/bugzilla/show_bug.cgi?id=97634 I was afraid it would suffer a slow death – but nope, fixed within a few days. Awesome! Now I only have to wait for the next release, and my OS's package maintainers. :)
*** Bug 97634 has been marked as a duplicate of this bug. ***
The releases/gcc-10 branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:48aa64322e824d674b955459ea3816f3047629a3 commit r10-9206-g48aa64322e824d674b955459ea3816f3047629a3 Author: Marek Polacek <polacek@redhat.com> Date: Wed Dec 2 10:47:49 2020 -0500 c++: ICE with switch and scoped enum bit-fields [PR98043] In this testcase we are crashing trying to gimplify a switch, because the types of the switch condition and case constants have different TYPE_PRECISIONs. This started with my r5-3726 fix: SWITCH_STMT_TYPE is supposed to be the original type of the switch condition before any conversions, so in the C++ FE we need to use unlowered_expr_type to get the unlowered type of enum bit-fields. Normally, the switch type is subject to integral promotions, but here we have a scoped enum type and those don't promote: enum class B { A }; struct C { B c : 8; }; switch (x.c) // type B case B::A: // type int, will be converted to B Here TREE_TYPE is "signed char" but SWITCH_STMT_TYPE is "B". When gimplifying this in gimplify_switch_expr, the index type is "B" and we convert all the case values to "B" in preprocess_case_label_vec, but SWITCH_COND is of type "signed char": gimple_switch_index should be the (possibly promoted) type, not the original type, so we gimplify the "x.c" SWITCH_COND to a SSA_NAME of type "signed char". And then we crash because the precision of the index type doesn't match the precision of the case value type. I think it makes sense to do the following; at the end of pop_switch we've already issued the switch warnings, and since scoped enums don't promote, it should be okay to use the type of SWITCH_STMT_COND. The r5-3726 change was about giving warnings for enum bit-fields anyway. gcc/cp/ChangeLog: PR c++/98043 * decl.c (pop_switch): If SWITCH_STMT_TYPE is a scoped enum type, set it to the type of SWITCH_STMT_COND. gcc/testsuite/ChangeLog: PR c++/98043 * g++.dg/cpp0x/enum41.C: New test. (cherry picked from commit 7482d5a3acb7a8a5564f5cddc4f9d2ebbaea75e4)
Fixed in GCC 10 too.