]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Handle RAW_DATA_CST in add_list_candidates [PR118532]
authorJakub Jelinek <jakub@redhat.com>
Tue, 21 Jan 2025 08:12:21 +0000 (09:12 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 21 Jan 2025 08:12:21 +0000 (09:12 +0100)
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.

gcc/cp/call.cc
gcc/cp/error.cc
gcc/testsuite/g++.dg/cpp/embed-22.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp/embed-23.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/pr118532.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/explicit20.C [new file with mode: 0644]

index 9e57261cf17d48bc319f6162d7ebf1b5ad4064d6..80015dfe9da66f9a125eebfadb2b7882875ab125 100644 (file)
@@ -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;
index 615ae0d1b65ae799991af183cf80111dc2126e51..a33afdb3d509871cfcee5f1a886a8d72e4a2119a 100644 (file)
@@ -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 (file)
index 0000000..754cac4
--- /dev/null
@@ -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 (file)
index 0000000..5775e67
--- /dev/null
@@ -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 (file)
index 0000000..f734373
--- /dev/null
@@ -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 (file)
index 0000000..7affb2a
--- /dev/null
@@ -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" }
+}