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
This commit is contained in:
parent
30cfa1bb50
commit
2d2e8123b5
@ -1,3 +1,12 @@
|
||||
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>
|
||||
|
||||
* dump.c (dump_op): New function.
|
||||
|
@ -88,7 +88,7 @@ static tree reference_binding PARAMS ((tree, tree, tree, int));
|
||||
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 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));
|
||||
@ -648,6 +648,9 @@ build_conv (code, type, from)
|
||||
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;
|
||||
@ -1024,8 +1027,7 @@ convert_class_to_reference (t, s, expr)
|
||||
return NULL_TREE;
|
||||
|
||||
conv = build1 (IDENTITY_CONV, s, expr);
|
||||
conv = build_conv (USER_CONV,
|
||||
non_reference (TREE_TYPE (TREE_TYPE (cand->fn))),
|
||||
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;
|
||||
@ -4764,26 +4766,25 @@ maybe_handle_implicit_object (ics)
|
||||
}
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
/* 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 int
|
||||
maybe_handle_ref_bind (ics, target_type)
|
||||
static tree
|
||||
maybe_handle_ref_bind (ics)
|
||||
tree* ics;
|
||||
tree* target_type;
|
||||
{
|
||||
if (TREE_CODE (*ics) == REF_BIND)
|
||||
{
|
||||
tree old_ics = *ics;
|
||||
*target_type = TREE_TYPE (TREE_TYPE (*ics));
|
||||
*ics = TREE_OPERAND (*ics, 0);
|
||||
tree type = TREE_TYPE (TREE_TYPE (old_ics));
|
||||
*ics = TREE_OPERAND (old_ics, 0);
|
||||
ICS_USER_FLAG (*ics) = ICS_USER_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
|
||||
@ -4810,8 +4811,6 @@ compare_ics (ics1, ics2)
|
||||
/* 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;
|
||||
|
||||
@ -4820,8 +4819,8 @@ compare_ics (ics1, ics2)
|
||||
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);
|
||||
target_type1 = maybe_handle_ref_bind (&ics1);
|
||||
target_type2 = maybe_handle_ref_bind (&ics2);
|
||||
|
||||
/* [over.ics.rank]
|
||||
|
||||
@ -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))
|
||||
{
|
||||
tree from = non_reference (from_type1);
|
||||
|
||||
/* [over.ics.rank]
|
||||
|
||||
--binding of an expression of type C to a reference of type
|
||||
@ -5070,8 +5071,8 @@ compare_ics (ics1, ics2)
|
||||
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 (from, to_type1)
|
||||
&& is_properly_derived_from (from, to_type2))
|
||||
{
|
||||
if (is_properly_derived_from (to_type1, to_type2))
|
||||
return 1;
|
||||
@ -5079,9 +5080,11 @@ compare_ics (ics1, ics2)
|
||||
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))
|
||||
{
|
||||
tree to = non_reference (to_type1);
|
||||
|
||||
/* [over.ics.rank]
|
||||
|
||||
--binding of an expression of type B to a reference of type
|
||||
@ -5089,8 +5092,8 @@ compare_ics (ics1, ics2)
|
||||
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_type1, to)
|
||||
&& is_properly_derived_from (from_type2, to))
|
||||
{
|
||||
if (is_properly_derived_from (from_type2, from_type1))
|
||||
return 1;
|
||||
@ -5118,7 +5121,7 @@ compare_ics (ics1, ics2)
|
||||
initialized by S2 refers is more cv-qualified than the type to
|
||||
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))
|
||||
return comp_cv_qualification (target_type2, target_type1);
|
||||
|
||||
|
47
gcc/testsuite/g++.dg/ref1.C
Normal file
47
gcc/testsuite/g++.dg/ref1.C
Normal file
@ -0,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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user