]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
re PR c++/18975 (Copying objects with mutable non-static data members)
authorNathan Sidwell <nathan@codesourcery.com>
Fri, 17 Dec 2004 16:19:23 +0000 (16:19 +0000)
committerNathan Sidwell <nathan@gcc.gnu.org>
Fri, 17 Dec 2004 16:19:23 +0000 (16:19 +0000)
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: r92321

gcc/cp/ChangeLog
gcc/cp/method.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/other/synth1.C [new file with mode: 0644]

index ccf61f4c51eaa5eb2f385da017f7bef15421295f..97185f93205892b3b8a80d50f0b72e604d60d1ee 100644 (file)
@@ -1,3 +1,10 @@
+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.
+
 2004-12-10  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
        PR c++/18731
index 0f72dc75514707d82566362c0f08dc16abfa32b8..42e50926f2673587a105906da7ee9163fbb30546 100644 (file)
@@ -583,14 +583,14 @@ do_build_copy_constructor (tree fndecl)
 
       for (; fields; fields = TREE_CHAIN (fields))
        {
-         tree init;
+         tree init = parm;
          tree field = fields;
          tree expr_type;
 
          if (TREE_CODE (field) != FIELD_DECL)
            continue;
 
-         init = parm;
+         expr_type = TREE_TYPE (field);
          if (DECL_NAME (field))
            {
              if (VFIELD_NAME_P (DECL_NAME (field)))
@@ -600,9 +600,7 @@ do_build_copy_constructor (tree fndecl)
              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)
+         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
@@ -613,14 +611,19 @@ do_build_copy_constructor (tree fndecl)
             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);
+           {
+             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);
+         member_init_list = tree_cons (field, init, member_init_list);
        }
       finish_mem_initializers (member_init_list);
     }
@@ -675,26 +678,27 @@ do_build_assign_ref (tree fndecl)
           fields; 
           fields = TREE_CHAIN (fields))
        {
-         tree comp, init, t;
+         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;
 
-         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 `%#D', can't use default assignment operator", field);
              continue;
            }
-         else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
+         else if (TREE_CODE (expr_type) == 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)))
@@ -704,24 +708,27 @@ do_build_assign_ref (tree fndecl)
              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)
+         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);
-         init = build (COMPONENT_REF,
-                       cp_build_qualified_type (TREE_TYPE (field), cvquals),
-                       init, 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))
-           finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
+           init = build_modify_expr (comp, NOP_EXPR, init);
          else
-           finish_expr_stmt (build (MODIFY_EXPR, TREE_TYPE (comp), comp,
-                                    init));
+           init = build (MODIFY_EXPR, TREE_TYPE (comp), comp, init);
+         finish_expr_stmt (init);
        }
     }
   finish_return_stmt (current_class_ref);
index 66d903d821cd8f42f4fa36347a833c331fee437f..4aba99a4f4c62da9b9357eee7cb60c5df2d73b60 100644 (file)
@@ -1,3 +1,8 @@
+2004-12-17  Nathan Sidwell  <nathan@codesourcery.com>
+
+       PR c++/18975
+       * g++.dg/other/synth1.C: New.
+
 2004-12-17  Jakub Jelinek  <jakub@redhat.com>
 
        * gcc.c-torture/execute/20041213-1.c: Move...
diff --git a/gcc/testsuite/g++.dg/other/synth1.C b/gcc/testsuite/g++.dg/other/synth1.C
new file mode 100644 (file)
index 0000000..5829c6c
--- /dev/null
@@ -0,0 +1,31 @@
+// 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; }