aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/class.c
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2008-07-24 15:15:00 -0400
committerJason Merrill <jason@gcc.gnu.org>2008-07-24 15:15:00 -0400
commitb87d79e640b3e9ab1e126bb6d87472b2a261a640 (patch)
tree38c6149cb50c1486bcdf000c5463ee69d1c647a7 /gcc/cp/class.c
parentc3005b0f0c8081ccb719740c3c27ee13d5697add (diff)
downloadgcc-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.c111
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));