From 40e5636e086e51f5908a1a01be9cba2218dc26d8 Mon Sep 17 00:00:00 2001 From: Marek Polacek Date: Thu, 12 Dec 2024 14:56:07 -0500 Subject: [PATCH] c++: ICE initializing array of aggrs [PR117985] This crash started with my r12-7803 but I believe the problem lies elsewhere. build_vec_init has cleanup_flags whose purpose is -- if I grok this correctly -- to avoid destructing an object multiple times. Let's say we are initializing an array of A. Then we might end up in a scenario similar to initlist-eh1.C: try { call A::A in a loop // #0 try { call a fn using the array } finally { // #1 call A::~A in a loop } } catch { // #2 call A::~A in a loop } cleanup_flags makes us emit a statement like D.3048 = 2; at #0 to disable performing the cleanup at #2, since #1 will take care of the destruction of the array. But if we are not emitting the loop because we can use a constant initializer (and use a single { a, b, ...}), we shouldn't generate the statement resetting the iterator to its initial value. Otherwise we crash in gimplify_var_or_parm_decl because it gets the stray decl D.3048. PR c++/117985 gcc/cp/ChangeLog: * init.cc (build_vec_init): Pop CLEANUP_FLAGS if we're not generating the loop. gcc/testsuite/ChangeLog: * g++.dg/cpp0x/initlist-array23.C: New test. * g++.dg/cpp0x/initlist-array24.C: New test. --- gcc/cp/init.cc | 9 ++++++ gcc/testsuite/g++.dg/cpp0x/initlist-array23.C | 28 +++++++++++++++++++ gcc/testsuite/g++.dg/cpp0x/initlist-array24.C | 27 ++++++++++++++++++ 3 files changed, 64 insertions(+) create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-array23.C create mode 100644 gcc/testsuite/g++.dg/cpp0x/initlist-array24.C diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index ae516407c9278..7dcc1152c720c 100644 --- a/gcc/cp/init.cc +++ b/gcc/cp/init.cc @@ -5109,6 +5109,15 @@ build_vec_init (tree base, tree maxindex, tree init, { if (!saw_non_const) { + /* If we're not generating the loop, we don't need to reset the + iterator. */ + if (cleanup_flags + && !vec_safe_is_empty (*cleanup_flags)) + { + auto l = (*cleanup_flags)->last (); + gcc_assert (TREE_PURPOSE (l) == iterator); + (*cleanup_flags)->pop (); + } tree const_init = build_constructor (atype, const_vec); return build2 (INIT_EXPR, atype, obase, const_init); } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-array23.C b/gcc/testsuite/g++.dg/cpp0x/initlist-array23.C new file mode 100644 index 0000000000000..cda2afb9fcccd --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-array23.C @@ -0,0 +1,28 @@ +// PR c++/117985 +// { dg-do compile { target c++11 } } + +struct _Vector_impl { + constexpr + _Vector_impl() {} +}; +struct _Vector_base { + ~_Vector_base(); + _Vector_impl _M_impl; +}; +struct vector : private _Vector_base {}; +struct string { + string(); +}; +struct VEC { + vector pane{}; +}; +struct FOO { + VEC screen[1]{}; + string debug_name; +}; + +int +main () +{ + FOO{}; +} diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-array24.C b/gcc/testsuite/g++.dg/cpp0x/initlist-array24.C new file mode 100644 index 0000000000000..7dda00d5c0b83 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-array24.C @@ -0,0 +1,27 @@ +// PR c++/117985 +// { dg-do compile { target c++20 } } + +struct _Vector_impl { + constexpr _Vector_impl() {} +}; +struct _Vector_base { + constexpr ~_Vector_base() {} + _Vector_impl _M_impl; +}; +struct vector : private _Vector_base {}; +struct string { + string(); +}; +struct VEC { + vector pane{}; +}; +struct FOO { + VEC screen[1]{}; + string debug_name; +}; + +int +main () +{ + FOO{}; +}