Commit 3d938426 by Mark Mitchell Committed by Mark Mitchell

call.c (merge_conversion_sequences): New function.

	* call.c (merge_conversion_sequences): New function.
	(build_conv): Set ICS_USER_FLAG for USER_CONVs.
	(convert_class_to_reference): Correct handling of second
	standard conversion sequence in a user-defined conversion
	sequence.
	(build_user_type_conversion_1): Use merge_conversion_sequences.
	* cp-tree.def: Add comments for CONV nodes.

	* g++.dg/init/ref3.C: New test.

From-SVN: r63930
parent ea67bef4
2003-03-06 Mark Mitchell <mark@codesourcery.com>
* call.c (merge_conversion_sequences): New function.
(build_conv): Set ICS_USER_FLAG for USER_CONVs.
(convert_class_to_reference): Correct handling of second
standard conversion sequence in a user-defined conversion
sequence.
(build_user_type_conversion_1): Use merge_conversion_sequences.
* cp-tree.def: Add comments for CONV nodes.
2003-03-07 Gabriel Dos Reis <gdr@integrable-solutions.net> 2003-03-07 Gabriel Dos Reis <gdr@integrable-solutions.net>
* error.c (init_error): Use C90 prototype style. * error.c (init_error): Use C90 prototype style.
......
/* Functions related to invoking methods and overloaded functions. /* Functions related to invoking methods and overloaded functions.
Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998, Copyright (C) 1987, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
1999, 2000, 2001, 2002 Free Software Foundation, Inc. 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Contributed by Michael Tiemann (tiemann@cygnus.com) and Contributed by Michael Tiemann (tiemann@cygnus.com) and
modified by Brendan Kehoe (brendan@cygnus.com). modified by Brendan Kehoe (brendan@cygnus.com).
...@@ -106,6 +106,7 @@ static tree call_builtin_trap (void); ...@@ -106,6 +106,7 @@ static tree call_builtin_trap (void);
static tree prep_operand (tree); static tree prep_operand (tree);
static void add_candidates (tree, tree, tree, tree, static void add_candidates (tree, tree, tree, tree,
int, struct z_candidate **); int, struct z_candidate **);
static tree merge_conversion_sequences (tree, tree);
tree tree
build_vfield_ref (tree datum, tree type) build_vfield_ref (tree datum, tree type)
...@@ -560,7 +561,12 @@ struct z_candidate GTY(()) { ...@@ -560,7 +561,12 @@ struct z_candidate GTY(()) {
tree fn; tree fn;
/* The arguments to use when calling this function. */ /* The arguments to use when calling this function. */
tree args; tree args;
/* The implicit conversion sequences for each of the arguments to
FN. */
tree convs; tree convs;
/* If FN is a user-defined conversion, the standard conversion
sequence from the type returned by FN to the desired destination
type. */
tree second_conv; tree second_conv;
int viable; int viable;
/* If FN is a member function, the binfo indicating the path used to /* If FN is a member function, the binfo indicating the path used to
...@@ -667,7 +673,7 @@ build_conv (enum tree_code code, tree type, tree from) ...@@ -667,7 +673,7 @@ build_conv (enum tree_code code, tree type, tree from)
break; break;
} }
ICS_STD_RANK (t) = rank; ICS_STD_RANK (t) = rank;
ICS_USER_FLAG (t) = ICS_USER_FLAG (from); ICS_USER_FLAG (t) = (code == USER_CONV || ICS_USER_FLAG (from));
ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from); ICS_BAD_FLAG (t) = ICS_BAD_FLAG (from);
return t; return t;
} }
...@@ -1034,15 +1040,15 @@ convert_class_to_reference (tree t, tree s, tree expr) ...@@ -1034,15 +1040,15 @@ convert_class_to_reference (tree t, tree s, tree expr)
LOOKUP_NORMAL); LOOKUP_NORMAL);
if (cand) if (cand)
{ /* Build a standard conversion sequence indicating the
conv = build1 (IDENTITY_CONV, s, expr); binding from the reference type returned by the
conv = build_conv (USER_CONV, TREE_TYPE (TREE_TYPE (cand->fn)), function to the desired REFERENCE_TYPE. */
conv); cand->second_conv
TREE_OPERAND (conv, 1) = build_zc_wrapper (cand); = (direct_reference_binding
ICS_USER_FLAG (conv) = 1; (reference_type,
cand->second_conv build1 (IDENTITY_CONV,
= direct_reference_binding (reference_type, conv); TREE_TYPE (TREE_TYPE (TREE_TYPE (cand->fn))),
} NULL_TREE)));
} }
conversions = TREE_CHAIN (conversions); conversions = TREE_CHAIN (conversions);
} }
...@@ -1063,11 +1069,21 @@ convert_class_to_reference (tree t, tree s, tree expr) ...@@ -1063,11 +1069,21 @@ convert_class_to_reference (tree t, tree s, tree expr)
build_this (expr), build_this (expr),
TREE_CHAIN (cand->args)); TREE_CHAIN (cand->args));
conv = cand->second_conv; /* Build a user-defined conversion sequence representing the
conversion. */
conv = build_conv (USER_CONV,
TREE_TYPE (TREE_TYPE (cand->fn)),
build1 (IDENTITY_CONV, TREE_TYPE (expr), expr));
TREE_OPERAND (conv, 1) = build_zc_wrapper (cand);
/* Merge it with the standard conversion sequence from the
conversion function's return type to the desired type. */
cand->second_conv = merge_conversion_sequences (conv, cand->second_conv);
if (cand->viable == -1) if (cand->viable == -1)
ICS_BAD_FLAG (conv) = 1; ICS_BAD_FLAG (conv) = 1;
return conv; return cand->second_conv;
} }
/* A reference of the indicated TYPE is being bound directly to the /* A reference of the indicated TYPE is being bound directly to the
...@@ -1077,7 +1093,13 @@ convert_class_to_reference (tree t, tree s, tree expr) ...@@ -1077,7 +1093,13 @@ convert_class_to_reference (tree t, tree s, tree expr)
static tree static tree
direct_reference_binding (tree type, tree conv) direct_reference_binding (tree type, tree conv)
{ {
tree t = TREE_TYPE (type); tree t;
my_friendly_assert (TREE_CODE (type) == REFERENCE_TYPE, 20030306);
my_friendly_assert (TREE_CODE (TREE_TYPE (conv)) != REFERENCE_TYPE,
20030306);
t = TREE_TYPE (type);
/* [over.ics.rank] /* [over.ics.rank]
...@@ -2428,6 +2450,35 @@ print_z_candidates (struct z_candidate *candidates) ...@@ -2428,6 +2450,35 @@ print_z_candidates (struct z_candidate *candidates)
} }
} }
/* USER_SEQ is a user-defined conversion sequence, beginning with a
USER_CONV. STD_SEQ is the standard conversion sequence applied to
the result of the conversion function to convert it to the final
desired type. Merge the the two sequences into a single sequence,
and return the merged sequence. */
static tree
merge_conversion_sequences (tree user_seq, tree std_seq)
{
tree *t;
my_friendly_assert (TREE_CODE (user_seq) == USER_CONV,
20030306);
/* Find the end of the second conversion sequence. */
t = &(std_seq);
while (TREE_CODE (*t) != IDENTITY_CONV)
t = &TREE_OPERAND (*t, 0);
/* Replace the identity conversion with the user conversion
sequence. */
*t = user_seq;
/* The entire sequence is a user-conversion sequence. */
ICS_USER_FLAG (std_seq) = 1;
return std_seq;
}
/* Returns the best overload candidate to perform the requested /* Returns the best overload candidate to perform the requested
conversion. This function is used for three the overloading situations conversion. This function is used for three the overloading situations
described in [over.match.copy], [over.match.conv], and [over.match.ref]. described in [over.match.copy], [over.match.conv], and [over.match.ref].
...@@ -2439,7 +2490,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ...@@ -2439,7 +2490,7 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
{ {
struct z_candidate *candidates, *cand; struct z_candidate *candidates, *cand;
tree fromtype = TREE_TYPE (expr); tree fromtype = TREE_TYPE (expr);
tree ctors = NULL_TREE, convs = NULL_TREE, *p; tree ctors = NULL_TREE, convs = NULL_TREE;
tree args = NULL_TREE; tree args = NULL_TREE;
/* We represent conversion within a hierarchy using RVALUE_CONV and /* We represent conversion within a hierarchy using RVALUE_CONV and
...@@ -2583,18 +2634,20 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags) ...@@ -2583,18 +2634,20 @@ build_user_type_conversion_1 (tree totype, tree expr, int flags)
return cand; return cand;
} }
for (p = &(cand->second_conv); TREE_CODE (*p) != IDENTITY_CONV; ) /* Build the user conversion sequence. */
p = &(TREE_OPERAND (*p, 0)); convs = build_conv
*p = build
(USER_CONV, (USER_CONV,
(DECL_CONSTRUCTOR_P (cand->fn) (DECL_CONSTRUCTOR_P (cand->fn)
? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))), ? totype : non_reference (TREE_TYPE (TREE_TYPE (cand->fn)))),
expr, build_zc_wrapper (cand)); build1 (IDENTITY_CONV, TREE_TYPE (expr), expr));
TREE_OPERAND (convs, 1) = build_zc_wrapper (cand);
ICS_USER_FLAG (cand->second_conv) = ICS_USER_FLAG (*p) = 1;
/* Combine it with the second conversion sequence. */
cand->second_conv = merge_conversion_sequences (convs,
cand->second_conv);
if (cand->viable == -1) if (cand->viable == -1)
ICS_BAD_FLAG (cand->second_conv) = ICS_BAD_FLAG (*p) = 1; ICS_BAD_FLAG (cand->second_conv) = 1;
return cand; return cand;
} }
......
/* This file contains the definitions and documentation for the /* This file contains the definitions and documentation for the
additional tree codes used in the GNU C++ compiler (see tree.def additional tree codes used in the GNU C++ compiler (see tree.def
for the standard codes). for the standard codes).
Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998, Copyright (C) 1987, 1988, 1990, 1993, 1997, 1998, 2003,
1999, 2000, 2001, 2002 Free Software Foundation, Inc. 1999, 2000, 2001, 2002, 2003 Free Software Foundation, Inc.
Hacked by Michael Tiemann (tiemann@cygnus.com) Hacked by Michael Tiemann (tiemann@cygnus.com)
This file is part of GCC. This file is part of GCC.
...@@ -270,7 +270,13 @@ DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", 'e', 1) ...@@ -270,7 +270,13 @@ DEFTREECODE (MUST_NOT_THROW_EXPR, "must_not_throw_expr", 'e', 1)
DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0) DEFTREECODE (TAG_DEFN, "tag_defn", 'e', 0)
/* And some codes for expressing conversions for overload resolution. */ /* The following codes are used to represent implicit conversion
sequences, in the sense of [over.best.ics]. The conversion
sequences are connected through their first operands, with the
first conversion to be performed at the end of the chain.
The innermost conversion (i.e, the one at the end of the chain) is
always an IDENTITY_CONV, corresponding to the identity conversion. */
DEFTREECODE (IDENTITY_CONV, "identity_conv", 'e', 1) DEFTREECODE (IDENTITY_CONV, "identity_conv", 'e', 1)
DEFTREECODE (LVALUE_CONV, "lvalue_conv", 'e', 1) DEFTREECODE (LVALUE_CONV, "lvalue_conv", 'e', 1)
......
...@@ -378,13 +378,8 @@ get_tinfo_decl (tree type) ...@@ -378,13 +378,8 @@ get_tinfo_decl (tree type)
static tree static tree
get_tinfo_ptr (tree type) get_tinfo_ptr (tree type)
{ {
tree exp = get_tinfo_decl (type); return build_nop (type_info_ptr_type,
build_address (get_tinfo_decl (type)));
/* Convert to type_info type. */
exp = build_unary_op (ADDR_EXPR, exp, 0);
exp = ocp_convert (type_info_ptr_type, exp, CONV_REINTERPRET, 0);
return exp;
} }
/* Return the type_info object for TYPE. */ /* Return the type_info object for TYPE. */
......
2003-03-06 Mark Mitchell <mark@codesourcery.com> 2003-03-06 Mark Mitchell <mark@codesourcery.com>
* g++.dg/init/ref3.C: New test.
PR c++/9965 PR c++/9965
* g++.dg/init/ref2.C: New test. * g++.dg/init/ref2.C: New test.
......
struct Base { };
struct Derived : public Base { };
struct Choose {
operator Base&();
operator Derived&();
};
void f()
{
Choose c;
Base& ref = c;
}
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