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]

C++ PATCH to synthesized copy constructors


While looking at the named return value optimization, I noticed that
g++.mike/p2846.C was broken in an unexpected way; the synthesized B copy
constructor was calling the A constructor that takes a const B&, rather
than the A copy constructor.

This was also broken in 2.95.  Applied to trunk.

2001-07-05  Jason Merrill  <jason_merrill@redhat.com>

	* cvt.c (convert_lvalue): New fn.
	* cp-tree.h: Declare it.
	* method.c (do_build_assign_ref): Use it.
        (do_build_copy_constructor): Convert parm to base types
	before calling base constructors.

*** cvt.c.~1~	Fri May 18 10:18:57 2001
--- cvt.c	Thu Jul  5 15:06:25 2001
*************** convert_from_reference (val)
*** 597,602 ****
--- 597,616 ----
      return build_indirect_ref (val, NULL);
    return val;
  }
+ 
+ /* Implicitly convert the lvalue EXPR to another lvalue of type TOTYPE,
+    preserving cv-qualification.  */
+ 
+ tree
+ convert_lvalue (totype, expr)
+      tree totype, expr;
+ {
+   totype = cp_build_qualified_type (totype, TYPE_QUALS (TREE_TYPE (expr)));
+   totype = build_reference_type (totype);
+   expr = convert_to_reference (totype, expr, CONV_IMPLICIT, LOOKUP_NORMAL,
+ 			       NULL_TREE);
+   return convert_from_reference (expr);
+ }
  
  /* Call this when we know (for any reason) that expr is not, in fact,
     zero.  This routine is like convert_pointer_to, but it pays
*** cp-tree.h.~1~	Mon Jul  2 16:06:05 2001
--- cp-tree.h	Tue Jul  3 18:04:22 2001
*************** extern tree get_primary_binfo           
*** 3735,3740 ****
--- 3735,3741 ----
  /* in cvt.c */
  extern tree convert_to_reference		PARAMS ((tree, tree, int, int, tree));
  extern tree convert_from_reference		PARAMS ((tree));
+ extern tree convert_lvalue			PARAMS ((tree, tree));
  extern tree convert_pointer_to_real		PARAMS ((tree, tree));
  extern tree convert_pointer_to			PARAMS ((tree, tree));
  extern tree ocp_convert				PARAMS ((tree, tree, int, int));
*** method.c.~1~	Wed Jun  6 22:55:10 2001
--- method.c	Thu Jul  5 15:05:01 2001
*************** do_build_copy_constructor (fndecl)
*** 557,581 ****
        int cvquals = CP_TYPE_QUALS (TREE_TYPE (parm));
        int i;
  
!       /* Initialize all the base-classes.  */
        for (t = CLASSTYPE_VBASECLASSES (current_class_type); t;
  	   t = TREE_CHAIN (t))
! 	base_init_list 
! 	  = tree_cons (BINFO_TYPE (TREE_VALUE (t)), parm, 
! 		       base_init_list);
        for (i = 0; i < n_bases; ++i)
  	{
  	  t = TREE_VEC_ELT (binfos, i);
  	  if (TREE_VIA_VIRTUAL (t))
  	    continue; 
  
! 	  base_init_list 
! 	    = tree_cons (BINFO_TYPE (t), parm, base_init_list);
  	}
  
        for (; fields; fields = TREE_CHAIN (fields))
  	{
! 	  tree init, t;
  	  tree field = fields;
  
  	  if (TREE_CODE (field) != FIELD_DECL)
--- 557,587 ----
        int cvquals = CP_TYPE_QUALS (TREE_TYPE (parm));
        int i;
  
!       /* Initialize all the base-classes with the parameter converted to
!          their type so that we get their copy constructor and not another
!          constructor that takes current_class_type.  */
        for (t = CLASSTYPE_VBASECLASSES (current_class_type); t;
  	   t = TREE_CHAIN (t))
! 	{
! 	  tree type = BINFO_TYPE (TREE_VALUE (t));
! 	  base_init_list = tree_cons (type, convert_lvalue (type, parm),
! 				      base_init_list);
! 	}
! 
        for (i = 0; i < n_bases; ++i)
  	{
  	  t = TREE_VEC_ELT (binfos, i);
  	  if (TREE_VIA_VIRTUAL (t))
  	    continue; 
  
! 	  t = BINFO_TYPE (t);
! 	  base_init_list = tree_cons (t, convert_lvalue (t, parm),
! 				      base_init_list);
  	}
  
        for (; fields; fields = TREE_CHAIN (fields))
  	{
! 	  tree init;
  	  tree field = fields;
  
  	  if (TREE_CODE (field) != FIELD_DECL)
*************** do_build_assign_ref (fndecl)
*** 645,656 ****
        for (i = 0; i < n_bases; ++i)
  	{
  	  tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
! 	  tree p = build_qualified_type (basetype, cvquals);
! 
! 	  p = convert_to_reference
! 	    (build_reference_type (p), parm,
! 	     CONV_IMPLICIT, LOOKUP_COMPLAIN, NULL_TREE);
! 	  p = convert_from_reference (p);
  	  p = build_member_call (basetype, ansi_assopname (NOP_EXPR),
  				 build_tree_list (NULL_TREE, p));
  	  finish_expr_stmt (p);
--- 651,657 ----
        for (i = 0; i < n_bases; ++i)
  	{
  	  tree basetype = BINFO_TYPE (TREE_VEC_ELT (binfos, i));
! 	  tree p = convert_lvalue (basetype, parm);
  	  p = build_member_call (basetype, ansi_assopname (NOP_EXPR),
  				 build_tree_list (NULL_TREE, p));
  	  finish_expr_stmt (p);
*** testsuite/g++.old-deja/g++.mike/p2846.C.~1~	Thu Dec 17 21:20:29 1998
--- testsuite/g++.old-deja/g++.mike/p2846.C	Tue Jul  3 17:48:58 2001
*************** extern "C" void exit(int);
*** 6,11 ****
--- 6,13 ----
  class A;
  class B;
  
+ int c;
+ 
  class A {
  public:
  
*************** public:
*** 30,35 ****
--- 32,38 ----
    virtual ~B(void){}
  
    void print(void) const {
+     ++c;
      printf("B::print\n");
    }
  
*************** int main ()
*** 50,55 ****
  {
    A titi;
    A toto = titi.compute();
!   printf("PASS\n");
!   return 0;
  }
--- 53,66 ----
  {
    A titi;
    A toto = titi.compute();
!   if (c != 1)
!     {
!       printf ("FAIL\n");
!       return 1;
!     }
!   else
!     {
!       printf("PASS\n");
!       return 0;
!     }
  }

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