Commit fd749a60 by Nathan Sidwell

re PR c++/18975 (Copying objects with mutable non-static data members)

cp:
	PR c++/18975
	* method.c (do_build_copy_constructor): Refactor. Don't const
	qualify a mutable field.
	(do_build_assign_ref): Likewise.
testsuite:
	PR c++/18975
	* g++.dg/other/synth1.C: New.

From-SVN: r92461
parent ebef4d30
2004-12-21 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.
2004-12-20 Matt Austern <austern@apple.com> 2004-12-20 Matt Austern <austern@apple.com>
PR c++/19044 PR c++/19044
* decl.c (make_rtl_for_nonlocal_decl): Use set_builtin_user_assembler_name * decl.c (make_rtl_for_nonlocal_decl): Use
set_builtin_user_assembler_name.
2004-12-19 Mark Mitchell <mark@codesourcery.com> 2004-12-19 Mark Mitchell <mark@codesourcery.com>
......
...@@ -497,7 +497,6 @@ static void ...@@ -497,7 +497,6 @@ static void
do_build_copy_constructor (tree fndecl) do_build_copy_constructor (tree fndecl)
{ {
tree parm = FUNCTION_FIRST_USER_PARM (fndecl); tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
tree t;
parm = convert_from_reference (parm); parm = convert_from_reference (parm);
...@@ -507,7 +506,7 @@ do_build_copy_constructor (tree fndecl) ...@@ -507,7 +506,7 @@ do_build_copy_constructor (tree fndecl)
if *this is a base subobject. */; if *this is a base subobject. */;
else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type)) else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
{ {
t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm); tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
finish_expr_stmt (t); finish_expr_stmt (t);
} }
else else
...@@ -551,22 +550,20 @@ do_build_copy_constructor (tree fndecl) ...@@ -551,22 +550,20 @@ do_build_copy_constructor (tree fndecl)
for (; fields; fields = TREE_CHAIN (fields)) for (; fields; fields = TREE_CHAIN (fields))
{ {
tree init; tree init = parm;
tree field = fields; tree field = fields;
tree expr_type; tree expr_type;
if (TREE_CODE (field) != FIELD_DECL) if (TREE_CODE (field) != FIELD_DECL)
continue; continue;
init = parm; expr_type = TREE_TYPE (field);
if (DECL_NAME (field)) if (DECL_NAME (field))
{ {
if (VFIELD_NAME_P (DECL_NAME (field))) if (VFIELD_NAME_P (DECL_NAME (field)))
continue; continue;
} }
else if ((t = TREE_TYPE (field)) != NULL_TREE else if (ANON_AGGR_TYPE_P (expr_type) && TYPE_FIELDS (expr_type))
&& ANON_AGGR_TYPE_P (t)
&& TYPE_FIELDS (t) != NULL_TREE)
/* Just use the field; anonymous types can't have /* Just use the field; anonymous types can't have
nontrivial copy ctors or assignment ops. */; nontrivial copy ctors or assignment ops. */;
else else
...@@ -577,14 +574,19 @@ do_build_copy_constructor (tree fndecl) ...@@ -577,14 +574,19 @@ do_build_copy_constructor (tree fndecl)
the field is "T", then the type will usually be "const the field is "T", then the type will usually be "const
T". (There are no cv-qualified variants of reference T". (There are no cv-qualified variants of reference
types.) */ types.) */
expr_type = TREE_TYPE (field);
if (TREE_CODE (expr_type) != REFERENCE_TYPE) if (TREE_CODE (expr_type) != REFERENCE_TYPE)
expr_type = cp_build_qualified_type (expr_type, cvquals); {
int quals = cvquals;
if (DECL_MUTABLE_P (field))
quals &= ~TYPE_QUAL_CONST;
expr_type = cp_build_qualified_type (expr_type, quals);
}
init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE); init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
init = build_tree_list (NULL_TREE, init); init = build_tree_list (NULL_TREE, init);
member_init_list member_init_list = tree_cons (field, init, member_init_list);
= tree_cons (field, init, member_init_list);
} }
finish_mem_initializers (member_init_list); finish_mem_initializers (member_init_list);
} }
...@@ -639,52 +641,57 @@ do_build_assign_ref (tree fndecl) ...@@ -639,52 +641,57 @@ do_build_assign_ref (tree fndecl)
fields; fields;
fields = TREE_CHAIN (fields)) fields = TREE_CHAIN (fields))
{ {
tree comp, init, t; tree comp = current_class_ref;
tree init = parm;
tree field = fields; tree field = fields;
tree expr_type;
int quals;
if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field)) if (TREE_CODE (field) != FIELD_DECL || DECL_ARTIFICIAL (field))
continue; continue;
if (CP_TYPE_CONST_P (TREE_TYPE (field))) expr_type = TREE_TYPE (field);
if (CP_TYPE_CONST_P (expr_type))
{ {
error ("non-static const member %q#D, can't use default " error ("non-static const member %q#D, can't use default "
"assignment operator", field); "assignment operator", field);
continue; continue;
} }
else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE) else if (TREE_CODE (expr_type) == REFERENCE_TYPE)
{ {
error ("non-static reference member %q#D, can't use " error ("non-static reference member %q#D, can't use "
"default assignment operator", field); "default assignment operator", field);
continue; continue;
} }
comp = current_class_ref;
init = parm;
if (DECL_NAME (field)) if (DECL_NAME (field))
{ {
if (VFIELD_NAME_P (DECL_NAME (field))) if (VFIELD_NAME_P (DECL_NAME (field)))
continue; continue;
} }
else if ((t = TREE_TYPE (field)) != NULL_TREE else if (ANON_AGGR_TYPE_P (expr_type)
&& ANON_AGGR_TYPE_P (t) && TYPE_FIELDS (expr_type) != NULL_TREE)
&& TYPE_FIELDS (t) != NULL_TREE)
/* Just use the field; anonymous types can't have /* Just use the field; anonymous types can't have
nontrivial copy ctors or assignment ops. */; nontrivial copy ctors or assignment ops. */;
else else
continue; continue;
comp = build3 (COMPONENT_REF, TREE_TYPE (field), comp, field, comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE);
NULL_TREE);
init = build3 (COMPONENT_REF, /* Compute the type of init->field */
cp_build_qualified_type (TREE_TYPE (field), cvquals), quals = cvquals;
init, field, NULL_TREE); if (DECL_MUTABLE_P (field))
quals &= ~TYPE_QUAL_CONST;
expr_type = cp_build_qualified_type (expr_type, quals);
init = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
if (DECL_NAME (field)) if (DECL_NAME (field))
finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init)); init = build_modify_expr (comp, NOP_EXPR, init);
else else
finish_expr_stmt (build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init = build2 (MODIFY_EXPR, TREE_TYPE (comp), comp, init);
init)); finish_expr_stmt (init);
} }
} }
finish_return_stmt (current_class_ref); finish_return_stmt (current_class_ref);
......
2004-12-21 Nathan Sidwell <nathan@codesourcery.com>
PR c++/18975
* g++.dg/other/synth1.C: New.
2004-12-21 James A. Morrison <phython@gcc.gnu.org> 2004-12-21 James A. Morrison <phython@gcc.gnu.org>
PR c/18963 PR c/18963
......
// 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; }
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