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++ PATCH: PR3637


This patches fixes PR3637, a GCC 2.95.x regression.

Bootstrapped and tested on i686-pc-linux-gnu, installed on the
branch and on the mainline (in a slightly different form).

-- 
Mark Mitchell                mark@codesourcery.com
CodeSourcery, LLC            http://www.codesourcery.com

2001-11-20  Mark Mitchell  <mark@codesourcery.com>

	PR c++/3637
	* call.c (non_reference): Add documentation.
	(convert_class_to_reference): Do not strip reference types
	from conversion operators.
	(maybe_handle_ref_bind): Simplify.
	(compare_ics): Correct handling of references.

Index: cp/call.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/cp/call.c,v
retrieving revision 1.255.2.18
diff -c -p -r1.255.2.18 call.c
*** call.c	2001/09/04 13:03:03	1.255.2.18
--- call.c	2001/11/20 08:30:16
*************** static tree reference_binding PARAMS ((t
*** 87,93 ****
  static tree non_reference PARAMS ((tree));
  static tree build_conv PARAMS ((enum tree_code, tree, tree));
  static int is_subseq PARAMS ((tree, tree));
! static int maybe_handle_ref_bind PARAMS ((tree*, tree*));
  static void maybe_handle_implicit_object PARAMS ((tree*));
  static struct z_candidate * add_candidate PARAMS ((struct z_candidate *,
  						   tree, tree, int));
--- 87,93 ----
  static tree non_reference PARAMS ((tree));
  static tree build_conv PARAMS ((enum tree_code, tree, tree));
  static int is_subseq PARAMS ((tree, tree));
! static tree maybe_handle_ref_bind PARAMS ((tree*));
  static void maybe_handle_implicit_object PARAMS ((tree*));
  static struct z_candidate * add_candidate PARAMS ((struct z_candidate *,
  						   tree, tree, int));
*************** build_conv (code, type, from)
*** 638,643 ****
--- 638,646 ----
    return t;
  }

+ /* If T is a REFERENCE_TYPE return the type to which T refers.
+    Otherwise, return T itself.  */
+
  static tree
  non_reference (t)
       tree t;
*************** convert_class_to_reference (t, s, expr)
*** 998,1005 ****
      return NULL_TREE;

    conv = build1 (IDENTITY_CONV, s, expr);
!   conv = build_conv (USER_CONV,
! 		     non_reference (TREE_TYPE (TREE_TYPE (cand->fn))),
  		     conv);
    TREE_OPERAND (conv, 1) = build_ptr_wrapper (cand);
    ICS_USER_FLAG (conv) = 1;
--- 1001,1007 ----
      return NULL_TREE;

    conv = build1 (IDENTITY_CONV, s, expr);
!   conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
  		     conv);
    TREE_OPERAND (conv, 1) = build_ptr_wrapper (cand);
    ICS_USER_FLAG (conv) = 1;
*************** maybe_handle_implicit_object (ics)
*** 4757,4779 ****
      }
  }

! /* If ICS is a REF_BIND, modify it appropriately, set TARGET_TYPE
!    to the type the reference originally referred to, and return 1.
!    Otherwise, return 0.  */

! static int
! maybe_handle_ref_bind (ics, target_type)
       tree* ics;
-      tree* target_type;
  {
    if (TREE_CODE (*ics) == REF_BIND)
      {
!       *target_type = TREE_TYPE (TREE_TYPE (*ics));
        *ics = TREE_OPERAND (*ics, 0);
!       return 1;
      }
!
!   return 0;
  }

  /* Compare two implicit conversion sequences according to the rules set 
out in
--- 4759,4780 ----
      }
  }

! /* If *ICS is a REF_BIND set *ICS to the remainder of the conversion,
!    and return the type to which the reference refers.  Otherwise,
!    leave *ICS unchanged and return NULL_TREE.  */

! static tree
! maybe_handle_ref_bind (ics)
       tree* ics;
  {
    if (TREE_CODE (*ics) == REF_BIND)
      {
!       tree type = TREE_TYPE (TREE_TYPE (*ics));
        *ics = TREE_OPERAND (*ics, 0);
!       return type;
      }
!
!   return NULL_TREE;
  }

  /* Compare two implicit conversion sequences according to the rules set 
out in
*************** compare_ics (ics1, ics2)
*** 4800,4807 ****
    /* REF_BINDING is non-zero if the result of the conversion sequence
       is a reference type.   In that case TARGET_TYPE is the
       type referred to by the reference.  */
-   int ref_binding1;
-   int ref_binding2;
    tree target_type1;
    tree target_type2;

--- 4801,4806 ----
*************** compare_ics (ics1, ics2)
*** 4810,4817 ****
    maybe_handle_implicit_object (&ics2);

    /* Handle reference parameters.  */
