]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: Fix up maybe_init_list_as_array for RAW_DATA_CST [PR118124]
authorJakub Jelinek <jakub@redhat.com>
Wed, 15 Jan 2025 07:53:13 +0000 (08:53 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Wed, 15 Jan 2025 07:59:46 +0000 (08:59 +0100)
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  <jakub@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.

gcc/cp/call.cc
gcc/cp/cp-tree.h
gcc/cp/tree.cc
gcc/testsuite/g++.dg/cpp0x/initlist-opt5.C [new file with mode: 0644]

index 65d613e37b302f9004f1d0577e0f56743b57bd00..63be8b58906b35302346c1ff1359d877cbd36331 100644 (file)
@@ -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);
index b65a2677b4ec8a0e690ffea87d4e1146cf6e7c68..2d17c4c77b56770a6fd857d6c526e855462f8643 100644 (file)
@@ -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);
index dd6e872e4e776dfc59111dd66e80d23dd617019f..988e99d18bbb755186a654ba8b5822021bf8ae2b 100644 (file)
@@ -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 (file)
index 0000000..65a1fd6
--- /dev/null
@@ -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 };