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