Commit ac177431 by Jason Merrill Committed by Jason Merrill

Machinery to support implicit delete/move.

	* cp-tree.h: (struct lang_type_class): Add lazy_move_assign,
	has_complex_move_ctor, has_complex_move_assign bitfields.
	(CLASSTYPE_LAZY_MOVE_ASSIGN): New.
	(TYPE_HAS_COMPLEX_MOVE_ASSIGN): New.
	(TYPE_HAS_COMPLEX_MOVE_CTOR): New.
	(enum special_function_kind): Add sfk_move_assignment.
	(LOOKUP_SPECULATIVE): New.
	* call.c (build_over_call): Return early if it's set.
	(build_over_call): Use trivial_fn_p.
	* class.c (check_bases): If the base has no default constructor,
	the derived one is non-trivial.  Handle move ctor/op=.
	(check_field_decl): Likewise.
	(check_bases_and_members): Handle move ctor/op=.
	(add_implicitly_declared_members): Handle CLASSTYPE_LAZY_MOVE_ASSIGN.
	(type_has_move_constructor, type_has_move_assign): New.
	* decl.c (grok_special_member_properties): Handle move ctor/op=.
	* method.c (type_has_trivial_fn, type_set_nontrivial_flag): New.
	(trivial_fn_p): New.
	(do_build_copy_constructor): Use it.
	(do_build_assign_ref): Likewise.  Handle move assignment.
	(build_stub_type, build_stub_object, locate_fn_flags): New.
	(locate_ctor): Use locate_fn_flags.
	(locate_copy, locate_dtor): Remove.
	(get_dtor, get_default_ctor, get_copy_ctor, get_copy_assign): New.
	(process_subob_fn, synthesized_method_walk): New.
	(maybe_explain_implicit_delete): New.
	(implicitly_declare_fn): Use synthesized_method_walk,
	type_has_trivial_fn, and type_set_nontrivial_flag.
	(defaulted_late_check): Set DECL_DELETED_FN.
	(defaultable_fn_check): Handle sfk_move_assignment.
	(lazily_declare_fn): Clear CLASSTYPE_LAZY_* early.  Don't declare
	implicitly deleted move ctor/op=.
	* search.c (lookup_fnfields_1): Handle sfk_move_assignment.
	(lookup_fnfields_slot): New.
	* semantics.c (omp_clause_info_fndecl): Remove.
	(cxx_omp_create_clause_info): Use get_default_ctor, get_copy_ctor,
	get_copy_assign, trivial_fn_p.
	(trait_expr_value): Adjust call to locate_ctor.
	* tree.c (special_function_p): Handle sfk_move_assignment.

