Implement defaulted/deleted functions as per N2346
authorJason Merrill <jason@redhat.com>
Thu, 24 Jul 2008 19:15:00 +0000 (15:15 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Thu, 24 Jul 2008 19:15:00 +0000 (15:15 -0400)
        Implement defaulted/deleted functions as per N2346
        * cp-tree.h (struct lang_decl_flags): Add defaulted_p bitfield.
        (DECL_DELETED_FN): New macro.
        (DECL_DEFAULTED_FN): New macro.
        * class.c (user_provided_p): New fn.
        (defaultable_fn_p): New fn.
        (type_has_user_provided_constructor): New fn.
        (type_has_user_provided_default_constructor): New fn.
        (check_methods): A defaulted fn is still trivial.
        (check_bases_and_members): Likewise.
        * decl.c (grok_special_member_properties): Likewise.
        (duplicate_decls): Complain about redeclaring a function as deleted.
        (start_decl): initialized==2 means deleted.
        (cp_finish_decl): Handle deleted/defaulted semantics.
        * decl2.c (grokfield): Likewise.
        (mark_used): Check DECL_DEFAULTED_FN instead of DECL_ARTIFICIAL.
        Complain about using a deleted fn.
        * init.c (build_value_init_1): Use type_has_user_provided_constructor.
        (perform_member_init): Check for a user-provided default constructor
        even if TYPE_NEEDS_CONSTRUCTING.
        (build_new_1): Likewise.
        * call.c (build_over_call): Don't call mark_used twice.
        * method.c (implicitly_declare_fn): Set DECL_DEFAULTED_FN.
        * search.c (check_final_overrider): Check for deleted mismatch.
        * parser.c (cp_parser_init_declarator): Tell start_decl about =delete.
        (cp_parser_pure_specifier): Handle =default and =delete.

        * error.c (maybe_warn_cpp0x): Suggest -std=gnu++0x as well.

From-SVN: r138123

19 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/error.c
gcc/cp/init.c
gcc/cp/mangle.c
gcc/cp/method.c
gcc/cp/parser.c
gcc/cp/search.c
gcc/testsuite/g++.dg/cpp0x/defaulted1.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp0x/defaulted2.C [new file with mode: 0644]
gcc/testsuite/g++.dg/parse/crash27.C
gcc/testsuite/g++.dg/parse/error15.C
gcc/testsuite/g++.dg/template/crash60.C
gcc/testsuite/g++.dg/template/crash7.C
gcc/testsuite/g++.old-deja/g++.pt/error2.C

index 3757dcfe9052ee8fe07e0568c0942db56e4724ee..c9eaf0f055aed28bc252ef408191a43b4bf599cb 100644 (file)
@@ -1,3 +1,34 @@
+2008-07-23  Jason Merrill  <jason@redhat.com>
+
+       Implement defaulted/deleted functions as per N2346
+       * cp-tree.h (struct lang_decl_flags): Add defaulted_p bitfield.
+       (DECL_DELETED_FN): New macro.
+       (DECL_DEFAULTED_FN): New macro.
+       * class.c (user_provided_p): New fn.
+       (defaultable_fn_p): New fn.
+       (type_has_user_provided_constructor): New fn.
+       (type_has_user_provided_default_constructor): New fn.
+       (check_methods): A defaulted fn is still trivial.
+       (check_bases_and_members): Likewise.
+       * decl.c (grok_special_member_properties): Likewise.
+       (duplicate_decls): Complain about redeclaring a function as deleted.
+       (start_decl): initialized==2 means deleted.
+       (cp_finish_decl): Handle deleted/defaulted semantics.
+       * decl2.c (grokfield): Likewise.
+       (mark_used): Check DECL_DEFAULTED_FN instead of DECL_ARTIFICIAL.
+       Complain about using a deleted fn.
+       * init.c (build_value_init_1): Use type_has_user_provided_constructor.
+       (perform_member_init): Check for a user-provided default constructor
+       even if TYPE_NEEDS_CONSTRUCTING.
+       (build_new_1): Likewise.
+       * call.c (build_over_call): Don't call mark_used twice.
+       * method.c (implicitly_declare_fn): Set DECL_DEFAULTED_FN.
+       * search.c (check_final_overrider): Check for deleted mismatch.
+       * parser.c (cp_parser_init_declarator): Tell start_decl about =delete.
+       (cp_parser_pure_specifier): Handle =default and =delete.
+
+       * error.c (maybe_warn_cpp0x): Suggest -std=gnu++0x as well.
+
 2008-07-23  Manuel Lopez-Ibanez  <manu@gcc.gnu.org>
 
        PR 35058
index 7cff6adb3a9ae11eb40152f062c74f93bd5bda88..2304b5da71be3cfa11a38bee2050632f1599c260 100644 (file)
@@ -5090,6 +5090,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
   int is_method = 0;
   int nargs;
   tree *argarray;
+  bool already_used = false;
 
   /* In a template, there is no need to perform all of the work that
      is normally done.  We are only interested in the type of the call
@@ -5310,7 +5311,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       /* [class.copy]: the copy constructor is implicitly defined even if
         the implementation elided its use.  */
       if (TYPE_HAS_COMPLEX_INIT_REF (DECL_CONTEXT (fn)))
-       mark_used (fn);
+       {
+         mark_used (fn);
+         already_used = true;
+       }
 
       /* If we're creating a temp and we already have one, don't create a
         new one.  If we're not creating a temp but we get one, use
@@ -5370,7 +5374,8 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
       return val;
     }
 
-  mark_used (fn);
+  if (!already_used)
+    mark_used (fn);
 
   if (DECL_VINDEX (fn) && (flags & LOOKUP_NONVIRTUAL) == 0)
     {
index 0c7a76c697a30903a0b21669904e5bdbbbba6993..0649eec2486a7054031a2766616232866d19e3a1 100644 (file)
@@ -3045,7 +3045,7 @@ check_field_decls (tree t, tree *access_decls,
 
       /* Core issue 80: A nonstatic data member is required to have a
         different name from the class iff the class has a
-        user-defined constructor.  */
+        user-declared constructor.  */
       if (constructor_name_p (DECL_NAME (x), t)
          && TYPE_HAS_USER_CONSTRUCTOR (t))
        permerror ("field %q+#D with same name as class", x);
@@ -3767,8 +3767,8 @@ check_methods (tree t)
          if (DECL_PURE_VIRTUAL_P (x))
            VEC_safe_push (tree, gc, CLASSTYPE_PURE_VIRTUALS (t), x);
        }
