Tested x86_64-pc-linux-gnu, applying to trunk.
-- 8< --
Here we have one empty subobject inside another; we didn't create a
CONSTRUCTOR for the outer one, so we don't have it as context for the inner.
PR c++/125315
gcc/cp/ChangeLog:
* constexpr.cc (init_subob_ctx): Allow both ctor and object
to be null for an empty subobject.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/no_unique_address16.C: New test.
---
gcc/cp/constexpr.cc | 7 ++++++-
gcc/testsuite/g++.dg/cpp2a/no_unique_address16.C | 10 ++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/no_unique_address16.C
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 9916b63d428..1fc8a56503c 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -6718,7 +6718,12 @@ init_subob_ctx (const constexpr_ctx *ctx, constexpr_ctx
&new_ctx,
else if (ctx->object)
ctxtype = TREE_TYPE (ctx->object);
else
- gcc_unreachable ();
+ {
+ /* This can happen if the enclosing object is also an empty subobject
+ (c++/125315). */
+ gcc_checking_assert (is_empty_class (type));
+ return;
+ }
if (VECTOR_TYPE_P (type)
&& VECTOR_TYPE_P (ctxtype)
diff --git a/gcc/testsuite/g++.dg/cpp2a/no_unique_address16.C
b/gcc/testsuite/g++.dg/cpp2a/no_unique_address16.C
new file mode 100644
index 00000000000..22c0b699f92
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/no_unique_address16.C
@@ -0,0 +1,10 @@
+// PR c++/125315
+// { dg-do compile { target c++20 } }
+// { dg-prune-output "used but never defined" }
+
+struct S{~S(){}};
+constexpr S& f(S& t);
+struct W{[[no_unique_address]]S v;};
+struct R:W{};
+S s;
+auto x=R{{f(s)}};
base-commit: 07aa3ec358ae66d512213b2be3c6f9646153bb45
--
2.54.0