aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>2001-11-20 09:00:33 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>2001-11-20 09:00:33 +0000
commit2d2e8123b5928675f46e2628e7cac9c13875d2cd (patch)
tree1e1d99f1028a63612d6994e142289a8582f99940 /gcc
parent30cfa1bb50d8470fa8ce0aa0db01a333385c46ee (diff)
downloadgcc-2d2e8123b5928675f46e2628e7cac9c13875d2cd.zip
gcc-2d2e8123b5928675f46e2628e7cac9c13875d2cd.tar.gz
gcc-2d2e8123b5928675f46e2628e7cac9c13875d2cd.tar.bz2
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
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog9
-rw-r--r--gcc/cp/call.c51
-rw-r--r--gcc/testsuite/g++.dg/ref1.C47
3 files changed, 83 insertions, 24 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index df49519..9d78cbe 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 91bc097..4d06dc5 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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);
diff --git a/gcc/testsuite/g++.dg/ref1.C b/gcc/testsuite/g++.dg/ref1.C
new file mode 100644
index 0000000..aaf04cf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ref1.C
@@ -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);
+}