aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog8
-rw-r--r--gcc/cp/call.c37
-rw-r--r--gcc/cp/init.c11
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C8
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/initlist-value.C26
6 files changed, 92 insertions, 3 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 45b8530..0352c2c 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+2011-06-29 Jason Merrill <jason@redhat.com>
+
+ DR 990
+ * call.c (convert_like_real) [ck_user]: Handle value-initialization.
+ (build_new_method_call_1): Likewise.
+ * init.c (expand_default_init): Handle direct list-initialization
+ of aggregates.
+
2011-06-27 Jakub Jelinek <jakub@redhat.com>
* cp-tree.h (union lang_tree_node): Use it in chain_next expression.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index cfaef7d8..e2d455a 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5592,6 +5592,18 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
tree convfn = cand->fn;
unsigned i;
+ /* If we're initializing from {}, it's value-initialization. */
+ if (BRACE_ENCLOSED_INITIALIZER_P (expr)
+ && CONSTRUCTOR_NELTS (expr) == 0
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (totype))
+ {
+ expr = build_value_init (totype, complain);
+ expr = get_target_expr_sfinae (expr, complain);
+ if (expr != error_mark_node)
+ TARGET_EXPR_LIST_INIT_P (expr) = true;
+ return expr;
+ }
+
expr = mark_rvalue_use (expr);
/* When converting from an init list we consider explicit
@@ -5634,7 +5646,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
{
int nelts = CONSTRUCTOR_NELTS (expr);
if (nelts == 0)
- expr = build_value_init (totype, tf_warning_or_error);
+ expr = build_value_init (totype, complain);
else if (nelts == 1)
expr = CONSTRUCTOR_ELT (expr, 0)->value;
else
@@ -7138,10 +7150,29 @@ build_new_method_call_1 (tree instance, tree fns, VEC(tree,gc) **args,
&& BRACE_ENCLOSED_INITIALIZER_P (VEC_index (tree, *args, 0))
&& CONSTRUCTOR_IS_DIRECT_INIT (VEC_index (tree, *args, 0)))
{
+ tree init_list = VEC_index (tree, *args, 0);
+
gcc_assert (VEC_length (tree, *args) == 1
&& !(flags & LOOKUP_ONLYCONVERTING));
- add_list_candidates (fns, first_mem_arg, VEC_index (tree, *args, 0),
+ /* If the initializer list has no elements and T is a class type with
+ a default constructor, the object is value-initialized. Handle
+ this here so we don't need to handle it wherever we use
+ build_special_member_call. */
+ if (CONSTRUCTOR_NELTS (init_list) == 0
+ && TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
+ && !processing_template_decl)
+ {
+ tree ob, init = build_value_init (basetype, complain);
+ if (integer_zerop (instance_ptr))
+ return get_target_expr_sfinae (init, complain);
+ ob = build_fold_indirect_ref (instance_ptr);
+ init = build2 (INIT_EXPR, TREE_TYPE (ob), ob, init);
+ TREE_SIDE_EFFECTS (init) = true;
+ return init;
+ }
+
+ add_list_candidates (fns, first_mem_arg, init_list,
basetype, explicit_targs, template_only,
conversion_path, access_binfo, flags, &candidates);
}
@@ -8365,7 +8396,7 @@ perform_implicit_conversion (tree type, tree expr, tsubst_flags_t complain)
permitted. If the conversion is valid, the converted expression is
returned. Otherwise, NULL_TREE is returned, except in the case
that TYPE is a class type; in that case, an error is issued. If
- C_CAST_P is true, then this direction initialization is taking
+ C_CAST_P is true, then this direct-initialization is taking
place as part of a static_cast being attempted as part of a C-style
cast. */
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 3ceed90..1719339 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -1443,6 +1443,17 @@ expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
tree rval;
VEC(tree,gc) *parms;
+ /* If we have direct-initialization from an initializer list, pull
+ it out of the TREE_LIST so the code below can see it. */
+ if (init && TREE_CODE (init) == TREE_LIST
+ && BRACE_ENCLOSED_INITIALIZER_P (TREE_VALUE (init))
+ && CONSTRUCTOR_IS_DIRECT_INIT (TREE_VALUE (init)))
+ {
+ gcc_checking_assert ((flags & LOOKUP_ONLYCONVERTING) == 0
+ && TREE_CHAIN (init) == NULL_TREE);
+ init = TREE_VALUE (init);
+ }
+
if (init && BRACE_ENCLOSED_INITIALIZER_P (init)
&& CP_AGGREGATE_TYPE_P (type))
{
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index ee72747..7ea6120 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2011-06-29 Jason Merrill <jason@redhat.com>
+
+ * g++.dg/cpp0x/constexpr-initlist4.C: New.
+ * g++.dg/cpp0x/initlist-value.C: New.
+
2011-06-29 Richard Sandiford <richard.sandiford@linaro.org>
* gcc.dg/torture/pr49169.c: Restrict to ARM and MIPS targets.
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C
new file mode 100644
index 0000000..8151857
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C
@@ -0,0 +1,8 @@
+// { dg-options -std=c++0x }
+
+struct A { int i; };
+struct B: A { constexpr B(): A{} {} };
+struct B2: A { constexpr B2(): A{1} {} };
+
+struct C { protected: int i; };
+struct D: C { constexpr D(): C{} {} };
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist-value.C b/gcc/testsuite/g++.dg/cpp0x/initlist-value.C
new file mode 100644
index 0000000..25a3373
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/initlist-value.C
@@ -0,0 +1,26 @@
+// Test for value-initialization via {}
+// { dg-options -std=c++0x }
+// { dg-do run }
+
+// Empty base so A isn't an aggregate
+struct B {};
+struct A: B {
+ int i;
+};
+
+struct C: A {
+ C(): A{} {}
+};
+
+int f(A a) { return a.i; }
+
+int main()
+{
+ A a{};
+ C c;
+ if (a.i != 0
+ || c.i != 0
+ || A{}.i != 0
+ || f({}) != 0)
+ return 1;
+}