On Fri, Jan 17, 2025 at 09:11:15PM +0100, Jakub Jelinek wrote: > 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.
Here is updated patch similarly to the PR118528 changes. Tested so far with GXX_TESTSUITE_STDS=98,11,14,17,20,23,26 make check-g++ RUNTESTFLAGS="dg.exp='embed* class-deduction-aggr*.C explicit*.C pr11853[24]*'" 2025-01-18 Jakub Jelinek <ja...@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.jj 2025-01-15 18:24:36.135503866 +0100 +++ gcc/cp/call.cc 2025-01-17 14:42:38.201643385 +0100 @@ -4258,11 +4258,30 @@ add_list_candidates (tree fns, tree firs /* 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; --- gcc/cp/error.cc.jj 2025-01-10 10:26:37.390685341 +0100 +++ gcc/cp/error.cc 2025-01-17 16:20:44.089508010 +0100 @@ -2289,7 +2289,26 @@ dump_expr_init_vec (cxx_pretty_printer * 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); } --- gcc/testsuite/g++.dg/cpp/embed-22.C.jj 2025-01-17 17:06:54.731279618 +0100 +++ gcc/testsuite/g++.dg/cpp/embed-22.C 2025-01-17 16:56:02.499282953 +0100 @@ -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); +} --- gcc/testsuite/g++.dg/cpp/embed-23.C.jj 2025-01-17 17:02:17.333105186 +0100 +++ gcc/testsuite/g++.dg/cpp/embed-23.C 2025-01-17 17:02:32.650893591 +0100 @@ -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" } +} --- gcc/testsuite/g++.dg/cpp0x/pr118532.C.jj 2025-01-17 16:56:25.849960395 +0100 +++ gcc/testsuite/g++.dg/cpp0x/pr118532.C 2025-01-17 16:56:42.419731513 +0100 @@ -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); +} --- gcc/testsuite/g++.dg/cpp2a/explicit20.C.jj 2025-01-17 17:02:56.475564490 +0100 +++ gcc/testsuite/g++.dg/cpp2a/explicit20.C 2025-01-17 17:03:22.240208592 +0100 @@ -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" } +} Jakub