re PR c++/66501 (Default move assignment does not move array members)
PR c++/66501 * class.c (type_has_nontrivial_assignment): New. * init.c (build_vec_init): Use it. * cp-tree.h: Declare it. * method.c (trivial_fn_p): Templates aren't trivial. From-SVN: r224843
This commit is contained in:
parent
d4c9e7f922
commit
115ef7c52e
|
@ -1,5 +1,11 @@
|
|||
2015-06-23 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/66501
|
||||
* class.c (type_has_nontrivial_assignment): New.
|
||||
* init.c (build_vec_init): Use it.
|
||||
* cp-tree.h: Declare it.
|
||||
* method.c (trivial_fn_p): Templates aren't trivial.
|
||||
|
||||
PR c++/66542
|
||||
* decl.c (expand_static_init): Make sure the destructor is callable
|
||||
here even if we have an initializer.
|
||||
|
|
|
@ -5136,6 +5136,24 @@ type_has_non_user_provided_default_constructor (tree t)
|
|||
return false;
|
||||
}
|
||||
|
||||
/* Return true if TYPE has some non-trivial assignment operator. */
|
||||
|
||||
bool
|
||||
type_has_nontrivial_assignment (tree type)
|
||||
{
|
||||
gcc_assert (TREE_CODE (type) != ARRAY_TYPE);
|
||||
if (CLASS_TYPE_P (type))
|
||||
for (tree fns
|
||||
= lookup_fnfields_slot_nolazy (type, ansi_assopname (NOP_EXPR));
|
||||
fns; fns = OVL_NEXT (fns))
|
||||
{
|
||||
tree fn = OVL_CURRENT (fns);
|
||||
if (!trivial_fn_p (fn))
|
||||
return true;
|
||||
}
|
||||
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
|
||||
|
|
|
@ -5295,6 +5295,7 @@ extern tree in_class_defaulted_default_constructor (tree);
|
|||
extern bool user_provided_p (tree);
|
||||
extern bool type_has_user_provided_constructor (tree);
|
||||
extern bool type_has_non_user_provided_default_constructor (tree);
|
||||
extern bool type_has_nontrivial_assignment (tree);
|
||||
extern bool vbase_has_user_provided_move_assign (tree);
|
||||
extern tree default_init_uninitialized_part (tree);
|
||||
extern bool trivial_default_constructor_is_constexpr (tree);
|
||||
|
|
|
@ -3460,8 +3460,7 @@ build_vec_init (tree base, tree maxindex, tree init,
|
|||
&& TREE_CODE (atype) == ARRAY_TYPE
|
||||
&& TREE_CONSTANT (maxindex)
|
||||
&& (from_array == 2
|
||||
? (!CLASS_TYPE_P (inner_elt_type)
|
||||
|| !TYPE_HAS_COMPLEX_COPY_ASSIGN (inner_elt_type))
|
||||
? !type_has_nontrivial_assignment (inner_elt_type)
|
||||
: !TYPE_NEEDS_CONSTRUCTING (type))
|
||||
&& ((TREE_CODE (init) == CONSTRUCTOR
|
||||
/* Don't do this if the CONSTRUCTOR might contain something
|
||||
|
|
|
@ -476,6 +476,8 @@ type_set_nontrivial_flag (tree ctype, special_function_kind sfk)
|
|||
bool
|
||||
trivial_fn_p (tree fn)
|
||||
{
|
||||
if (TREE_CODE (fn) == TEMPLATE_DECL)
|
||||
return false;
|
||||
if (!DECL_DEFAULTED_FN (fn))
|
||||
return false;
|
||||
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
// PR c++/66501
|
||||
// { dg-do run { target c++11 } }
|
||||
|
||||
int total_size;
|
||||
|
||||
struct Object
|
||||
{
|
||||
int size = 0;
|
||||
|
||||
Object () = default;
|
||||
|
||||
~Object () {
|
||||
total_size -= size;
|
||||
}
|
||||
|
||||
Object (const Object &) = delete;
|
||||
Object & operator= (const Object &) = delete;
|
||||
|
||||
Object (Object && b) {
|
||||
size = b.size;
|
||||
b.size = 0;
|
||||
}
|
||||
|
||||
Object & operator= (Object && b) {
|
||||
if (this != & b) {
|
||||
total_size -= size;
|
||||
size = b.size;
|
||||
b.size = 0;
|
||||
}
|
||||
return * this;
|
||||
}
|
||||
|
||||
void grow () {
|
||||
size ++;
|
||||
total_size ++;
|
||||
}
|
||||
};
|
||||
|
||||
struct Container {
|
||||
Object objects[2];
|
||||
};
|
||||
|
||||
int main (void)
|
||||
{
|
||||
Container container;
|
||||
|
||||
// grow some objects in the container
|
||||
for (auto & object : container.objects)
|
||||
object.grow ();
|
||||
|
||||
// now empty it
|
||||
container = Container ();
|
||||
|
||||
return total_size;
|
||||
}
|
Loading…
Reference in New Issue