Commit 32bfcf80 by Jason Merrill Committed by Jason Merrill

re PR c++/57319 (bogus "defaulted move assignment for ... calls a non-trivial…

re PR c++/57319 (bogus "defaulted move assignment for ... calls a non-trivial move assignment operator for virtual base ...")

	PR c++/57319
	* class.c (vbase_has_user_provided_move_assign): New.
	* method.c (synthesized_method_walk): Check it.
	* cp-tree.h: Declare it.

From-SVN: r199114
parent 9f0bdc93
2013-05-20 Jason Merrill <jason@redhat.com> 2013-05-20 Jason Merrill <jason@redhat.com>
PR c++/57319
* class.c (vbase_has_user_provided_move_assign): New.
* method.c (synthesized_method_walk): Check it.
* cp-tree.h: Declare it.
PR c++/57325 PR c++/57325
* tree.c (build_cplus_array_type): Copy layout info if element * tree.c (build_cplus_array_type): Copy layout info if element
type is complete. type is complete.
......
...@@ -4831,6 +4831,44 @@ type_has_user_provided_default_constructor (tree t) ...@@ -4831,6 +4831,44 @@ type_has_user_provided_default_constructor (tree t)
return false; return false;
} }
/* TYPE is being used as a virtual base, and has a non-trivial move
assignment. Return true if this is due to there being a user-provided
move assignment in TYPE or one of its subobjects; if there isn't, then
multiple move assignment can't cause any harm. */
bool
vbase_has_user_provided_move_assign (tree type)
{
/* Does the type itself have a user-provided move assignment operator? */
for (tree fns
= lookup_fnfields_slot_nolazy (type, ansi_assopname (NOP_EXPR));
fns; fns = OVL_NEXT (fns))
{
tree fn = OVL_CURRENT (fns);
if (move_fn_p (fn) && user_provided_p (fn))
return true;
}
/* Do any of its bases? */
tree binfo = TYPE_BINFO (type);
tree base_binfo;
for (int i = 0; BINFO_BASE_ITERATE (binfo, i, base_binfo); ++i)
if (vbase_has_user_provided_move_assign (BINFO_TYPE (base_binfo)))
return true;
/* Or non-static data members? */
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
{
if (TREE_CODE (field) == FIELD_DECL
&& CLASS_TYPE_P (TREE_TYPE (field))
&& vbase_has_user_provided_move_assign (TREE_TYPE (field)))
return true;
}
/* Seems not. */
return false;
}
/* If default-initialization leaves part of TYPE uninitialized, returns /* If default-initialization leaves part of TYPE uninitialized, returns
a DECL for the field or TYPE itself (DR 253). */ a DECL for the field or TYPE itself (DR 253). */
......
...@@ -5090,6 +5090,7 @@ extern tree in_class_defaulted_default_constructor (tree); ...@@ -5090,6 +5090,7 @@ extern tree in_class_defaulted_default_constructor (tree);
extern bool user_provided_p (tree); extern bool user_provided_p (tree);
extern bool type_has_user_provided_constructor (tree); extern bool type_has_user_provided_constructor (tree);
extern bool type_has_user_provided_default_constructor (tree); extern bool type_has_user_provided_default_constructor (tree);
extern bool vbase_has_user_provided_move_assign (tree);
extern tree default_init_uninitialized_part (tree); extern tree default_init_uninitialized_part (tree);
extern bool trivial_default_constructor_is_constexpr (tree); extern bool trivial_default_constructor_is_constexpr (tree);
extern bool type_has_constexpr_default_constructor (tree); extern bool type_has_constexpr_default_constructor (tree);
......
...@@ -1353,7 +1353,8 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, ...@@ -1353,7 +1353,8 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
if (diag && assign_p && move_p if (diag && assign_p && move_p
&& BINFO_VIRTUAL_P (base_binfo) && BINFO_VIRTUAL_P (base_binfo)
&& rval && TREE_CODE (rval) == FUNCTION_DECL && rval && TREE_CODE (rval) == FUNCTION_DECL
&& move_fn_p (rval) && !trivial_fn_p (rval)) && move_fn_p (rval) && !trivial_fn_p (rval)
&& vbase_has_user_provided_move_assign (basetype))
warning (OPT_Wvirtual_move_assign, warning (OPT_Wvirtual_move_assign,
"defaulted move assignment for %qT calls a non-trivial " "defaulted move assignment for %qT calls a non-trivial "
"move assignment operator for virtual base %qT", "move assignment operator for virtual base %qT",
......
// PR c++/57319
// { dg-require-effective-target c++11 }
namespace N1 {
struct A { };
struct B: virtual A { };
struct C: virtual B { };
struct D: C
{
void operator= (D &);
};
}
namespace N2 {
struct A { A& operator=(A&&); };
struct B: virtual A { }; // { dg-warning "move assignment" }
struct C: virtual B { }; // { dg-warning "move assignment" }
struct D: C
{
void operator= (D &);
};
}
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