This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR3637
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Peter Schmid <schmid at snake dot iap dot physik dot tu-darmstadt dot de>
- Date: Tue, 20 Nov 2001 00:56:09 -0800
- Subject: 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);
+ }