https://gcc.gnu.org/g:28b05e4317a6eade2ba46076ef17f9e138c57a34

commit r15-7980-g28b05e4317a6eade2ba46076ef17f9e138c57a34
Author: Jakub Jelinek <ja...@redhat.com>
Date:   Wed Mar 12 08:01:09 2025 +0100

    c++: Handle RAW_DATA_CST in modules.cc [PR119076]
    
    The following testcases (one with #embed, one with large initializer
    turned into RAW_DATA_CST) show that I forgot to handle RAW_DATA_CST in
    module streaming.
    
    Similar to the PCH case we need to stream out RAW_DATA_CST with NULL
    RAW_DATA_OWNER (i.e. a tree which has data owned by libcpp buffer) so
    that it will be streamed back in as STRING_CST which owns the data,
    but because the data can be really large (hopefully not so much for
    header modules though), without actually trying to build a STRING_CST
    on the module writing side because that would mean another large
    allocation and copying of the large data.
    RAW_DATA_CST with RAW_DATA_OWNER then needs to be streamed out and in
    by streaming the owner and offset from owner's data and length.
    
    2025-03-12  Jakub Jelinek  <ja...@redhat.com>
    
            PR c++/119076
            * module.cc (trees_out::start): Handle RAW_DATA_CST.
            (trees_in::start): Likewise.
            (trees_out::core_vals): Likewise.
            (trees_in::core_vals): Likewise.
    
            * g++.dg/modules/pr119076-1_a.H: New test.
            * g++.dg/modules/pr119076-1_b.C: New test.
            * g++.dg/modules/pr119076-2_a.H: New test.
            * g++.dg/modules/pr119076-2_b.C: New test.

Diff:
---
 gcc/cp/module.cc                            | 65 +++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/modules/pr119076-1_a.H | 41 ++++++++++++++++++
 gcc/testsuite/g++.dg/modules/pr119076-1_b.C | 12 ++++++
 gcc/testsuite/g++.dg/modules/pr119076-2_a.H | 65 +++++++++++++++++++++++++++++
 gcc/testsuite/g++.dg/modules/pr119076-2_b.C | 12 ++++++
 5 files changed, 195 insertions(+)

diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 97c3549093c9..9a1cd5244c2c 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -5379,6 +5379,30 @@ trees_out::start (tree t, bool code_streamed)
       str (TREE_STRING_POINTER (t), TREE_STRING_LENGTH (t));
       break;
 
+    case RAW_DATA_CST:
+      if (RAW_DATA_OWNER (t) == NULL_TREE)
+       {
+         /* Stream RAW_DATA_CST with no owner (i.e. data pointing
+            into libcpp buffers) as something we can stream in as
+            STRING_CST which owns the data.  */
+         u (0);
+         /* Can't use str (RAW_DATA_POINTER (t), RAW_DATA_LENGTH (t));
+            here as there isn't a null termination after it.  */
+         z (RAW_DATA_LENGTH (t));
+         if (RAW_DATA_LENGTH (t))
+           if (void *ptr = buf (RAW_DATA_LENGTH (t) + 1))
+             {
+               memcpy (ptr, RAW_DATA_POINTER (t), RAW_DATA_LENGTH (t));
+               ((char *) ptr)[RAW_DATA_LENGTH (t)] = '\0';
+             }
+       }
+      else
+       {
+         gcc_assert (RAW_DATA_LENGTH (t));
+         u (RAW_DATA_LENGTH (t));
+       }
+      break;
+
     case VECTOR_CST:
       u (VECTOR_CST_LOG2_NPATTERNS (t));
       u (VECTOR_CST_NELTS_PER_PATTERN (t));
@@ -5472,6 +5496,24 @@ trees_in::start (unsigned code)
       }
       break;
 
