https://gcc.gnu.org/g:f263f2d525eb9a1b60c2a356eb64262819b6bab0
commit r15-6907-gf263f2d525eb9a1b60c2a356eb64262819b6bab0 Author: Jakub Jelinek <ja...@redhat.com> Date: Wed Jan 15 08:46:48 2025 +0100 c++: Fix ICEs with large initializer lists or ones including #embed [PR118124] The following testcases ICE due to RAW_DATA_CST not being handled where it should be during ck_list conversions. The last 2 testcases started ICEing with r15-6339 committed yesterday (speedup of large initializers), the first two already with r15-5958 (#embed optimization for C++). For conversion to initializer_list<unsigned char> or char/signed char we can optimize and keep RAW_DATA_CST with adjusted type if we report narrowing errors if needed, for others this converts each element separately. 2025-01-15 Jakub Jelinek <ja...@redhat.com> PR c++/118124 * call.cc (convert_like_internal): Handle RAW_DATA_CST in ck_list handling. Formatting fixes. * g++.dg/cpp/embed-15.C: New test. * g++.dg/cpp/embed-16.C: New test. * g++.dg/cpp0x/initlist-opt3.C: New test. * g++.dg/cpp0x/initlist-opt4.C: New test. Diff: --- gcc/cp/call.cc | 95 ++++++++++++++++++++++++++++-- gcc/testsuite/g++.dg/cpp/embed-15.C | 35 +++++++++++ gcc/testsuite/g++.dg/cpp/embed-16.C | 18 ++++++ gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C | 47 +++++++++++++++ gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C | 20 +++++++ 5 files changed, 209 insertions(+), 6 deletions(-) diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 602f496e1806..65d613e37b30 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -8806,8 +8806,9 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, if (tree init = maybe_init_list_as_array (elttype, expr)) { - elttype = cp_build_qualified_type - (elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST); + elttype + = cp_build_qualified_type (elttype, (cp_type_quals (elttype) + | TYPE_QUAL_CONST)); array = build_array_of_n_type (elttype, len); array = build_vec_init_expr (array, init, complain); array = get_target_expr (array); @@ -8815,13 +8816,94 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, } else if (len) { - tree val; unsigned ix; - + tree val; + unsigned ix; tree new_ctor = build_constructor (init_list_type_node, NULL); /* Convert all the elements. */ FOR_EACH_CONSTRUCTOR_VALUE (CONSTRUCTOR_ELTS (expr), ix, val) { + if (TREE_CODE (val) == RAW_DATA_CST) + { + tree elt_type; + conversion *next; + /* For conversion to initializer_list<unsigned char> or + initializer_list<char> or initializer_list<signed char> + we can optimize and keep RAW_DATA_CST with adjusted + type if we report narrowing errors if needed, for + others this converts each element separately. */ + if (convs->u.list[ix]->kind == ck_std + && (elt_type = convs->u.list[ix]->type) + && (TREE_CODE (elt_type) == INTEGER_TYPE + || is_byte_access_type (elt_type)) + && TYPE_PRECISION (elt_type) == CHAR_BIT + && (next = next_conversion (convs->u.list[ix])) + && next->kind == ck_identity) + { + if (!TYPE_UNSIGNED (elt_type) + /* For RAW_DATA_CST, TREE_TYPE (val) can be + either integer_type_node (when it has been + created by the lexer from CPP_EMBED) or + after digestion/conversion some integral + type with CHAR_BIT precision. For int with + precision higher than CHAR_BIT or unsigned char + diagnose narrowing conversions from + that int/unsigned char to signed char if any + byte has most significant bit set. */ + && (TYPE_UNSIGNED (TREE_TYPE (val)) + || (TYPE_PRECISION (TREE_TYPE (val)) + > CHAR_BIT))) + for (int i = 0; i < RAW_DATA_LENGTH (val); ++i) + { + if (RAW_DATA_SCHAR_ELT (val, i) >= 0) + continue; + else if (complain & tf_error) + { + location_t loc + = cp_expr_loc_or_input_loc (val); + int savederrorcount = errorcount; + permerror_opt (loc, OPT_Wnarrowing, + "narrowing conversion of " + "%qd from %qH to %qI", + RAW_DATA_UCHAR_ELT (val, i), + TREE_TYPE (val), elt_type); + if (errorcount != savederrorcount) + return error_mark_node; + } + else + return error_mark_node; + } + tree sub = copy_node (val); + TREE_TYPE (sub) = elt_type; + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (new_ctor), + NULL_TREE, sub); + } + else + { + for (int i = 0; i < RAW_DATA_LENGTH (val); ++i) + { + tree elt + = build_int_cst (TREE_TYPE (val), + RAW_DATA_UCHAR_ELT (val, i)); + tree sub + = convert_like (convs->u.list[ix], elt, + fn, argnum, false, false, + /*nested_p=*/true, complain); + if (sub == error_mark_node) + return sub; + if (!check_narrowing (TREE_TYPE (sub), elt, + complain)) + return error_mark_node; + tree nc = new_ctor; + CONSTRUCTOR_APPEND_ELT (CONSTRUCTOR_ELTS (nc), + NULL_TREE, sub); + if (!TREE_CONSTANT (sub)) + TREE_CONSTANT (new_ctor) = false; + } + } + len += RAW_DATA_LENGTH (val) - 1; + continue; + } tree sub = convert_like (convs->u.list[ix], val, fn, argnum, false, false, /*nested_p=*/true, complain); @@ -8836,8 +8918,9 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, TREE_CONSTANT (new_ctor) = false; } /* Build up the array. */ - elttype = cp_build_qualified_type - (elttype, cp_type_quals (elttype) | TYPE_QUAL_CONST); + elttype + = cp_build_qualified_type (elttype, (cp_type_quals (elttype) + | TYPE_QUAL_CONST)); array = build_array_of_n_type (elttype, len); array = finish_compound_literal (array, new_ctor, complain); /* This is dubious now, should be blessed by P2752. */ diff --git a/gcc/testsuite/g++.dg/cpp/embed-15.C b/gcc/testsuite/g++.dg/cpp/embed-15.C new file mode 100644 index 000000000000..a3994536e576 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp/embed-15.C @@ -0,0 +1,35 @@ +// PR c++/118124 +// { dg-do compile { target c++11 } } +// { dg-options "-O2" } + +namespace std { +template <class T> struct initializer_list { +private: + const T *_M_array; + __SIZE_TYPE__ _M_len; +}; +} +struct A { + A (std::initializer_list<char>); +}; +A a { +#embed __FILE__ +}; +struct B { + B (std::initializer_list<unsigned char>); +}; +B b { +#embed __FILE__ +}; +struct C { + C (std::initializer_list<int>); +}; +C c { +#embed __FILE__ +}; +struct D { + D (std::initializer_list<float>); +}; +D d { +#embed __FILE__ +}; diff --git a/gcc/testsuite/g++.dg/cpp/embed-16.C b/gcc/testsuite/g++.dg/cpp/embed-16.C new file mode 100644 index 000000000000..868dce2f165c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp/embed-16.C @@ -0,0 +1,18 @@ +// PR c++/118124 +// { dg-do compile { target c++11 } } +// { dg-options "-O2" } +// non-ASCII chars here: áéí + +namespace std { +template <class T> struct initializer_list { +private: + const T *_M_array; + __SIZE_TYPE__ _M_len; +}; +} +struct A { + A (std::initializer_list<signed char>); +}; +A a { +#embed __FILE__ +}; // { dg-error "narrowing conversion of '\[0-9]*' from 'int' to 'signed char'" } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C b/gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C new file mode 100644 index 000000000000..fa279882322d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-opt3.C @@ -0,0 +1,47 @@ +// PR c++/118124 +// { dg-do compile { target c++11 } } +// { dg-options "-O2" } + +namespace std { +template <class T> struct initializer_list { +private: + const T *_M_array; + __SIZE_TYPE__ _M_len; +}; +} +struct A { + A (std::initializer_list<char>); +}; +A a { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; +struct B { + B (std::initializer_list<unsigned char>); +}; +B b { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; +struct C { + C (std::initializer_list<int>); +}; +C c { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; +struct D { + D (std::initializer_list<float>); +}; +D d { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C b/gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C new file mode 100644 index 000000000000..080dee3cf026 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-opt4.C @@ -0,0 +1,20 @@ +// PR c++/118124 +// { dg-do compile { target c++11 } } +// { dg-options "-O2" } + +namespace std { +template <class T> struct initializer_list { +private: + const T *_M_array; + __SIZE_TYPE__ _M_len; +}; +} +struct A { + A (std::initializer_list<signed char>); +}; +A a { 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, + 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 209, 0, 1, 2, 3, + 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, + 6, 7, 8, 9, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0, 1, 2, 3, 4, 5 }; // { dg-error "narrowing conversion of '209' from 'int' to 'signed char'" }