On 12/16/24 6:48 PM, Marek Polacek wrote:
Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/branches?
-- >8 --
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): Clear CLEANUP_FLAGS if we're not
generating the loop.
truncate seems dangerous, there might be other things in cleanup_flags
that we want to leave alone. I think it would be safer to assert that
the last element in the vec is iterator, and then pop it.
gcc/testsuite/ChangeLog:
* g++.dg/cpp0x/initlist-array23.C: New test.
* g++.dg/cpp0x/initlist-array24.C: New test.
---
gcc/cp/init.cc | 4 +++
gcc/testsuite/g++.dg/cpp0x/initlist-array23.C | 28 +++++++++++++++++++
gcc/testsuite/g++.dg/cpp0x/initlist-array24.C | 27 ++++++++++++++++++
3 files changed, 59 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 ae516407c92..5dcb24ef735 100644
--- a/gcc/cp/init.cc
+++ b/gcc/cp/init.cc
@@ -5109,6 +5109,10 @@ 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_truncate (*cleanup_flags, 0);
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 00000000000..cda2afb9fcc
--- /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 00000000000..7dda00d5c0b
--- /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{};
+}
base-commit: 56f1863ade1bf416e09da305615ecb2ae04602a8