The introduction of = default means that now we need to separate TYPE_NEEDS_CONSTRUCTING from the notion that we need to call a constructor for non-aggregate initialization of a class. This patch does that by introducing a new function type_build_ctor_call for the latter case and adjusting callers appropriately.

Tested x86_64-pc-linux-gnu, applied to trunk.
commit 16f7c1cf85a246874faa9b8932c11d682eb5af2e
Author: Jason Merrill <ja...@redhat.com>
Date:   Mon May 9 16:46:25 2011 -0400

        PR c++/48930
        * class.c (type_build_ctor_call): New.
        * cp-tree.h: Declare it.
        * decl.c (check_initializer): Use it instead of
        TYPE_NEEDS_CONSTRUCTING.
        * init.c (build_value_init, build_value_init_noctor): Likewise.
        (perform_member_init, expand_aggr_init_1, build_new_1): Likewise.
        (build_vec_init): Likewise.
        * typeck2.c (process_init_constructor_array): Likewise.
        (process_init_constructor_record): Likewise.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 198eca6..293dd1c 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4466,6 +4466,27 @@ type_has_move_assign (tree t)
   return false;
 }
 
+/* Nonzero if we need to build up a constructor call when initializing an
+   object of this class, either because it has a user-provided constructor
+   or because it doesn't have a default constructor (so we need to give an
+   error if no initializer is provided).  Use TYPE_NEEDS_CONSTRUCTING when
+   what you care about is whether or not an object can be produced by a
+   constructor (e.g. so we don't set TREE_READONLY on const variables of
+   such type); use this function when what you care about is whether or not
+   to try to call a constructor to create an object.  The latter case is
+   the former plus some cases of constructors that cannot be called.  */
+
+bool
+type_build_ctor_call (tree t)
+{
+  tree inner;
+  if (TYPE_NEEDS_CONSTRUCTING (t))
+    return true;
+  inner = strip_array_types (t);
+  return (CLASS_TYPE_P (inner) && !TYPE_HAS_DEFAULT_CONSTRUCTOR (inner)
+         && !ANON_AGGR_TYPE_P (inner));
+}
+
 /* Remove all zero-width bit-fields from T.  */
 
 static void
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index efcdeef..1705232 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4787,6 +4787,7 @@ extern bool type_has_constexpr_default_constructor (tree);
 extern bool type_has_virtual_destructor                (tree);
 extern bool type_has_move_constructor          (tree);
 extern bool type_has_move_assign               (tree);
