aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2025-01-21 09:12:21 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2025-01-21 09:12:21 +0100
commit843ca8a964bcfeae72d9d48e2dd549fa818120e3 (patch)
tree2ee2b3f765e50fe4de1996065e715610fa88702a
parentd559fbab6123e2f8bfaeb3672f921bf53a00dba6 (diff)
downloadgcc-843ca8a964bcfeae72d9d48e2dd549fa818120e3.zip
gcc-843ca8a964bcfeae72d9d48e2dd549fa818120e3.tar.gz
gcc-843ca8a964bcfeae72d9d48e2dd549fa818120e3.tar.bz2
c++: Handle RAW_DATA_CST in add_list_candidates [PR118532]
This is the second bug discovered today with the https://gcc.gnu.org/pipermail/gcc-patches/2025-January/673945.html hack but then turned into proper testcases where embed-2[23].C FAILed since introduction of optimized #embed support and the others when optimizing large C++ initializers using RAW_DATA_CST. The add_list_candidates problem is the same as with make_tree_vector_from_ctor, unfortunately it can't call that function because it can have those additional artificial arguments that need to be pushed earlier. When working on the patch, I've also noticed an error where we didn't know how to dump RAW_DATA_CST, so I've added support for that too. 2025-01-21 Jakub Jelinek <jakub@redhat.com> PR c++/118532 * call.cc (add_list_candidates): Handle RAW_DATA_CST among init_list elts. * error.cc (dump_expr_init_vec): Handle RAW_DATA_CST among v elts. * g++.dg/cpp/embed-22.C: New test. * g++.dg/cpp/embed-23.C: New test. * g++.dg/cpp0x/pr118532.C: New test. * g++.dg/cpp2a/explicit20.C: New test.
-rw-r--r--gcc/cp/call.cc23
-rw-r--r--gcc/cp/error.cc21
-rw-r--r--gcc/testsuite/g++.dg/cpp/embed-22.C24
-rw-r--r--gcc/testsuite/g++.dg/cpp/embed-23.C21
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr118532.C25
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/explicit20.C23
6 files changed, 134 insertions, 3 deletions
diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 9e57261..80015df 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -4258,11 +4258,30 @@ add_list_candidates (tree fns, tree first_arg,
/* Expand the CONSTRUCTOR into a new argument vec. */
vec<tree, va_gc> *new_args;
- vec_alloc (new_args, nart + CONSTRUCTOR_NELTS (init_list));
+ unsigned nelts = nart + CONSTRUCTOR_NELTS (init_list);
+ vec_alloc (new_args, nelts);
for (unsigned i = 0; i < nart; ++i)
new_args->quick_push ((*args)[i]);
for (unsigned i = 0; i < CONSTRUCTOR_NELTS (init_list); ++i)
- new_args->quick_push (CONSTRUCTOR_ELT (init_list, i)->value);
+ if (TREE_CODE (CONSTRUCTOR_ELT (init_list, i)->value) == RAW_DATA_CST)
+ {
+ tree raw_data = CONSTRUCTOR_ELT (init_list, i)->value;
+ nelts += RAW_DATA_LENGTH (raw_data) - 1;
+ vec_safe_reserve (new_args, nelts - new_args->length ());
+ if (TYPE_PRECISION (TREE_TYPE (raw_data)) > CHAR_BIT
+ || TYPE_UNSIGNED (TREE_TYPE (raw_data)))
+ for (unsigned j = 0; j < (unsigned) RAW_DATA_LENGTH (raw_data); ++j)
+ new_args->quick_push (build_int_cst (TREE_TYPE (raw_data),
+ RAW_DATA_UCHAR_ELT (raw_data,
+ j)));
+ else
+ for (unsigned j = 0; j < (unsigned) RAW_DATA_LENGTH (raw_data); ++j)
+ new_args->quick_push (build_int_cst (TREE_TYPE (raw_data),
+ RAW_DATA_SCHAR_ELT (raw_data,
+ j)));
+ }
+ else
+ new_args->quick_push (CONSTRUCTOR_ELT (init_list, i)->value);
/* We aren't looking for list-ctors anymore. */
flags &= ~LOOKUP_LIST_ONLY;
diff --git a/gcc/cp/error.cc b/gcc/cp/error.cc
index 615ae0d..a33afdb 100644
--- a/gcc/cp/error.cc
+++ b/gcc/cp/error.cc
@@ -2289,7 +2289,26 @@ dump_expr_init_vec (cxx_pretty_printer *pp, vec<constructor_elt, va_gc> *v,
FOR_EACH_CONSTRUCTOR_VALUE (v, idx, value)
{
- dump_expr (pp, value, flags | TFF_EXPR_IN_PARENS);
+ if (TREE_CODE (value) == RAW_DATA_CST)
+ for (unsigned i = 0; i < (unsigned) RAW_DATA_LENGTH (value); ++i)
+ {
+ if (TYPE_UNSIGNED (TREE_TYPE (value))
+ || TYPE_PRECISION (TREE_TYPE (value)) > CHAR_BIT)
+ pp_decimal_int (pp, RAW_DATA_UCHAR_ELT (value, i));
+ else
+ pp_decimal_int (pp, RAW_DATA_SCHAR_ELT (value, i));
+ if (i == RAW_DATA_LENGTH (value) - 1U)
+ break;
+ else if (i == 9 && RAW_DATA_LENGTH (value) > 20)
+ {
+ pp_string (pp, ", ..., ");
+ i = RAW_DATA_LENGTH (value) - 11;
+ }
+ else
+ pp_separate_with_comma (pp);
+ }
+ else
+ dump_expr (pp, value, flags | TFF_EXPR_IN_PARENS);
if (idx != v->length () - 1)
pp_separate_with_comma (pp);
}
diff --git a/gcc/testsuite/g++.dg/cpp/embed-22.C b/gcc/testsuite/g++.dg/cpp/embed-22.C
new file mode 100644
index 0000000..754cac4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/embed-22.C
@@ -0,0 +1,24 @@
+// PR c++/118532
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+struct S {
+ S (int, int, int);
+#define I8 int, int, int, int, int, int, int, int
+#define I64 I8, I8, I8, I8, I8, I8, I8, I8
+ S (I64, I64, I64, I64, I8);
+};
+
+void
+foo (S &)
+{
+}
+
+int
+main ()
+{
+ S s = {
+#embed __FILE__ limit (264)
+ };
+ foo (s);
+}
diff --git a/gcc/testsuite/g++.dg/cpp/embed-23.C b/gcc/testsuite/g++.dg/cpp/embed-23.C
new file mode 100644
index 0000000..5775e677
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp/embed-23.C
@@ -0,0 +1,21 @@
+// PR c++/118532
+// { dg-do compile { target c++20 } }
+// { dg-options "" }
+
+constexpr int fn0 () { return 0; }
+constexpr int fn1 () { return 1; }
+
+struct S {
+ explicit(fn0()) S(int, int, int);
+#define I8 int, int, int, int, int, int, int, int
+#define I64 I8, I8, I8, I8, I8, I8, I8, I8
+ explicit(fn1()) S(I64, I64, I64, I64, I8);
+};
+
+int
+main ()
+{
+ S s4 = {
+#embed __FILE__ limit (264)
+ }; // { dg-error "converting" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr118532.C b/gcc/testsuite/g++.dg/cpp0x/pr118532.C
new file mode 100644
index 0000000..f734373
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/pr118532.C
@@ -0,0 +1,25 @@
+// PR c++/118532
+// { dg-do compile { target c++11 } }
+
+struct S {
+ S (int, int, int);
+#define I8 int, int, int, int, int, int, int, int
+#define I64 I8, I8, I8, I8, I8, I8, I8, I8
+ S (I64, I64, I64, I64, I8);
+};
+
+void
+foo (S &)
+{
+}
+
+int
+main ()
+{
+ S s = {
+#undef I8
+#define I8 1, 2, 3, 4, 5, 6, 7, 8
+ I64, I64, I64, I64, I8
+ };
+ foo (s);
+}
diff --git a/gcc/testsuite/g++.dg/cpp2a/explicit20.C b/gcc/testsuite/g++.dg/cpp2a/explicit20.C
new file mode 100644
index 0000000..7affb2a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/explicit20.C
@@ -0,0 +1,23 @@
+// PR c++/118532
+// { dg-do compile { target c++20 } }
+// { dg-options "" }
+
+constexpr int fn0 () { return 0; }
+constexpr int fn1 () { return 1; }
+
+struct S {
+ explicit(fn0()) S(int, int, int);
+#define I8 int, int, int, int, int, int, int, int
+#define I64 I8, I8, I8, I8, I8, I8, I8, I8
+ explicit(fn1()) S(I64, I64, I64, I64, I8);
+};
+
+int
+main ()
+{
+ S s4 = {
+#undef I8
+#define I8 1, 2, 3, 4, 5, 6, 7, 8
+ I64, I64, I64, I64, I8
+ }; // { dg-error "converting" }
+}