!   ref_binding1 = maybe_handle_ref_bind (&ics1, &target_type1);
!   ref_binding2 = maybe_handle_ref_bind (&ics2, &target_type2);

    /* [over.ics.rank]

--- 4809,4816 ----
    maybe_handle_implicit_object (&ics2);

    /* Handle reference parameters.  */
!   target_type1 = maybe_handle_ref_bind (&ics1);
!   target_type2 = maybe_handle_ref_bind (&ics2);

    /* [over.ics.rank]

*************** compare_ics (ics1, ics2)
*** 5050,5058 ****
  	    }
  	}
      }
!   else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1))
  	   && same_type_p (from_type1, from_type2))
      {
        /* [over.ics.rank]
  	
  	 --binding of an expression of type C to a reference of type
--- 5049,5059 ----
  	    }
  	}
      }
!   else if (CLASS_TYPE_P (non_reference (from_type1))
  	   && same_type_p (from_type1, from_type2))
      {
+       tree from = non_reference (from_type1);
+
        /* [over.ics.rank]
  	
  	 --binding of an expression of type C to a reference of type
*************** compare_ics (ics1, ics2)
*** 5060,5067 ****
  	   reference of type A&

  	 --conversion of C to B is better than conversion of C to A,  */
!       if (is_properly_derived_from (from_type1, to_type1)
! 	  && is_properly_derived_from (from_type1, to_type2))
  	{
  	  if (is_properly_derived_from (to_type1, to_type2))
  	    return 1;
--- 5061,5068 ----
  	   reference of type A&

  	 --conversion of C to B is better than conversion of C to A,  */
!       if (is_properly_derived_from (from, to_type1)
! 	  && is_properly_derived_from (from, to_type2))
  	{
  	  if (is_properly_derived_from (to_type1, to_type2))
  	    return 1;
*************** compare_ics (ics1, ics2)
*** 5069,5077 ****
  	    return -1;
  	}
      }
!   else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1))
  	   && same_type_p (to_type1, to_type2))
      {
        /* [over.ics.rank]

  	 --binding of an expression of type B to a reference of type
--- 5070,5080 ----
  	    return -1;
  	}
      }
!   else if (CLASS_TYPE_P (non_reference (to_type1))
  	   && same_type_p (to_type1, to_type2))
      {
+       tree to = non_reference (to_type1);
+
        /* [over.ics.rank]

  	 --binding of an expression of type B to a reference of type
*************** compare_ics (ics1, ics2)
*** 5079,5086 ****
  	   reference of type A&,

  	 --onversion of B to A is better than conversion of C to A  */
!       if (is_properly_derived_from (from_type1, to_type1)
! 	  && is_properly_derived_from (from_type2, to_type1))
  	{
  	  if (is_properly_derived_from (from_type2, from_type1))
  	    return 1;
--- 5082,5089 ----
  	   reference of type A&,

  	 --onversion of B to A is better than conversion of C to A  */
!       if (is_properly_derived_from (from_type1, to)
! 	  && is_properly_derived_from (from_type2, to))
  	{
  	  if (is_properly_derived_from (from_type2, from_type1))
  	    return 1;
*************** compare_ics (ics1, ics2)
*** 5108,5114 ****
       initialized by S2 refers is more cv-qualified than the type to
       which the reference initialized by S1 refers */

!   if (ref_binding1 && ref_binding2
        && same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
      return comp_cv_qualification (target_type2, target_type1);

--- 5111,5117 ----
       initialized by S2 refers is more cv-qualified than the type to
       which the reference initialized by S1 refers */

!   if (target_type1 && target_type2
        && same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
      return comp_cv_qualification (target_type2, target_type1);

Index: testsuite/g++.dg/ref1.C
===================================================================
RCS file: ref1.C
diff -N ref1.C
*** /dev/null	Tue May  5 13:32:27 1998
--- ref1.C	Tue Nov 20 00:30:23 2001
***************
*** 0 ****
--- 1,47 ----
+ // Origin: Peter Schmid <schmid@snake.iap.physik.tu-darmstadt.de>
+
+ // { dg-do link }
+
+ template <class T>
+ class Ptr {
+ protected:
+   T * ptr;
+
+ public:
+
+   Ptr(void) : ptr(0) { };
+   Ptr(T * p) : ptr(p) { };
+
+   ~Ptr(void) { delete ptr; }
+
+   operator T & () { return *ptr; }
+ };
+
+ class base {
+ public:
+   base(void) { }
+   ~base(void) { }
+ };
+
+
+ class foo : public base {
+ private:
+   foo(const foo & rv);
+
+ public:
+
+   foo(void) { }
+   ~foo(void) { }
+ };
+
+ void func2(base & b) {
+   // ...
+ }
+
+ int main () {
+   Ptr<foo> f = new foo;
+   /* This should not result in a copy; the result of the conversion
+      operator should be bound directly to the reference argument to
+      `func2'.  */
+   func2(f);
+ }


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