-      /* All user-declared destructors are non-trivial.  */
-      if (DECL_DESTRUCTOR_P (x))
+      /* All user-provided destructors are non-trivial.  */
+      if (DECL_DESTRUCTOR_P (x) && !DECL_DEFAULTED_FN (x))
        TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t) = 1;
     }
 }
@@ -4067,6 +4067,86 @@ type_has_user_nondefault_constructor (tree t)
   return false;
 }
 
+/* Returns true iff FN is a user-provided function, i.e. user-declared
+   and not defaulted at its first declaration.  */
+
+static 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)));
+}
+
+/* Returns true iff class T has a user-provided constructor.  */
+
+bool
+type_has_user_provided_constructor (tree t)
+{
+  tree fns;
+
+  if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+    return false;
+
+  /* This can happen in error cases; avoid crashing.  */
+  if (!CLASSTYPE_METHOD_VEC (t))
+    return false;
+
+  for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+    if (user_provided_p (OVL_CURRENT (fns)))
+      return true;
+
+  return false;
+}
+
+/* Returns true iff class T has a user-provided default constructor.  */
+
+bool
+type_has_user_provided_default_constructor (tree t)
+{
+  tree fns;
+
+  if (!TYPE_HAS_USER_CONSTRUCTOR (t))
+    return false;
+
+  for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
+    {
+      tree fn = OVL_CURRENT (fns);
+      if (user_provided_p (fn)
+         && (skip_artificial_parms_for (fn, DECL_ARGUMENTS (fn))
+             == NULL_TREE))
+       return true;
+    }
+
+  return false;
+}
+
+/* Returns true if FN can be explicitly defaulted.  */
+
+bool
+defaultable_fn_p (tree fn)
+{
+  if (DECL_CONSTRUCTOR_P (fn))
+    {
+      if (skip_artificial_parms_for (fn, DECL_ARGUMENTS (fn))
+         == NULL_TREE)
+       return true;
+      else if (copy_fn_p (fn) > 0)
+       return true;
+      else
+       return false;
+    }
+  else if (DECL_DESTRUCTOR_P (fn))
+    return true;
+  else if (DECL_ASSIGNMENT_OPERATOR_P (fn))
+    return copy_fn_p (fn);
+  else
+    return false;
+}
+
 /* Remove all zero-width bit-fields from T.  */
 
 static void
@@ -4158,6 +4238,8 @@ check_bases_and_members (tree t)
      should take a non-const reference argument.  */
   int no_const_asn_ref;
   tree access_decls;
+  bool saved_complex_asn_ref;
+  bool saved_nontrivial_dtor;
 
   /* By default, we use const reference arguments and generate default
      constructors.  */
@@ -4171,6 +4253,12 @@ check_bases_and_members (tree t)
   /* Check all the method declarations.  */
   check_methods (t);
 
+  /* Save the initial values of these flags which only indicate whether
+     or not the class has user-provided functions.  As we analyze the
+     bases and members we can set these flags for other reasons.  */
+  saved_complex_asn_ref = TYPE_HAS_COMPLEX_ASSIGN_REF (t);
+  saved_nontrivial_dtor = TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t);
+
   /* Check all the data member declarations.  We cannot call
      check_field_decls until we have called check_bases check_methods,
      as check_field_decls depends on TYPE_HAS_NONTRIVIAL_DESTRUCTOR
@@ -4186,30 +4274,27 @@ check_bases_and_members (tree t)
 
   /* Do some bookkeeping that will guide the generation of implicitly
      declared member functions.  */
-  TYPE_HAS_COMPLEX_INIT_REF (t)
-    |= (TYPE_HAS_INIT_REF (t) || TYPE_CONTAINS_VPTR_P (t));
+  TYPE_HAS_COMPLEX_INIT_REF (t) |= TYPE_CONTAINS_VPTR_P (t);
   /* We need to call a constructor for this class if it has a
-     user-declared constructor, or if the default constructor is going
+     user-provided constructor, or if the default constructor is going
      to initialize the vptr.  (This is not an if-and-only-if;
      TYPE_NEEDS_CONSTRUCTING is set elsewhere if bases or members
      themselves need constructing.)  */
   TYPE_NEEDS_CONSTRUCTING (t)
-    |= (TYPE_HAS_USER_CONSTRUCTOR (t) || TYPE_CONTAINS_VPTR_P (t));
+    |= (type_has_user_provided_constructor (t) || TYPE_CONTAINS_VPTR_P (t));
   /* [dcl.init.aggr]
 
-     An aggregate is an array or a class with no user-declared
+     An aggregate is an array or a class with no user-provided
      constructors ... and no virtual functions.  
 
      Again, other conditions for being an aggregate are checked
      elsewhere.  */
   CLASSTYPE_NON_AGGREGATE (t)
-    |= (TYPE_HAS_USER_CONSTRUCTOR (t) || TYPE_POLYMORPHIC_P (t));
+    |= (type_has_user_provided_constructor (t) || TYPE_POLYMORPHIC_P (t));
   CLASSTYPE_NON_POD_P (t)
     |= (CLASSTYPE_NON_AGGREGATE (t)
-       || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
-       || TYPE_HAS_ASSIGN_REF (t));
-  TYPE_HAS_COMPLEX_ASSIGN_REF (t)
-    |= TYPE_HAS_ASSIGN_REF (t) || TYPE_CONTAINS_VPTR_P (t);
+       || saved_nontrivial_dtor || saved_complex_asn_ref);
+  TYPE_HAS_COMPLEX_ASSIGN_REF (t) |= TYPE_CONTAINS_VPTR_P (t);
   TYPE_HAS_COMPLEX_DFLT (t)
     |= (TYPE_HAS_DEFAULT_CONSTRUCTOR (t) || TYPE_CONTAINS_VPTR_P (t));
 
index 6bc5d2d2782d55ebda7a5b769cb17d43e49ca65f..1488d4ce6f96340bddc89e69ce23d658cc54034d 100644 (file)
@@ -1609,7 +1609,7 @@ struct lang_decl_flags GTY(())
   unsigned repo_available_p : 1;
   unsigned hidden_friend_p : 1;
   unsigned threadprivate_p : 1;
