Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk/branches?
-- >8 --
When looking into 125315 I came up with another test that crashes
due to an empty object. It still crashes even after Jason's patch.
Here we have a subobject nested in an empty object:
{.w = {.v = TARGET_EXPR <f(s)>}}
w's type is W, an empty union due to [[no_unique_address]], so
init_subob_ctx clears the ctor, but then we recurse to
{.v = TARGET_EXPR <f(s)>}
with a null ctx->ctor so the call to get_or_insert_ctor_field in
cxx_eval_bare_aggregate crashes. This fixes the crash similarly
to c++/125315.
no_unique_address18.C worked fine even before this patch because
there we don't have an empty object. But let's test it also.
PR c++/125336
gcc/cp/ChangeLog:
* constexpr.cc (cxx_eval_bare_aggregate): Don't call
get_or_insert_ctor_field when there is no CONSTRUCTOR. Assert
is_empty_class.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/no_unique_address17.C: New test.
* g++.dg/cpp2a/no_unique_address18.C: New test.
---
gcc/cp/constexpr.cc | 8 ++++++--
gcc/testsuite/g++.dg/cpp2a/no_unique_address17.C | 12 ++++++++++++
gcc/testsuite/g++.dg/cpp2a/no_unique_address18.C | 12 ++++++++++++
3 files changed, 30 insertions(+), 2 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/no_unique_address17.C
create mode 100644 gcc/testsuite/g++.dg/cpp2a/no_unique_address18.C
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 1fc8a56503c..84896170d05 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -6841,7 +6841,11 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree
t,
/* Like in cxx_eval_store_expression, omit entries for empty fields. */
bool no_slot = new_ctx.ctor == NULL_TREE;
int pos_hint = -1;
- if (new_ctx.ctor != ctx->ctor && !no_slot)
+ if (!ctx->ctor)
+ /* The enclosing object could be an empty subobject so we have no
+ CONSTRUCTOR (c++/125336). */
+ gcc_checking_assert (is_empty_class (type));
+ else if (new_ctx.ctor != ctx->ctor && !no_slot)
{
/* If we built a new CONSTRUCTOR, attach it now so that other
initializers can refer to it. */
@@ -6892,7 +6896,7 @@ cxx_eval_bare_aggregate (const constexpr_ctx *ctx, tree t,
gcc_assert (is_empty_class (TREE_TYPE (TREE_TYPE (index))));
changed = true;
}
- else
+ else if (ctx->ctor)
{
if (TREE_CODE (type) == UNION_TYPE
&& (*p)->last().index != index)
diff --git a/gcc/testsuite/g++.dg/cpp2a/no_unique_address17.C
b/gcc/testsuite/g++.dg/cpp2a/no_unique_address17.C
new file mode 100644
index 00000000000..11099698a9b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/no_unique_address17.C
@@ -0,0 +1,12 @@
+// PR c++/125336
+// { dg-do compile { target c++20 } }
+// { dg-prune-output "used but never defined" }
+
+struct S{ };
+constexpr S& f (S&);
+union W {
+ [[no_unique_address]] S v;
+};
+struct R { W w; };
+S s;
+auto x = R{{ f(s) }};
diff --git a/gcc/testsuite/g++.dg/cpp2a/no_unique_address18.C
b/gcc/testsuite/g++.dg/cpp2a/no_unique_address18.C
new file mode 100644
index 00000000000..bea8a65b8a0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/no_unique_address18.C
@@ -0,0 +1,12 @@
+// PR c++/125336
+// { dg-do compile { target c++20 } }
+// { dg-prune-output "used but never defined" }
+
+struct S { int i; };
+constexpr S& f (S&);
+union W {
+ [[no_unique_address]] S v;
+};
+struct R { W w; };
+S s;
+auto x = R{{ f(s) }};
base-commit: f108e23d2bff50d0ee8cf0d25a08be5432b702b6
--
2.54.0