diff options
author | Jason Merrill <jason@redhat.com> | 2008-07-24 15:15:00 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2008-07-24 15:15:00 -0400 |
commit | b87d79e640b3e9ab1e126bb6d87472b2a261a640 (patch) | |
tree | 38c6149cb50c1486bcdf000c5463ee69d1c647a7 /gcc/cp/class.c | |
parent | c3005b0f0c8081ccb719740c3c27ee13d5697add (diff) | |
download | gcc-b87d79e640b3e9ab1e126bb6d87472b2a261a640.zip gcc-b87d79e640b3e9ab1e126bb6d87472b2a261a640.tar.gz gcc-b87d79e640b3e9ab1e126bb6d87472b2a261a640.tar.bz2 |
Implement defaulted/deleted functions as per N2346
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
Diffstat (limited to 'gcc/cp/class.c')
-rw-r--r-- | gcc/cp/class.c | 111 |
1 files changed, 98 insertions, 13 deletions
diff --git a/gcc/cp/class.c b/gcc/cp/class.c index 0c7a76c..0649eec 100644 --- a/gcc/cp/class.c +++ b/gcc/cp/class.c @@ -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)); |