+    case RAW_DATA_CST:
+      {
+       size_t l = u ();
+       if (l == 0)
+         {
+           /* Stream in RAW_DATA_CST with no owner as STRING_CST
+              which owns the data.  */
+           const char *chars = str (&l);
+           t = build_string (l, chars);
+         }
+       else
+         {
+           t = make_node (RAW_DATA_CST);
+           RAW_DATA_LENGTH (t) = l;
+         }
+      }
+      break;
+
     case VECTOR_CST:
       {
        unsigned log2_npats = u ();
@@ -6383,6 +6425,22 @@ trees_out::core_vals (tree t)
       /* Streamed during start.  */
       break;
 
+    case RAW_DATA_CST:
+      if (RAW_DATA_OWNER (t) == NULL_TREE)
+       break; /* Streamed as STRING_CST during start.  */
+      WT (RAW_DATA_OWNER (t));
+      if (streaming_p ())
+       {
+         if (TREE_CODE (RAW_DATA_OWNER (t)) == RAW_DATA_CST)
+           z (RAW_DATA_POINTER (t) - RAW_DATA_POINTER (RAW_DATA_OWNER (t)));
+         else if (TREE_CODE (RAW_DATA_OWNER (t)) == STRING_CST)
+           z (RAW_DATA_POINTER (t)
+              - TREE_STRING_POINTER (RAW_DATA_OWNER (t)));
+         else
+           gcc_unreachable ();
+       }
+      break;
+
     case VECTOR_CST:
       for (unsigned ix = vector_cst_encoded_nelts (t); ix--;)
        WT (VECTOR_CST_ENCODED_ELT (t, ix));
@@ -6917,6 +6975,13 @@ trees_in::core_vals (tree t)
       /* Streamed during start.  */
       break;
 
+    case RAW_DATA_CST:
+      RT (RAW_DATA_OWNER (t));
+      gcc_assert (TREE_CODE (RAW_DATA_OWNER (t)) == STRING_CST
+                 && TREE_STRING_LENGTH (RAW_DATA_OWNER (t)));
+      RAW_DATA_POINTER (t) = TREE_STRING_POINTER (RAW_DATA_OWNER (t)) + z ();
+      break;
+
     case VECTOR_CST:
       for (unsigned ix = vector_cst_encoded_nelts (t); ix--;)
        RT (VECTOR_CST_ENCODED_ELT (t, ix));
diff --git a/gcc/testsuite/g++.dg/modules/pr119076-1_a.H 
b/gcc/testsuite/g++.dg/modules/pr119076-1_a.H
new file mode 100644
index 000000000000..17eb756eb720
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr119076-1_a.H
@@ -0,0 +1,41 @@
+// { dg-additional-options "-fmodule-header -Wno-pedantic" }
+// { dg-module-cmi {} }
+
+constexpr unsigned char a[] = {
+#embed __FILE__
+};
+
+constexpr int
+foo (const unsigned char *p, int s)
+{
+  int r = 0;
+  for (int i = 0; i < s; ++i)
+    r += p[i];
+  return r;
+}
+
+constexpr int b = foo (a, sizeof a);
+
+inline int
+bar ()
+{
+  const unsigned char b[] = {
+    #embed __FILE__
+  };
+  int r = 0;
+  for (int i = 0; i < sizeof b; ++i)
+    r += b[i];
+  return r;
+}
+
+inline int
+baz ()
+{
+  const long int c[] = {
+    #embed __FILE__
+  };
+  int r = 0;
+  for (int i = 0; i < sizeof (c) / sizeof (c[0]); ++i)
+    r += c[i];
+  return r;
+}
diff --git a/gcc/testsuite/g++.dg/modules/pr119076-1_b.C 
b/gcc/testsuite/g++.dg/modules/pr119076-1_b.C
new file mode 100644
index 000000000000..e6528d141144
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr119076-1_b.C
@@ -0,0 +1,12 @@
+// PR c++/119076
+// { dg-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+import "pr119076-1_a.H";
+
+int
+main ()
+{
+  if (bar () != b || baz () != b)
+    __builtin_abort ();
+}
diff --git a/gcc/testsuite/g++.dg/modules/pr119076-2_a.H 
b/gcc/testsuite/g++.dg/modules/pr119076-2_a.H
new file mode 100644
index 000000000000..7c139fd63d6b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr119076-2_a.H
@@ -0,0 +1,65 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+constexpr unsigned char a[] = {
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+};
+
+constexpr int
+foo (const unsigned char *p, int s)
+{
+  int r = 0;
+  for (int i = 0; i < s; ++i)
+    r += p[i];
+  return r;
+}
+
+constexpr int b = foo (a, sizeof a);
+
+inline int
+bar ()
+{
+  const unsigned char b[] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+  };
+  int r = 0;
+  for (int i = 0; i < sizeof b; ++i)
+    r += b[i];
+  return r;
+}
+
+inline int
+baz ()
+{
+  const long int c[] = {
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+    0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+  };
+  int r = 0;
+  for (int i = 0; i < sizeof (c) / sizeof (c[0]); ++i)
+    r += c[i];
+  return r;
+}
diff --git a/gcc/testsuite/g++.dg/modules/pr119076-2_b.C 
b/gcc/testsuite/g++.dg/modules/pr119076-2_b.C
new file mode 100644
index 000000000000..3dba75f29497
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr119076-2_b.C
@@ -0,0 +1,12 @@
+// PR c++/119076
+// { dg-do run }
+// { dg-additional-options "-fmodules-ts" }
+
+import "pr119076-2_a.H";
+
+int
+main ()
+{
+  if (bar () != b || baz () != b)
+    __builtin_abort ();
+}

Reply via email to