DR 990
authorJason Merrill <jason@redhat.com>
Wed, 29 Jun 2011 14:08:55 +0000 (10:08 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Wed, 29 Jun 2011 14:08:55 +0000 (10:08 -0400)
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.

From-SVN: r175639

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/init.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/constexpr-initlist4.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/initlist-value.C [new file with mode: 0644]

index 45b85302afc1a3b62e6f1205d6256db4ce44a5c2..0352c2ccf44c751bfce8293dfc23b94b3ed703d4 100644 (file)
@@ -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.
index cfaef7d8ec116a7da44793333ac542a7dd3a59ef..e2d455afcdeb0af68581cfb31c30ca233ddd4bf0 100644 (file)
@@ -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.  */
 
index 3ceed90f3b5c49b177bb9c81d43a8c52fff9cad5..17193393398905638f02dc71a6ebc9c361597615 100644 (file)
@@ -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))
     {
index ee7274790fd91099457a9d40f3d5998ac37c44c7..7ea6120583f27d0da8e8dc263e2089e45bd97bdf 100644 (file)
@@ -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 (file)
index 0000000..8151857
--- /dev/null
@@ -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 (file)
index 0000000..25a3373
--- /dev/null
@@ -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;
+}