public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
From: Patrick Palka <ppalka@gcc.gnu.org>
To: gcc-cvs@gcc.gnu.org
Subject: [gcc r13-3491] c++ modules: enum TYPE_MIN/MAX_VALUE streaming [PR106848]
Date: Tue, 25 Oct 2022 17:41:54 +0000 (GMT)	[thread overview]
Message-ID: <20221025174154.95B6B3858C50@sourceware.org> (raw)

https://gcc.gnu.org/g:15d67c11ac0479b08e3badcafdee7e0a6f062349

commit r13-3491-g15d67c11ac0479b08e3badcafdee7e0a6f062349
Author: Patrick Palka <ppalka@redhat.com>
Date:   Tue Oct 25 13:41:18 2022 -0400

    c++ modules: enum TYPE_MIN/MAX_VALUE streaming [PR106848]
    
    In the frontend, the TYPE_MIN/MAX_VALUE of ENUMERAL_TYPE is the same as
    that of the enum's underlying type (see start_enum).  And the underlying
    type of an enum is always known, even for an opaque enum that lacks a
    definition.
    
    But currently, we stream TYPE_MIN/MAX_VALUE of an enum only as part of
    its definition.  So if the enum is declared but never defined, the
    ENUMERAL_TYPE we stream in will have empty TYPE_MIN/MAX_VALUE fields
    despite these fields being non-empty on stream out.
    
    And even if the enum is defined, read_enum_def updates these fields only
    on the main variant of the enum type, so for other variants (that we may
    have streamed in earlier) these fields remain empty.  That these fields
    are unexpectedly empty for some ENUMERAL_TYPEs is ultimately the cause
    of the below two PRs.
    
    This patch fixes this by making us stream TYPE_MIN/MAX_VALUE directly
    for each ENUMERAL_TYPE rather than as part of the enum's definition, so
    that we naturally also stream these fields for opaque enums (and each
    enum type variant).
    
            PR c++/106848
            PR c++/102600
    
    gcc/cp/ChangeLog:
    
            * module.cc (trees_out::core_vals): Stream TYPE_MAX_VALUE and
            TYPE_MIN_VALUE of ENUMERAL_TYPE.
            (trees_in::core_vals): Likewise.
            (trees_out::write_enum_def): Don't stream them here.
            (trees_in::read_enum_def): Likewise.
    
    gcc/testsuite/ChangeLog:
    
            * g++.dg/modules/enum-9_a.H: New test.
            * g++.dg/modules/enum-9_b.C: New test.
            * g++.dg/modules/enum-10_a.H: New test.
            * g++.dg/modules/enum-10_b.C: New test.
            * g++.dg/modules/enum-11_a.H: New test.
            * g++.dg/modules/enum-11_b.C: New test.