-  /* One unused bit.  */
+  unsigned defaulted_p : 1;
 
   union lang_decl_u {
     /* In a FUNCTION_DECL for which DECL_THUNK_P holds, this is
@@ -2626,6 +2626,14 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
 #define CP_DECL_THREADPRIVATE_P(DECL) \
   (DECL_LANG_SPECIFIC (VAR_DECL_CHECK (DECL))->decl_flags.threadprivate_p)
 
+/* Nonzero if DECL was declared with '= delete'.  */
+#define DECL_DELETED_FN(DECL) \
+  (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->decl_flags.threadprivate_p)
+
+/* Nonzero if DECL was declared with '= default'.  */
+#define DECL_DEFAULTED_FN(DECL) \
+  (DECL_LANG_SPECIFIC (FUNCTION_DECL_CHECK (DECL))->decl_flags.defaulted_p)
+
 /* Record whether a typedef for type `int' was actually `signed int'.  */
 #define C_TYPEDEF_EXPLICITLY_SIGNED(EXP) DECL_LANG_FLAG_1 (EXP)
 
@@ -4171,6 +4179,9 @@ extern void check_for_override                    (tree, tree);
 extern void push_class_stack                   (void);
 extern void pop_class_stack                    (void);
 extern bool type_has_user_nondefault_constructor (tree);
+extern bool type_has_user_provided_constructor  (tree);
+extern bool type_has_user_provided_default_constructor (tree);
+extern bool defaultable_fn_p                   (tree);
 
 /* in cvt.c */
 extern tree convert_to_reference               (tree, tree, int, int, tree);
index cc9e8c8bbc0d833530d26d3a0d06d764350d68a7..d02cab2c867f31311c5891a5c0e236b9a9ef5b37 100644 (file)
@@ -1613,6 +1613,12 @@ duplicate_decls (tree newdecl, tree olddecl, bool newdecl_is_friend)
          warning (OPT_Wredundant_decls, "redundant redeclaration of %qD in same scope", newdecl);
          warning (OPT_Wredundant_decls, "previous declaration of %q+D", olddecl);
        }
+
+      if (DECL_DELETED_FN (newdecl))
+       {
+         error ("deleted definition of %qD", newdecl);
+         error ("after previous declaration %q+D", olddecl);
+       }
     }
 
   /* Deal with C++: must preserve virtual function table size.  */
@@ -3931,13 +3937,14 @@ groktypename (cp_decl_specifier_seq *type_specifiers,
    grokfield.)  The DECL corresponding to the DECLARATOR is returned.
    If an error occurs, the error_mark_node is returned instead.
    
