]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix up RAW_DATA_CST handling in braced_list_to_string [PR122302]
authorJakub Jelinek <jakub@redhat.com>
Wed, 22 Oct 2025 11:11:52 +0000 (13:11 +0200)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 22 Oct 2025 11:11:52 +0000 (13:11 +0200)
The following testcase is miscompiled, because a RAW_DATA_CST tree
node is shared by multiple CONSTRUCTORs and when the braced_list_to_string
function changes one to extend the RAW_DATA_CST over the single preceding
and single succeeding INTEGER_CST, it changes the RAW_DATA_CST in
the other CONSTRUCTOR where the elts around it are still present.

Fixed by tweaking a copy of it instead, like we handle it in other spots.

2025-10-22  Jakub Jelinek  <jakub@redhat.com>

PR c++/122302
* c-common.cc (braced_list_to_string): Call copy_node on RAW_DATA_CST
before changing RAW_DATA_POINTER and RAW_DATA_LENGTH on it.

* g++.dg/cpp0x/pr122302.C: New test.
* g++.dg/cpp/embed-27.C: New test.

gcc/c-family/c-common.cc
gcc/testsuite/g++.dg/cpp/embed-27.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr122302.C [new file with mode: 0644]

index 54e16f7081348c242cf3542f4d966970d79977d0..f2eed03370655f5fd80f9711a6348641544a4279 100644 (file)
@@ -10296,6 +10296,7 @@ braced_list_to_string (tree type, tree ctor, bool member)
                    j = i - start;
                  else
                    j -= start;
+                 value = copy_node (value);
                  RAW_DATA_POINTER (value) -= start;
                  RAW_DATA_LENGTH (value) += start + end;
                  i += end;
diff --git a/gcc/testsuite/g++.dg/cpp/embed-27.C b/gcc/testsuite/g++.dg/cpp/embed-27.C
new file mode 100644 (file)
index 0000000..dffb8b9
--- /dev/null
@@ -0,0 +1,38 @@
+// PR c++/122302
+// { dg-do run { target c++11 } }
+// { dg-options "-O2" }
+
+unsigned char b[] = {
+#embed "embed-27.C"
+};
+
+struct A {
+  unsigned char a[sizeof (b)] = { 
+#embed "embed-27.C"
+  };
+};
+
+void
+foo ()
+{
+  A a;
+  for (int i = 0; i < sizeof (b); ++i)
+    if (a.a[i] != b[i])
+      __builtin_abort ();
+}
+
+void
+bar ()
+{
+  A a;
+  for (int i = 0; i < sizeof (b); ++i)
+    if (a.a[i] != b[i])
+      __builtin_abort ();
+}
+
+int
+main ()
+{
+  foo ();
+  bar ();
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr122302.C b/gcc/testsuite/g++.dg/cpp0x/pr122302.C
new file mode 100644 (file)
index 0000000..248b6a4
--- /dev/null
@@ -0,0 +1,40 @@
+// PR c++/122302
+// { dg-do run { target c++11 } }
+// { dg-options "-O2" }
+
+struct A {
+  unsigned char a[130] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+                          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+                          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+                          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+                          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+                          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+                          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+                          1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
+                          1, 2 };
+};
+
+void
+foo ()
+{
+  A a;
+  for (int i = 0; i < 130; ++i)
+    if (a.a[i] != (i & 15) + 1)
+      __builtin_abort ();
+}
+
+void
+bar ()
+{
+  A a;
+  for (int i = 0; i < 130; ++i)
+    if (a.a[i] != (i & 15) + 1)
+      __builtin_abort ();
+}
+
+int
+main ()
+{
+  foo ();
+  bar ();
+}