summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/call.c22
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl.c4
-rw-r--r--gcc/cp/init.c4
-rw-r--r--gcc/testsuite/g++.dg/init/array34.C13
6 files changed, 51 insertions, 2 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 1690aebbfc9..e349084e499 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index ad39637c8b7..1466c4b4db8 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 465fa0f78ef..810df7de29c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 52ceefce03b..5c268b10b7f 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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);
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 6edc0a5df8b..2ee24739259 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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
index 00000000000..c5f608b1f87
--- /dev/null
+++ b/gcc/testsuite/g++.dg/init/array34.C
@@ -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;
+}