-   DECLSPECS are the decl-specifiers for the declaration.  INITIALIZED
-   is true if an explicit initializer is present, but false if this is
-   a variable implicitly initialized via a default constructor.
-   ATTRIBUTES and PREFIX_ATTRIBUTES are GNU attributes associated with
-   this declaration.  *PUSHED_SCOPE_P is set to the scope entered in
-   this function, if any; if set, the caller is responsible for
-   calling pop_scope.  */
+   DECLSPECS are the decl-specifiers for the declaration.  INITIALIZED is 1
+   if an explicit initializer is present, or 2 for an explicitly defaulted
+   function, or 3 for an explicitly deleted function, but 0 if this is a
+   variable implicitly initialized via a default constructor.  ATTRIBUTES
+   and PREFIX_ATTRIBUTES are GNU attributes associated with this
+   declaration.  *PUSHED_SCOPE_P is set to the scope entered in this
+   function, if any; if set, the caller is responsible for calling
+   pop_scope.  */
 
 tree
 start_decl (const cp_declarator *declarator,
@@ -3991,12 +3998,15 @@ start_decl (const cp_declarator *declarator,
     switch (TREE_CODE (decl))
       {
       case TYPE_DECL:
-       error ("typedef %qD is initialized (use __typeof__ instead)", decl);
+       error ("typedef %qD is initialized (use decltype instead)", decl);
        return error_mark_node;
 
       case FUNCTION_DECL:
-       error ("function %q#D is initialized like a variable", decl);
-       return error_mark_node;
+       if (initialized == 3)
+         /* We'll handle the rest of the semantics later, but we need to
+            set this now so it's visible to duplicate_decls.  */
+         DECL_DELETED_FN (decl) = 1;
+       break;
 
       default:
        break;
@@ -5686,10 +5696,38 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
       else
        abstract_virtuals_error (decl, type);
 
-      if (TREE_CODE (decl) == FUNCTION_DECL
-         || TREE_TYPE (decl) == error_mark_node)
+      if (TREE_TYPE (decl) == error_mark_node)
        /* No initialization required.  */
        ;
+      else if (TREE_CODE (decl) == FUNCTION_DECL)
+       {
+         if (init)
+           {
+             if (init == ridpointers[(int)RID_DELETE])
+               {
+                 /* fixme check this is 1st decl */
+                 DECL_DELETED_FN (decl) = 1;
+                 DECL_DECLARED_INLINE_P (decl) = 1;
+                 DECL_INITIAL (decl) = error_mark_node;
+               }
+             else if (init == ridpointers[(int)RID_DEFAULT])
+               {
+                 if (!defaultable_fn_p (decl))
+                   error ("%qD cannot be defaulted", decl);
+                 else
+                   {
+                     /* An out-of-class default definition is defined at
+                        the point where it is explicitly defaulted.  */
+                     DECL_DEFAULTED_FN (decl) = 1;
+                     if (DECL_INITIAL (decl) == error_mark_node)
+                       synthesize_method (decl);
+                   }
+               }
+             else
+               error ("function %q#D is initialized like a variable", decl);
+           }
+         /* else no initialization required.  */
+       }
       else if (DECL_EXTERNAL (decl)
               && ! (DECL_LANG_SPECIFIC (decl)
                     && DECL_NOT_REALLY_EXTERN (decl)))
@@ -7361,7 +7399,7 @@ check_var_type (tree identifier, tree type)
       Don't make a DECL node; just return the ..._TYPE node.
      FIELD for a struct or union field; make a FIELD_DECL.
      BITFIELD for a field with specified width.
-   INITIALIZED is 1 if the decl has an initializer.
+   INITIALIZED is as for start_decl.
 
    ATTRLIST is a pointer to the list of attributes, which may be NULL
    if there are none; *ATTRLIST may be modified if attributes from inside
@@ -7459,6 +7497,9 @@ grokdeclarator (const cp_declarator *declarator,
   else if (decl_context == BITFIELD)
     bitfield = 1, decl_context = FIELD;
 
+  if (initialized > 1)
+    funcdef_flag = true;
+
   /* Look inside a declarator for the name being declared
      and get it as a string, for an error message.  */
   for (id_declarator = declarator;
@@ -9670,6 +9711,8 @@ grok_special_member_properties (tree decl)
             are no other parameters or else all other parameters have
             default arguments.  */
          TYPE_HAS_INIT_REF (class_type) = 1;
+         if (!DECL_DEFAULTED_FN (decl))
+           TYPE_HAS_COMPLEX_INIT_REF (class_type) = 1;
          if (ctor > 1)
            TYPE_HAS_CONST_INIT_REF (class_type) = 1;
        }
@@ -9691,6 +9734,8 @@ grok_special_member_properties (tree decl)
       if (assop)
        {
          TYPE_HAS_ASSIGN_REF (class_type) = 1;
+         if (!DECL_DEFAULTED_FN (decl))
+           TYPE_HAS_COMPLEX_ASSIGN_REF (class_type) = 1;
          if (assop != 1)
            TYPE_HAS_CONST_ASSIGN_REF (class_type) = 1;
        }
index f14f94d16b51e15edbd2ab904a424e4320e50ad8..6e6151d23f753045c783a86886fd0cebfe7b4c57 100644 (file)
@@ -821,7 +821,25 @@ grokfield (const cp_declarator *declarator,
        {
          /* Initializers for functions are rejected early in the parser.
             If we get here, it must be a pure specifier for a method.  */
-         if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
+         if (init == ridpointers[(int)RID_DELETE])
+           {
+             DECL_DELETED_FN (value) = 1;
+             DECL_DECLARED_INLINE_P (value) = 1;
+             DECL_INITIAL (value) = error_mark_node;
+           }
+         else if (init == ridpointers[(int)RID_DEFAULT])
+           {
+             if (!defaultable_fn_p (value))
+               error ("%qD cannot be defaulted", value);
+             else
+               {
+                 DECL_DEFAULTED_FN (value) = 1;
+                 DECL_INITIALIZED_IN_CLASS_P (value) = 1;
+                 DECL_DECLARED_INLINE_P (value) = 1;
+                 DECL_INLINE (value) = 1;
+               }
+           }
+         else if (TREE_CODE (TREE_TYPE (value)) == METHOD_TYPE)
            {
              gcc_assert (error_operand_p (init) || integer_zerop (init));
              DECL_PURE_VIRTUAL_P (value) = 1;
@@ -3739,7 +3757,7 @@ mark_used (tree decl)
   /* Is it a synthesized method that needs to be synthesized?  */
   if (TREE_CODE (decl) == FUNCTION_DECL
       && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl)
-      && DECL_ARTIFICIAL (decl)
+      && DECL_DEFAULTED_FN (decl)
       && !DECL_THUNK_P (decl)
       && ! DECL_INITIAL (decl)
       /* Kludge: don't synthesize for default args.  Unfortunately this
@@ -3752,6 +3770,12 @@ mark_used (tree decl)
       /* If we've already synthesized the method we don't need to
         do the instantiation test below.  */
     }
+  else if (TREE_CODE (decl) == FUNCTION_DECL
+          && DECL_DELETED_FN (decl))
+    {
+      error ("deleted function %q+D", decl);
+      error ("used here");
+    }
   else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
           && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
           && (!DECL_EXPLICIT_INSTANTIATION (decl)
index d3ec82aaaefb319d184734a8f2134a249c221c0f..ef26ad9114a026d94537218560a76bebe8556f58 100644 (file)
@@ -2685,7 +2685,7 @@ maybe_warn_cpp0x (const char* str)
     /* We really want to suppress this warning in system headers,
        because libstdc++ uses variadic templates even when we aren't
        in C++0x mode. */
-    pedwarn (0, "%s only available with -std=c++0x", str);
+    pedwarn (0, "%s only available with -std=c++0x or -std=gnu++0x", str);
 }
 
 /* Warn about the use of variadic templates when appropriate.  */
index 7319568b4b4d085f2887c055def904ee266f1e85..3dd6c4e328b62250c92813664eae8471506994e5 100644 (file)
@@ -346,7 +346,7 @@ build_value_init_1 (tree type, bool have_ctor)
 
   if (CLASS_TYPE_P (type))
     {
-      if (TYPE_HAS_USER_CONSTRUCTOR (type) && !have_ctor)
+      if (type_has_user_provided_constructor (type) && !have_ctor)
        return build_cplus_new
          (type,
           build_special_member_call (NULL_TREE, complete_ctor_identifier,
@@ -516,8 +516,17 @@ perform_member_init (tree member, tree init)
                                             tf_warning_or_error));
        }
       else
-       finish_expr_stmt (build_aggr_init (decl, init, 0, 
-                                           tf_warning_or_error));
+       {
+         if (CP_TYPE_CONST_P (type)
+             && init == NULL_TREE
+             && !type_has_user_provided_default_constructor (type))
+           /* TYPE_NEEDS_CONSTRUCTING can be set just because we have a
+              vtable; still give this diagnostic.  */
+           permerror ("%Juninitialized member %qD with %<const%> type %qT",
+                      current_function_decl, member, type);
+         finish_expr_stmt (build_aggr_init (decl, init, 0, 
+                                            tf_warning_or_error));
+       }
     }
   else
     {
@@ -1883,7 +1892,9 @@ build_new_1 (tree placement, tree type, tree nelts, tree init,
     return error_mark_node;
 
   is_initialized = (TYPE_NEEDS_CONSTRUCTING (elt_type) || init);
-  if (CP_TYPE_CONST_P (elt_type) && !is_initialized)
+
+  if (CP_TYPE_CONST_P (elt_type) && !init
+      && !type_has_user_provided_default_constructor (elt_type))
     {
       if (complain & tf_error)
         error ("uninitialized const in %<new%> of %q#T", elt_type);
index 1bc72b86a2de0a794cd11b5111954954ae525372..0703d0a96f7ca4bf71565061adc2d5d3d4893349 100644 (file)
@@ -1056,7 +1056,10 @@ write_unqualified_name (const tree decl)
   else if (DECL_LANG_SPECIFIC (decl) != NULL && DECL_DESTRUCTOR_P (decl))
     write_special_name_destructor (decl);
   else if (DECL_NAME (decl) == NULL_TREE)
-    write_source_name (DECL_ASSEMBLER_NAME (decl));
+    {
+      gcc_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
+      write_source_name (DECL_ASSEMBLER_NAME (decl));
+    }
   else if (DECL_CONV_FN_P (decl))
     {
       /* Conversion operator. Handle it right here.
index bd63d0cba52ee5699d29f439f60abcc68764e027..f3d23eba23dc22fab35a1e2aecfae03c92ea0b0e 100644 (file)
@@ -1108,6 +1108,7 @@ implicitly_declare_fn (special_function_kind kind, tree type, bool const_p)
   rest_of_decl_compilation (fn, toplevel_bindings_p (), at_eof);
   DECL_IN_AGGR_P (fn) = 1;
   DECL_ARTIFICIAL (fn) = 1;
+  DECL_DEFAULTED_FN (fn) = 1;
   DECL_NOT_REALLY_EXTERN (fn) = 1;
   DECL_DECLARED_INLINE_P (fn) = 1;
   DECL_INLINE (fn) = 1;
index 420b92cea10c7a790cb49a819d51cc67973cc45a..15b66b03b9586a6b45f0fb1863ab5be8ad99e93e 100644 (file)
@@ -12378,7 +12378,7 @@ cp_parser_init_declarator (cp_parser* parser,
   tree initializer;
   tree decl = NULL_TREE;
   tree scope;
-  bool is_initialized;
+  int is_initialized;
   /* Only valid if IS_INITIALIZED is true.  In that case, CPP_EQ if
      initialized with "= ..", CPP_OPEN_PAREN if initialized with
      "(...)".  */
@@ -12514,8 +12514,18 @@ cp_parser_init_declarator (cp_parser* parser,
       || token->type == CPP_OPEN_PAREN
       || token->type == CPP_OPEN_BRACE)
     {
-      is_initialized = true;
+      is_initialized = 1;
       initialization_kind = token->type;
+
+      if (token->type == CPP_EQ
+         && function_declarator_p (declarator))
+       {
+         cp_token *t2 = cp_lexer_peek_nth_token (parser->lexer, 2);
+         if (t2->keyword == RID_DEFAULT)
+           is_initialized = 2;
+         else if (t2->keyword == RID_DELETE)
+           is_initialized = 3;
+       }
     }
   else
     {
@@ -12527,7 +12537,7 @@ cp_parser_init_declarator (cp_parser* parser,
          cp_parser_error (parser, "expected initializer");
          return error_mark_node;
        }
-      is_initialized = false;
+      is_initialized = 0;
       initialization_kind = CPP_EOF;
     }
 
@@ -15681,6 +15691,15 @@ cp_parser_pure_specifier (cp_parser* parser)
     return error_mark_node;
   /* Look for the `0' token.  */
   token = cp_lexer_consume_token (parser->lexer);
+
+  /* Accept = default or = delete in c++0x mode.  */
+  if (token->keyword == RID_DEFAULT
+      || token->keyword == RID_DELETE)
+    {
+      maybe_warn_cpp0x ("defaulted and deleted functions");
+      return token->u.value;
+    }
+
   /* c_lex_with_flags marks a single digit '0' with PURE_ZERO.  */
   if (token->type != CPP_NUMBER || !(token->flags & PURE_ZERO))
     {
index cee29240e9e5fa135af33a8f4d2d6b366e933f17..7fc040bc8c47f2368f64d3a3f678c1213713b89c 100644 (file)
@@ -1912,6 +1912,20 @@ check_final_overrider (tree overrider, tree basefn)
       return 0;
     }
 
+  if (DECL_DELETED_FN (basefn) != DECL_DELETED_FN (overrider))
+    {
+      if (DECL_DELETED_FN (overrider))
+       {
+         error ("deleted function %q+D", overrider);
+         error ("overriding non-deleted function %q+D", basefn);
+       }
+      else
+       {
+         error ("non-deleted function %q+D", overrider);
+         error ("overriding deleted function %q+D", basefn);
+       }
+      return 0;
+    }
   return 1;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted1.C b/gcc/testsuite/g++.dg/cpp0x/defaulted1.C
new file mode 100644 (file)
index 0000000..e8fe37e
--- /dev/null
@@ -0,0 +1,43 @@
+// Positive test for defaulted/deleted fns
+// { dg-do run }
+// { dg-options "-std=c++0x" }
+
+struct A
+{
+  int i;
+  A() = default;
+  A(const A&) = delete;
+  A& operator=(const A&) = default;
+  ~A();
+};
+
+A::~A() = default;
+
+void f() = delete;
+
+struct B
+{
+  int i;
+  B() = default;
+};
+
+int main()
+{
+  A a1, a2;
+  B b = {1};
+  a1 = a2;
+}
+
+// fns defaulted in class defn are trivial
+struct C
+{
+  C() = default;
+  C(const C&) = default;
+  C& operator=(const C&) = default;
+  ~C() = default;
+};
+
+union U
+{
+  C c;
+};
diff --git a/gcc/testsuite/g++.dg/cpp0x/defaulted2.C b/gcc/testsuite/g++.dg/cpp0x/defaulted2.C
new file mode 100644 (file)
index 0000000..ea06d92
--- /dev/null
@@ -0,0 +1,66 @@
+// Negative test for defaulted/deleted fns.
+// { dg-options "-std=c++0x" }
+
+void f();                      // { dg-error "previous" }
+void f() = delete;             // { dg-error "deleted" }
+
+struct A
+{
+  A() { }                      // { dg-error "previous" }
+  void f() = default;          // { dg-error "default" }
+};
+
+A::A() = default;              // { dg-error "redefinition" }
+
+void g() {}                    // { dg-error "previous" }
+void g() = delete;             // { dg-error "redefinition" }
+
+struct B
+{
+  B() = default;
+};
+
+const B b;                     // { dg-error "uninitialized const" }
+
+struct C
+{
+  virtual void f() = delete;   // { dg-error "overriding deleted" }
+};
+
+struct D: public C
+{
+  virtual void f();            // { dg-error "non-deleted function" }
+};
+
+struct E
+{
+  const B b;
+  E() { }                      // { dg-error "uninitialized" }
+};
+
+struct F
+{
+  F() = default;
+  F(const F&) = delete;                // { dg-error "deleted" }
+};
+
+struct G
+{
+  G();
+};
+
+// ctor defaulted after class defn is not trivial
+G::G() = default;
+
+union U
+{
+  G g;                         // { dg-error "constructor" }
+};
+
+int main()
+{
+  F f;
+  F f2(f);                     // { dg-error "used" }
+  B* b = new const B;          // { dg-error "uninitialized const" }
+}
+
index 069436666d3bc44c0ac15cbfdbf77574aff6bf04..217928781d332901ddc2ee4fc3d98a0f6b485371 100644 (file)
@@ -1,5 +1,4 @@
 // Bug: 23225
 
 void Dispatcher()
-        (__builtin_offsetof (ArgsType, largeMsgLen))
-       /* { dg-error "function " "function" { target *-*-* } 4 } */
+        (__builtin_offsetof (ArgsType, largeMsgLen)) // { dg-error "initialize|end of input" }
index 5903a585e973957260c567d631410a4747751f01..5d30b554369716bdbb554675af650f5a2648e91a 100644 (file)
@@ -35,4 +35,4 @@ struct C
   typename N::A f7;   // { dg-error "15: error: invalid use of template-name 'N::A' without an argument list" }
 };
 
-// { dg-bogus "bogus excess errors in declaration" "bogus excess errors in declaration" { xfail *-*-* } 17 }
+// { dg-bogus "bogus excess errors in declaration" "bogus excess errors in declaration" { target *-*-* } 17 }
index 9e1d88b243233a1f36955b73c595d8e794c4aa58..c579775917ed6146b5fa004143101e6b3db27072 100644 (file)
@@ -5,5 +5,5 @@ struct A
     template<int> void foo(X);  // { dg-error "declared" }
 };
 
-template<int> void f()(0);      // { dg-error "initialized" }
+template<int> void f()(0);      // { dg-error "initialize" }
  
index 5b17928f5bbc878db16ad2adeb7a13d4b94b5024..ae07d91e739972bc81a512ebe0448ee7aa368f48 100644 (file)
@@ -6,8 +6,10 @@
 // nested type.
 
 template <typename> struct A
-{                                      // { dg-error "candidates" }
+{                                      // { not-dg-error "candidates" }
     template <typename> A(typename A::X) {} // { dg-error "no type" }
 };
 
-A<void> a;     // { dg-error "instantiated|no match" }
+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.
index 2f777afdc70afc3f9162de3bbf51f345b5ef5961..40f7a7cb67f7791c338df4baf2d135298cb8098e 100644 (file)
@@ -2,7 +2,7 @@
 // Origin: Carl Nygard <cnygard@bellatlantic.net>
 
 template <class RT>
-class Test { // { dg-error "" } in instantiation
+class Test {
 public:
   Test(const RT& c = RT()) {} // { dg-error "" } reference to void
 };