Hi!

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.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2025-03-04  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.

--- gcc/cp/module.cc.jj 2025-01-28 09:23:38.195599960 +0100
+++ gcc/cp/module.cc    2025-03-04 00:52:50.947063367 +0100
@@ -5319,6 +5319,30 @@ trees_out::start (tree t, bool code_stre
       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));
@@ -5400,6 +5424,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 ();
@@ -6311,6 +6353,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));
@@ -6845,6 +6903,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));
--- gcc/testsuite/g++.dg/modules/pr119076-1_a.H.jj      2025-03-03 
10:22:17.514294281 +0100
+++ gcc/testsuite/g++.dg/modules/pr119076-1_a.H 2025-03-03 12:04:10.041822216 
+0100
@@ -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;
+}
--- gcc/testsuite/g++.dg/modules/pr119076-1_b.C.jj      2025-03-03 
10:22:21.241242404 +0100
+++ gcc/testsuite/g++.dg/modules/pr119076-1_b.C 2025-03-03 12:00:43.439674082 
+0100
@@ -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 ();
+}
--- gcc/testsuite/g++.dg/modules/pr119076-2_a.H.jj      2025-03-03 
12:02:12.254448113 +0100
+++ gcc/testsuite/g++.dg/modules/pr119076-2_a.H 2025-03-03 12:03:19.239523473 
+0100
@@ -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;
+}
--- gcc/testsuite/g++.dg/modules/pr119076-2_b.C.jj      2025-03-03 
12:03:31.627352476 +0100
+++ gcc/testsuite/g++.dg/modules/pr119076-2_b.C 2025-03-03 12:03:40.061236054 
+0100
@@ -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 ();
+}

        Jakub

Reply via email to