Diff:
---
 gcc/cp/module.cc                         | 39 ++++++++++++++++++++------------
 gcc/testsuite/g++.dg/modules/enum-10_a.H |  5 ++++
 gcc/testsuite/g++.dg/modules/enum-10_b.C |  6 +++++
 gcc/testsuite/g++.dg/modules/enum-11_a.H |  5 ++++
 gcc/testsuite/g++.dg/modules/enum-11_b.C |  8 +++++++
 gcc/testsuite/g++.dg/modules/enum-9_a.H  | 13 +++++++++++
 gcc/testsuite/g++.dg/modules/enum-9_b.C  |  6 +++++
 7 files changed, 67 insertions(+), 15 deletions(-)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 73971e7ff47..9957df510e6 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -6017,9 +6017,17 @@ trees_out::core_vals (tree t)
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
     {
+      if (code == ENUMERAL_TYPE)
+	{
+	  /* These fields get set even for opaque enums that lack a
+	     definition, so we stream them directly for each ENUMERAL_TYPE.
+	     We stream TYPE_VALUES as part of the definition.  */
+	  WT (t->type_non_common.maxval);
+	  WT (t->type_non_common.minval);
+	}
       /* Records and unions hold FIELDS, VFIELD & BINFO on these
 	 things.  */
-      if (!RECORD_OR_UNION_CODE_P (code) && code != ENUMERAL_TYPE)
+      else if (!RECORD_OR_UNION_CODE_P (code))
 	{
 	  // FIXME: These are from tpl_parm_value's 'type' writing.
 	  // Perhaps it should just be doing them directly?
@@ -6530,9 +6538,17 @@ trees_in::core_vals (tree t)
 
   if (CODE_CONTAINS_STRUCT (code, TS_TYPE_NON_COMMON))
     {
+      if (code == ENUMERAL_TYPE)
+	{
+	  /* These fields get set even for opaque enums that lack a
+	     definition, so we stream them directly for each ENUMERAL_TYPE.
+	     We stream TYPE_VALUES as part of the definition.  */
+	  RT (t->type_non_common.maxval);
+	  RT (t->type_non_common.minval);
+	}
       /* Records and unions hold FIELDS, VFIELD & BINFO on these
 	 things.  */
-      if (!RECORD_OR_UNION_CODE_P (code) && code != ENUMERAL_TYPE)
+      else if (!RECORD_OR_UNION_CODE_P (code))
 	{
 	  /* This is not clobbering TYPE_CACHED_VALUES, because this
 	     is a type that doesn't have any.  */
@@ -12217,8 +12233,8 @@ trees_out::write_enum_def (tree decl)
   tree type = TREE_TYPE (decl);
 
   tree_node (TYPE_VALUES (type));
-  tree_node (TYPE_MIN_VALUE (type));
-  tree_node (TYPE_MAX_VALUE (type));
+  /* Note that we stream TYPE_MIN/MAX_VALUE directly as part of the
+     ENUMERAL_TYPE.  */
 }
 
 void
@@ -12242,8 +12258,6 @@ trees_in::read_enum_def (tree defn, tree maybe_template)
 {
   tree type = TREE_TYPE (defn);
   tree values = tree_node ();
-  tree min = tree_node ();
-  tree max = tree_node ();
 
   if (get_overrun ())
     return false;
@@ -12254,8 +12268,8 @@ trees_in::read_enum_def (tree defn, tree maybe_template)
   if (installing)
     {
       TYPE_VALUES (type) = values;
-      TYPE_MIN_VALUE (type) = min;
-      TYPE_MAX_VALUE (type) = max;
+      /* Note that we stream TYPE_MIN/MAX_VALUE directly as part of the
+	 ENUMERAL_TYPE.  */
 
       rest_of_type_compilation (type, DECL_NAMESPACE_SCOPE_P (defn));
     }
@@ -12269,22 +12283,17 @@ trees_in::read_enum_def (tree defn, tree maybe_template)
 	  tree new_decl = TREE_VALUE (values);
 
 	  if (DECL_NAME (known_decl) != DECL_NAME (new_decl))
-	    goto bad;
+	    break;
 	      
 	  new_decl = maybe_duplicate (new_decl);
 
 	  if (!cp_tree_equal (DECL_INITIAL (known_decl),
 			      DECL_INITIAL (new_decl)))
-	    goto bad;
+	    break;
 	}
 
       if (known || values)
-	goto bad;
-
-      if (!cp_tree_equal (TYPE_MIN_VALUE (type), min)
-	  || !cp_tree_equal (TYPE_MAX_VALUE (type), max))
 	{
-	bad:;
 	  error_at (DECL_SOURCE_LOCATION (maybe_dup),
 		    "definition of %qD does not match", maybe_dup);
 	  inform (DECL_SOURCE_LOCATION (defn),
diff --git a/gcc/testsuite/g++.dg/modules/enum-10_a.H b/gcc/testsuite/g++.dg/modules/enum-10_a.H
new file mode 100644
index 00000000000..fb7d10ad3b6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-10_a.H
@@ -0,0 +1,5 @@
+// PR c++/106848
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+typedef enum memory_order { memory_order_seq_cst } memory_order;
diff --git a/gcc/testsuite/g++.dg/modules/enum-10_b.C b/gcc/testsuite/g++.dg/modules/enum-10_b.C
new file mode 100644
index 00000000000..76dc3152963
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-10_b.C
@@ -0,0 +1,6 @@
+// PR c++/106848
+// { dg-additional-options "-fmodules-ts -g" }
+
+import "enum-10_a.H";
+
+memory_order x = memory_order_seq_cst;
diff --git a/gcc/testsuite/g++.dg/modules/enum-11_a.H b/gcc/testsuite/g++.dg/modules/enum-11_a.H
new file mode 100644
index 00000000000..1aecabfd0bd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-11_a.H
@@ -0,0 +1,5 @@
+// PR c++/102600
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+enum class byte : unsigned char { };
diff --git a/gcc/testsuite/g++.dg/modules/enum-11_b.C b/gcc/testsuite/g++.dg/modules/enum-11_b.C
new file mode 100644
index 00000000000..4d77cab8953
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-11_b.C
@@ -0,0 +1,8 @@
+// PR c++/102600
+// { dg-additional-options -fmodules-ts }
+
+import "enum-11_a.H";
+
+void push(byte) {}
+void write(char v) { push(static_cast<byte>(v)); }
+int main() { write(char{}); }
diff --git a/gcc/testsuite/g++.dg/modules/enum-9_a.H b/gcc/testsuite/g++.dg/modules/enum-9_a.H
new file mode 100644
index 00000000000..0dd4a0f2fb1
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-9_a.H
@@ -0,0 +1,13 @@
+// PR c++/106848
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+
+template<typename _T1>
+struct pair {
+  using type = void(*)(const _T1&);
+};
+
+struct _ScannerBase {
+  enum _TokenT { _S_token_anychar };
+  pair<_TokenT> _M_token_tbl;
+};
diff --git a/gcc/testsuite/g++.dg/modules/enum-9_b.C b/gcc/testsuite/g++.dg/modules/enum-9_b.C
new file mode 100644
index 00000000000..95e2812b81e
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/enum-9_b.C
@@ -0,0 +1,6 @@
+// PR c++/106848
+// { dg-additional-options "-fmodules-ts -g" }
+
+import "enum-9_a.H";
+
+_ScannerBase s;

                 reply	other threads:[~2022-10-25 17:41 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20221025174154.95B6B3858C50@sourceware.org \
    --to=ppalka@gcc.gnu.org \
    --cc=gcc-cvs@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).