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
This commit is contained in:
Jason Merrill 2010-07-13 18:23:49 -04:00 committed by Jason Merrill
parent 8caa8b6590
commit 7487bca5bb
8 changed files with 110 additions and 15 deletions

View File

@ -1,5 +1,15 @@
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
* mangle.c (write_type): Canonicalize.
(canonicalize_for_substitution): Retain cv-quals on FUNCTION_TYPE.

View File

@ -130,7 +130,7 @@ static void finish_struct_methods (tree);
static void maybe_warn_about_overly_private_class (tree);
static int 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 build_simple_base_path (tree expr, tree binfo);
static tree build_vtbl_ref_1 (tree, tree);
@ -139,13 +139,13 @@ static void build_vtbl_initializer (tree, tree, tree, tree, int *,
static int count_fields (tree);
static int add_fields_to_record_type (tree, struct sorted_fields_type*, int);
static bool check_bitfield_decl (tree);
static void check_field_decl (tree, tree, int *, int *, int *);
static void check_field_decls (tree, tree *, int *, int *);
static void check_field_decl (tree, tree, int *, int *, int *, 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 void build_base_fields (record_layout_info, splay_tree, tree *);
static void check_methods (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 tree create_vtable_ptr (tree, tree *);
static void include_empty_classes (record_layout_info);
@ -1249,7 +1249,9 @@ handle_using_decl (tree using_decl, tree t)
static void
check_bases (tree t,
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 seen_non_virtual_nearly_empty_base_p;
@ -1288,6 +1290,10 @@ check_bases (tree t,
if (TYPE_HAS_COPY_ASSIGN (basetype)
&& !TYPE_HAS_CONST_COPY_ASSIGN (basetype))
*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))
/* 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)
static void
add_implicitly_declared_members (tree t,
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. */
if (!CLASSTYPE_DESTRUCTORS (t))
@ -2682,6 +2690,26 @@ add_implicitly_declared_members (tree t,
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
a virtual function from a base class. */
if (TYPE_POLYMORPHIC_P (t)
@ -2830,7 +2858,9 @@ check_field_decl (tree field,
tree t,
int* cant_have_const_ctor,
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));
@ -2847,7 +2877,8 @@ check_field_decl (tree field,
for (fields = TYPE_FIELDS (type); fields; fields = TREE_CHAIN (fields))
if (TREE_CODE (fields) == FIELD_DECL && !DECL_C_BIT_FIELD (field))
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,
etc. */
@ -2893,6 +2924,11 @@ check_field_decl (tree field,
if (TYPE_HAS_COPY_ASSIGN (type)
&& !TYPE_HAS_CONST_COPY_ASSIGN (type))
*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)
{
@ -2932,7 +2968,9 @@ check_field_decl (tree field,
static void
check_field_decls (tree t, tree *access_decls,
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 *next;
@ -3124,7 +3162,9 @@ check_field_decls (tree t, tree *access_decls,
check_field_decl (x, t,
cant_have_const_ctor_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 (CP_TYPE_CONST_P (type))
@ -4447,6 +4487,8 @@ check_bases_and_members (tree t)
/* Nonzero if the implicitly generated assignment operator
should take a non-const reference argument. */
int no_const_asn_ref;
int cant_have_lazy_ctor = 0;
int cant_have_lazy_opeq = 0;
tree access_decls;
bool saved_complex_asn_ref;
bool saved_nontrivial_dtor;
@ -4459,7 +4501,8 @@ check_bases_and_members (tree t)
/* Check all the base-classes. */
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_methods (t);
@ -4476,7 +4519,9 @@ check_bases_and_members (tree t)
being set appropriately. */
check_field_decls (t, &access_decls,
&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
class contains just a vptr. */
@ -4548,7 +4593,9 @@ check_bases_and_members (tree t)
/* Synthesize any needed methods. */
add_implicitly_declared_members (t,
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
and don't need to worry about clones. */

View File

@ -1326,6 +1326,7 @@ struct GTY(()) lang_type_class {
unsigned lazy_move_assign : 1;
unsigned has_complex_move_ctor : 1;
unsigned has_complex_move_assign : 1;
unsigned has_user_opeq : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
@ -1334,7 +1335,7 @@ struct GTY(()) lang_type_class {
/* 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
remove a flag. */
unsigned dummy : 4;
unsigned dummy : 3;
tree primary_base;
VEC(tree_pair_s,gc) *vcall_indices;
@ -3142,6 +3143,10 @@ more_aggr_init_expr_args_p (const aggr_init_expr_arg_iterator *iter)
user-declared constructor. */
#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
underneath is actually a call to a constructor. This is needed
when the constructor must initialize local storage (which can

View File

@ -10293,6 +10293,8 @@ grok_special_member_properties (tree decl)
int assop = copy_fn_p (decl);
if (!DECL_ARTIFICIAL (decl))
TYPE_HAS_USER_OPEQ (class_type) = 1;
if (assop)
{
TYPE_HAS_COPY_ASSIGN (class_type) = 1;

View File

@ -1004,6 +1004,7 @@ synthesized_method_walk (tree ctype, special_function_kind sfk, bool const_p,
#endif
assign_p = false;
check_vdtor = false;
switch (sfk)
{
case sfk_move_assignment:

View File

@ -1,3 +1,8 @@
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

View File

@ -0,0 +1,25 @@
// 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;

View File

@ -3,7 +3,7 @@
struct virt { virt () {} virt (int i) {} };
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 {
top () {} // { dg-bogus "der\\(const" }