aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/tree.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/tree.cc')
-rw-r--r--gcc/cp/tree.cc287
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