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 (); +}