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]

Re: [C++] Fix for 18975


Nathan Sidwell wrote:
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

I've installed this on the mainline, as I now undertand it to be open for bug fixes and regressions.

nathan
--
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.317
diff -c -3 -p -r1.317 method.c
*** cp/method.c	10 Nov 2004 17:34:47 -0000	1.317
--- cp/method.c	17 Dec 2004 14:13:55 -0000
*************** static void
*** 497,503 ****
  do_build_copy_constructor (tree fndecl)
  {
    tree parm = FUNCTION_FIRST_USER_PARM (fndecl);
-   tree t;
  
    parm = convert_from_reference (parm);
  
--- 497,502 ----
*************** do_build_copy_constructor (tree fndecl)
*** 507,513 ****
         if *this is a base subobject.  */;
    else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
      {
!       t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
        finish_expr_stmt (t);
      }
    else
--- 506,512 ----
         if *this is a base subobject.  */;
    else if (TYPE_HAS_TRIVIAL_INIT_REF (current_class_type))
      {
!       tree t = build2 (INIT_EXPR, void_type_node, current_class_ref, parm);
        finish_expr_stmt (t);
      }
    else
*************** do_build_copy_constructor (tree fndecl)
*** 551,572 ****
  
        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)))
  		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
--- 550,569 ----
  
        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)))
  		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)
*** 577,590 ****
  	     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 = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
  	  init = build_tree_list (NULL_TREE, init);
  
! 	  member_init_list
! 	    = tree_cons (field, init, member_init_list);
  	}
        finish_mem_initializers (member_init_list);
      }
--- 574,592 ----
  	     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 = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
  	  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)
*** 639,690 ****
  	   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 %q#D, can't use default "
                       "assignment operator", field);
  	      continue;
  	    }
! 	  else if (TREE_CODE (TREE_TYPE (field)) == REFERENCE_TYPE)
  	    {
  	      error ("non-static reference member %q#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)))
  		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 = build3 (COMPONENT_REF, TREE_TYPE (field), comp, field,
! 			 NULL_TREE);
! 	  init = build3 (COMPONENT_REF,
! 			 cp_build_qualified_type (TREE_TYPE (field), cvquals),
! 			 init, field, NULL_TREE);
  
  	  if (DECL_NAME (field))
! 	    finish_expr_stmt (build_modify_expr (comp, NOP_EXPR, init));
  	  else
! 	    finish_expr_stmt (build2 (MODIFY_EXPR, TREE_TYPE (comp), comp,
! 				      init));
  	}
      }
    finish_return_stmt (current_class_ref);
--- 641,697 ----
  	   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 %q#D, can't use default "
                       "assignment operator", field);
  	      continue;
  	    }
! 	  else if (TREE_CODE (expr_type) == REFERENCE_TYPE)
  	    {
  	      error ("non-static reference member %q#D, can't use "
                       "default assignment operator", field);
  	      continue;
  	    }
  
  	  if (DECL_NAME (field))
  	    {
  	      if (VFIELD_NAME_P (DECL_NAME (field)))
  		continue;
  	    }
! 	  else if (ANON_AGGR_TYPE_P (expr_type)
! 		   && TYPE_FIELDS (expr_type) != NULL_TREE)
  	    /* Just use the field; anonymous types can't have
  	       nontrivial copy ctors or assignment ops.  */;
  	  else
  	    continue;
  
! 	  comp = build3 (COMPONENT_REF, expr_type, comp, field, NULL_TREE);
! 	  
! 	  /* 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 = build3 (COMPONENT_REF, expr_type, init, field, NULL_TREE);
  
  	  if (DECL_NAME (field))
! 	    init = build_modify_expr (comp, NOP_EXPR, init);
  	  else
! 	    init = build2 (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]