public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] c++: constexpr init of union sub-aggr w/ base [PR105491]
@ 2022-05-06 15:22 Patrick Palka
  2022-05-06 15:56 ` Jason Merrill
  0 siblings, 1 reply; 15+ messages in thread
From: Patrick Palka @ 2022-05-06 15:22 UTC (permalink / raw)
  To: gcc-patches

Here ever since r10-7313-gb599bf9d6d1e18, reduced_constant_expression_p
in C++11/14 is rejecting the marked sub-aggregate initializer (of type S)

  W w = {.D.2445={.s={.D.2387={.m=0}, .b=0}}}
                     ^

ultimately because said initializer has CONSTRUCTOR_NO_CLEARING set, and
so the function proceeds to verify that all fields of S are initialized.
And before C++17 we don't expect to see base class fields (since
next_initializable_field skips over the), so the base class initializer
causes r_c_e_p to return false.  The base class initializer comes from
the constructor call S::S(int).

The reason this is caused by r10-7313-gb599bf9d6d1e18 is because in that
commit we began using CONSTRUCTOR_NO_CLEARING to also track whether we're
in middle of activating a union member.  This overloaded use of the flag
affects clear_no_implicit_zero, which recurses into sub-aggregate
initializers only if the outer initializer has CONSTRUCTOR_NO_CLEARING
set.  After that commit, the outer union initializer above no longer has
the flag set at this point and so clear_no_implicit_zero no longer clears
CONSTRUCTOR_NO_CLEARING for the marked inner initializer.

This patch fixes this by restoring the recursive behavior of
clear_no_implicit_zero for union initializers.  Arguably we should
we could improve reduced_constant_expression_p to accept the marked
initializer in C++11/14 even if it has CONSTRUCTOR_NO_CLEARING set, but
adjusting clear_no_implicit_zero seems safer to backport.

Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
trunk/12/11/10?

	PR c++/105491

gcc/cp/ChangeLog:

	* constexpr.cc (clear_no_implicit_zero): Recurse into a union
	initializer even if CONSTRUCTOR_NO_CLEARING is already cleared.

gcc/testsuite/ChangeLog:

	* g++.dg/cpp0x/constexpr-union7.C: New test.
	* g++.dg/cpp0x/constexpr-union7a.C: New test.
	* g++.dg/cpp2a/constinit17.C: New test.
---
 gcc/cp/constexpr.cc                           |  7 +++++-
 gcc/testsuite/g++.dg/cpp0x/constexpr-union7.C | 17 +++++++++++++
 .../g++.dg/cpp0x/constexpr-union7a.C          | 15 ++++++++++++
 gcc/testsuite/g++.dg/cpp2a/constinit17.C      | 24 +++++++++++++++++++
 4 files changed, 62 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-union7.C
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/constexpr-union7a.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/constinit17.C

diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc
index 9b1e71857fc..75fecbcbcb7 100644
--- a/gcc/cp/constexpr.cc
+++ b/gcc/cp/constexpr.cc
@@ -1886,7 +1886,12 @@ cxx_eval_internal_function (const constexpr_ctx *ctx, tree t,
 static void
 clear_no_implicit_zero (tree ctor)
 {
-  if (CONSTRUCTOR_NO_CLEARING (ctor))
+  if (CONSTRUCTOR_NO_CLEARING (ctor)
+      /* For a union initializer, the flag could already be cleared but not
+	 necessarily yet for its sub-aggregates, since for unions the flag is
+	 also used by cxx_eval_store_expression to track whether we're in the
+	 middle of activating one of its members.  */
+      || TREE_CODE (TREE_TYPE (ctor)) == UNION_TYPE)
     {
       CONSTRUCTOR_NO_CLEARING (ctor) = false;
       for (auto &e: CONSTRUCTOR_ELTS (ctor))
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-union7.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-union7.C
new file mode 100644
index 00000000000..b3147d9db50
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-union7.C
@@ -0,0 +1,17 @@
+// PR c++/105491
+// { dg-do compile { target c++11 } }
+
+struct V {
+  int m = 0;
+};
+struct S : V {
+  constexpr S(int) : b() { }
+  bool b;
+};
+struct W {
+  constexpr W() : s(0) { }
+  union {
+    S s;
+  };
+};
+constexpr W w;
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-union7a.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-union7a.C
new file mode 100644
index 00000000000..b676e7d1748
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-union7a.C
@@ -0,0 +1,15 @@
+// PR c++/105491
+// { dg-do compile { target c++11 } }
+
+struct V {
+  int m = 0;
+};
+struct S : V {
+  constexpr S(int) : b() { }
+  bool b;
+};
+union W {
+  constexpr W() : s(0) { }
+  S s;
+};
+constexpr W w;
diff --git a/gcc/testsuite/g++.dg/cpp2a/constinit17.C b/gcc/testsuite/g++.dg/cpp2a/constinit17.C
new file mode 100644
index 00000000000..6431654ac85
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constinit17.C
@@ -0,0 +1,24 @@
+// PR c++/105491
+// { dg-do compile { target c++11 } }
+
+class Message {
+  virtual int GetMetadata();
+};
+class ProtobufCFileOptions : Message {
+public:
+  constexpr ProtobufCFileOptions(int);
+  bool no_generate_;
+  bool const_strings_;
+  bool use_oneof_field_name_;
+  bool gen_pack_helpers_;
+  bool gen_init_helpers_;
+};
+constexpr ProtobufCFileOptions::ProtobufCFileOptions(int)
+    : no_generate_(), const_strings_(), use_oneof_field_name_(),
+      gen_pack_helpers_(), gen_init_helpers_() {}
+struct ProtobufCFileOptionsDefaultTypeInternal {
+  constexpr ProtobufCFileOptionsDefaultTypeInternal() : _instance({}) {}
+  union {
+    ProtobufCFileOptions _instance;
+  };
+} __constinit _ProtobufCFileOptions_default_instance_;
-- 
2.36.0.63.gf5aaf72f1b


^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, other threads:[~2022-05-31 19:06 UTC | newest]

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-05-06 15:22 [PATCH] c++: constexpr init of union sub-aggr w/ base [PR105491] Patrick Palka
2022-05-06 15:56 ` Jason Merrill
2022-05-06 16:04   ` Marek Polacek
2022-05-06 16:40   ` Patrick Palka
2022-05-06 18:00     ` Patrick Palka
2022-05-06 18:22       ` Jason Merrill
2022-05-06 19:24         ` Patrick Palka
2022-05-06 20:10           ` Patrick Palka
2022-05-06 20:27             ` Jason Merrill
2022-05-06 20:46               ` Patrick Palka
2022-05-07 21:18                 ` Jason Merrill
2022-05-17 16:34                   ` Patrick Palka
2022-05-18 14:22                     ` Jason Merrill
2022-05-31 16:41                       ` Patrick Palka
2022-05-31 19:06                         ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).