re PR c++/53650 (large array causes huge memory use)
authorJason Merrill <jason@redhat.com>
Thu, 3 Jan 2013 16:51:41 +0000 (11:51 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 3 Jan 2013 16:51:41 +0000 (11:51 -0500)
PR c++/53650
* call.c (type_has_extended_temps): New.
* cp-tree.h: Declare it.
* decl.c (check_initializer): Use build_aggr_init for arrays
if it is false.
* init.c (build_vec_init): Avoid mixed signed/unsigned arithmetic.

From-SVN: r194860

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/testsuite/g++.dg/init/array34.C [new file with mode: 0644]

index 1690aeb..e349084 100644 (file)
@@ -1,3 +1,12 @@
+2013-01-03  Jason Merrill  <jason@redhat.com>
+
+       PR c++/53650
+       * call.c (type_has_extended_temps): New.
+       * cp-tree.h: Declare it.
+       * decl.c (check_initializer): Use build_aggr_init for arrays
+       if it is false.
+       * init.c (build_vec_init): Avoid mixed signed/unsigned arithmetic.
+
 2013-01-02  Jason Merrill  <jason@redhat.com>
 
        PR c++/54325
index ad39637..1466c4b 100644 (file)
@@ -9234,6 +9234,28 @@ extend_ref_init_temps (tree decl, tree init, vec<tree, va_gc> **cleanups)
   return init;
 }
 
+/* Returns true iff an initializer for TYPE could contain temporaries that
+   need to be extended because they are bound to references or
+   std::initializer_list.  */
+
+bool
+type_has_extended_temps (tree type)
+{
+  type = strip_array_types (type);
+  if (TREE_CODE (type) == REFERENCE_TYPE)
+    return true;
+  if (CLASS_TYPE_P (type))
+    {
+      if (is_std_init_list (type))
+       return true;
+      for (tree f = next_initializable_field (TYPE_FIELDS (type));
+          f; f = next_initializable_field (DECL_CHAIN (f)))
+       if (type_has_extended_temps (TREE_TYPE (f)))
+         return true;
+    }
+  return false;
+}
+
 /* Returns true iff TYPE is some variant of std::initializer_list.  */
 
 bool
index 465fa0f..810df7d 100644 (file)
@@ -4952,6 +4952,7 @@ extern tree initialize_reference          (tree, tree, int,
                                                 tsubst_flags_t);
 extern tree extend_ref_init_temps              (tree, tree, vec<tree, va_gc>**);
 extern tree make_temporary_var_for_ref_to_temp (tree, tree);
+extern bool type_has_extended_temps            (tree);
 extern tree strip_top_quals                    (tree);
 extern bool reference_related_p                        (tree, tree);
 extern tree perform_implicit_conversion                (tree, tree, tsubst_flags_t);
index 52ceefc..5c268b1 100644 (file)
@@ -5657,7 +5657,9 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
       if ((type_build_ctor_call (type) || CLASS_TYPE_P (type))
          && !(flags & LOOKUP_ALREADY_DIGESTED)
          && !(init && BRACE_ENCLOSED_INITIALIZER_P (init)
-              && CP_AGGREGATE_TYPE_P (type)))
+              && CP_AGGREGATE_TYPE_P (type)
+              && (CLASS_TYPE_P (type)
+                  || type_has_extended_temps (type))))
        {
          init_code = build_aggr_init_full_exprs (decl, init, flags);
 
index 6edc0a5..2ee2473 100644 (file)
@@ -3637,7 +3637,9 @@ build_vec_init (tree base, tree maxindex, tree init,
       if (TREE_CODE (type) == ARRAY_TYPE)
        m = cp_build_binary_op (input_location,
                                MULT_EXPR, m,
-                               array_type_nelts_total (type),
+                               /* Avoid mixing signed and unsigned.  */
+                               convert (TREE_TYPE (m),
+                                        array_type_nelts_total (type)),
                                complain);
 
       finish_cleanup_try_block (try_block);
diff --git a/gcc/testsuite/g++.dg/init/array34.C b/gcc/testsuite/g++.dg/init/array34.C
new file mode 100644 (file)
index 0000000..c5f608b
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/53650
+// We should loop over array inits if they don't involve temporaries
+// that need extending.
+// { dg-final { scan-assembler-times "_ZN5ClassC1Ev" 1 } }
+
+struct Class {
+  Class();
+};
+
+int main() {
+  Class table [10] = {};
+  return 0;
+}