diff options
-rw-r--r-- | gcc/cp/ChangeLog | 8 | ||||
-rw-r--r-- | gcc/cp/call.c | 37 | ||||
-rw-r--r-- | gcc/cp/init.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 5 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C | 8 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp0x/initlist-value.C | 26 |
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; +} |