This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[C++] Fix for 18975


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; }

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]