aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMarek Polacek <polacek@redhat.com>2024-12-12 14:56:07 -0500
committerMarek Polacek <polacek@redhat.com>2024-12-17 12:01:18 -0500
commit40e5636e086e51f5908a1a01be9cba2218dc26d8 (patch)
tree7d98b6f76d5979e83120afff846661d2d61ea73b /gcc
parentd17b09c07a1da0e3950718aabc2cbdb90cae402b (diff)
downloadgcc-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.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/init.cc9
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-array23.C28
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-array24.C27
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{};
+}