This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[C++] Fix for 18975
- From: Nathan Sidwell <nathan at codesourcery dot com>
- To: GCC Patches <gcc-patches at gcc dot gnu dot org>
- Date: Fri, 17 Dec 2004 16:15:00 +0000
- Subject: [C++] Fix for 18975
- Organization: Codesourcery LLC
This fixes 18975 on the 3.4 branch. We were neglecting to consider the
mutable specifier on a member when synthesizing a copy ctor, or an assignment
operator, and subsequently selecting the wrong overload.
The mainline fix is similar and will be queued for when non-regression
fixes can be applied
booted & tested on i686-pc-linux-gnu.
--
Nathan Sidwell :: http://www.codesourcery.com :: CodeSourcery LLC
nathan@codesourcery.com :: http://www.planetfall.pwp.blueyonder.co.uk
2004-12-17 Nathan Sidwell <nathan@codesourcery.com>
PR c++/18975
* method.c (do_build_copy_constructor): Refactor. Don't const
qualify a mutable field.
(do_build_assign_ref): Likewise.
Index: cp/method.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/method.c,v
retrieving revision 1.275.4.4
diff -c -3 -p -r1.275.4.4 method.c
*** cp/method.c 8 Jun 2004 06:30:32 -0000 1.275.4.4
--- cp/method.c 17 Dec 2004 14:25:30 -0000
*************** do_build_copy_constructor (tree fndecl)
*** 583,596 ****
for (; fields; fields = TREE_CHAIN (fields))
{
! tree init;
tree field = fields;
tree expr_type;
if (TREE_CODE (field) != FIELD_DECL)
continue;
! init = parm;
if (DECL_NAME (field))
{
if (VFIELD_NAME_P (DECL_NAME (field)))
--- 583,596 ----
for (; fields; fields = TREE_CHAIN (fields))
{
! tree init = parm;
tree field = fields;
tree expr_type;
if (TREE_CODE (field) != FIELD_DECL)
continue;
! expr_type = TREE_TYPE (field);
if (DECL_NAME (field))
{
if (VFIELD_NAME_P (DECL_NAME (field)))
*************** do_build_copy_constructor (tree fndecl)
*** 600,608 ****
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field)
continue;
}
! else if ((t = TREE_TYPE (field)) != NULL_TREE
! && ANON_AGGR_TYPE_P (t)
! && TYPE_FIELDS (t) != NULL_TREE)
/* Just use the field; anonymous types can't have
nontrivial copy ctors or assignment ops. */;
else
--- 600,606 ----
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field)
continue;
}
! else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type))
/* Just use the field; anonymous types can't have
nontrivial copy ctors or assignment ops. */;
else
*************** do_build_copy_constructor (tree fndecl)
*** 613,626 ****
the field is "T", then the type will usually be "const
T". (There are no cv-qualified variants of reference
types.) */
- expr_type = TREE_TYPE (field);
if (TREE_CODE (expr_type) != REFERENCE_TYPE)
! expr_type = cp_build_qualified_type (expr_type, cvquals);
init = build (COMPONENT_REF, expr_type, init, field);
init = build_tree_list (NULL_TREE, init);
! member_init_list
! = tree_cons (field, init, member_init_list);
}
finish_mem_initializers (member_init_list);
}
--- 611,629 ----
the field is "T", then the type will usually be "const
T". (There are no cv-qualified variants of reference
types.) */
if (TREE_CODE (expr_type) != REFERENCE_TYPE)
! {
! int quals = cvquals;
!
! if (DECL_MUTABLE_P (field))
! quals &= ~TYPE_QUAL_CONST;
! expr_type = cp_build_qualified_type (expr_type, quals);
! }
!
init = build (COMPONENT_REF, expr_type, init, field);
init = build_tree_list (NULL_TREE, init);
! member_init_list = tree_cons (field, init, member_init_list);
}
finish_mem_initializers (member_init_list);
}
*************** do_build_assign_ref (tree fndecl)
*** 675,700 ****
fields;
fields = TREE_CHAIN (fields))
{
! tree comp, init, t;
tree field = fields;
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
! if (CP_TYPE_CONST_P (TREE_TYPE (field)))
{
error ("non-static const member `%#D', can't use default assignment operator", field);
continue;
}
! else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
{
error ("non-static reference member `%#D', can't use default assignment operator", field);
continue;
}
- comp = current_class_ref;
- init = parm;
-
if (DECL_NAME (field))
{
if (VFIELD_NAME_P (DECL_NAME (field)))
--- 678,704 ----
fields;
fields = TREE_CHAIN (fields))
{
! tree comp = current_class_ref;
! tree init = parm;
tree field = fields;
+ tree expr_type;
+ int quals;
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue;
! expr_type = TREE_TYPE (field);
! if (CP_TYPE_CONST_P (expr_type))
{
error ("non-static const member `%#D', can't use default assignment operator", field);
continue;
}
! else if (TREE_CODE (expr_type) == REFERENCE_TYPE)
{
error ("non-static reference member `%#D', can't use default assignment operator", field);
continue;
}
if (DECL_NAME (field))
{
if (VFIELD_NAME_P (DECL_NAME (field)))
*************** do_build_assign_ref (tree fndecl)
*** 704,727 ****
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field)
continue;
}
! else if ((t = TREE_TYPE (field)) != NULL_TREE
! && ANON_AGGR_TYPE_P (t)
! && TYPE_FIELDS (t) != NULL_TREE)
/* Just use the field; anonymous types can't have
nontrivial copy ctors or assignment ops. */;
else
continue;
comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field);
! init = build (COMPONENT_REF,
! cp_build_qualified_type (TREE_TYPE (field), cvquals),
! init, field);
if (DECL_NAME (field))
! finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
else
! finish_expr_stmt (build (MODIFY_EXPR, TREE_TYPE (comp), comp,
! init));
}
}
finish_return_stmt (current_class_ref);
--- 708,734 ----
if (IDENTIFIER_CLASS_VALUE (DECL_NAME (field)) != field)
continue;
}
! else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type))
/* Just use the field; anonymous types can't have
nontrivial copy ctors or assignment ops. */;
else
continue;
comp = build (COMPONENT_REF, TREE_TYPE (field), comp, field);
!
! /* Compute the type of init->field */
! quals = cvquals;
! if (DECL_MUTABLE_P (field))
! quals &= ~TYPE_QUAL_CONST;
! expr_type = cp_build_qualified_type (expr_type, quals);
!
! init = build (COMPONENT_REF, expr_type, init, field);
if (DECL_NAME (field))
! init = build_modify_expr (comp, NOP_EXPR, init);
else
! init = build (MODIFY_EXPR, TREE_TYPE (comp), comp, init);
! finish_expr_stmt (init);
}
}
finish_return_stmt (current_class_ref);
// Copyright (C) 2004 Free Software Foundation, Inc.
// Contributed by Nathan Sidwell 17 Dec 2004 <nathan@codesourcery.com>
// PR 18975: Rejects legal
// Origin: Wolfgang Roehrl <wolfgang.roehrl@de.gi-de.com>
struct PTR
{
PTR ();
PTR (PTR&);
PTR& operator= (PTR&);
private:
PTR (const PTR&);
PTR& operator= (const PTR&);
};
struct XYZ
{
XYZ (PTR& p) : ptr(p) {}
mutable PTR ptr;
};
XYZ f1 ();
XYZ f2 (void) { return f1(); }
void f3 (XYZ& dst, const XYZ& src) { dst = src; }