+extern bool type_build_ctor_call               (tree);
 extern void defaulted_late_check               (tree);
 extern bool defaultable_fn_check               (tree);
 extern void fixup_type_variants                        (tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index ab36d18..eff2360 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -5410,7 +5410,7 @@ check_initializer (tree decl, tree init, int flags, tree 
*cleanup)
     ;
   else if (TREE_CODE (type) == REFERENCE_TYPE)
     init = grok_reference_init (decl, type, init, cleanup);
-  else if (init || TYPE_NEEDS_CONSTRUCTING (type))
+  else if (init || type_build_ctor_call (type))
     {
       if (!init)
        check_for_uninitialized_const_var (decl);
@@ -5445,7 +5445,7 @@ check_initializer (tree decl, tree init, int flags, tree 
*cleanup)
       if (type == error_mark_node)
        return NULL_TREE;
 
-      if (TYPE_NEEDS_CONSTRUCTING (type)
+      if (type_build_ctor_call (type)
          || (CLASS_TYPE_P (type)
              && !(init && BRACE_ENCLOSED_INITIALIZER_P (init))))
        {
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index b71ddfc..7d7adbe 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -341,7 +341,7 @@ build_value_init (tree type, tsubst_flags_t complain)
                                      NULL, type, LOOKUP_NORMAL,
                                      complain),
           complain);
-      else if (TYPE_NEEDS_CONSTRUCTING (type))
+      else if (type_build_ctor_call (type))
        {
          /* This is a class that needs constructing, but doesn't have
             a user-provided constructor.  So we need to zero-initialize
@@ -371,7 +371,7 @@ build_value_init_noctor (tree type, tsubst_flags_t complain)
      SFINAE-enabled.  */
   if (CLASS_TYPE_P (type))
     {
-      gcc_assert (!TYPE_NEEDS_CONSTRUCTING (type));
+      gcc_assert (!type_build_ctor_call (type));
        
       if (TREE_CODE (type) != UNION_TYPE)
        {
@@ -530,7 +530,7 @@ perform_member_init (tree member, tree init)
          finish_expr_stmt (init);
        }
     }
-  else if (TYPE_NEEDS_CONSTRUCTING (type))
+  else if (type_build_ctor_call (type))
     {
       if (TREE_CODE (type) == ARRAY_TYPE)
        {
@@ -1568,7 +1568,7 @@ expand_aggr_init_1 (tree binfo, tree true_exp, tree exp, 
tree init, int flags,
        /* Fall through.  */;
       /* If there isn't, but we still need to call the constructor,
         zero out the object first.  */
-      else if (TYPE_NEEDS_CONSTRUCTING (type))
+      else if (type_build_ctor_call (type))
        {
          init = build_zero_init (type, NULL_TREE, /*static_storage_p=*/false);
          init = build2 (INIT_EXPR, type, exp, init);
@@ -2046,7 +2046,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree 
nelts,
   if (abstract_virtuals_error_sfinae (NULL_TREE, elt_type, complain))
     return error_mark_node;
 
-  is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || *init != NULL);
+  is_initialized = (type_build_ctor_call (elt_type) || *init != NULL);
 
   if (*init == NULL)
     {
@@ -2351,7 +2351,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree 
nelts,
             rebuild it at instantiation time, so just build up a single
             constructor call to get any appropriate diagnostics.  */
          init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
-         if (TYPE_NEEDS_CONSTRUCTING (elt_type))
+         if (type_build_ctor_call (elt_type))
            init_expr = build_special_member_call (init_expr,
                                                   complete_ctor_identifier,
                                                   init, elt_type,
@@ -2408,7 +2408,7 @@ build_new_1 (VEC(tree,gc) **placement, tree type, tree 
nelts,
        {
          init_expr = cp_build_indirect_ref (data_addr, RO_NULL, complain);
 
-         if (TYPE_NEEDS_CONSTRUCTING (type) && !explicit_value_init_p)
+         if (type_build_ctor_call (type) && !explicit_value_init_p)
            {
              init_expr = build_special_member_call (init_expr,
                                                     complete_ctor_identifier,
@@ -3164,8 +3164,7 @@ build_vec_init (tree base, tree maxindex, tree init,
     {
       if (init)
        /* OK, we set base2 above.  */;
-      else if (TYPE_LANG_SPECIFIC (type)
-              && TYPE_NEEDS_CONSTRUCTING (type)
+      else if (CLASS_TYPE_P (type)
               && ! TYPE_HAS_DEFAULT_CONSTRUCTOR (type))
        {
           if (complain & tf_error)
@@ -3181,7 +3180,7 @@ build_vec_init (tree base, tree maxindex, tree init,
      We do need to keep going if we're copying an array.  */
 
   if (from_array
-      || ((TYPE_NEEDS_CONSTRUCTING (type) || explicit_value_init_p)
+      || ((type_build_ctor_call (type) || explicit_value_init_p)
          && ! (host_integerp (maxindex, 0)
                && (num_initialized_elts
                    == tree_low_cst (maxindex, 0) + 1))))
@@ -3221,7 +3220,7 @@ build_vec_init (tree base, tree maxindex, tree init,
          if (from_array == 2)
            elt_init = cp_build_modify_expr (to, NOP_EXPR, from, 
                                             complain);
-         else if (TYPE_NEEDS_CONSTRUCTING (type))
+         else if (type_build_ctor_call (type))
            elt_init = build_aggr_init (to, from, 0, complain);
          else if (from)
            elt_init = cp_build_modify_expr (to, NOP_EXPR, from,
@@ -3247,7 +3246,7 @@ build_vec_init (tree base, tree maxindex, tree init,
        }
       else
        {
-         gcc_assert (TYPE_NEEDS_CONSTRUCTING (type));
+         gcc_assert (type_build_ctor_call (type));
          elt_init = build_aggr_init (to, init, 0, complain);
        }
 
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index ec6b5d3..26b9816 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -1048,7 +1048,7 @@ process_init_constructor_array (tree type, tree init,
       {
        tree next;
 
-       if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (type)))
+       if (type_build_ctor_call (TREE_TYPE (type)))
          {
            /* If this type needs constructors run for default-initialization,
              we can't rely on the back end to do it for us, so build up
@@ -1144,7 +1144,7 @@ process_init_constructor_record (tree type, tree init,
                                LOOKUP_IMPLICIT, complain);
          ++idx;
        }
-      else if (TYPE_NEEDS_CONSTRUCTING (TREE_TYPE (field)))
+      else if (type_build_ctor_call (TREE_TYPE (field)))
        {
          /* If this type needs constructors run for
             default-initialization, we can't rely on the back end to do it
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted25.C 
b/gcc/testsuite/g++.dg/cpp0x/defaulted25.C
new file mode 100644
index 0000000..2a38fed
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/defaulted25.C
@@ -0,0 +1,10 @@
+// PR c++/48930
+// { dg-options -std=c++0x }
+// { dg-prune-output "note" }
+
+struct A
+{
+  A(const A&) = default;
+};
+
+A a;                           // { dg-error "no match" }
diff --git a/gcc/testsuite/g++.dg/template/crash7.C 
b/gcc/testsuite/g++.dg/template/crash7.C
index ae07d91..7fda9a9 100644
--- a/gcc/testsuite/g++.dg/template/crash7.C
+++ b/gcc/testsuite/g++.dg/template/crash7.C
@@ -5,11 +5,10 @@
 // PR c++/10108: ICE in tsubst_decl for error due to non-existence
 // nested type.
 
-template <typename> struct A
-{                                      // { not-dg-error "candidates" }
+template <typename> struct A   // { dg-message "A.void.::A.const A" }
+{
     template <typename> A(typename A::X) {} // { dg-error "no type" }
 };
 
-A<void> a;     // { not-dg-error "instantiated|no match" }
-// We currently don't give the "no match" error because we don't add the
-// invalid constructor template to TYPE_METHODS.
+A<void> a;     // { dg-error "instantiated|no match" }
+// { dg-prune-output "note" }

Reply via email to