OSDN Git Service

PR c++/38796, Core issue 906
[pf3gnuchains/gcc-fork.git] / gcc / cp / class.c
index d29d661..d737bdf 100644 (file)
@@ -3843,7 +3843,7 @@ check_methods (tree t)
            VEC_safe_push (tree, gc, CLASSTYPE_PURE_VIRTUALS (t), x);
        }
       /* All user-provided destructors are non-trivial.  */
-      if (DECL_DESTRUCTOR_P (x) && !DECL_DEFAULTED_FN (x))
+      if (DECL_DESTRUCTOR_P (x) && user_provided_p (x))
        TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1;
     }
 }
@@ -4174,17 +4174,17 @@ type_has_user_nondefault_constructor (tree t)
 }
 
 /* Returns true iff FN is a user-provided function, i.e. user-declared
-   and not defaulted at its first declaration.  */
+   and not defaulted at its first declaration; or explicit, private,
+   protected, or non-const.  */
 
-static bool
+bool
 user_provided_p (tree fn)
 {
   if (TREE_CODE (fn) == TEMPLATE_DECL)
     return true;
   else
     return (!DECL_ARTIFICIAL (fn)
-           && !(DECL_DEFAULTED_FN (fn)
-                && DECL_INITIALIZED_IN_CLASS_P (fn)));
+           && !DECL_DEFAULTED_IN_CLASS_P (fn));
 }
 
 /* Returns true iff class T has a user-provided constructor.  */
@@ -4238,31 +4238,6 @@ type_has_user_provided_default_constructor (tree t)
   return false;
 }
 
-/* Returns true if FN can be explicitly defaulted.  */
-
-bool
-defaultable_fn_p (tree fn)
-{
-  if (DECL_CONSTRUCTOR_P (fn))
-    {
-      if (FUNCTION_FIRST_USER_PARMTYPE (fn) == void_list_node)
-       return true;
-      else if (copy_fn_p (fn) > 0
-              && (TREE_CHAIN (FUNCTION_FIRST_USER_PARMTYPE (fn))
-                  == void_list_node))
-       return true;
-      else
-       return false;
-    }
-  else if (DECL_DESTRUCTOR_P (fn))
-    return true;
-  else if (DECL_ASSIGNMENT_OPERATOR_P (fn)
-          && DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR)
-    return copy_fn_p (fn);
-  else
-    return false;
-}
-
 /* Remove all zero-width bit-fields from T.  */
 
 static void
@@ -4356,6 +4331,7 @@ check_bases_and_members (tree t)
   tree access_decls;
   bool saved_complex_asn_ref;
   bool saved_nontrivial_dtor;
+  tree fn;
 
   /* By default, we use const reference arguments and generate default
      constructors.  */
@@ -4453,6 +4429,31 @@ check_bases_and_members (tree t)
                                   cant_have_const_ctor,
                                   no_const_asn_ref);
 
+  /* Check defaulted declarations here so we have cant_have_const_ctor
+     and don't need to worry about clones.  */
+  for (fn = TYPE_METHODS (t); fn; fn = TREE_CHAIN (fn))
+    if (DECL_DEFAULTED_IN_CLASS_P (fn))
+      {
+       int copy = copy_fn_p (fn);
+       if (copy > 0)
+         {
+           bool imp_const_p
+             = (DECL_CONSTRUCTOR_P (fn) ? !cant_have_const_ctor
+                : !no_const_asn_ref);
+           bool fn_const_p = (copy == 2);
+
+           if (fn_const_p && !imp_const_p)
+             /* If the function is defaulted outside the class, we just
+                give the synthesis error.  */
+             error ("%q+D declared to take const reference, but implicit "
+                    "declaration would take non-const", fn);
+           else if (imp_const_p && !fn_const_p)
+             error ("%q+D declared to take non-const reference cannot be "
+                    "defaulted in the class body", fn);
+         }
+       defaulted_late_check (fn);
+      }
+
   if (LAMBDA_TYPE_P (t))
     {
       /* "The closure type associated with a lambda-expression has a deleted