Commit 2d2e8123 by Mark Mitchell Committed by Mark Mitchell

re PR c++/3637 (Internal compiler error in finish_member_declaration)

	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.

From-SVN: r47209
parent 30cfa1bb
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.
2001-11-19 John Wilkinson <johnw@research.att.com> 2001-11-19 John Wilkinson <johnw@research.att.com>
* dump.c (dump_op): New function. * dump.c (dump_op): New function.
......
...@@ -88,7 +88,7 @@ static tree reference_binding PARAMS ((tree, tree, tree, int)); ...@@ -88,7 +88,7 @@ static tree reference_binding PARAMS ((tree, tree, tree, int));
static tree non_reference PARAMS ((tree)); static tree non_reference PARAMS ((tree));
static tree build_conv PARAMS ((enum tree_code, tree, tree)); static tree build_conv PARAMS ((enum tree_code, tree, tree));
static int is_subseq PARAMS ((tree, tree)); static int is_subseq PARAMS ((tree, tree));
static int maybe_handle_ref_bind PARAMS ((tree*, tree*)); static tree maybe_handle_ref_bind PARAMS ((tree*));
static void maybe_handle_implicit_object PARAMS ((tree*)); static void maybe_handle_implicit_object PARAMS ((tree*));
static struct z_candidate * add_candidate PARAMS ((struct z_candidate *, static struct z_candidate * add_candidate PARAMS ((struct z_candidate *,
tree, tree, int)); tree, tree, int));
...@@ -648,6 +648,9 @@ build_conv (code, type, from) ...@@ -648,6 +648,9 @@ build_conv (code, type, from)
return t; return t;
} }
/* If T is a REFERENCE_TYPE return the type to which T refers.
Otherwise, return T itself. */
static tree static tree
non_reference (t) non_reference (t)
tree t; tree t;
...@@ -1024,8 +1027,7 @@ convert_class_to_reference (t, s, expr) ...@@ -1024,8 +1027,7 @@ convert_class_to_reference (t, s, expr)
return NULL_TREE; return NULL_TREE;
conv = build1 (IDENTITY_CONV, s, expr); conv = build1 (IDENTITY_CONV, s, expr);
conv = build_conv (USER_CONV, conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)),
non_reference (TREE_TYPE (TREE_TYPE (cand->fn))),
conv); conv);
TREE_OPERAND (conv, 1) = build_ptr_wrapper (cand); TREE_OPERAND (conv, 1) = build_ptr_wrapper (cand);
ICS_USER_FLAG (conv) = 1; ICS_USER_FLAG (conv) = 1;
...@@ -4764,26 +4766,25 @@ maybe_handle_implicit_object (ics) ...@@ -4764,26 +4766,25 @@ maybe_handle_implicit_object (ics)
} }
} }
/* If ICS is a REF_BIND, modify it appropriately, set TARGET_TYPE /* If *ICS is a REF_BIND set *ICS to the remainder of the conversion,
to the type the reference originally referred to, and return 1. and return the type to which the reference refers. Otherwise,
Otherwise, return 0. */ leave *ICS unchanged and return NULL_TREE. */
static int static tree
maybe_handle_ref_bind (ics, target_type) maybe_handle_ref_bind (ics)
tree* ics; tree* ics;
tree* target_type;
{ {
if (TREE_CODE (*ics) == REF_BIND) if (TREE_CODE (*ics) == REF_BIND)
{ {
tree old_ics = *ics; tree old_ics = *ics;
*target_type = TREE_TYPE (TREE_TYPE (*ics)); tree type = TREE_TYPE (TREE_TYPE (old_ics));
*ics = TREE_OPERAND (*ics, 0); *ics = TREE_OPERAND (old_ics, 0);
ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics); ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics);
ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics); ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics);
return 1; return type;
} }
return 0; return NULL_TREE;
} }
/* Compare two implicit conversion sequences according to the rules set out in /* Compare two implicit conversion sequences according to the rules set out in
...@@ -4810,8 +4811,6 @@ compare_ics (ics1, ics2) ...@@ -4810,8 +4811,6 @@ compare_ics (ics1, ics2)
/* REF_BINDING is non-zero if the result of the conversion sequence /* REF_BINDING is non-zero if the result of the conversion sequence
is a reference type. In that case TARGET_TYPE is the is a reference type. In that case TARGET_TYPE is the
type referred to by the reference. */ type referred to by the reference. */
int ref_binding1;
int ref_binding2;
tree target_type1; tree target_type1;
tree target_type2; tree target_type2;
...@@ -4820,8 +4819,8 @@ compare_ics (ics1, ics2) ...@@ -4820,8 +4819,8 @@ compare_ics (ics1, ics2)
maybe_handle_implicit_object (&ics2); maybe_handle_implicit_object (&ics2);
/* Handle reference parameters. */ /* Handle reference parameters. */
ref_binding1 = maybe_handle_ref_bind (&ics1, &target_type1); target_type1 = maybe_handle_ref_bind (&ics1);
ref_binding2 = maybe_handle_ref_bind (&ics2, &target_type2); target_type2 = maybe_handle_ref_bind (&ics2);
/* [over.ics.rank] /* [over.ics.rank]
...@@ -5060,9 +5059,11 @@ compare_ics (ics1, ics2) ...@@ -5060,9 +5059,11 @@ compare_ics (ics1, ics2)
} }
} }
} }
else if (IS_AGGR_TYPE_CODE (TREE_CODE (from_type1)) else if (CLASS_TYPE_P (non_reference (from_type1))
&& same_type_p (from_type1, from_type2)) && same_type_p (from_type1, from_type2))
{ {
tree from = non_reference (from_type1);
/* [over.ics.rank] /* [over.ics.rank]
--binding of an expression of type C to a reference of type --binding of an expression of type C to a reference of type
...@@ -5070,8 +5071,8 @@ compare_ics (ics1, ics2) ...@@ -5070,8 +5071,8 @@ compare_ics (ics1, ics2)
reference of type A& reference of type A&
--conversion of C to B is better than conversion of C to A, */ --conversion of C to B is better than conversion of C to A, */
if (is_properly_derived_from (from_type1, to_type1) if (is_properly_derived_from (from, to_type1)
&& is_properly_derived_from (from_type1, to_type2)) && is_properly_derived_from (from, to_type2))
{ {
if (is_properly_derived_from (to_type1, to_type2)) if (is_properly_derived_from (to_type1, to_type2))
return 1; return 1;
...@@ -5079,9 +5080,11 @@ compare_ics (ics1, ics2) ...@@ -5079,9 +5080,11 @@ compare_ics (ics1, ics2)
return -1; return -1;
} }
} }
else if (IS_AGGR_TYPE_CODE (TREE_CODE (to_type1)) else if (CLASS_TYPE_P (non_reference (to_type1))
&& same_type_p (to_type1, to_type2)) && same_type_p (to_type1, to_type2))
{ {
tree to = non_reference (to_type1);
/* [over.ics.rank] /* [over.ics.rank]
--binding of an expression of type B to a reference of type --binding of an expression of type B to a reference of type
...@@ -5089,8 +5092,8 @@ compare_ics (ics1, ics2) ...@@ -5089,8 +5092,8 @@ compare_ics (ics1, ics2)
reference of type A&, reference of type A&,
--onversion of B to A is better than conversion of C to A */ --onversion of B to A is better than conversion of C to A */
if (is_properly_derived_from (from_type1, to_type1) if (is_properly_derived_from (from_type1, to)
&& is_properly_derived_from (from_type2, to_type1)) && is_properly_derived_from (from_type2, to))
{ {
if (is_properly_derived_from (from_type2, from_type1)) if (is_properly_derived_from (from_type2, from_type1))
return 1; return 1;
...@@ -5118,7 +5121,7 @@ compare_ics (ics1, ics2) ...@@ -5118,7 +5121,7 @@ compare_ics (ics1, ics2)
initialized by S2 refers is more cv-qualified than the type to initialized by S2 refers is more cv-qualified than the type to
which the reference initialized by S1 refers */ which the reference initialized by S1 refers */
if (ref_binding1 && ref_binding2 if (target_type1 && target_type2
&& same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2)) && same_type_ignoring_top_level_qualifiers_p (to_type1, to_type2))
return comp_cv_qualification (target_type2, target_type1); return comp_cv_qualification (target_type2, target_type1);
......
// 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);
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment