Commit 7487bca5 by Jason Merrill Committed by Jason Merrill

re PR c++/44909 ([C++0x] Copy constructors implicitly deleted)

	PR c++/44909
	* cp-tree.h (struct lang_type_class): Add has_user_opeq.
	(TYPE_HAS_USER_OPEQ): New.
	* decl.c (grok_special_member_properties): Set it.
	* class.c (add_implicitly_declared_members): Don't lazily declare
	constructors/operator= if a base or member has a user-declared one.
	(check_bases_and_members, check_bases): Adjust.
	(check_field_decls, check_field_decl): Adjust.
	* method.c (synthesized_method_walk): Initialize check_vdtor.

From-SVN: r162159
parent 8caa8b65
2010-07-13 Jason Merrill <jason@redhat.com> 2010-07-13 Jason Merrill <jason@redhat.com>
PR c++/44909
* cp-tree.h (struct lang_type_class): Add has_user_opeq.
(TYPE_HAS_USER_OPEQ): New.
* decl.c (grok_special_member_properties): Set it.
* class.c (add_implicitly_declared_members): Don't lazily declare
constructors/operator= if a base or member has a user-declared one.
(check_bases_and_members, check_bases): Adjust.
(check_field_decls, check_field_decl): Adjust.
* method.c (synthesized_method_walk): Initialize check_vdtor.
PR c++/44540 PR c++/44540
* mangle.c (write_type): Canonicalize. * mangle.c (write_type): Canonicalize.
(canonicalize_for_substitution): Retain cv-quals on FUNCTION_TYPE. (canonicalize_for_substitution): Retain cv-quals on FUNCTION_TYPE.
......
...@@ -130,7 +130,7 @@ static void finish_struct_methods (tree); ...@@ -130,7 +130,7 @@ static void finish_struct_methods (tree);
static void maybe_warn_about_overly_private_class (tree); static void maybe_warn_about_overly_private_class (tree);
static int method_name_cmp (const void *, const void *); static int method_name_cmp (const void *, const void *);
static int resort_method_name_cmp (const void *, const void *); static int resort_method_name_cmp (const void *, const void *);
static void add_implicitly_declared_members (tree, int, int); static void add_implicitly_declared_members (tree, int, int, int, int);
static tree fixed_type_or_null (tree, int *, int *); static tree fixed_type_or_null (tree, int *, int *);
static tree build_simple_base_path (tree expr, tree binfo); static tree build_simple_base_path (tree expr, tree binfo);
static tree build_vtbl_ref_1 (tree, tree); static tree build_vtbl_ref_1 (tree, tree);
...@@ -139,13 +139,13 @@ static void build_vtbl_initializer (tree, tree, tree, tree, int *, ...@@ -139,13 +139,13 @@ static void build_vtbl_initializer (tree, tree, tree, tree, int *,
static int count_fields (tree); static int count_fields (tree);
static int add_fields_to_record_type (tree, struct sorted_fields_type*, int); static int add_fields_to_record_type (tree, struct sorted_fields_type*, int);
static bool check_bitfield_decl (tree); static bool check_bitfield_decl (tree);
static void check_field_decl (tree, tree, int *, int *, int *); static void check_field_decl (tree, tree, int *, int *, int *, int *, int *);
static void check_field_decls (tree, tree *, int *, int *); static void check_field_decls (tree, tree *, int *, int *, int *, int *);
static tree *build_base_field (record_layout_info, tree, splay_tree, tree *); static tree *build_base_field (record_layout_info, tree, splay_tree, tree *);
static void build_base_fields (record_layout_info, splay_tree, tree *); static void build_base_fields (record_layout_info, splay_tree, tree *);
static void check_methods (tree); static void check_methods (tree);
static void remove_zero_width_bit_fields (tree); static void remove_zero_width_bit_fields (tree);
static void check_bases (tree, int *, int *); static void check_bases (tree, int *, int *, int *, int *);
static void check_bases_and_members (tree); static void check_bases_and_members (tree);
static tree create_vtable_ptr (tree, tree *); static tree create_vtable_ptr (tree, tree *);
static void include_empty_classes (record_layout_info); static void include_empty_classes (record_layout_info);
...@@ -1249,7 +1249,9 @@ handle_using_decl (tree using_decl, tree t) ...@@ -1249,7 +1249,9 @@ handle_using_decl (tree using_decl, tree t)
static void static void
check_bases (tree t, check_bases (tree t,
int* cant_have_const_ctor_p, int* cant_have_const_ctor_p,
int* no_const_asn_ref_p) int* no_const_asn_ref_p,
int* cant_have_lazy_ctor,
int* cant_have_lazy_opeq)
{ {
int i; int i;
int seen_non_virtual_nearly_empty_base_p; int seen_non_virtual_nearly_empty_base_p;
...@@ -1288,6 +1290,10 @@ check_bases (tree t, ...@@ -1288,6 +1290,10 @@ check_bases (tree t,
if (TYPE_HAS_COPY_ASSIGN (basetype) if (TYPE_HAS_COPY_ASSIGN (basetype)
&& !TYPE_HAS_CONST_COPY_ASSIGN (basetype)) && !TYPE_HAS_CONST_COPY_ASSIGN (basetype))
*no_const_asn_ref_p = 1; *no_const_asn_ref_p = 1;
if (TYPE_HAS_USER_CONSTRUCTOR (basetype))
*cant_have_lazy_ctor = 1;
if (TYPE_HAS_USER_OPEQ (basetype))
*cant_have_lazy_opeq = 1;
if (BINFO_VIRTUAL_P (base_binfo)) if (BINFO_VIRTUAL_P (base_binfo))
/* A virtual base does not effect nearly emptiness. */ /* A virtual base does not effect nearly emptiness. */
...@@ -2628,7 +2634,9 @@ maybe_add_class_template_decl_list (tree type, tree t, int friend_p) ...@@ -2628,7 +2634,9 @@ maybe_add_class_template_decl_list (tree type, tree t, int friend_p)
static void static void
add_implicitly_declared_members (tree t, add_implicitly_declared_members (tree t,
int cant_have_const_cctor, int cant_have_const_cctor,
int cant_have_const_assignment) int cant_have_const_assignment,
int cant_have_lazy_ctor,
int cant_have_lazy_opeq)
{ {
/* Destructor. */ /* Destructor. */
if (!CLASSTYPE_DESTRUCTORS (t)) if (!CLASSTYPE_DESTRUCTORS (t))
...@@ -2682,6 +2690,26 @@ add_implicitly_declared_members (tree t, ...@@ -2682,6 +2690,26 @@ add_implicitly_declared_members (tree t,
CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 1; CLASSTYPE_LAZY_MOVE_ASSIGN (t) = 1;
} }
/* If a base or member type has a user-declared constructor or operator=,
we need to declare ours now to avoid issues with circular lazy
declarations (cpp0x/implicit6.C). */
if (cant_have_lazy_ctor)
{
if (CLASSTYPE_LAZY_DEFAULT_CTOR (t))
lazily_declare_fn (sfk_constructor, t);
if (CLASSTYPE_LAZY_COPY_CTOR (t))
lazily_declare_fn (sfk_copy_constructor, t);
if (CLASSTYPE_LAZY_MOVE_CTOR (t))
lazily_declare_fn (sfk_move_constructor, t);
}
if (cant_have_lazy_opeq)
{
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);
}
/* We can't be lazy about declaring functions that might override /* We can't be lazy about declaring functions that might override
a virtual function from a base class. */ a virtual function from a base class. */
if (TYPE_POLYMORPHIC_P (t) if (TYPE_POLYMORPHIC_P (t)
...@@ -2830,7 +2858,9 @@ check_field_decl (tree field, ...@@ -2830,7 +2858,9 @@ check_field_decl (tree field,
tree t, tree t,
int* cant_have_const_ctor, int* cant_have_const_ctor,
int* no_const_asn_ref, int* no_const_asn_ref,
int* any_default_members) int* any_default_members,
int* cant_have_lazy_ctor,
int* cant_have_lazy_opeq)
{ {
tree type = strip_array_types (TREE_TYPE (field)); tree type = strip_array_types (TREE_TYPE (field));
...@@ -2847,7 +2877,8 @@ check_field_decl (tree field, ...@@ -2847,7 +2877,8 @@ check_field_decl (tree field,
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields)) for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field)) if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field))
check_field_decl (fields, t, cant_have_const_ctor, check_field_decl (fields, t, cant_have_const_ctor,
no_const_asn_ref, any_default_members); no_const_asn_ref, any_default_members,
cant_have_lazy_ctor, cant_have_lazy_opeq);
} }
/* Check members with class type for constructors, destructors, /* Check members with class type for constructors, destructors,
etc. */ etc. */
...@@ -2893,6 +2924,11 @@ check_field_decl (tree field, ...@@ -2893,6 +2924,11 @@ check_field_decl (tree field,
if (TYPE_HAS_COPY_ASSIGN (type) if (TYPE_HAS_COPY_ASSIGN (type)
&& !TYPE_HAS_CONST_COPY_ASSIGN (type)) && !TYPE_HAS_CONST_COPY_ASSIGN (type))
*no_const_asn_ref = 1; *no_const_asn_ref = 1;
if (TYPE_HAS_USER_CONSTRUCTOR (type))
*cant_have_lazy_ctor = 1;
if (TYPE_HAS_USER_OPEQ (type))
*cant_have_lazy_opeq = 1;
} }
if (DECL_INITIAL (field) != NULL_TREE) if (DECL_INITIAL (field) != NULL_TREE)
{ {
...@@ -2932,7 +2968,9 @@ check_field_decl (tree field, ...@@ -2932,7 +2968,9 @@ check_field_decl (tree field,
static void static void
check_field_decls (tree t, tree *access_decls, check_field_decls (tree t, tree *access_decls,
int *cant_have_const_ctor_p, int *cant_have_const_ctor_p,
int *no_const_asn_ref_p) int *no_const_asn_ref_p,
int *cant_have_lazy_ctor_p,
int *cant_have_lazy_opeq_p)
{ {
tree *field; tree *field;
tree *next; tree *next;
...@@ -3124,7 +3162,9 @@ check_field_decls (tree t, tree *access_decls, ...@@ -3124,7 +3162,9 @@ check_field_decls (tree t, tree *access_decls,
check_field_decl (x, t, check_field_decl (x, t,
cant_have_const_ctor_p, cant_have_const_ctor_p,
no_const_asn_ref_p, no_const_asn_ref_p,
&any_default_members); &any_default_members,
cant_have_lazy_ctor_p,
cant_have_lazy_opeq_p);
/* If any field is const, the structure type is pseudo-const. */ /* If any field is const, the structure type is pseudo-const. */
if (CP_TYPE_CONST_P (type)) if (CP_TYPE_CONST_P (type))
...@@ -4447,6 +4487,8 @@ check_bases_and_members (tree t) ...@@ -4447,6 +4487,8 @@ check_bases_and_members (tree t)
/* Nonzero if the implicitly generated assignment operator /* Nonzero if the implicitly generated assignment operator
should take a non-const reference argument. */ should take a non-const reference argument. */
int no_const_asn_ref; int no_const_asn_ref;
int cant_have_lazy_ctor = 0;
int cant_have_lazy_opeq = 0;
tree access_decls; tree access_decls;
bool saved_complex_asn_ref; bool saved_complex_asn_ref;
bool saved_nontrivial_dtor; bool saved_nontrivial_dtor;
...@@ -4459,7 +4501,8 @@ check_bases_and_members (tree t) ...@@ -4459,7 +4501,8 @@ check_bases_and_members (tree t)
/* Check all the base-classes. */ /* Check all the base-classes. */
check_bases (t, &cant_have_const_ctor, check_bases (t, &cant_have_const_ctor,
&no_const_asn_ref); &no_const_asn_ref, &cant_have_lazy_ctor,
&cant_have_lazy_opeq);
/* Check all the method declarations. */ /* Check all the method declarations. */
check_methods (t); check_methods (t);
...@@ -4476,7 +4519,9 @@ check_bases_and_members (tree t) ...@@ -4476,7 +4519,9 @@ check_bases_and_members (tree t)
being set appropriately. */ being set appropriately. */
check_field_decls (t, &access_decls, check_field_decls (t, &access_decls,
&cant_have_const_ctor, &cant_have_const_ctor,
&no_const_asn_ref); &no_const_asn_ref,
&cant_have_lazy_ctor,
&cant_have_lazy_opeq);
/* A nearly-empty class has to be vptr-containing; a nearly empty /* A nearly-empty class has to be vptr-containing; a nearly empty
class contains just a vptr. */ class contains just a vptr. */
...@@ -4548,7 +4593,9 @@ check_bases_and_members (tree t) ...@@ -4548,7 +4593,9 @@ check_bases_and_members (tree t)
/* Synthesize any needed methods. */ /* Synthesize any needed methods. */
add_implicitly_declared_members (t, add_implicitly_declared_members (t,
cant_have_const_ctor, cant_have_const_ctor,
no_const_asn_ref); no_const_asn_ref,
cant_have_lazy_ctor,
cant_have_lazy_opeq);
/* Check defaulted declarations here so we have cant_have_const_ctor /* Check defaulted declarations here so we have cant_have_const_ctor
and don't need to worry about clones. */ and don't need to worry about clones. */
......
...@@ -1326,6 +1326,7 @@ struct GTY(()) lang_type_class { ...@@ -1326,6 +1326,7 @@ struct GTY(()) lang_type_class {
unsigned lazy_move_assign : 1; unsigned lazy_move_assign : 1;
unsigned has_complex_move_ctor : 1; unsigned has_complex_move_ctor : 1;
unsigned has_complex_move_assign : 1; unsigned has_complex_move_assign : 1;
unsigned has_user_opeq : 1;
/* When adding a flag here, consider whether or not it ought to /* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If apply to a template instance if it applies to the template. If
...@@ -1334,7 +1335,7 @@ struct GTY(()) lang_type_class { ...@@ -1334,7 +1335,7 @@ struct GTY(()) lang_type_class {
/* There are some bits left to fill out a 32-bit word. Keep track /* 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 of this by updating the size of this bitfield whenever you add or
remove a flag. */ remove a flag. */
unsigned dummy : 4; unsigned dummy : 3;
tree primary_base; tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices; VEC(tree_pair_s,gc) *vcall_indices;
...@@ -3142,6 +3143,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter) ...@@ -3142,6 +3143,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
user-declared constructor. */ user-declared constructor. */
#define TYPE_HAS_USER_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1 (NODE)) #define TYPE_HAS_USER_CONSTRUCTOR(NODE) (TYPE_LANG_FLAG_1 (NODE))
/* ...or a user-declared operator=. */
#define TYPE_HAS_USER_OPEQ(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->has_user_opeq)
/* When appearing in an INDIRECT_REF, it means that the tree structure /* When appearing in an INDIRECT_REF, it means that the tree structure
underneath is actually a call to a constructor. This is needed underneath is actually a call to a constructor. This is needed
when the constructor must initialize local storage (which can when the constructor must initialize local storage (which can
......
...@@ -10293,6 +10293,8 @@ grok_special_member_properties (tree decl) ...@@ -10293,6 +10293,8 @@ grok_special_member_properties (tree decl)
int assop = copy_fn_p (decl); int assop = copy_fn_p (decl);
if (!DECL_ARTIFICIAL (decl))
TYPE_HAS_USER_OPEQ (class_type) = 1;
if (assop) if (assop)
{ {
TYPE_HAS_COPY_ASSIGN (class_type) = 1; TYPE_HAS_COPY_ASSIGN (class_type) = 1;
......
...@@ -1004,6 +1004,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p, ...@@ -1004,6 +1004,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
#endif #endif
assign_p = false; assign_p = false;
check_vdtor = false;
switch (sfk) switch (sfk)
{ {
case sfk_move_assignment: case sfk_move_assignment:
......
2010-07-13 Jason Merrill <jason@redhat.com> 2010-07-13 Jason Merrill <jason@redhat.com>
PR c++/44909
* g++.dg/cpp0x/implicit6.C: New.
2010-07-13 Jason Merrill <jason@redhat.com>
PR c++/44540 PR c++/44540
* g++.dg/abi/noreturn1.C: New. * g++.dg/abi/noreturn1.C: New.
* g++.dg/abi/noreturn2.C: New. * g++.dg/abi/noreturn2.C: New.
......
// Circular implicit declarations were causing errors
// { dg-options -std=c++0x }
struct Ray;
struct Vector
{
virtual void f(); // make non-trivially-copyable
Vector();
Vector(const Ray &) ;
};
struct array
{
Vector v;
};
struct Ray
{
array a;
operator Vector();
};
extern Ray r1;
Ray r2=r1;
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
struct virt { virt () {} virt (int i) {} }; struct virt { virt () {} virt (int i) {} };
struct der : public virtual virt { // { dg-message "8:der::der" } struct der : public virtual virt { // { dg-message "8:der::der" }
der (int i) : virt(i) {} // { dg-message "3:candidates are: der" } der (int i) : virt(i) {} // { dg-message "3:der::der" }
}; };
struct top : public der { struct top : public der {
top () {} // { dg-bogus "der\\(const" } top () {} // { dg-bogus "der\\(const" }
......
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