Commit 27b8d0cd by Mark Mitchell Committed by Mark Mitchell

call.c (NEED_TEMPORARY_P): New macro.

	* call.c (NEED_TEMPORARY_P): New macro.
	(standard_conversion): Set it, for derived-to-base conversions.
	(reference_related_p): New function.
	(reference_compatible_p): Likewise.
	(convert_class_to_reference): Likewise.
	(direct_reference_binding): Likewise.
	(reference_binding): Rework for standards-compliance.
	(convert_like): Adjust accordingly.
	(maybe_handle_ref_bind): Simplify; the right conversion sequences
	are now built up in reference_binding.
	(initialize_reference): New function.
	* cp-tree.h (ICS_USER_FLAG): Document.
	(ICS_THIS_FLAG): Likewise.
	(ICS_BAD_FLAG): Likewise.
	(NEED_TEMPORARY_P): Likewise.
	(cp_lvalue_kind): New type.
	(real_lvalue_p): Return it.
	* error.c (dump_expr): Provide more accurate representation for
	AGGR_INIT_EXPRs.
	* init.c (expand_default_init): Do not try to perform implicit
	conversions for a brace-enclosed initializer.
	* search.c (lookup_conversions): Document.
	* tree.c (lvalue_p_1): Return a cp_lvalue_kind.  Calculate
	appropriately.
	(real_lvalue_p): Adjust accordingly.
	(lvalue_p): Likewise.
	(build_cplus_new): Don't allow the creation of an abstract class.
	* typeck.c (convert_for_initialization): Use initialize_reference.

