PR c++/86320 - memory-hog with std::array of pair
authorJason Merrill <jason@redhat.com>
Wed, 27 Jun 2018 02:59:44 +0000 (22:59 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 27 Jun 2018 02:59:44 +0000 (22:59 -0400)
* typeck2.c (process_init_constructor_array): Only compute a
constant initializer once.

In this PR, we have a large std::array of pairs.  Since the C array is
wrapped in a class we don't go to build_vec_init, so we end up with
digest_init wanting to build up the element initializer for each element of
the array.

In the more general case, like 80272, we have a data structure problem: we
don't currently have a good way of expressing the same dynamic
initialization of many elements within a CONSTRUCTOR.  RANGE_EXPR probably
ought to work, but will need more work at genericize or gimplify time.

But in this case, the initialization for each element reduces to constant
0, so we don't even need to add anything to the CONSTRUCTOR.  We just need
to realize that if the initializer for one element is 0, the others will be
as well, and we don't need to iterate over the whole array.

For the trunk, I also use a RANGE_EXPR to handle constant initialization by
a value other than 0.

void foo ()
{
  std::array<std::pair<int, int>, 1024 * 1024> arr {};
}

From-SVN: r262173

gcc/cp/ChangeLog
gcc/cp/typeck2.c

index 3043165a1e6e65112590cdfa39c1e19b52907640..90d1545d7344f839ab406fb4e52ed02eb68b884e 100644 (file)
@@ -1,5 +1,9 @@
 2018-06-26  Jason Merrill  <jason@redhat.com>
 
+       PR c++/86320 - memory-hog with std::array of pair
+       * typeck2.c (process_init_constructor_array): Only compute a
+       constant initializer once.
+
        PR c++/80290 - memory-hog with std::pair.
        * pt.c (fn_type_unification): Add convs parameter.
        (check_non_deducible_conversion): Remember conversion.
index 43e236de41c1d7deaa14bc13571bb52d35bad71d..91aa5a62856d13517cb5f4d07d1427eb87895b89 100644 (file)
@@ -1365,8 +1365,22 @@ process_init_constructor_array (tree type, tree init, int nested,
        if (next)
          {
            flags |= picflag_from_initializer (next);
-           CONSTRUCTOR_APPEND_ELT (v, size_int (i), next);
+           if (len > i+1
+               && (initializer_constant_valid_p (next, TREE_TYPE (next))
+                   == null_pointer_node))
+             {
+               tree range = build2 (RANGE_EXPR, size_type_node,
+                                    build_int_cst (size_type_node, i),
+                                    build_int_cst (size_type_node, len - 1));
+               CONSTRUCTOR_APPEND_ELT (v, range, next);
+               break;
+             }
+           else
+             CONSTRUCTOR_APPEND_ELT (v, size_int (i), next);
          }
+       else
+         /* Don't bother checking all the other elements.  */
+         break;
       }
 
   CONSTRUCTOR_ELTS (init) = v;