diff options
author | Marek Polacek <polacek@redhat.com> | 2024-12-12 14:56:07 -0500 |
---|---|---|
committer | Marek Polacek <polacek@redhat.com> | 2024-12-17 12:01:18 -0500 |
commit | 40e5636e086e51f5908a1a01be9cba2218dc26d8 (patch) | |
tree | 7d98b6f76d5979e83120afff846661d2d61ea73b | |
parent | d17b09c07a1da0e3950718aabc2cbdb90cae402b (diff) | |
download | gcc-40e5636e086e51f5908a1a01be9cba2218dc26d8.zip gcc-40e5636e086e51f5908a1a01be9cba2218dc26d8.tar.gz gcc-40e5636e086e51f5908a1a01be9cba2218dc26d8.tar.bz2 |
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.
-rw-r--r-- | gcc/cp/init.cc | 9 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/initlist-array23.C | 28 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/initlist-array24.C | 27 |
3 files changed, 64 insertions, 0 deletions
diff --git a/gcc/cp/init.cc b/gcc/cp/init.cc index ae51640..7dcc115 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 0000000..cda2afb --- /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 0000000..7dda00d --- /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{}; +} |