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.
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
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);
&& 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
bool
trivial_fn_p (tree fn)
{
+ if (TREE_CODE (fn) == TEMPLATE_DECL)
+ return false;
if (!DECL_DEFAULTED_FN (fn))
return false;
--- /dev/null
+// 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;
+}