From-SVN: r28221
parent ac1d97ce
1999-07-22 Mark Mitchell <mark@codesourcery.com>
* call.c (NEED_TEMPORARY_P): New macro.
(standard_conversion): Set it, for derived-to-base conversions.
(reference_related_p): New function.
(reference_compatible_p): Likewise.
(convert_class_to_reference): Likewise.
(direct_reference_binding): Likewise.
(reference_binding): Rework for standards-compliance.
(convert_like): Adjust accordingly.
(maybe_handle_ref_bind): Simplify; the right conversion sequences
are now built up in reference_binding.
(initialize_reference): New function.
* cp-tree.h (ICS_USER_FLAG): Document.
(ICS_THIS_FLAG): Likewise.
(ICS_BAD_FLAG): Likewise.
(NEED_TEMPORARY_P): Likewise.
(cp_lvalue_kind): New type.
(real_lvalue_p): Return it.
* error.c (dump_expr): Provide more accurate representation for
AGGR_INIT_EXPRs.
* init.c (expand_default_init): Do not try to perform implicit
conversions for a brace-enclosed initializer.
* search.c (lookup_conversions): Document.
* tree.c (lvalue_p_1): Return a cp_lvalue_kind. Calculate
appropriately.
(real_lvalue_p): Adjust accordingly.
(lvalue_p): Likewise.
(build_cplus_new): Don't allow the creation of an abstract class.
* typeck.c (convert_for_initialization): Use initialize_reference.
1999-07-21 Gavin Romig-Koch <gavin@cygnus.com> 1999-07-21 Gavin Romig-Koch <gavin@cygnus.com>
* lex.c (real_yylex) : Correct the test for overflow when lexing * lex.c (real_yylex) : Correct the test for overflow when lexing
......
...@@ -92,6 +92,10 @@ static struct z_candidate * add_candidate PROTO((struct z_candidate *, ...@@ -92,6 +92,10 @@ static struct z_candidate * add_candidate PROTO((struct z_candidate *,
tree, tree, int)); tree, tree, int));
static tree source_type PROTO((tree)); static tree source_type PROTO((tree));
static void add_warning PROTO((struct z_candidate *, struct z_candidate *)); static void add_warning PROTO((struct z_candidate *, struct z_candidate *));
static int reference_related_p PROTO ((tree, tree));
static int reference_compatible_p PROTO ((tree, tree));
static tree convert_class_to_reference PROTO ((tree, tree, tree));
static tree direct_reference_binding PROTO ((tree, tree));
tree tree
build_vfield_ref (datum, type) build_vfield_ref (datum, type)
...@@ -534,6 +538,10 @@ struct z_candidate { ...@@ -534,6 +538,10 @@ struct z_candidate {
#define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE) #define ICS_THIS_FLAG(NODE) TREE_LANG_FLAG_2 (NODE)
#define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE) #define ICS_BAD_FLAG(NODE) TREE_LANG_FLAG_3 (NODE)
/* In a REF_BIND or a BASE_CONV, this indicates that a temporary
should be created to hold the result of the conversion. */
#define NEED_TEMPORARY_P(NODE) (TREE_LANG_FLAG_4 ((NODE)))
#define USER_CONV_CAND(NODE) \ #define USER_CONV_CAND(NODE) \
((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1))) ((struct z_candidate *)WRAPPER_PTR (TREE_OPERAND (NODE, 1)))
#define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn) #define USER_CONV_FN(NODE) (USER_CONV_CAND (NODE)->fn)
...@@ -767,6 +775,11 @@ standard_conversion (to, from, expr) ...@@ -767,6 +775,11 @@ standard_conversion (to, from, expr)
if (TREE_CODE (conv) == RVALUE_CONV) if (TREE_CODE (conv) == RVALUE_CONV)
conv = TREE_OPERAND (conv, 0); conv = TREE_OPERAND (conv, 0);
conv = build_conv (BASE_CONV, to, conv); conv = build_conv (BASE_CONV, to, conv);
/* The derived-to-base conversion indicates the initialization
of a parameter with base type from an object of a derived
type. A temporary object is created to hold the result of
the conversion. */
NEED_TEMPORARY_P (conv) = 1;
} }
else else
return 0; return 0;
...@@ -774,6 +787,197 @@ standard_conversion (to, from, expr) ...@@ -774,6 +787,197 @@ standard_conversion (to, from, expr)
return conv; return conv;
} }
/* Returns non-zero if T1 is reference-related to T2. */
static int
reference_related_p (t1, t2)
tree t1;
tree t2;
{
t1 = TYPE_MAIN_VARIANT (t1);
t2 = TYPE_MAIN_VARIANT (t2);
/* [dcl.init.ref]
Given types "cv1 T1" and "cv2 T2," "cv1 T1" is reference-related
to "cv2 T2" if T1 is the same type as T2, or T1 is a base class
of T2. */
return (same_type_p (t1, t2)
|| (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
&& DERIVED_FROM_P (t1, t2)));
}
/* Returns non-zero if T1 is reference-compatible with T2. */
static int
reference_compatible_p (t1, t2)
tree t1;
tree t2;
{
/* [dcl.init.ref]
"cv1 T1" is reference compatible with "cv2 T2" if T1 is
reference-related to T2 and cv1 is the same cv-qualification as,
or greater cv-qualification than, cv2. */
return (reference_related_p (t1, t2)
&& at_least_as_qualified_p (t1, t2));
}
/* Determine whether or not the EXPR (of class type S) can be
converted to T as in [over.match.ref]. */
static tree
convert_class_to_reference (t, s, expr)
tree t;
tree s;
tree expr;
{
tree conversions;
tree arglist;
tree conv;
struct z_candidate *candidates;
struct z_candidate *cand;
/* [over.match.ref]
Assuming that "cv1 T" is the underlying type of the reference
being initialized, and "cv S" is the type of the initializer
expression, with S a class type, the candidate functions are
selected as follows:
--The conversion functions of S and its base classes are
considered. Those that are not hidden within S and yield type
"reference to cv2 T2", where "cv1 T" is reference-compatible
(_dcl.init.ref_) with "cv2 T2", are candidate functions.
The argument list has one argument, which is the initializer
expression. */
candidates = 0;
/* Conceptually, we should take the address of EXPR and put it in
the argument list. Unfortunately, however, that can result in
error messages, which we should not issue now because we are just
trying to find a conversion operator. Therefore, we use NULL,
cast to the appropriate type. */
arglist = build_int_2 (0, 0);
TREE_TYPE (arglist) = build_pointer_type (s);
arglist = build_scratch_list (NULL_TREE, arglist);
for (conversions = lookup_conversions (s);
conversions;
conversions = TREE_CHAIN (conversions))
{
tree fns = TREE_VALUE (conversions);
while (fns)
{
tree f = OVL_CURRENT (fns);
tree t2 = TREE_TYPE (TREE_TYPE (f));
struct z_candidate *old_candidates = candidates;
/* If this is a template function, try to get an exact
match. */
if (TREE_CODE (f) == TEMPLATE_DECL)
{
candidates
= add_template_candidate (candidates,
f,
NULL_TREE,
arglist,
build_reference_type (t),
LOOKUP_NORMAL,
DEDUCE_CONV);
if (candidates != old_candidates)
{
/* Now, see if the conversion function really returns
an lvalue of the appropriate type. From the
point of view of unification, simply returning an
rvalue of the right type is good enough. */
f = candidates->fn;
t2 = TREE_TYPE (TREE_TYPE (f));
if (TREE_CODE (t2) != REFERENCE_TYPE
|| !reference_compatible_p (t, TREE_TYPE (t2)))
candidates = candidates->next;
}
}
else if (TREE_CODE (t2) == REFERENCE_TYPE
&& reference_compatible_p (t, TREE_TYPE (t2)))
candidates
= add_function_candidate (candidates, f, arglist,
LOOKUP_NORMAL);
if (candidates != old_candidates)
candidates->basetype_path = TREE_PURPOSE (conversions);
fns = OVL_NEXT (fns);
}
}
/* If none of the conversion functions worked out, let our caller
know. */
if (!any_viable (candidates))
return NULL_TREE;
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (!cand)
return NULL_TREE;
conv = build_conv (IDENTITY_CONV, s, expr);
conv = build_conv (USER_CONV,
non_reference (TREE_TYPE (TREE_TYPE (cand->fn))),
expr);
TREE_OPERAND (conv, 1) = build_expr_ptr_wrapper (cand);
ICS_USER_FLAG (conv) = 1;
if (cand->viable == -1)
ICS_BAD_FLAG (conv) = 1;
cand->second_conv = conv;
return conv;
}
/* A reference of the indicated TYPE is being bound directly to the
expression represented by the implicit conversion sequence CONV.
Return a conversion sequence for this binding. */
static tree
direct_reference_binding (type, conv)
tree type;
tree conv;
{
tree t = TREE_TYPE (type);
/* [over.ics.rank]
When a parameter of reference type binds directly
(_dcl.init.ref_) to an argument expression, the implicit
conversion sequence is the identity conversion, unless the
argument expression has a type that is a derived class of the
parameter type, in which case the implicit conversion sequence is
a derived-to-base Conversion.
If the parameter binds directly to the result of applying a
conversion function to the argument expression, the implicit
conversion sequence is a user-defined conversion sequence
(_over.ics.user_), with the second standard conversion sequence
either an identity conversion or, if the conversion function
returns an entity of a type that is a derived class of the
parameter type, a derived-to-base conversion. */
if (!same_type_p (TYPE_MAIN_VARIANT (t),
TYPE_MAIN_VARIANT (TREE_TYPE (conv))))
{
/* Represent the derived-to-base conversion. */
conv = build_conv (BASE_CONV, t, conv);
/* We will actually be binding to the base-class subobject in
the derived class, so we mark this conversion appropriately.
That way, convert_like knows not to generate a temporary. */
NEED_TEMPORARY_P (conv) = 0;
}
return build_conv (REF_BIND, type, conv);
}
/* Returns the conversion path from type FROM to reference type TO for /* Returns the conversion path from type FROM to reference type TO for
purposes of reference binding. For lvalue binding, either pass a purposes of reference binding. For lvalue binding, either pass a
reference type to FROM or an lvalue expression to EXPR. reference type to FROM or an lvalue expression to EXPR.
...@@ -786,11 +990,12 @@ reference_binding (rto, rfrom, expr, flags) ...@@ -786,11 +990,12 @@ reference_binding (rto, rfrom, expr, flags)
tree rto, rfrom, expr; tree rto, rfrom, expr;
int flags; int flags;
{ {
tree conv; tree conv = NULL_TREE;
int lvalue = 1;
tree to = TREE_TYPE (rto); tree to = TREE_TYPE (rto);
tree from = rfrom; tree from = rfrom;
int related; int related_p;
int compatible_p;
cp_lvalue_kind lvalue_p = clk_none;
if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr)) if (TREE_CODE (to) == FUNCTION_TYPE && expr && type_unknown_p (expr))
{ {
...@@ -800,54 +1005,123 @@ reference_binding (rto, rfrom, expr, flags) ...@@ -800,54 +1005,123 @@ reference_binding (rto, rfrom, expr, flags)
from = TREE_TYPE (expr); from = TREE_TYPE (expr);
} }
related_p = reference_related_p (to, from);
compatible_p = reference_compatible_p (to, from);
if (TREE_CODE (from) == REFERENCE_TYPE) if (TREE_CODE (from) == REFERENCE_TYPE)
{
/* Anything with reference type is an lvalue. */
lvalue_p = clk_ordinary;
from = TREE_TYPE (from); from = TREE_TYPE (from);
else if (! expr || ! real_lvalue_p (expr)) }
lvalue = 0; else if (expr)
lvalue_p = real_lvalue_p (expr);
related = (same_type_p (TYPE_MAIN_VARIANT (to),
TYPE_MAIN_VARIANT (from))
|| (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& DERIVED_FROM_P (to, from)));
if (lvalue && related && at_least_as_qualified_p (to, from)) if (lvalue_p && compatible_p)
{ {
conv = build1 (IDENTITY_CONV, from, expr); /* [dcl.init.ref]
if (same_type_p (TYPE_MAIN_VARIANT (to), If the intializer expression
TYPE_MAIN_VARIANT (from)))
conv = build_conv (REF_BIND, rto, conv); -- is an lvalue (but not an lvalue for a bit-field), and "cv1 T1"
else is reference-compatible with "cv2 T2,"
{
conv = build_conv (REF_BIND, rto, conv);
ICS_STD_RANK (conv) = STD_RANK;
}
}
else
conv = NULL_TREE;
if (! conv) the reference is bound directly to the initializer exprssion
lvalue. */
conv = build1 (IDENTITY_CONV, from, expr);
conv = direct_reference_binding (rto, conv);
if ((lvalue_p & clk_bitfield) != 0
&& CP_TYPE_CONST_NON_VOLATILE_P (to))
/* For the purposes of overload resolution, we ignore the fact
this expression is a bitfield. (In particular,
[over.ics.ref] says specifically that a function with a
non-const reference parameter is viable even if the
argument is a bitfield.)
However, when we actually call the function we must create
a temporary to which to bind the reference. If the
reference is volatile, or isn't const, then we cannot make
a temporary, so we just issue an error when the conversion
actually occurs. */
NEED_TEMPORARY_P (conv) = 1;
return conv;
}
else if (CLASS_TYPE_P (from) && !(flags & LOOKUP_NO_CONVERSION))
{ {
conv = standard_conversion (to, rfrom, expr); /* [dcl.init.ref]
If the initializer exprsesion
-- has a class type (i.e., T2 is a class type) can be
implicitly converted to an lvalue of type "cv3 T3," where
"cv1 T1" is reference-compatible with "cv3 T3". (this
conversion is selected by enumerating the applicable
conversion functions (_over.match.ref_) and choosing the
best one through overload resolution. (_over.match_).
the reference is bound to the lvalue result of the conversion
in the second case. */
conv = convert_class_to_reference (to, from, expr);
if (conv) if (conv)
{ return direct_reference_binding (rto, conv);
conv = build_conv (REF_BIND, rto, conv); }
/* Bind directly to a base subobject of a class rvalue. Do it /* [over.ics.rank]
after building the conversion for proper handling of ICS_RANK. */
if (TREE_CODE (TREE_OPERAND (conv, 0)) == BASE_CONV) When a parameter of reference type is not bound directly to an
TREE_OPERAND (conv, 0) = TREE_OPERAND (TREE_OPERAND (conv, 0), 0); argument expression, the conversion sequence is the one required
} to convert the argument expression to the underlying type of the
if (conv reference according to _over.best.ics_. Conceptually, this
&& ((! (CP_TYPE_CONST_NON_VOLATILE_P (to) conversion sequence corresponds to copy-initializing a temporary
&& (flags & LOOKUP_NO_TEMP_BIND) == 0)) of the underlying type with the argument expression. Any
/* If T1 is reference-related to T2, cv1 must be the same difference in top-level cv-qualification is subsumed by the
cv-qualification as, or greater cv-qualification than, initialization itself and does not constitute a conversion. */
cv2; otherwise, the program is ill-formed. */
|| (related && !at_least_as_qualified_p (to, from)))) /* [dcl.init.ref]
ICS_BAD_FLAG (conv) = 1;
Otherwise, the reference shall be to a non-volatile const type. */
if (!CP_TYPE_CONST_NON_VOLATILE_P (to))
return NULL_TREE;
/* [dcl.init.ref]
If the initializer expression is an rvalue, with T2 a class type,
and "cv1 T1" is reference-compatible with "cv2 T2", the reference
is bound in one of the following ways:
-- The reference is bound to the object represented by the rvalue
or to a sub-object within that object.
In this case, the implicit conversion sequence is supposed to be
same as we would obtain by generating a temporary. Fortunately,
if the types are reference compatible, then this is either an
identity conversion or the derived-to-base conversion, just as
for direct binding. */
if (CLASS_TYPE_P (from) && compatible_p)
{
conv = build1 (IDENTITY_CONV, from, expr);
return direct_reference_binding (rto, conv);
} }
/* [dcl.init.ref]
Otherwise, a temporary of type "cv1 T1" is created and
initialized from the initializer expression using the rules for a
non-reference copy initialization. If T1 is reference-related to
T2, cv1 must be the same cv-qualification as, or greater
cv-qualification than, cv2; otherwise, the program is ill-formed. */
if (related_p && !at_least_as_qualified_p (to, from))
return NULL_TREE;
conv = implicit_conversion (to, from, expr, flags);
if (!conv)
return NULL_TREE;
conv = build_conv (REF_BIND, rto, conv);
/* This reference binding, unlike those above, requires the
creation of a temporary. */
NEED_TEMPORARY_P (conv) = 1;
return conv; return conv;
} }
...@@ -2885,7 +3159,8 @@ convert_like (convs, expr) ...@@ -2885,7 +3159,8 @@ convert_like (convs, expr)
{ {
if (ICS_BAD_FLAG (convs) if (ICS_BAD_FLAG (convs)
&& TREE_CODE (convs) != USER_CONV && TREE_CODE (convs) != USER_CONV
&& TREE_CODE (convs) != AMBIG_CONV) && TREE_CODE (convs) != AMBIG_CONV
&& TREE_CODE (convs) != REF_BIND)
{ {
tree t = convs; tree t = convs;
for (; t; t = TREE_OPERAND (t, 0)) for (; t; t = TREE_OPERAND (t, 0))
...@@ -2938,8 +3213,6 @@ convert_like (convs, expr) ...@@ -2938,8 +3213,6 @@ convert_like (convs, expr)
case IDENTITY_CONV: case IDENTITY_CONV:
if (type_unknown_p (expr)) if (type_unknown_p (expr))
expr = instantiate_type (TREE_TYPE (convs), expr, 1); expr = instantiate_type (TREE_TYPE (convs), expr, 1);
if (TREE_READONLY_DECL_P (expr))
expr = decl_constant_value (expr);
return expr; return expr;
case AMBIG_CONV: case AMBIG_CONV:
/* Call build_user_type_conversion again for the error. */ /* Call build_user_type_conversion again for the error. */
...@@ -2954,6 +3227,12 @@ convert_like (convs, expr) ...@@ -2954,6 +3227,12 @@ convert_like (convs, expr)
if (expr == error_mark_node) if (expr == error_mark_node)
return error_mark_node; return error_mark_node;
/* Convert a constant variable to its underlying value, unless we
are about to bind it to a reference, in which case we need to
leave it as an lvalue. */
if (TREE_READONLY_DECL_P (expr) && TREE_CODE (convs) != REF_BIND)
expr = decl_constant_value (expr);
switch (TREE_CODE (convs)) switch (TREE_CODE (convs))
{ {
case RVALUE_CONV: case RVALUE_CONV:
...@@ -2961,6 +3240,12 @@ convert_like (convs, expr) ...@@ -2961,6 +3240,12 @@ convert_like (convs, expr)
return expr; return expr;
/* else fall through */ /* else fall through */
case BASE_CONV: case BASE_CONV:
if (TREE_CODE (convs) == BASE_CONV
&& !NEED_TEMPORARY_P (convs))
/* We are going to bind a reference directly to a base-class
subobject of EXPR. We don't have to generate any code
here. */
return expr;
{ {
tree cvt_expr = build_user_type_conversion tree cvt_expr = build_user_type_conversion
(TREE_TYPE (convs), expr, LOOKUP_NORMAL); (TREE_TYPE (convs), expr, LOOKUP_NORMAL);
...@@ -2988,10 +3273,37 @@ convert_like (convs, expr) ...@@ -2988,10 +3273,37 @@ convert_like (convs, expr)
} }
case REF_BIND: case REF_BIND:
return convert_to_reference {
(TREE_TYPE (convs), expr, tree ref_type = TREE_TYPE (convs);
CONV_IMPLICIT, LOOKUP_NORMAL|LOOKUP_NO_CONVERSION,
error_mark_node); /* If necessary, create a temporary. */
if (NEED_TEMPORARY_P (convs))
{
tree type = TREE_TYPE (TREE_OPERAND (convs, 0));
tree slot = build_decl (VAR_DECL, NULL_TREE, type);
DECL_ARTIFICIAL (slot) = 1;
expr = build (TARGET_EXPR, type, slot, expr,
NULL_TREE, NULL_TREE);
TREE_SIDE_EFFECTS (expr) = 1;
}
/* Take the address of the thing to which we will bind the
reference. */
expr = build_unary_op (ADDR_EXPR, expr, 1);
if (expr == error_mark_node)
return error_mark_node;
/* Convert it to a pointer to the type referred to by the
reference. This will adjust the pointer if a derived to
base conversion is being performed. */
expr = cp_convert (build_pointer_type (TREE_TYPE (ref_type)),
expr);
/* Convert the pointer to the desired reference type. */
expr = build1 (NOP_EXPR, ref_type, expr);
return expr;
}
case LVALUE_CONV: case LVALUE_CONV:
return decay_conversion (expr); return decay_conversion (expr);
...@@ -3687,43 +3999,8 @@ maybe_handle_ref_bind (ics, target_type) ...@@ -3687,43 +3999,8 @@ maybe_handle_ref_bind (ics, target_type)
{ {
if (TREE_CODE (*ics) == REF_BIND) if (TREE_CODE (*ics) == REF_BIND)
{ {
/* [over.ics.rank]
When a parameter of reference type binds directly
(_dcl.init.ref_) to an argument expression, the implicit
conversion sequence is the identity conversion, unless the
argument expression has a type that is a derived class of the
parameter type, in which case the implicit conversion
sequence is a derived-to-base Conversion.
If the parameter binds directly to the result of applying a
conversion function to the argument expression, the implicit
conversion sequence is a user-defined conversion sequence
(_over.ics.user_), with the second standard conversion
sequence either an identity conversion or, if the conversion
function returns an entity of a type that is a derived class
of the parameter type, a derived-to-base Conversion.
When a parameter of reference type is not bound directly to
an argument expression, the conversion sequence is the one
required to convert the argument expression to the underlying
type of the reference according to _over.best.ics_.
Conceptually, this conversion sequence corresponds to
copy-initializing a temporary of the underlying type with the
argument expression. Any difference in top-level
cv-qualification is subsumed by the initialization itself and
does not constitute a conversion. */
tree old_ics = *ics;
*target_type = TREE_TYPE (TREE_TYPE (*ics)); *target_type = TREE_TYPE (TREE_TYPE (*ics));
*ics = TREE_OPERAND (*ics, 0); *ics = TREE_OPERAND (*ics, 0);
if (TREE_CODE (*ics) == IDENTITY_CONV
&& is_properly_derived_from (TREE_TYPE (*ics), *target_type))
*ics = build_conv (BASE_CONV, *target_type, *ics);
ICS_USER_FLAG (*ics) = ICS_USER_FLAG (old_ics);
ICS_BAD_FLAG (*ics) = ICS_BAD_FLAG (old_ics);
return 1; return 1;
} }
...@@ -4386,3 +4663,24 @@ can_convert_arg (to, from, arg) ...@@ -4386,3 +4663,24 @@ can_convert_arg (to, from, arg)
tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL); tree t = implicit_conversion (to, from, arg, LOOKUP_NORMAL);
return (t && ! ICS_BAD_FLAG (t)); return (t && ! ICS_BAD_FLAG (t));
} }
/* Convert EXPR to the indicated reference TYPE, in a way suitable for
initializing a variable of that TYPE. Return the converted
expression. */
tree
initialize_reference (type, expr)
tree type;
tree expr;
{
tree conv;
conv = reference_binding (type, TREE_TYPE (expr), expr, LOOKUP_NORMAL);
if (!conv || ICS_BAD_FLAG (conv))
{
cp_error ("could not convert `%E' to `%T'", expr, type);
return error_mark_node;
}
return convert_like (conv, expr);
}
...@@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -34,6 +34,7 @@ Boston, MA 02111-1307, USA. */
TREE_INDIRECT_USING (in NAMESPACE_DECL). TREE_INDIRECT_USING (in NAMESPACE_DECL).
IDENTIFIER_MARKED (used by search routines). IDENTIFIER_MARKED (used by search routines).
LOCAL_BINDING_P (in CPLUS_BINDING) LOCAL_BINDING_P (in CPLUS_BINDING)
ICS_USER_FLAG (in _CONV)
1: IDENTIFIER_VIRTUAL_P. 1: IDENTIFIER_VIRTUAL_P.
TI_PENDING_TEMPLATE_FLAG. TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE. TEMPLATE_PARMS_FOR_INLINE.
...@@ -43,17 +44,21 @@ Boston, MA 02111-1307, USA. */ ...@@ -43,17 +44,21 @@ Boston, MA 02111-1307, USA. */
C_DECLARED_LABEL_FLAG. C_DECLARED_LABEL_FLAG.
INHERITED_VALUE_BINDING_P (in CPLUS_BINDING) INHERITED_VALUE_BINDING_P (in CPLUS_BINDING)
BASELINK_P (in TREE_LIST) BASELINK_P (in TREE_LIST)
ICS_ELLIPSIS_FLAG (in _CONV)
2: IDENTIFIER_OPNAME_P. 2: IDENTIFIER_OPNAME_P.
BINFO_VBASE_MARKED. BINFO_VBASE_MARKED.
BINFO_FIELDS_MARKED. BINFO_FIELDS_MARKED.
TYPE_VIRTUAL_P. TYPE_VIRTUAL_P.
ICS_THIS_FLAG (in _CONV)
3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE). 3: TYPE_USES_VIRTUAL_BASECLASSES (in a class TYPE).
BINFO_VTABLE_PATH_MARKED. BINFO_VTABLE_PATH_MARKED.
BINFO_PUSHDECLS_MARKED. BINFO_PUSHDECLS_MARKED.
(TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out). (TREE_REFERENCE_EXPR) (in NON_LVALUE_EXPR) (commented-out).
ICS_BAD_FLAG (in _CONV)
4: BINFO_NEW_VTABLE_MARKED. 4: BINFO_NEW_VTABLE_MARKED.
TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR, TREE_HAS_CONSTRUCTOR (in INDIRECT_REF, SAVE_EXPR, CONSTRUCTOR,
or FIELD_DECL). or FIELD_DECL).
NEED_TEMPORARY_P (in REF_BIND, BASE_CONV)
5: Not used. 5: Not used.
6: Not used. 6: Not used.
...@@ -2140,6 +2145,14 @@ extern int flag_new_for_scope; ...@@ -2140,6 +2145,14 @@ extern int flag_new_for_scope;
enum tag_types { record_type, class_type, union_type, enum_type, enum tag_types { record_type, class_type, union_type, enum_type,
signature_type }; signature_type };
/* The various kinds of lvalues we distinguish. */
typedef enum cp_lvalue_kind {
clk_none = 0, /* Things that are not an lvalue. */
clk_ordinary = 1, /* An ordinary lvalue. */
clk_class = 2, /* An rvalue of class-type. */
clk_bitfield = 4, /* An lvalue for a bit-field. */
} cp_lvalue_kind;
/* Zero means prototype weakly, as in ANSI C (no args means nothing). /* Zero means prototype weakly, as in ANSI C (no args means nothing).
Each language context defines how this variable should be set. */ Each language context defines how this variable should be set. */
extern int strict_prototype; extern int strict_prototype;
...@@ -2753,6 +2766,7 @@ extern int enforce_access PROTO((tree, tree)); ...@@ -2753,6 +2766,7 @@ extern int enforce_access PROTO((tree, tree));
extern tree convert_default_arg PROTO((tree, tree, tree)); extern tree convert_default_arg PROTO((tree, tree, tree));
extern tree convert_arg_to_ellipsis PROTO((tree)); extern tree convert_arg_to_ellipsis PROTO((tree));
extern int is_properly_derived_from PROTO((tree, tree)); extern int is_properly_derived_from PROTO((tree, tree));
extern tree initialize_reference PROTO((tree, tree));
/* in class.c */ /* in class.c */
extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int)); extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
...@@ -3363,7 +3377,7 @@ extern tree arbitrate_lookup PROTO((tree, tree, tree)); ...@@ -3363,7 +3377,7 @@ extern tree arbitrate_lookup PROTO((tree, tree, tree));
extern int pod_type_p PROTO((tree)); extern int pod_type_p PROTO((tree));
extern void unshare_base_binfos PROTO((tree)); extern void unshare_base_binfos PROTO((tree));
extern int member_p PROTO((tree)); extern int member_p PROTO((tree));
extern int real_lvalue_p PROTO((tree)); extern cp_lvalue_kind real_lvalue_p PROTO((tree));
extern tree build_min PVPROTO((enum tree_code, tree, ...)); extern tree build_min PVPROTO((enum tree_code, tree, ...));
extern tree build_min_nt PVPROTO((enum tree_code, ...)); extern tree build_min_nt PVPROTO((enum tree_code, ...));
extern tree min_tree_cons PROTO((tree, tree, tree)); extern tree min_tree_cons PROTO((tree, tree, tree));
......
...@@ -1409,7 +1409,22 @@ dump_expr (t, nop) ...@@ -1409,7 +1409,22 @@ dump_expr (t, nop)
break; break;
case AGGR_INIT_EXPR: case AGGR_INIT_EXPR:
{
tree fn = NULL_TREE;
if (TREE_CODE (TREE_OPERAND (t, 0)) == ADDR_EXPR)
fn = TREE_OPERAND (TREE_OPERAND (t, 0), 0);
if (fn && TREE_CODE (fn) == FUNCTION_DECL)
{
if (DECL_CONSTRUCTOR_P (fn))
OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t))); OB_PUTID (TYPE_IDENTIFIER (TREE_TYPE (t)));
else
dump_decl (fn, 0);
}
else
dump_expr (TREE_OPERAND (t, 0), 0);
}
OB_PUTC ('('); OB_PUTC ('(');
if (TREE_OPERAND (t, 1)) if (TREE_OPERAND (t, 1))
dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1))); dump_expr_list (TREE_CHAIN (TREE_OPERAND (t, 1)));
......
...@@ -1177,6 +1177,10 @@ expand_default_init (binfo, true_exp, exp, init, flags) ...@@ -1177,6 +1177,10 @@ expand_default_init (binfo, true_exp, exp, init, flags)
to run a new constructor; and catching an exception, where we to run a new constructor; and catching an exception, where we
have already built up the constructor call so we could wrap it have already built up the constructor call so we could wrap it
in an exception region. */; in an exception region. */;
else if (TREE_CODE (init) == CONSTRUCTOR)
/* A brace-enclosed initializer has whatever type is
required. There's no need to convert it. */
;
else else
init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags); init = ocp_convert (type, init, CONV_IMPLICIT|CONV_FORCE_TEMP, flags);
......
...@@ -3150,6 +3150,12 @@ add_conversions (binfo, data) ...@@ -3150,6 +3150,12 @@ add_conversions (binfo, data)
return NULL_TREE; return NULL_TREE;
} }
/* Return a TREE_LIST containing all the non-hidden user-defined
conversion functions for TYPE (and its base-classes). The
TREE_VALUE of each node is a FUNCTION_DECL or an OVERLOAD
containing the conversion functions. The TREE_PURPOSE is the BINFO
from which the conversion functions in this node were selected. */
tree tree
lookup_conversions (type) lookup_conversions (type)
tree type; tree type;
......
...@@ -36,27 +36,30 @@ static int list_hash PROTO((tree, tree, tree)); ...@@ -36,27 +36,30 @@ static int list_hash PROTO((tree, tree, tree));
static tree list_hash_lookup PROTO((int, tree, tree, tree)); static tree list_hash_lookup PROTO((int, tree, tree, tree));
static void propagate_binfo_offsets PROTO((tree, tree)); static void propagate_binfo_offsets PROTO((tree, tree));
static int avoid_overlap PROTO((tree, tree)); static int avoid_overlap PROTO((tree, tree));
static int lvalue_p_1 PROTO((tree, int)); static cp_lvalue_kind lvalue_p_1 PROTO((tree, int));
static int equal_functions PROTO((tree, tree)); static int equal_functions PROTO((tree, tree));
static tree no_linkage_helper PROTO((tree)); static tree no_linkage_helper PROTO((tree));
static tree build_srcloc PROTO((char *, int)); static tree build_srcloc PROTO((char *, int));
#define CEIL(x,y) (((x) + (y) - 1) / (y)) #define CEIL(x,y) (((x) + (y) - 1) / (y))
/* Returns non-zero if REF is an lvalue. If /* If REF is an lvalue, returns the kind of lvalue that REF is.
TREAT_CLASS_RVALUES_AS_LVALUES is non-zero, rvalues of class type Otherwise, returns clk_none. If TREAT_CLASS_RVALUES_AS_LVALUES is
are considered lvalues. */ non-zero, rvalues of class type are considered lvalues. */
static int static cp_lvalue_kind
lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
tree ref; tree ref;
int treat_class_rvalues_as_lvalues; int treat_class_rvalues_as_lvalues;
{ {
cp_lvalue_kind op1_lvalue_kind = clk_none;
cp_lvalue_kind op2_lvalue_kind = clk_none;
if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE) if (TREE_CODE (TREE_TYPE (ref)) == REFERENCE_TYPE)
return 1; return clk_ordinary;
if (ref == current_class_ptr && flag_this_is_variable <= 0) if (ref == current_class_ptr && flag_this_is_variable <= 0)
return 0; return clk_none;
switch (TREE_CODE (ref)) switch (TREE_CODE (ref))
{ {
...@@ -64,7 +67,6 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) ...@@ -64,7 +67,6 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
what they refer to are valid lvals. */ what they refer to are valid lvals. */
case PREINCREMENT_EXPR: case PREINCREMENT_EXPR:
case PREDECREMENT_EXPR: case PREDECREMENT_EXPR:
case COMPONENT_REF:
case SAVE_EXPR: case SAVE_EXPR:
case UNSAVE_EXPR: case UNSAVE_EXPR:
case TRY_CATCH_EXPR: case TRY_CATCH_EXPR:
...@@ -75,20 +77,37 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) ...@@ -75,20 +77,37 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
return lvalue_p_1 (TREE_OPERAND (ref, 0), return lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues); treat_class_rvalues_as_lvalues);
case COMPONENT_REF:
op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
if (op1_lvalue_kind
/* The "field" can be a FUNCTION_DECL or an OVERLOAD in some
situations. */
&& TREE_CODE (TREE_OPERAND (ref, 1)) == FIELD_DECL
&& DECL_BIT_FIELD (TREE_OPERAND (ref, 1)))
{
/* Clear the ordinary bit. If this object was a class
rvalue we want to preserve that information. */
op1_lvalue_kind &= ~clk_ordinary;
/* The lvalue is for a btifield. */
op1_lvalue_kind |= clk_bitfield;
}
return op1_lvalue_kind;
case STRING_CST: case STRING_CST:
return 1; return clk_ordinary;
case VAR_DECL: case VAR_DECL:
if (TREE_READONLY (ref) && ! TREE_STATIC (ref) if (TREE_READONLY (ref) && ! TREE_STATIC (ref)
&& DECL_LANG_SPECIFIC (ref) && DECL_LANG_SPECIFIC (ref)
&& DECL_IN_AGGR_P (ref)) && DECL_IN_AGGR_P (ref))
return 0; return clk_none;
case INDIRECT_REF: case INDIRECT_REF:
case ARRAY_REF: case ARRAY_REF:
case PARM_DECL: case PARM_DECL:
case RESULT_DECL: case RESULT_DECL:
if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE) if (TREE_CODE (TREE_TYPE (ref)) != METHOD_TYPE)
return 1; return clk_ordinary;
break; break;
/* A currently unresolved scope ref. */ /* A currently unresolved scope ref. */
...@@ -96,72 +115,84 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues) ...@@ -96,72 +115,84 @@ lvalue_p_1 (ref, treat_class_rvalues_as_lvalues)
my_friendly_abort (103); my_friendly_abort (103);
case OFFSET_REF: case OFFSET_REF:
if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL) if (TREE_CODE (TREE_OPERAND (ref, 1)) == FUNCTION_DECL)
return 1; return clk_ordinary;
return (lvalue_p_1 (TREE_OPERAND (ref, 0), /* Fall through. */
treat_class_rvalues_as_lvalues) case MAX_EXPR:
&& lvalue_p_1 (TREE_OPERAND (ref, 1), case MIN_EXPR:
treat_class_rvalues_as_lvalues)); op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues);
op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues);
break; break;
case COND_EXPR: case COND_EXPR:
return (lvalue_p_1 (TREE_OPERAND (ref, 1), op1_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues) treat_class_rvalues_as_lvalues);
&& lvalue_p_1 (TREE_OPERAND (ref, 2), op2_lvalue_kind = lvalue_p_1 (TREE_OPERAND (ref, 2),
treat_class_rvalues_as_lvalues)); treat_class_rvalues_as_lvalues);
break;
case MODIFY_EXPR: case MODIFY_EXPR:
return 1; return clk_ordinary;
case COMPOUND_EXPR: case COMPOUND_EXPR:
return lvalue_p_1 (TREE_OPERAND (ref, 1), return lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues); treat_class_rvalues_as_lvalues);
case MAX_EXPR:
case MIN_EXPR:
return (lvalue_p_1 (TREE_OPERAND (ref, 0),
treat_class_rvalues_as_lvalues)
&& lvalue_p_1 (TREE_OPERAND (ref, 1),
treat_class_rvalues_as_lvalues));
case TARGET_EXPR: case TARGET_EXPR:
return treat_class_rvalues_as_lvalues; return treat_class_rvalues_as_lvalues ? clk_class : clk_none;
case CALL_EXPR: case CALL_EXPR:
return (treat_class_rvalues_as_lvalues return ((treat_class_rvalues_as_lvalues
&& IS_AGGR_TYPE (TREE_TYPE (ref))); && IS_AGGR_TYPE (TREE_TYPE (ref)))
? clk_class : clk_none);
case FUNCTION_DECL: case FUNCTION_DECL:
/* All functions (except non-static-member functions) are /* All functions (except non-static-member functions) are
lvalues. */ lvalues. */
return !DECL_NONSTATIC_MEMBER_FUNCTION_P (ref); return (DECL_NONSTATIC_MEMBER_FUNCTION_P (ref)
? clk_none : clk_ordinary);
default: default:
break; break;
} }
return 0; /* If one operand is not an lvalue at all, then this expression is
not an lvalue. */
if (!op1_lvalue_kind || !op2_lvalue_kind)
return clk_none;
/* Otherwise, it's an lvalue, and it has all the odd properties
contributed by either operand. */
op1_lvalue_kind = op1_lvalue_kind | op2_lvalue_kind;
/* It's not an ordinary lvalue if it involves either a bit-field or
a class rvalue. */
if ((op1_lvalue_kind & ~clk_ordinary) != clk_none)
op1_lvalue_kind &= ~clk_ordinary;
return op1_lvalue_kind;
} }
/* Return nonzero if REF is an lvalue valid for this language. /* If REF is an lvalue, returns the kind of lvalue that REF is.
Lvalues can be assigned, unless they have TREE_READONLY, or unless Otherwise, returns clk_none. Lvalues can be assigned, unless they
they are FUNCTION_DECLs. Lvalues can have their address taken, have TREE_READONLY, or unless they are FUNCTION_DECLs. Lvalues can
unless they have DECL_REGISTER. */ have their address taken, unless they have DECL_REGISTER. */
int cp_lvalue_kind
real_lvalue_p (ref) real_lvalue_p (ref)
tree ref; tree ref;
{ {
return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0); return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/0);
} }
/* This differs from real_lvalue_p in that class rvalues are considered /* This differs from real_lvalue_p in that class rvalues are
lvalues. */ considered lvalues. */
int int
lvalue_p (ref) lvalue_p (ref)
tree ref; tree ref;
{ {
return lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1); return
(lvalue_p_1 (ref, /*treat_class_rvalues_as_lvalues=*/1) != clk_none);
} }
/* Return nonzero if REF is an lvalue valid for this language; /* Return nonzero if REF is an lvalue valid for this language;
...@@ -193,6 +224,11 @@ build_cplus_new (type, init) ...@@ -193,6 +224,11 @@ build_cplus_new (type, init)
tree slot; tree slot;
tree rval; tree rval;
/* Make sure that we're not trying to create an instance of an
abstract class. */
if (CLASSTYPE_ABSTRACT_VIRTUALS (type))
abstract_virtuals_error (NULL_TREE, type);
if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR) if (TREE_CODE (init) != CALL_EXPR && TREE_CODE (init) != AGGR_INIT_EXPR)
return convert (type, init); return convert (type, init);
......
...@@ -7122,8 +7122,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum) ...@@ -7122,8 +7122,7 @@ convert_for_initialization (exp, type, rhs, flags, errtype, fndecl, parmnum)
if (fndecl) if (fndecl)
savew = warningcount, savee = errorcount; savew = warningcount, savee = errorcount;
rhs = convert_to_reference (type, rhs, CONV_IMPLICIT, flags, rhs = initialize_reference (type, rhs);
exp ? exp : error_mark_node);
if (fndecl) if (fndecl)
{ {
if (warningcount > savew) if (warningcount > savew)
......
// Build don't link: // Build don't link:
// Based on a bug report by Stephen Vavasis <vavasis@CS.Cornell.EDU> // Based on a bug report by Stephen Vavasis <vavasis@CS.Cornell.EDU>
// excess errors test - XFAIL *-*-*
// declares template operator!= // declares template operator!=
#include <utility> #include <utility>
......
//Build don't link: //Build don't link:
// the template operator!= interferes. It should be in a namespace. // the template operator!= interferes. It should be in a namespace.
// excess errors test - XFAIL *-*-*
#include <utility> #include <utility>
......
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