diff options
Diffstat (limited to 'gcc/cp/tree.cc')
-rw-r--r-- | gcc/cp/tree.cc | 287 |
1 files changed, 287 insertions, 0 deletions
diff --git a/gcc/cp/tree.cc b/gcc/cp/tree.cc index accce0e..a7b8908 100644 --- a/gcc/cp/tree.cc +++ b/gcc/cp/tree.cc @@ -4716,6 +4716,293 @@ trivial_type_p (const_tree t) return scalarish_type_p (t); } +/* Returns 1 iff type T is a default-movable type, as defined in + [class.prop]. */ + +static bool +default_movable_type_p (tree t) +{ + if (!CLASS_TYPE_P (t) || !COMPLETE_TYPE_P (t)) + return false; + if (CLASSTYPE_LAZY_DESTRUCTOR (t)) + lazily_declare_fn (sfk_destructor, t); + if (tree dtor = CLASSTYPE_DESTRUCTOR (t)) + if (user_provided_p (dtor) || DECL_DELETED_FN (dtor)) + return false; + + tree copy_ctor = NULL_TREE, move_ctor = NULL_TREE; + tree copy_assign = NULL_TREE, move_assign = NULL_TREE; + if (CLASSTYPE_LAZY_MOVE_CTOR (t)) + move_ctor = lazily_declare_fn (sfk_move_constructor, t); + if (CLASSTYPE_LAZY_MOVE_ASSIGN (t)) + move_assign = lazily_declare_fn (sfk_move_assignment, t); + if (!move_ctor) + for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter) + if (TREE_CODE (*iter) == FUNCTION_DECL) + { + if (copy_fn_p (*iter)) + copy_ctor = *iter; + else if (move_fn_p (*iter)) + { + move_ctor = *iter; + break; + } + } + if (!move_assign) + for (ovl_iterator iter (get_class_binding_direct (t, + assign_op_identifier)); + iter; ++iter) + if (TREE_CODE (*iter) == FUNCTION_DECL) + { + if (copy_fn_p (*iter)) + copy_assign = *iter; + else if (move_fn_p (*iter)) + { + move_assign = *iter; + break; + } + } + if (!move_ctor) + { + if (CLASSTYPE_LAZY_COPY_CTOR (t)) + copy_ctor = lazily_declare_fn (sfk_copy_constructor, t); + if (!copy_ctor) + return false; + if (user_provided_p (copy_ctor) + || DECL_DELETED_FN (copy_ctor) + || DECL_CONTEXT (copy_ctor) != t + || DECL_INHERITED_CTOR (copy_ctor)) + return false; + } + else if (user_provided_p (move_ctor) + || DECL_DELETED_FN (move_ctor) + || DECL_CONTEXT (move_ctor) != t + || DECL_INHERITED_CTOR (move_ctor)) + return false; + if (!move_assign) + { + if (CLASSTYPE_LAZY_COPY_ASSIGN (t)) + copy_assign = lazily_declare_fn (sfk_copy_assignment, t); + if (!copy_assign) + return false; + if (user_provided_p (copy_assign) + || DECL_DELETED_FN (copy_assign) + || DECL_CONTEXT (copy_assign) != t) + return false; + } + else if (user_provided_p (move_assign) + || DECL_DELETED_FN (move_assign) + || DECL_CONTEXT (move_assign) != t) + return false; + return true; +} + +/* Returns 1 iff type T is a union with no user declared special member + functions. */ + +static bool +union_with_no_declared_special_member_fns (tree t) +{ + if (TREE_CODE (t) != UNION_TYPE) + return false; + + for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter) + if (TREE_CODE (*iter) == FUNCTION_DECL + && !DECL_ARTIFICIAL (*iter) + && (default_ctor_p (*iter) || copy_fn_p (*iter) || move_fn_p (*iter))) + return false; + + for (ovl_iterator iter (get_class_binding_direct (t, assign_op_identifier)); + iter; ++iter) + if (TREE_CODE (*iter) == FUNCTION_DECL + && !DECL_ARTIFICIAL (*iter) + && (copy_fn_p (*iter) || move_fn_p (*iter))) + return false; + + if (tree dtor = CLASSTYPE_DESTRUCTOR (t)) + if (!DECL_ARTIFICIAL (dtor)) + return false; + + return true; +} + +/* Returns 1 iff type T is a trivially relocatable type, as defined in + [basic.types.general] and [class.prop]. */ + +bool +trivially_relocatable_type_p (tree t) +{ + t = strip_array_types (t); + + if (!CLASS_TYPE_P (t)) + return scalarish_type_p (t); + + t = TYPE_MAIN_VARIANT (t); + if (CLASSTYPE_TRIVIALLY_RELOCATABLE_COMPUTED (t)) + return CLASSTYPE_TRIVIALLY_RELOCATABLE_BIT (t); + if (!COMPLETE_TYPE_P (t)) + return false; + + if (!CLASSTYPE_TRIVIALLY_RELOCATABLE_BIT (t) + && !union_with_no_declared_special_member_fns (t) + && !default_movable_type_p (t)) + { + nontriv: + CLASSTYPE_TRIVIALLY_RELOCATABLE_BIT (t) = 0; + CLASSTYPE_TRIVIALLY_RELOCATABLE_COMPUTED (t) = 1; + return false; + } + + if (CLASSTYPE_VBASECLASSES (t)) + goto nontriv; + + if (CLASSTYPE_LAZY_DESTRUCTOR (t)) + lazily_declare_fn (sfk_destructor, t); + if (tree dtor = CLASSTYPE_DESTRUCTOR (t)) + if (DECL_DELETED_FN (dtor)) + goto nontriv; + + tree binfo, base_binfo; + unsigned int i; + for (binfo = TYPE_BINFO (t), i = 0; + BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) + { + tree basetype = TREE_TYPE (base_binfo); + if (!trivially_relocatable_type_p (basetype)) + goto nontriv; + } + + for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL + && !DECL_ARTIFICIAL (field) + && !DECL_UNNAMED_BIT_FIELD (field)) + { + tree type = TREE_TYPE (field); + if (type == error_mark_node) + goto nontriv; + if (!TYPE_REF_P (type) && !trivially_relocatable_type_p (type)) + goto nontriv; + } + + CLASSTYPE_TRIVIALLY_RELOCATABLE_BIT (t) = 1; + CLASSTYPE_TRIVIALLY_RELOCATABLE_COMPUTED (t) = 1; + return true; +} + +/* Returns 1 iff type T is a replaceable type, as defined in [basic.types] + and [class]. */ + +bool +replaceable_type_p (tree t) +{ + t = strip_array_types (t); + + if (cv_qualified_p (t)) + return false; + + if (!CLASS_TYPE_P (t)) + return scalarish_type_p (t); + + t = TYPE_MAIN_VARIANT (t); + if (CLASSTYPE_REPLACEABLE_COMPUTED (t)) + return CLASSTYPE_REPLACEABLE_BIT (t); + if (!COMPLETE_TYPE_P (t)) + return false; + + if (!CLASSTYPE_REPLACEABLE_BIT (t) + && !union_with_no_declared_special_member_fns (t) + && !default_movable_type_p (t)) + { + nonrepl: + CLASSTYPE_REPLACEABLE_BIT (t) = 0; + CLASSTYPE_REPLACEABLE_COMPUTED (t) = 1; + return false; + } + + if (CLASSTYPE_LAZY_DESTRUCTOR (t)) + lazily_declare_fn (sfk_destructor, t); + if (tree dtor = CLASSTYPE_DESTRUCTOR (t)) + if (DECL_DELETED_FN (dtor)) + goto nonrepl; + + tree copy_ctor = NULL_TREE, move_ctor = NULL_TREE; + tree copy_assign = NULL_TREE, move_assign = NULL_TREE; + if (CLASSTYPE_LAZY_MOVE_CTOR (t)) + move_ctor = lazily_declare_fn (sfk_move_constructor, t); + if (CLASSTYPE_LAZY_MOVE_ASSIGN (t)) + move_assign = lazily_declare_fn (sfk_move_assignment, t); + if (!move_ctor) + for (ovl_iterator iter (CLASSTYPE_CONSTRUCTORS (t)); iter; ++iter) + if (TREE_CODE (*iter) == FUNCTION_DECL) + { + if (copy_fn_p (*iter)) + copy_ctor = *iter; + else if (move_fn_p (*iter)) + { + move_ctor = *iter; + break; + } + } + if (!move_assign) + for (ovl_iterator iter (get_class_binding_direct (t, + assign_op_identifier)); + iter; ++iter) + if (TREE_CODE (*iter) == FUNCTION_DECL) + { + if (copy_fn_p (*iter)) + copy_assign = *iter; + else if (move_fn_p (*iter)) + { + move_assign = *iter; + break; + } + } + if (!move_ctor) + { + if (CLASSTYPE_LAZY_COPY_CTOR (t)) + copy_ctor = lazily_declare_fn (sfk_copy_constructor, t); + if (!copy_ctor || DECL_DELETED_FN (copy_ctor)) + goto nonrepl; + } + else if (DECL_DELETED_FN (move_ctor)) + goto nonrepl; + if (!move_assign) + { + if (CLASSTYPE_LAZY_COPY_ASSIGN (t)) + copy_assign = lazily_declare_fn (sfk_copy_assignment, t); + if (!copy_assign || DECL_DELETED_FN (copy_assign)) + goto nonrepl; + } + else if (DECL_DELETED_FN (move_assign)) + goto nonrepl; + + tree binfo, base_binfo; + unsigned int i; + for (binfo = TYPE_BINFO (t), i = 0; + BINFO_BASE_ITERATE (binfo, i, base_binfo); i++) + { + tree basetype = TREE_TYPE (base_binfo); + if (!replaceable_type_p (basetype)) + goto nonrepl; + } + + for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field)) + if (TREE_CODE (field) == FIELD_DECL + && !DECL_ARTIFICIAL (field) + && !DECL_UNNAMED_BIT_FIELD (field)) + { + tree type = TREE_TYPE (field); + if (type == error_mark_node) + goto nonrepl; + if (!replaceable_type_p (type)) + goto nonrepl; + } + + CLASSTYPE_REPLACEABLE_BIT (t) = 1; + CLASSTYPE_REPLACEABLE_COMPUTED (t) = 1; + return true; +} + /* Returns 1 iff type T is a POD type, as defined in [basic.types]. */ bool |