https://gcc.gnu.org/g:64828272cde415bf2d7222eec87147ba84980f3d
commit r15-6908-g64828272cde415bf2d7222eec87147ba84980f3d Author: Jakub Jelinek <ja...@redhat.com> Date: Wed Jan 15 08:53:13 2025 +0100 c++: Fix up maybe_init_list_as_array for RAW_DATA_CST [PR118124] The previous patch made me look around some more and I found maybe_init_list_as_array doesn't handle RAW_DATA_CSTs correctly either, while the RAW_DATA_CST is properly split during finish_compound_literal, it was using CONSTRUCTOR_NELTS as the size of the arrays, which is wrong, RAW_DATA_CST could stand for far more initializers. 2025-01-15 Jakub Jelinek <ja...@redhat.com> PR c++/118124 * cp-tree.h (build_array_of_n_type): Change second argument type from int to unsigned HOST_WIDE_INT. * tree.cc (build_array_of_n_type): Likewise. * call.cc (count_ctor_elements): New function. (maybe_init_list_as_array): Use it instead of CONSTRUCTOR_NELTS. (convert_like_internal): Use length from init's type instead of len when handling the maybe_init_list_as_array case. * g++.dg/cpp0x/initlist-opt5.C: New test. Diff: --- gcc/cp/call.cc | 23 ++++++++++++++++++++--- gcc/cp/cp-tree.h | 2 +- gcc/cp/tree.cc | 2 +- gcc/testsuite/g++.dg/cpp0x/initlist-opt5.C | 23 +++++++++++++++++++++++ 4 files changed, 45 insertions(+), 5 deletions(-) diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc index 65d613e37b30..63be8b58906b 100644 --- a/gcc/cp/call.cc +++ b/gcc/cp/call.cc @@ -4331,6 +4331,20 @@ has_non_trivial_temporaries (tree expr) return false; } +/* Return number of initialized elements in CTOR. */ + +static unsigned HOST_WIDE_INT +count_ctor_elements (tree ctor) +{ + unsigned HOST_WIDE_INT len = 0; + for (constructor_elt &e: CONSTRUCTOR_ELTS (ctor)) + if (TREE_CODE (e.value) == RAW_DATA_CST) + len += RAW_DATA_LENGTH (e.value); + else + ++len; + return len; +} + /* We're initializing an array of ELTTYPE from INIT. If it seems useful, return INIT as an array (of its own type) so the caller can initialize the target array in a loop. */ @@ -4392,7 +4406,8 @@ maybe_init_list_as_array (tree elttype, tree init) if (!is_xible (INIT_EXPR, elttype, copy_argtypes)) return NULL_TREE; - tree arr = build_array_of_n_type (init_elttype, CONSTRUCTOR_NELTS (init)); + unsigned HOST_WIDE_INT len = count_ctor_elements (init); + tree arr = build_array_of_n_type (init_elttype, len); arr = finish_compound_literal (arr, init, tf_none); DECL_MERGEABLE (TARGET_EXPR_SLOT (arr)) = true; return arr; @@ -8801,7 +8816,7 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, { /* Conversion to std::initializer_list<T>. */ tree elttype = TREE_VEC_ELT (CLASSTYPE_TI_ARGS (totype), 0); - unsigned len = CONSTRUCTOR_NELTS (expr); + unsigned HOST_WIDE_INT len = CONSTRUCTOR_NELTS (expr); tree array; if (tree init = maybe_init_list_as_array (elttype, expr)) @@ -8809,7 +8824,9 @@ convert_like_internal (conversion *convs, tree expr, tree fn, int argnum, elttype = cp_build_qualified_type (elttype, (cp_type_quals (elttype) | TYPE_QUAL_CONST)); - array = build_array_of_n_type (elttype, len); + tree index_type = TYPE_DOMAIN (TREE_TYPE (init)); + array = build_cplus_array_type (elttype, index_type); + len = TREE_INT_CST_LOW (TYPE_MAX_VALUE (index_type)) + 1; array = build_vec_init_expr (array, init, complain); array = get_target_expr (array); array = cp_build_addr_expr (array, complain); diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index b65a2677b4ec..2d17c4c77b56 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -8179,7 +8179,7 @@ extern tree build_aggr_init_expr (tree, tree); extern tree get_target_expr (tree, tsubst_flags_t = tf_warning_or_error); extern tree build_cplus_array_type (tree, tree, int is_dep = -1); -extern tree build_array_of_n_type (tree, int); +extern tree build_array_of_n_type (tree, unsigned HOST_WIDE_INT); extern bool array_of_runtime_bound_p (tree); extern bool vla_type_p (tree); extern tree build_array_copy (tree); diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index dd6e872e4e77..988e99d18bbb 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -1207,7 +1207,7 @@ build_cplus_array_type (tree elt_type, tree index_type, int dependent) /* Return an ARRAY_TYPE with element type ELT and length N. */ tree -build_array_of_n_type (tree elt, int n) +build_array_of_n_type (tree elt, unsigned HOST_WIDE_INT n) { return build_cplus_array_type (elt, build_index_type (size_int (n - 1))); } diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-opt5.C b/gcc/testsuite/g++.dg/cpp0x/initlist-opt5.C new file mode 100644 index 000000000000..65a1fd6e6f7c --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/initlist-opt5.C @@ -0,0 +1,23 @@ +// 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; + decltype (sizeof 0) _M_len; +}; +} +struct B { + B (int); +}; +struct A { + A (std::initializer_list<B>); +}; +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 };