Tested x86_64-pc-linux-gnu, applying to trunk.
-- 8< --
Here, because we don't build a CONSTRUCTOR for an empty base, we were
wrongly marking the Foo CONSTRUCTOR as complete after initializing the Empty
member. Fixed by checking empty_base here as well.
PR c++/112439
gcc/cp/ChangeLog:
* constexpr.cc (cxx_eval_store_expression): Check empty_base
before marking a CONSTRUCTOR readonly.
gcc/testsuite/ChangeLog:
* g++.dg/cpp2a/no_unique_address15.C: New test.
---
gcc/cp/constexpr.cc | 1 +
.../g++.dg/cpp2a/no_unique_address15.C | 19 +++++++++++++++++++
2 files changed, 20 insertions(+)
create mode 100644 gcc/testsuite/g++.dg/cpp2a/no_unique_address15.C
diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 6350fe15408..2ebb1470dd5 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -6694,6 +6694,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree
t,
object. Make a note of this fact by marking the CONSTRUCTOR
TREE_READONLY. */
if (TREE_CODE (t) == INIT_EXPR
+ && !empty_base
&& TREE_CODE (*valp) == CONSTRUCTOR
&& TYPE_READONLY (type))
{
diff --git a/gcc/testsuite/g++.dg/cpp2a/no_unique_address15.C
b/gcc/testsuite/g++.dg/cpp2a/no_unique_address15.C
new file mode 100644
index 00000000000..3e7cf0838e1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/no_unique_address15.C
@@ -0,0 +1,19 @@
+// PR c++/112439
+// { dg-do compile { target c++14 } }
+
+struct Empty {};
+
+class Foo {
+public:
+ constexpr Foo(int x, Empty y, int z) : a(x), b(y)
+ {
+ c = z;
+ }
+
+private:
+ int a{};
+ [[no_unique_address]] Empty b{};
+ [[no_unique_address]] int c{};
+};
+
+constexpr Foo r{1, {}, 3};
base-commit: e0701f8f7b6dcddb299eb5345e510cf9ea419150
prerequisite-patch-id: 710b09d2d596e61c5634974a1dca99c51506d903
--
2.39.3