diff options
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)); |