From-SVN: r161579
parent 46408846
2010-06-29 Jason Merrill <jason@redhat.com>
Machinery to support implicit delete/move.
* cp-tree.h: (struct lang_type_class): Add lazy_move_assign,
has_complex_move_ctor, has_complex_move_assign bitfields.
(CLASSTYPE_LAZY_MOVE_ASSIGN): New.
(TYPE_HAS_COMPLEX_MOVE_ASSIGN): New.
(TYPE_HAS_COMPLEX_MOVE_CTOR): New.
(enum special_function_kind): Add sfk_move_assignment.
(LOOKUP_SPECULATIVE): New.
* call.c (build_over_call): Return early if it's set.
(build_over_call): Use trivial_fn_p.
* class.c (check_bases): If the base has no default constructor,
the derived one is non-trivial. Handle move ctor/op=.
(check_field_decl): Likewise.
(check_bases_and_members): Handle move ctor/op=.
(add_implicitly_declared_members): Handle CLASSTYPE_LAZY_MOVE_ASSIGN.
(type_has_move_constructor, type_has_move_assign): New.
* decl.c (grok_special_member_properties): Handle move ctor/op=.
* method.c (type_has_trivial_fn, type_set_nontrivial_flag): New.
(trivial_fn_p): New.
(do_build_copy_constructor): Use it.
(do_build_assign_ref): Likewise. Handle move assignment.
(build_stub_type, build_stub_object, locate_fn_flags): New.
(locate_ctor): Use locate_fn_flags.
(locate_copy, locate_dtor): Remove.
(get_dtor, get_default_ctor, get_copy_ctor, get_copy_assign): New.
(process_subob_fn, synthesized_method_walk): New.
(maybe_explain_implicit_delete): New.
(implicitly_declare_fn): Use synthesized_method_walk,
type_has_trivial_fn, and type_set_nontrivial_flag.
(defaulted_late_check): Set DECL_DELETED_FN.
(defaultable_fn_check): Handle sfk_move_assignment.
(lazily_declare_fn): Clear CLASSTYPE_LAZY_* early. Don't declare
implicitly deleted move ctor/op=.
* search.c (lookup_fnfields_1): Handle sfk_move_assignment.
(lookup_fnfields_slot): New.
* semantics.c (omp_clause_info_fndecl): Remove.
(cxx_omp_create_clause_info): Use get_default_ctor, get_copy_ctor,
get_copy_assign, trivial_fn_p.
(trait_expr_value): Adjust call to locate_ctor.
* tree.c (special_function_p): Handle sfk_move_assignment.
* class.c (type_has_virtual_destructor): New.
* cp-tree.h: Declare it.
* semantics.c (trait_expr_value): Use it.
......
......@@ -5613,6 +5613,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
if (DECL_FUNCTION_MEMBER_P (fn))
{
tree access_fn;
/* If FN is a template function, two cases must be considered.
For example:
......@@ -5640,10 +5641,41 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
different access. */
if (DECL_TEMPLATE_INFO (fn)
&& DECL_MEMBER_TEMPLATE_P (DECL_TI_TEMPLATE (fn)))
perform_or_defer_access_check (cand->access_path,
DECL_TI_TEMPLATE (fn), fn);
access_fn = DECL_TI_TEMPLATE (fn);
else
perform_or_defer_access_check (cand->access_path, fn, fn);
access_fn = fn;
if (flags & LOOKUP_SPECULATIVE)
{
/* If we're checking for implicit delete, we don't want access
control errors. */
if (!accessible_p (cand->access_path, access_fn, true))
{
/* Unless we're under maybe_explain_implicit_delete. */
if (flags & LOOKUP_COMPLAIN)
enforce_access (cand->access_path, access_fn, fn);
return error_mark_node;
}
}
else
perform_or_defer_access_check (cand->access_path, access_fn, fn);
}
/* If we're checking for implicit delete, don't bother with argument
conversions. */
if (flags & LOOKUP_SPECULATIVE)
{
if (DECL_DELETED_FN (fn))
{
if (flags & LOOKUP_COMPLAIN)
mark_used (fn);
return error_mark_node;
}
if (cand->viable == 1)
return fn;
else if (!(flags & LOOKUP_COMPLAIN))
/* Reject bad conversions now. */
return error_mark_node;
/* else continue to get conversion error. */
}
/* Find maximum size of vector to hold converted arguments. */
......@@ -5824,6 +5856,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
tree targ;
tree arg = argarray[num_artificial_parms_for (fn)];
tree fa;
bool trivial = trivial_fn_p (fn);
/* Pull out the real argument, disregarding const-correctness. */
targ = arg;
......@@ -5848,13 +5881,12 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
if (TREE_CODE (arg) == TARGET_EXPR
&& TARGET_EXPR_LIST_INIT_P (arg))
{
/* Copy-list-initialization doesn't require the copy constructor
/* Copy-list-initialization doesn't require the constructor
to be defined. */
}
/* [class.copy]: the copy constructor is implicitly defined even if
the implementation elided its use. */
else if (TYPE_HAS_COMPLEX_COPY_CTOR (DECL_CONTEXT (fn))
|| move_fn_p (fn))
else if (!trivial)
{
mark_used (fn);
already_used = true;
......@@ -5872,13 +5904,10 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
{
if (TREE_CODE (arg) == TARGET_EXPR)
return arg;
else if (TYPE_HAS_TRIVIAL_COPY_CTOR (DECL_CONTEXT (fn))
&& !move_fn_p (fn))
else if (trivial)
return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
}
else if (TREE_CODE (arg) == TARGET_EXPR
|| (TYPE_HAS_TRIVIAL_COPY_CTOR (DECL_CONTEXT (fn))
&& !move_fn_p (fn)))
else if (TREE_CODE (arg) == TARGET_EXPR || trivial)
{
tree to = stabilize_reference (cp_build_indirect_ref (fa, RO_NULL,
complain));
......@@ -5888,8 +5917,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
}
}
else if (DECL_OVERLOADED_OPERATOR_P (fn) == NOP_EXPR
&& copy_fn_p (fn)
&& TYPE_HAS_TRIVIAL_COPY_ASSIGN (DECL_CONTEXT (fn)))
&& trivial_fn_p (fn))
{
tree to = stabilize_reference
(cp_build_indirect_ref (argarray[0], RO_NULL, complain));
......
......@@ -1314,10 +1314,14 @@ check_bases (tree t,
TYPE_HAS_COMPLEX_COPY_ASSIGN (t)
|= TYPE_HAS_COMPLEX_COPY_ASSIGN (basetype);
TYPE_HAS_COMPLEX_COPY_CTOR (t) |= TYPE_HAS_COMPLEX_COPY_CTOR (basetype);
TYPE_HAS_COMPLEX_MOVE_ASSIGN (t)
|= TYPE_HAS_COMPLEX_MOVE_ASSIGN (basetype);
TYPE_HAS_COMPLEX_MOVE_CTOR (t) |= TYPE_HAS_COMPLEX_MOVE_CTOR (basetype);
TYPE_POLYMORPHIC_P (t) |= TYPE_POLYMORPHIC_P (basetype);
CLASSTYPE_CONTAINS_EMPTY_CLASS_P (t)
|= CLASSTYPE_CONTAINS_EMPTY_CLASS_P (basetype);
TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (basetype);
TYPE_HAS_COMPLEX_DFLT (t) |= (!TYPE_HAS_DEFAULT_CONSTRUCTOR (basetype)
|| TYPE_HAS_COMPLEX_DFLT (basetype));
/* A standard-layout class is a class that:
...
......@@ -2670,6 +2674,7 @@ add_implicitly_declared_members (tree t,
a virtual function from a base class. */
if (TYPE_POLYMORPHIC_P (t)
&& (CLASSTYPE_LAZY_COPY_ASSIGN (t)
|| CLASSTYPE_LAZY_MOVE_ASSIGN (t)
|| CLASSTYPE_LAZY_DESTRUCTOR (t)))
{
tree binfo = TYPE_BINFO (t);
......@@ -2686,6 +2691,8 @@ add_implicitly_declared_members (tree t,
{
if (CLASSTYPE_LAZY_COPY_ASSIGN (t))
lazily_declare_fn (sfk_copy_assignment, t);
if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
lazily_declare_fn (sfk_move_assignment, t);
}
else if (DECL_DESTRUCTOR_P (fn)
&& CLASSTYPE_LAZY_DESTRUCTOR (t))
......@@ -2848,6 +2855,8 @@ check_field_decl (tree field,
if (TYPE_HAS_COMPLEX_COPY_ASSIGN (type))
error ("member %q+#D with copy assignment operator not allowed in union",
field);
/* Don't bother diagnosing move assop now; C++0x has more
flexible unions. */
}
else
{
......@@ -2856,7 +2865,10 @@ check_field_decl (tree field,
|= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type);
TYPE_HAS_COMPLEX_COPY_ASSIGN (t) |= TYPE_HAS_COMPLEX_COPY_ASSIGN (type);
TYPE_HAS_COMPLEX_COPY_CTOR (t) |= TYPE_HAS_COMPLEX_COPY_CTOR (type);
TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_HAS_COMPLEX_DFLT (type);
TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) |= TYPE_HAS_COMPLEX_MOVE_ASSIGN (type);
TYPE_HAS_COMPLEX_MOVE_CTOR (t) |= TYPE_HAS_COMPLEX_MOVE_CTOR (type);
TYPE_HAS_COMPLEX_DFLT (t) |= (!TYPE_HAS_DEFAULT_CONSTRUCTOR (type)
|| TYPE_HAS_COMPLEX_DFLT (type));
}
if (!TYPE_HAS_CONST_COPY_CTOR (type))
......@@ -3022,6 +3034,7 @@ check_field_decls (tree t, tree *access_decls,
only way to initialize nonstatic const and reference
members. */
TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1;
}
type = strip_array_types (type);
......@@ -3108,6 +3121,7 @@ check_field_decls (tree t, tree *access_decls,
only way to initialize nonstatic const and reference
members. */
TYPE_HAS_COMPLEX_COPY_ASSIGN (t) = 1;
TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) = 1;
}
/* A field that is pseudo-const makes the structure likewise. */
else if (CLASS_TYPE_P (type))
......@@ -4277,6 +4291,50 @@ type_has_virtual_destructor (tree type)
return (dtor && DECL_VIRTUAL_P (dtor));
}
/* Returns true iff class T has a move constructor. */
bool
type_has_move_constructor (tree t)
{
tree fns;
if (CLASSTYPE_LAZY_MOVE_CTOR (t))
{
gcc_assert (COMPLETE_TYPE_P (t));
lazily_declare_fn (sfk_move_constructor, t);
}
if (!CLASSTYPE_METHOD_VEC (t))
return false;
for (fns = CLASSTYPE_CONSTRUCTORS (t); fns; fns = OVL_NEXT (fns))
if (move_fn_p (OVL_CURRENT (fns)))
return true;
return false;
}
/* Returns true iff class T has a move assignment operator. */
bool
type_has_move_assign (tree t)
{
tree fns;
if (CLASSTYPE_LAZY_MOVE_ASSIGN (t))
{
gcc_assert (COMPLETE_TYPE_P (t));
lazily_declare_fn (sfk_move_assignment, t);
}
for (fns = lookup_fnfields_slot (t, ansi_assopname (NOP_EXPR));
fns; fns = OVL_NEXT (fns))
if (move_fn_p (OVL_CURRENT (fns)))
return true;
return false;
}
/* Remove all zero-width bit-fields from T. */
static void
......@@ -4411,6 +4469,7 @@ check_bases_and_members (tree t)
/* Do some bookkeeping that will guide the generation of implicitly
declared member functions. */
TYPE_HAS_COMPLEX_COPY_CTOR (t) |= TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_MOVE_CTOR (t) |= TYPE_CONTAINS_VPTR_P (t);
/* We need to call a constructor for this class if it has a
user-provided constructor, or if the default constructor is going
to initialize the vptr. (This is not an if-and-only-if;
......@@ -4434,6 +4493,7 @@ check_bases_and_members (tree t)
|| saved_nontrivial_dtor || saved_complex_asn_ref);
CLASSTYPE_NON_STD_LAYOUT (t) |= TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_COPY_ASSIGN (t) |= TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_MOVE_ASSIGN (t) |= TYPE_CONTAINS_VPTR_P (t);
TYPE_HAS_COMPLEX_DFLT (t) |= TYPE_CONTAINS_VPTR_P (t);
/* If the class has no user-declared constructor, but does have
......
......@@ -1307,10 +1307,13 @@ struct GTY(()) lang_type_class {
unsigned has_complex_dflt : 1;
unsigned has_list_ctor : 1;
unsigned non_std_layout : 1;
unsigned lazy_move_ctor : 1;
unsigned is_literal : 1;
unsigned lazy_move_ctor : 1;
unsigned lazy_move_assign : 1;
unsigned has_complex_move_ctor : 1;
unsigned has_complex_move_assign : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
so, make sure to copy it in instantiate_class_template! */
......@@ -1318,7 +1321,7 @@ struct GTY(()) lang_type_class {
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
unsigned dummy : 7;
unsigned dummy : 4;
tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices;
......@@ -1416,6 +1419,11 @@ struct GTY((variable_size)) lang_type {
#define CLASSTYPE_LAZY_COPY_ASSIGN(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->lazy_copy_assign)
/* Nonzero means that NODE (a class type) has an assignment operator
-- but that it has not yet been declared. */
#define CLASSTYPE_LAZY_MOVE_ASSIGN(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->lazy_move_assign)
/* Nonzero means that NODE (a class type) has a destructor -- but that
it has not yet been declared. */
#define CLASSTYPE_LAZY_DESTRUCTOR(NODE) \
......@@ -3166,6 +3174,12 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
/* Nonzero if there is a non-trivial X::X(cv X&) for this class. */
#define TYPE_HAS_COMPLEX_COPY_CTOR(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_copy_ctor)
/* Nonzero if there is a non-trivial X::op=(X&&) for this class. */
#define TYPE_HAS_COMPLEX_MOVE_ASSIGN(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_move_assign)
/* Nonzero if there is a non-trivial X::X(X&&) for this class. */
#define TYPE_HAS_COMPLEX_MOVE_CTOR(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_move_ctor)
/* Nonzero if there is a non-trivial default constructor for this class. */
#define TYPE_HAS_COMPLEX_DFLT(NODE) (LANG_TYPE_CLASS_CHECK (NODE)->has_complex_dflt)
......@@ -3869,6 +3883,7 @@ typedef enum special_function_kind {
sfk_copy_constructor, /* A copy constructor. */
sfk_move_constructor, /* A move constructor. */
sfk_copy_assignment, /* A copy assignment operator. */
sfk_move_assignment, /* A move assignment operator. */
sfk_destructor, /* A destructor. */
sfk_complete_destructor, /* A destructor for complete objects. */
sfk_base_destructor, /* A destructor for base subobjects. */
......@@ -4163,12 +4178,21 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
/* We're inside an init-list, so narrowing conversions are ill-formed. */
#define LOOKUP_NO_NARROWING (LOOKUP_PREFER_RVALUE << 1)
/* Avoid user-defined conversions for the first parameter of a copy
constructor. */
constructor (or move constructor). */
#define LOOKUP_NO_COPY_CTOR_CONVERSION (LOOKUP_NO_NARROWING << 1)
/* This is the first parameter of a copy constructor. */
#define LOOKUP_COPY_PARM (LOOKUP_NO_COPY_CTOR_CONVERSION << 1)
/* We only want to consider list constructors. */
#define LOOKUP_LIST_ONLY (LOOKUP_COPY_PARM << 1)
/* Return after determining which function to call and checking access.
Used by sythesized_method_walk to determine which functions will
be called to initialize subobjects, in order to determine exception
specification and possible implicit delete.
This is kind of a hack, but since access control doesn't respect SFINAE
we can't just use tf_none to avoid access control errors, we need
another mechanism. Exiting early also avoids problems with trying
to perform argument conversions when the class isn't complete yet. */
#define LOOKUP_SPECULATIVE (LOOKUP_LIST_ONLY << 1)
#define LOOKUP_NAMESPACES_ONLY(F) \
(((F) & LOOKUP_PREFER_NAMESPACES) && !((F) & LOOKUP_PREFER_TYPES))
......@@ -4656,6 +4680,8 @@ extern bool user_provided_p (tree);
extern bool type_has_user_provided_constructor (tree);
extern bool type_has_user_provided_default_constructor (tree);
extern bool type_has_virtual_destructor (tree);
extern bool type_has_move_constructor (tree);
extern bool type_has_move_assign (tree);
extern void defaulted_late_check (tree);
extern bool defaultable_fn_check (tree);
extern void fixup_type_variants (tree);
......@@ -4921,15 +4947,19 @@ extern void init_method (void);
extern tree make_thunk (tree, bool, tree, tree);
extern void finish_thunk (tree);
extern void use_thunk (tree, bool);
extern bool trivial_fn_p (tree);
extern bool maybe_explain_implicit_delete (tree);
extern void synthesize_method (tree);
extern tree lazily_declare_fn (special_function_kind,
tree);
extern tree skip_artificial_parms_for (const_tree, tree);
extern int num_artificial_parms_for (const_tree);
extern tree make_alias_for (tree, tree);
extern tree locate_copy (tree, void *);
extern tree locate_ctor (tree, void *);
extern tree locate_dtor (tree, void *);
extern tree get_copy_ctor (tree);
extern tree get_copy_assign (tree);
extern tree get_default_ctor (tree);
extern tree get_dtor (tree);
extern tree locate_ctor (tree);
/* In optimize.c */
extern bool maybe_clone_body (tree);
......@@ -5070,6 +5100,7 @@ extern int accessible_p (tree, tree, bool);
extern tree lookup_field_1 (tree, tree, bool);
extern tree lookup_field (tree, tree, int, bool);
extern int lookup_fnfields_1 (tree, tree);
extern tree lookup_fnfields_slot (tree, tree);
extern int class_method_index_for_fn (tree, tree);
extern tree lookup_fnfields (tree, tree, int);
extern tree lookup_member (tree, tree, int, bool);
......
......@@ -10273,6 +10273,8 @@ grok_special_member_properties (tree decl)
if (user_provided_p (decl))
TYPE_HAS_COMPLEX_DFLT (class_type) = 1;
}
else if (move_fn_p (decl) && user_provided_p (decl))
TYPE_HAS_COMPLEX_MOVE_CTOR (class_type) = 1;
else if (is_list_ctor (decl))
TYPE_HAS_LIST_CTOR (class_type) = 1;
}
......@@ -10294,6 +10296,8 @@ grok_special_member_properties (tree decl)
if (assop != 1)
TYPE_HAS_CONST_COPY_ASSIGN (class_type) = 1;
}
else if (move_fn_p (decl) && user_provided_p (decl))
TYPE_HAS_COMPLEX_MOVE_ASSIGN (class_type) = 1;
}
/* Destructors are handled in check_methods. */
}
......
......@@ -1335,7 +1335,7 @@ lookup_conversion_operator (tree class_type, tree type)
}
/* TYPE is a class type. Return the index of the fields within
the method vector with name NAME, or -1 is no such field exists. */
the method vector with name NAME, or -1 if no such field exists. */
int
lookup_fnfields_1 (tree type, tree name)
......@@ -1361,9 +1361,13 @@ lookup_fnfields_1 (tree type, tree name)
if (CLASSTYPE_LAZY_MOVE_CTOR (type))
lazily_declare_fn (sfk_move_constructor, type);
}
else if (name == ansi_assopname(NOP_EXPR)
&& CLASSTYPE_LAZY_COPY_ASSIGN (type))
lazily_declare_fn (sfk_copy_assignment, type);
else if (name == ansi_assopname (NOP_EXPR))
{
if (CLASSTYPE_LAZY_COPY_ASSIGN (type))
lazily_declare_fn (sfk_copy_assignment, type);
if (CLASSTYPE_LAZY_MOVE_ASSIGN (type))
lazily_declare_fn (sfk_move_assignment, type);
}
else if ((name == dtor_identifier
|| name == base_dtor_identifier
|| name == complete_dtor_identifier
......@@ -1441,6 +1445,18 @@ lookup_fnfields_1 (tree type, tree name)
return -1;
}
/* TYPE is a class type. Return the field within the method vector with
name NAME, or NULL_TREE if no such field exists. */
tree
lookup_fnfields_slot (tree type, tree name)
{
int ix = lookup_fnfields_1 (type, name);
if (ix < 0)
return NULL_TREE;
return VEC_index (tree, CLASSTYPE_METHOD_VEC (type), ix);
}
/* Like lookup_fnfields_1, except that the name is extracted from
FUNCTION, which is a FUNCTION_DECL or a TEMPLATE_DECL. */
......@@ -1889,6 +1905,7 @@ check_final_overrider (tree overrider, tree basefn)
{
error ("deleted function %q+D", overrider);
error ("overriding non-deleted function %q+D", basefn);
maybe_explain_implicit_delete (overrider);
}
else
{
......
......@@ -3527,31 +3527,6 @@ finalize_nrv (tree *tp, tree var, tree result)
htab_delete (data.visited);
}
/* Return the declaration for the function called by CALL_EXPR T,
TYPE is the class type of the clause decl. */
static tree
omp_clause_info_fndecl (tree t, tree type)
{
tree ret = get_callee_fndecl (t);
if (ret)
return ret;
gcc_assert (TREE_CODE (t) == CALL_EXPR);
t = CALL_EXPR_FN (t);
STRIP_NOPS (t);
if (TREE_CODE (t) == OBJ_TYPE_REF)
{
t = cp_fold_obj_type_ref (t, type);
if (TREE_CODE (t) == ADDR_EXPR
&& TREE_CODE (TREE_OPERAND (t, 0)) == FUNCTION_DECL)
return TREE_OPERAND (t, 0);
}
return NULL_TREE;
}
/* Create CP_OMP_CLAUSE_INFO for clause C. Returns true if it is invalid. */
bool
......@@ -3569,80 +3544,27 @@ cxx_omp_create_clause_info (tree c, tree type, bool need_default_ctor,
info = make_tree_vec (3);
CP_OMP_CLAUSE_INFO (c) = info;
if (need_default_ctor
|| (need_copy_ctor && !TYPE_HAS_TRIVIAL_COPY_CTOR (type)))
if (need_default_ctor || need_copy_ctor)
{
VEC(tree,gc) *vec;
if (need_default_ctor)
vec = NULL;
t = get_default_ctor (type);
else
{
t = build_int_cst (build_pointer_type (type), 0);
t = build1 (INDIRECT_REF, type, t);
vec = make_tree_vector_single (t);
}
t = build_special_member_call (NULL_TREE, complete_ctor_identifier,
&vec, type, LOOKUP_NORMAL,
tf_warning_or_error);
t = get_copy_ctor (type);
if (vec != NULL)
release_tree_vector (vec);
if (targetm.cxx.cdtor_returns_this () || errorcount)
/* Because constructors and destructors return this,
the call will have been cast to "void". Remove the
cast here. We would like to use STRIP_NOPS, but it
wouldn't work here because TYPE_MODE (t) and
TYPE_MODE (TREE_OPERAND (t, 0)) are different.
They are VOIDmode and Pmode, respectively. */
if (TREE_CODE (t) == NOP_EXPR)
t = TREE_OPERAND (t, 0);
TREE_VEC_ELT (info, 0) = get_callee_fndecl (t);
if (t && !trivial_fn_p (t))
TREE_VEC_ELT (info, 0) = t;
}
if ((need_default_ctor || need_copy_ctor)
&& TYPE_HAS_NONTRIVIAL_DESTRUCTOR (type))
{
t = build_int_cst (build_pointer_type (type), 0);
t = build1 (INDIRECT_REF, type, t);
t = build_special_member_call (t, complete_dtor_identifier,
NULL, type, LOOKUP_NORMAL,
tf_warning_or_error);
TREE_VEC_ELT (info, 1) = get_dtor (type);
if (targetm.cxx.cdtor_returns_this () || errorcount)
/* Because constructors and destructors return this,
the call will have been cast to "void". Remove the
cast here. We would like to use STRIP_NOPS, but it
wouldn't work here because TYPE_MODE (t) and
TYPE_MODE (TREE_OPERAND (t, 0)) are different.
They are VOIDmode and Pmode, respectively. */
if (TREE_CODE (t) == NOP_EXPR)
t = TREE_OPERAND (t, 0);
TREE_VEC_ELT (info, 1) = omp_clause_info_fndecl (t, type);
}
if (need_copy_assignment && !TYPE_HAS_TRIVIAL_COPY_ASSIGN (type))
if (need_copy_assignment)
{
VEC(tree,gc) *vec;
t = build_int_cst (build_pointer_type (type), 0);
t = build1 (INDIRECT_REF, type, t);
vec = make_tree_vector_single (t);
t = build_special_member_call (t, ansi_assopname (NOP_EXPR),
&vec, type, LOOKUP_NORMAL,
tf_warning_or_error);
release_tree_vector (vec);
/* We'll have called convert_from_reference on the call, which
may well have added an indirect_ref. It's unneeded here,
and in the way, so kill it. */
if (TREE_CODE (t) == INDIRECT_REF)
t = TREE_OPERAND (t, 0);
t = get_copy_assign (type);
TREE_VEC_ELT (info, 2) = omp_clause_info_fndecl (t, type);
if (t && !trivial_fn_p (t))
TREE_VEC_ELT (info, 2) = t;
}
return errorcount != save_errorcount;
......@@ -5076,7 +4998,7 @@ trait_expr_value (cp_trait_kind kind, tree type1, tree type2)
type1 = strip_array_types (type1);
return (trait_expr_value (CPTK_HAS_TRIVIAL_CONSTRUCTOR, type1, type2)
|| (CLASS_TYPE_P (type1)
&& (t = locate_ctor (type1, NULL))
&& (t = locate_ctor (type1))
&& TYPE_NOTHROW_P (TREE_TYPE (t))));
case CPTK_HAS_TRIVIAL_CONSTRUCTOR:
......
......@@ -2847,7 +2847,12 @@ special_function_p (const_tree decl)
if (DECL_CONSTRUCTOR_P (decl))
return sfk_constructor;
if (DECL_OVERLOADED_OPERATOR_P (decl) == NOP_EXPR)
return sfk_copy_assignment;
{
if (copy_fn_p (decl))
return sfk_copy_assignment;
if (move_fn_p (decl))
return sfk_move_assignment;
}
if (DECL_MAYBE_IN_CHARGE_DESTRUCTOR_P (decl))
return sfk_destructor;
if (DECL_COMPLETE_DESTRUCTOR_P (decl))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment