aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2010-06-29 20:51:44 -0400
committerJason Merrill <jason@gcc.gnu.org>2010-06-29 20:51:44 -0400
commitd758e847c4ce6eda350809463cd87307c7e9c19c (patch)
tree232413e607b8465ed633e240d607739a6cbba07c /gcc/cp
parent54ca9930b79c8f759919fdbe671ff24ce4141b0c (diff)
downloadgcc-d758e847c4ce6eda350809463cd87307c7e9c19c.zip
gcc-d758e847c4ce6eda350809463cd87307c7e9c19c.tar.gz
gcc-d758e847c4ce6eda350809463cd87307c7e9c19c.tar.bz2
Enable implicitly declared move constructor/operator= (N3053).
gcc/cp/ * class.c (add_implicitly_declared_members): A class with no explicitly declared copy or move constructor gets both declared implicitly, and similarly for operator=. (check_bases): A type with no copy ctor does not inhibit a const copy ctor in a derived class. (check_field_decl): Likewise. (check_bases_and_members): A nonexistent copy ctor/op= is non-trivial. * tree.c (type_has_nontrivial_copy_init): Adjust semantics. (trivially_copyable_p): Likewise. * call.c (convert_like_real): Use type_has_nontrivial_copy_init. * class.c (finish_struct_bits): Likewise. * tree.c (build_target_expr_with_type): Likewise. * typeck2.c (store_init_value): Likewise. libstdc++-v3/ * include/bits/unordered_map.h: Explicitly default copy constructors. * include/bits/unordered_set.h: Likewise. From-SVN: r161582
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog16
-rw-r--r--gcc/cp/call.c4
-rw-r--r--gcc/cp/class.c40
-rw-r--r--gcc/cp/tree.c24
-rw-r--r--gcc/cp/typeck2.c2
5 files changed, 62 insertions, 24 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 8c9b424..e0646a1d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,21 @@
2010-06-29 Jason Merrill <jason@redhat.com>
+ Enable implicitly declared move constructor/operator= (N3053).
+ * class.c (add_implicitly_declared_members): A class with no
+ explicitly declared copy or move constructor gets both declared
+ implicitly, and similarly for operator=.
+ (check_bases): A type with no copy ctor does not inhibit
+ a const copy ctor in a derived class. It does mean the derived
+ one is non-trivial.
+ (check_field_decl): Likewise.
+ (check_bases_and_members): A nonexistent copy ctor/op= is non-trivial.
+ * tree.c (type_has_nontrivial_copy_init): Adjust semantics.
+ (trivially_copyable_p): Likewise.
+ * call.c (convert_like_real): Use type_has_nontrivial_copy_init.
+ * class.c (finish_struct_bits): Likewise.
+ * tree.c (build_target_expr_with_type): Likewise.
+ * typeck2.c (store_init_value): Likewise.
+
Enable implicitly deleted functions (N2346)
* class.c (check_bases_and_members): Adjust lambda flags.
* method.c (implicitly_declare_fn): Set DECL_DELETED_FN if appropriate.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 9f4a520..7e632d0 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -5197,7 +5197,7 @@ convert_like_real (conversion *convs, tree expr, tree fn, int argnum,
OK. */
if ((lvalue & clk_packed)
&& CLASS_TYPE_P (type)
- && !TYPE_HAS_TRIVIAL_COPY_CTOR (type))
+ && type_has_nontrivial_copy_init (type))
{
if (complain & tf_error)
error ("cannot bind packed field %qE to %qT",
@@ -5905,7 +5905,7 @@ build_over_call (struct z_candidate *cand, int flags, tsubst_flags_t complain)
if (TREE_CODE (arg) == TARGET_EXPR)
return arg;
else if (trivial)
- return build_target_expr_with_type (arg, DECL_CONTEXT (fn));
+ return force_target_expr (DECL_CONTEXT (fn), arg);
}
else if (TREE_CODE (arg) == TARGET_EXPR || trivial)
{
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 031a4ea..a2ed863 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -1282,7 +1282,8 @@ check_bases (tree t,
assignment operators that take const references, then the
derived class cannot have such a member automatically
generated. */
- if (! TYPE_HAS_CONST_COPY_CTOR (basetype))
+ if (TYPE_HAS_COPY_CTOR (basetype)
+ && ! TYPE_HAS_CONST_COPY_CTOR (basetype))
*cant_have_const_ctor_p = 1;
if (TYPE_HAS_COPY_ASSIGN (basetype)
&& !TYPE_HAS_CONST_COPY_ASSIGN (basetype))
@@ -1312,8 +1313,10 @@ check_bases (tree t,
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|= TYPE_HAS_NONTRIVIAL_DESTRUCTOR (basetype);
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_COPY_ASSIGN (basetype)
+ || !TYPE_HAS_COPY_ASSIGN (basetype));
+ TYPE_HAS_COMPLEX_COPY_CTOR (t) |= (TYPE_HAS_COMPLEX_COPY_CTOR (basetype)
+ || !TYPE_HAS_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);
@@ -1545,7 +1548,8 @@ finish_struct_bits (tree t)
mode to be BLKmode, and force its TREE_ADDRESSABLE bit to be
nonzero. This will cause it to be passed by invisible reference
and prevent it from being returned in a register. */
- if (! TYPE_HAS_TRIVIAL_COPY_CTOR (t) || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
+ if (type_has_nontrivial_copy_init (t)
+ || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t))
{
tree variants;
DECL_MODE (TYPE_MAIN_DECL (t)) = BLKmode;
@@ -2647,27 +2651,28 @@ add_implicitly_declared_members (tree t,
If a class definition does not explicitly declare a copy
constructor, one is declared implicitly. */
- if (! TYPE_HAS_COPY_CTOR (t) && ! TYPE_FOR_JAVA (t))
+ if (! TYPE_HAS_COPY_CTOR (t) && ! TYPE_FOR_JAVA (t)
+ && !type_has_move_constructor (t))
{
TYPE_HAS_COPY_CTOR (t) = 1;
TYPE_HAS_CONST_COPY_CTOR (t) = !cant_have_const_cctor;
CLASSTYPE_LAZY_COPY_CTOR (t) = 1;
+ if (cxx_dialect >= cxx0x)
+ CLASSTYPE_LAZY_MOVE_CTOR (t) = 1;
}
- /* Currently only lambdas get a lazy move ctor, but N3053 adds them for
- other classes. */
- if (LAMBDA_TYPE_P (t))
- CLASSTYPE_LAZY_MOVE_CTOR (t) = 1;
-
/* If there is no assignment operator, one will be created if and
when it is needed. For now, just record whether or not the type
of the parameter to the assignment operator will be a const or
non-const reference. */
- if (!TYPE_HAS_COPY_ASSIGN (t) && !TYPE_FOR_JAVA (t))
+ if (!TYPE_HAS_COPY_ASSIGN (t) && !TYPE_FOR_JAVA (t)
+ && !type_has_move_assign (t))
{
TYPE_HAS_COPY_ASSIGN (t) = 1;
TYPE_HAS_CONST_COPY_ASSIGN (t) = !cant_have_const_assignment;
CLASSTYPE_LAZY_COPY_ASSIGN (t) = 1;
+ if (cxx_dialect >= cxx0x)
+ CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 1;
}
/* We can't be lazy about declaring functions that might override
@@ -2863,18 +2868,23 @@ check_field_decl (tree field,
TYPE_NEEDS_CONSTRUCTING (t) |= TYPE_NEEDS_CONSTRUCTING (type);
TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)
|= 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_COPY_ASSIGN (t)
+ |= (TYPE_HAS_COMPLEX_COPY_ASSIGN (type)
+ || !TYPE_HAS_COPY_ASSIGN (type));
+ TYPE_HAS_COMPLEX_COPY_CTOR (t) |= (TYPE_HAS_COMPLEX_COPY_CTOR (type)
+ || !TYPE_HAS_COPY_CTOR (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))
+ if (TYPE_HAS_COPY_CTOR (type)
+ && !TYPE_HAS_CONST_COPY_CTOR (type))
*cant_have_const_ctor = 1;
- if (!TYPE_HAS_CONST_COPY_ASSIGN (type))
+ if (TYPE_HAS_COPY_ASSIGN (type)
+ && !TYPE_HAS_CONST_COPY_ASSIGN (type))
*no_const_asn_ref = 1;
}
if (DECL_INITIAL (field) != NULL_TREE)
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 3367a09..6d1ff10 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -479,7 +479,7 @@ build_target_expr_with_type (tree init, tree type)
if (TREE_CODE (init) == TARGET_EXPR)
return init;
- else if (CLASS_TYPE_P (type) && !TYPE_HAS_TRIVIAL_COPY_CTOR (type)
+ else if (CLASS_TYPE_P (type) && type_has_nontrivial_copy_init (type)
&& !VOID_TYPE_P (TREE_TYPE (init))
&& TREE_CODE (init) != COND_EXPR
&& TREE_CODE (init) != CONSTRUCTOR
@@ -497,7 +497,8 @@ build_target_expr_with_type (tree init, tree type)
/* Like the above function, but without the checking. This function should
only be used by code which is deliberately trying to subvert the type
- system, such as call_builtin_trap. */
+ system, such as call_builtin_trap. Or build_over_call, to avoid
+ infinite recursion. */
tree
force_target_expr (tree type, tree init)
@@ -2368,7 +2369,9 @@ type_has_nontrivial_default_init (const_tree t)
return 0;
}
-/* Returns true iff copying an object of type T is non-trivial. */
+/* Returns true iff copying an object of type T (including via move
+ constructor) is non-trivial. That is, T has no non-trivial copy
+ constructors and no non-trivial move constructors. */
bool
type_has_nontrivial_copy_init (const_tree t)
@@ -2376,7 +2379,12 @@ type_has_nontrivial_copy_init (const_tree t)
t = strip_array_types (CONST_CAST_TREE (t));
if (CLASS_TYPE_P (t))
- return TYPE_HAS_COMPLEX_COPY_CTOR (t);
+ {
+ gcc_assert (COMPLETE_TYPE_P (t));
+ return ((TYPE_HAS_COPY_CTOR (t)
+ && TYPE_HAS_COMPLEX_COPY_CTOR (t))
+ || TYPE_HAS_COMPLEX_MOVE_CTOR (t));
+ }
else
return 0;
}
@@ -2390,8 +2398,12 @@ trivially_copyable_p (const_tree t)
t = strip_array_types (CONST_CAST_TREE (t));
if (CLASS_TYPE_P (t))
- return (TYPE_HAS_TRIVIAL_COPY_CTOR (t)
- && TYPE_HAS_TRIVIAL_COPY_ASSIGN (t)
+ return ((!TYPE_HAS_COPY_CTOR (t)
+ || !TYPE_HAS_COMPLEX_COPY_CTOR (t))
+ && !TYPE_HAS_COMPLEX_MOVE_CTOR (t)
+ && (!TYPE_HAS_COPY_ASSIGN (t)
+ || !TYPE_HAS_COMPLEX_COPY_ASSIGN (t))
+ && !TYPE_HAS_COMPLEX_MOVE_ASSIGN (t)
&& TYPE_HAS_TRIVIAL_DESTRUCTOR (t));
else
return scalarish_type_p (t);
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index c8dae54..f62bbb5 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -714,7 +714,7 @@ store_init_value (tree decl, tree init, int flags)
if (MAYBE_CLASS_TYPE_P (type))
{
- gcc_assert (TYPE_HAS_TRIVIAL_COPY_CTOR (type)
+ gcc_assert (!type_has_nontrivial_copy_init (type)
|| TREE_CODE (init) == CONSTRUCTOR);
if (TREE_CODE (init) == TREE_LIST)