re PR c++/48930 ([C++0x] Invalid implicitly declared default c'tor)
authorJason Merrill <jason@redhat.com>
Tue, 10 May 2011 17:58:46 +0000 (13:58 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Tue, 10 May 2011 17:58:46 +0000 (13:58 -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.

From-SVN: r173628

gcc/cp/ChangeLog
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/init.c
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/defaulted25.C [new file with mode: 0644]
gcc/testsuite/g++.dg/template/crash7.C

index 34359f01fde2242c8f8c822b46dce5d732ea0ee2..580a3fc01cbae2d09db898cdd40b7d5706ba9f74 100644 (file)
@@ -1,5 +1,16 @@
 2011-05-10  Jason Merrill  <jason@redhat.com>
 
+       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.
+
        PR c++/48736
        * pt.c (tsubst_copy_and_build): Handle substitution of a pack
        expansion producing another expansion.
index 198eca654315246f2cc3be624b63a044a02e049e..293dd1c0bd511446c44461cb69798b75d3b87824 100644 (file)
@@ -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
index efcdeefd38db96f13c7fe187b41c2ab14d92511c..1705232b9c8451f94942ce94b4fa4a8e6ca9f82e 100644 (file)
@@ -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);
index ab36d18552ae7f9ce60fdd6efdc46fda094c1077..eff23608b6afba8ebb9f4b3bcedd0b1dc30f3a02 100644 (file)
@@ -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))))
        {
index b71ddfc0f9f7b627a349b8458e5978c47fda87dc..7d7adbe04050f310c74790a52ddf50803f868e6b 100644 (file)
@@ -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);
        }
 
index ec6b5d378504cb9fb103a8b86994d7bad6720121..26b9816d54807a2df43e9cb977a9c1fd5b42cc1b 100644 (file)
@@ -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
index 4a63e60e1446e311f5264983d34652397782dd8f..45739d01bfa18d14dca53691606d476289b9fb20 100644 (file)
@@ -1,5 +1,8 @@
 2011-05-10  Jason Merrill  <jason@redhat.com>
 
+       * g++.dg/cpp0x/defaulted25.C: New.
+       * g++.dg/template/crash7.C: Adjust.
+
        * g++.dg/cpp0x/variadic108.C: New.
 
 2011-05-10  Ville Voutilainen  <ville.voutilainen@gmail.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted25.C b/gcc/testsuite/g++.dg/cpp0x/defaulted25.C
new file mode 100644 (file)
index 0000000..2a38fed
--- /dev/null
@@ -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" }
index ae07d91e739972bc81a512ebe0448ee7aa368f48..7fda9a9ba19657d596be89e98f529fdeaaa33d2d 100644 (file)
@@ -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" }