Hi!

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.

Fixed thusly, ok for trunk if it passes bootstrap/regtest?

2024-12-19  Jakub Jelinek  <ja...@redhat.com>

        PR c++/118124
        * call.cc (maybe_init_list_as_array): Adjust len for RAW_DATA_CST
        elements.
        (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.

--- gcc/cp/call.cc.jj   2024-12-19 16:10:12.977071898 +0100
+++ gcc/cp/call.cc      2024-12-19 16:55:40.953546502 +0100
@@ -4386,7 +4386,13 @@ maybe_init_list_as_array (tree elttype,
   if (!is_xible (INIT_EXPR, elttype, copy_argtypes))
     return NULL_TREE;
 
-  tree arr = build_array_of_n_type (init_elttype, CONSTRUCTOR_NELTS (init));
+  unsigned int len = CONSTRUCTOR_NELTS (init);
+  if (INTEGRAL_TYPE_P (init_elttype))
+    for (constructor_elt &e: CONSTRUCTOR_ELTS (init))
+      if (TREE_CODE (e.value) == RAW_DATA_CST)
+       len += RAW_DATA_LENGTH (e.value) - 1;
+
+  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;
@@ -8768,7 +8774,9 @@ convert_like_internal (conversion *convs
          {
            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);
--- gcc/testsuite/g++.dg/cpp0x/initlist-opt5.C.jj       2024-12-19 
16:56:44.113675894 +0100
+++ gcc/testsuite/g++.dg/cpp0x/initlist-opt5.C  2024-12-19 16:37:28.335605902 
+0100
@@ -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 };

        Jakub

Reply via email to