Noticed ICE today when was building dolpjin-emu with a weekly gcc snapshot and current gcc master. Minimal reproducer: // $ cat bug.cc struct TVec3 { TVec3(); int data; }; using Vec3 = TVec3; struct { Vec3 position{}; } EmulatePoint_state; void EmulatePoint() { EmulatePoint_state = {}; } /tmp/gcc/xg++ -B/tmp/gcc -c bug.cc -freport-bug bug.cc: In function ‘void EmulatePoint()’: bug.cc:9:42: internal compiler error: in cp_gimplify_expr, at cp/cp-gimplify.cc:746 9 | void EmulatePoint() { EmulatePoint_state = {}; } | ~~~~~~~~~~~~~~~~~~~^~~~ 0x7a0fb2 cp_gimplify_expr(tree_node**, gimple**, gimple**) /home/slyfox/dev/git/gcc/gcc/cp/cp-gimplify.cc:746 0xd9fb80 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) /home/slyfox/dev/git/gcc/gcc/gimplify.cc:14893 0xdab095 gimplify_init_ctor_preeval /home/slyfox/dev/git/gcc/gcc/gimplify.cc:4678 0xdab19d gimplify_init_ctor_preeval /home/slyfox/dev/git/gcc/gcc/gimplify.cc:4664 0xdac73d gimplify_init_constructor /home/slyfox/dev/git/gcc/gcc/gimplify.cc:5243 0xdacf76 gimplify_modify_expr_rhs /home/slyfox/dev/git/gcc/gcc/gimplify.cc:5560 0xdad79f gimplify_modify_expr /home/slyfox/dev/git/gcc/gcc/gimplify.cc:5926 0xd9b0b1 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) /home/slyfox/dev/git/gcc/gcc/gimplify.cc:14984 0xda029d gimplify_stmt(tree_node**, gimple**) /home/slyfox/dev/git/gcc/gcc/gimplify.cc:7039 0xda18fc gimplify_cleanup_point_expr /home/slyfox/dev/git/gcc/gcc/gimplify.cc:6778 0xd9c491 gimplify_expr(tree_node**, gimple**, gimple**, bool (*)(tree_node*), int) /home/slyfox/dev/git/gcc/gcc/gimplify.cc:15377 0xda029d gimplify_stmt(tree_node**, gimple**) /home/slyfox/dev/git/gcc/gcc/gimplify.cc:7039 0xda1e49 gimplify_body(tree_node*, bool) /home/slyfox/dev/git/gcc/gcc/gimplify.cc:16230 0xda2365 gimplify_function_tree(tree_node*) /home/slyfox/dev/git/gcc/gcc/gimplify.cc:16384 0xbaceda cgraph_node::analyze() /home/slyfox/dev/git/gcc/gcc/cgraphunit.cc:675 0xbaf6a5 analyze_functions /home/slyfox/dev/git/gcc/gcc/cgraphunit.cc:1240 0xbb0795 symbol_table::finalize_compilation_unit() /home/slyfox/dev/git/gcc/gcc/cgraphunit.cc:2500 Please submit a full bug report, with preprocessed source. Please include the complete backtrace with any bug report. See <https://gcc.gnu.org/bugs/> for instructions. Preprocessed source stored into /tmp/ccpGKHxu.out file, please attach this to your bugreport. $ /tmp/gcc/xg++ -B/tmp/gcc -v Reading specs from /tmp/gcc/specs COLLECT_GCC=/tmp/gcc/xg++ COLLECT_LTO_WRAPPER=/tmp/gcc/lto-wrapper Target: x86_64-pc-linux-gnu Configured with: /home/slyfox/dev/git/gcc/configure --disable-multilib --disable-bootstrap --with-native-system-header-dir=/nix/store/vccvfa5bjb9dv4x6zq5gjf1yp58y4brg-glibc-2.33-108-dev/include --prefix=/tmp/__td__ CFLAGS='-O1 -ggdb3' CXXFLAGS='-O1 -ggdb3' LDFLAGS='-O1 -ggdb3' Thread model: posix Supported LTO compression algorithms: zlib gcc version 12.0.1 20220217 (experimental) (GCC)
Started with r10-5822-g08f594eb399dab0637b57b0ca4b0a5ce912b8171
Note I noticed it does not ICE with -std=c++11 . Nor with --enable-checking=release
The attached 93280 test no longer ICEs but looks like it was never added to the testsuite. The 104583 test, modified so that it closely resembles 93280, still ICEs. The problem is that in 104583 we have a value-init from {}, so this code in convert_like_internal 7960 /* If we're initializing from {}, it's value-initialization. */ 7961 if (BRACE_ENCLOSED_INITIALIZER_P (expr) 7962 && CONSTRUCTOR_NELTS (expr) == 0 7963 && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype) 7964 && !processing_template_decl) 7965 { 7966 bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr); ... 7974 TARGET_EXPR_DIRECT_INIT_P (expr) = direct; sets TARGET_EXPR_DIRECT_INIT_P (line #1 in 104583). This does not happen in 93280. When gimplifying, the #2 line, we have d = {.a=TARGET_EXPR <D.2474, <<< Unknown tree: aggr_init_expr 4 __ct_comp D.2474 (struct A *) <<< Unknown tree: void_cst >>> >>>>} where the TARGET_EXPR is the one with TARGET_EXPR_DIRECT_INIT_P set. In gimplify_init_ctor_preeval we do 4724 FOR_EACH_VEC_SAFE_ELT (v, ix, ce) 4725 gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data); so we gimplify the TARGET_EXPR, crashing at 744 case TARGET_EXPR: 745 /* A TARGET_EXPR that expresses direct-initialization should have been 746 elided by cp_gimplify_init_expr. */ 747 gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p)); but there is no INIT_EXPR so cp_gimplify_init_expr was never called! // 93280.C struct A { template <typename T> A(T); int c; }; struct D { A a{0}; }; void f() { D d; d = {}; } // 104583.C struct A { A(); int c; }; struct D { A a{}; // #1 }; void g() { D d; d = {}; // #2 }
Candidate fix: --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -679,10 +679,10 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain) if (simple_target) init = TARGET_EXPR_INITIAL (init); init = break_out_target_exprs (init, /*loc*/true); - if (in_ctor && init && TREE_CODE (init) == TARGET_EXPR) - /* This expresses the full initialization, prevent perform_member_init from - calling another constructor (58162). */ - TARGET_EXPR_DIRECT_INIT_P (init) = true; + if (init && TREE_CODE (init) == TARGET_EXPR) + /* If this expresses the full initialization, prevent perform_member_init + from calling another constructor (58162). */ + TARGET_EXPR_DIRECT_INIT_P (init) = in_ctor; if (simple_target && TREE_CODE (init) != CONSTRUCTOR) /* Now put it back so C++17 copy elision works. */ init = get_target_expr (init);
Patch posted.
The trunk branch has been updated by Marek Polacek <mpolacek@gcc.gnu.org>: https://gcc.gnu.org/g:f8c1f29a0b47b4b4a3c1506678f7ca2ce4b7ffbb commit r12-7919-gf8c1f29a0b47b4b4a3c1506678f7ca2ce4b7ffbb Author: Marek Polacek <polacek@redhat.com> Date: Fri Mar 25 17:46:07 2022 -0400 c++: ICE with aggregate assignment and DMI [PR104583] The attached 93280 test no longer ICEs but looks like it was never added to the testsuite. The 104583 test, modified so that it closely resembles 93280, still ICEs. The problem is that in 104583 we have a value-init from {} (the line A a{};), so this code in convert_like_internal 7960 /* If we're initializing from {}, it's value-initialization. */ 7961 if (BRACE_ENCLOSED_INITIALIZER_P (expr) 7962 && CONSTRUCTOR_NELTS (expr) == 0 7963 && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype) 7964 && !processing_template_decl) 7965 { 7966 bool direct = CONSTRUCTOR_IS_DIRECT_INIT (expr); ... 7974 TARGET_EXPR_DIRECT_INIT_P (expr) = direct; sets TARGET_EXPR_DIRECT_INIT_P. This does not happen in 93280 where we initialize from {0}. In 104583, when gimplifying, the d = {}; line, we have d = {.a=TARGET_EXPR <D.2474, <<< Unknown tree: aggr_init_expr 4 __ct_comp D.2474 (struct A *) <<< Unknown tree: void_cst >>> >>>>} where the TARGET_EXPR is the one with TARGET_EXPR_DIRECT_INIT_P set. In gimplify_init_ctor_preeval we do 4724 FOR_EACH_VEC_SAFE_ELT (v, ix, ce) 4725 gimplify_init_ctor_preeval (&ce->value, pre_p, post_p, data); so we gimplify the TARGET_EXPR, crashing at 744 case TARGET_EXPR: 745 /* A TARGET_EXPR that expresses direct-initialization should have been 746 elided by cp_gimplify_init_expr. */ 747 gcc_checking_assert (!TARGET_EXPR_DIRECT_INIT_P (*expr_p)); but there is no INIT_EXPR so cp_gimplify_init_expr was never called! Now, the fix for c++/93280 <https://gcc.gnu.org/pipermail/gcc-patches/2020-January/538414.html> says "let's only set TARGET_EXPR_DIRECT_INIT_P when we're using the DMI in a constructor." and the comment talks about the full initialization. Is is accurate to say that our TARGET_EXPR does not represent the full initialization, because it only initializes the 'a' subobject? If so, then maybe get_nsdmi should clear TARGET_EXPR_DIRECT_INIT_P when in_ctor is false. I've compared the 93280.s and 104583.s files, they differ only in one movl $0, so there are no extra calls and similar. PR c++/93280 PR c++/104583 gcc/cp/ChangeLog: * init.cc (get_nsdmi): Set TARGET_EXPR_DIRECT_INIT_P to in_ctor. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/nsdmi-list7.C: New test. * g++.dg/cpp0x/nsdmi-list8.C: New test.
Fixed on trunk so far.
GCC 10.4 is being released, retargeting bugs to GCC 10.5.
GCC 10 branch is being closed.