Commit a7a64a77 by Mark Mitchell Committed by Mark Mitchell

cp-tree.h (CP_INTEGRAL_TYPE_P): New macro.

	* cp-tree.h (CP_INTEGRAL_TYPE_P): New macro.
	(ARITHMETIC_TYPE_P): Adjust definition for standard conformance.
	(strip_top_quals): Declare.
	(ncp_convert): Likewise.
	(type_after_usual_arithmetic_converions): Likewise.
	(composite_pointer_type): Likewise.
	* call.c (strip_top_quals): Don't make it static.
	(promoted_arithmetic_type_p): New function.
	(conditional_conversion): Likewise.
	(null_ptr_cst_p): Allow `false' as a NULL pointer constant.
	(standard_conversion): Use same_type_p.  Don't build BASE_CONVs
	for converting a type to itself.
	(reference_binding): Honor LOOKUP_NO_TEMP_BIND.
	(implicit_conversion): Make sure the from and to types are
	complete.
	(add_builtin_candidate): Correct handling of ?: operator.
	(add_builtin_candidates): Improve documentation.
	(build_conditional_expr): New function.
	(can_convert): Implement in terms of can_convert_arg.
	(ncp_convert): New function.
	* typeck.c (type_after_usual_arithmetic_conversions): New
	function, split out from common_type.
	(composite_pointer_type): New function, split out from
	build_conditional_expr.
	(common_type): Use type_after_usual_arithmetic_conversions.
	Remove redundant attribute merging.
	(comptypes): Tidy.  Handle COMPLEX_TYPE.
	(build_binary_op_nodefault): Use null_ptr_cst_p.
	(build_conditional_expr): Remove.
	(convert_for_assignment): Use new conversion functions.

	* cp-tree.h (abstract_virtuals_error): Change declaration.
	* typeck2.c (abstract_virtuals_error): Check to see if an error
	ocurred, and return a boolean value accordingly.
	(build_functional_cast): Adjust accordingly.
	* class.c (finish_struct_1): Likewise.
	* cvt.c (ocp_convert): Likewise.
	* decl.c (cp_finish_decl): Likewise.
	(grokparams): Likewise.
	(grok_op_properties): Likewise.
	(start_function): Likewise.
	* init.c (build_new_1): Likewise.

	* pt.c (unify): Don't get confused by pointers-to-member functions.

	* search.c (build_cplus_new): Robustify.

From-SVN: r28262
parent 5cabd6f5
1999-07-26 Mark Mitchell <mark@codesourcery.com>
* cp-tree.h (CP_INTEGRAL_TYPE_P): New macro.
(ARITHMETIC_TYPE_P): Adjust definition for standard conformance.
(strip_top_quals): Declare.
(ncp_convert): Likewise.
(type_after_usual_arithmetic_converions): Likewise.
(composite_pointer_type): Likewise.
* call.c (strip_top_quals): Don't make it static.
(promoted_arithmetic_type_p): New function.
(conditional_conversion): Likewise.
(null_ptr_cst_p): Allow `false' as a NULL pointer constant.
(standard_conversion): Use same_type_p. Don't build BASE_CONVs
for converting a type to itself.
(reference_binding): Honor LOOKUP_NO_TEMP_BIND.
(implicit_conversion): Make sure the from and to types are
complete.
(add_builtin_candidate): Correct handling of ?: operator.
(add_builtin_candidates): Improve documentation.
(build_conditional_expr): New function.
(can_convert): Implement in terms of can_convert_arg.
(ncp_convert): New function.
* typeck.c (type_after_usual_arithmetic_conversions): New
function, split out from common_type.
(composite_pointer_type): New function, split out from
build_conditional_expr.
(common_type): Use type_after_usual_arithmetic_conversions.
Remove redundant attribute merging.
(comptypes): Tidy. Handle COMPLEX_TYPE.
(build_binary_op_nodefault): Use null_ptr_cst_p.
(build_conditional_expr): Remove.
(convert_for_assignment): Use new conversion functions.
* cp-tree.h (abstract_virtuals_error): Change declaration.
* typeck2.c (abstract_virtuals_error): Check to see if an error
ocurred, and return a boolean value accordingly.
(build_functional_cast): Adjust accordingly.
* class.c (finish_struct_1): Likewise.
* cvt.c (ocp_convert): Likewise.
* decl.c (cp_finish_decl): Likewise.
(grokparams): Likewise.
(grok_op_properties): Likewise.
(start_function): Likewise.
* init.c (build_new_1): Likewise.
* pt.c (unify): Don't get confused by pointers-to-member functions.
* search.c (build_cplus_new): Robustify.
1999-07-24 Richard Henderson <rth@cygnus.com>
* decl.c (ptr_type_node, va_list_type_node): New.
......
......@@ -82,7 +82,6 @@ static struct z_candidate * add_function_candidate
static tree implicit_conversion PROTO((tree, tree, tree, int));
static tree standard_conversion PROTO((tree, tree, tree));
static tree reference_binding PROTO((tree, tree, tree, int));
static tree strip_top_quals PROTO((tree));
static tree non_reference PROTO((tree));
static tree build_conv PROTO((enum tree_code, tree, tree));
static int is_subseq PROTO((tree, tree));
......@@ -96,6 +95,8 @@ 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));
static int promoted_arithmetic_type_p PROTO ((tree));
static tree conditional_conversion PROTO ((tree, tree));
tree
build_vfield_ref (datum, type)
......@@ -550,8 +551,12 @@ int
null_ptr_cst_p (t)
tree t;
{
/* [conv.ptr]
A null pointer constant is an integral constant expression
(_expr.const_) rvalue of integer type that evaluates to zero. */
if (t == null_node
|| (integer_zerop (t) && TREE_CODE (TREE_TYPE (t)) == INTEGER_TYPE))
|| (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)) && integer_zerop (t)))
return 1;
return 0;
}
......@@ -595,7 +600,7 @@ non_reference (t)
return t;
}
static tree
tree
strip_top_quals (t)
tree t;
{
......@@ -655,7 +660,7 @@ standard_conversion (to, from, expr)
else if (fromref || (expr && real_lvalue_p (expr)))
conv = build_conv (RVALUE_CONV, from, conv);
if (from == to)
if (same_type_p (from, to))
return conv;
if ((tcode == POINTER_TYPE || TYPE_PTRMEMFUNC_P (to))
......@@ -770,7 +775,7 @@ standard_conversion (to, from, expr)
ICS_STD_RANK (conv) = PROMO_RANK;
}
else if (IS_AGGR_TYPE (to) && IS_AGGR_TYPE (from)
&& DERIVED_FROM_P (to, from))
&& is_properly_derived_from (from, to))
{
if (TREE_CODE (conv) == RVALUE_CONV)
conv = TREE_OPERAND (conv, 0);
......@@ -1069,6 +1074,11 @@ reference_binding (rto, rfrom, expr, flags)
return direct_reference_binding (rto, conv);
}
/* From this point on, we conceptually need temporaries, even if we
elide them. Only the cases above are "direct bindings". */
if (flags & LOOKUP_NO_TEMP_BIND)
return NULL_TREE;
/* [over.ics.rank]
When a parameter of reference type is not bound directly to an
......@@ -1141,6 +1151,9 @@ implicit_conversion (to, from, expr, flags)
tree conv;
struct z_candidate *cand;
complete_type (from);
complete_type (to);
if (TREE_CODE (to) == REFERENCE_TYPE)
conv = reference_binding (to, from, expr, flags);
else
......@@ -1461,6 +1474,24 @@ is_complete (t)
return TYPE_SIZE (complete_type (t)) != NULL_TREE;
}
/* Returns non-zero if TYPE is a promoted arithmetic type. */
static int
promoted_arithmetic_type_p (type)
tree type;
{
/* [over.built]
In this section, the term promoted integral type is used to refer
to those integral types which are preserved by integral promotion
(including e.g. int and long but excluding e.g. char).
Similarly, the term promoted arithmetic type refers to promoted
integral types plus floating types. */
return ((INTEGRAL_TYPE_P (type)
&& same_type_p (type_promotes_to (type), type))
|| TREE_CODE (type) == REAL_TYPE);
}
/* Create any builtin operator overload candidates for the operator in
question given the converted operand types TYPE1 and TYPE2. The other
args are passed through from add_builtin_candidates to
......@@ -1800,43 +1831,41 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
break;
case COND_EXPR:
/* Kludge around broken overloading rules whereby
bool ? const char& : enum is ambiguous
(between int and const char&). */
flags |= LOOKUP_NO_TEMP_BIND;
/* [over.builtin]
/* Extension: Support ?: of enumeral type. Hopefully this will not
be an extension for long. */
if (TREE_CODE (type1) == ENUMERAL_TYPE && type1 == type2)
break;
else if (TREE_CODE (type1) == ENUMERAL_TYPE
|| TREE_CODE (type2) == ENUMERAL_TYPE)
return candidates;
if (ARITHMETIC_TYPE_P (type1) && ARITHMETIC_TYPE_P (type2))
break;
if (TREE_CODE (type1) == TREE_CODE (type2)
&& (TREE_CODE (type1) == REFERENCE_TYPE
|| TREE_CODE (type1) == POINTER_TYPE
|| TYPE_PTRMEMFUNC_P (type1)
|| IS_AGGR_TYPE (type1)))
For every pair of promoted arithmetic types L and R, there
exist candidate operator functions of the form
LR operator?(bool, L, R);
where LR is the result of the usual arithmetic conversions
between types L and R.
For every type T, where T is a pointer or pointer-to-member
type, there exist candidate operator functions of the form T
operator?(bool, T, T); */
if (promoted_arithmetic_type_p (type1)
&& promoted_arithmetic_type_p (type2))
/* That's OK. */
break;
if (TREE_CODE (type1) == REFERENCE_TYPE
|| TREE_CODE (type2) == REFERENCE_TYPE)
/* Otherwise, the types should be pointers. */
if (!(TREE_CODE (type1) == POINTER_TYPE
|| TYPE_PTRMEM_P (type1)
|| TYPE_PTRMEMFUNC_P (type1))
|| !(TREE_CODE (type2) == POINTER_TYPE
|| TYPE_PTRMEM_P (type2)
|| TYPE_PTRMEMFUNC_P (type2)))
return candidates;
if (((TYPE_PTRMEMFUNC_P (type1) || TREE_CODE (type1) == POINTER_TYPE)
&& null_ptr_cst_p (args[1]))
|| IS_AGGR_TYPE (type1))
{
type2 = type1;
break;
}
if (((TYPE_PTRMEMFUNC_P (type2) || TREE_CODE (type2) == POINTER_TYPE)
&& null_ptr_cst_p (args[0]))
|| IS_AGGR_TYPE (type2))
{
type1 = type2;
/* We don't check that the two types are the same; the logic
below will actually create two candidates; one in which both
parameter types are TYPE1, and one in which both parameter
types are TYPE2. */
break;
}
/* These arguments do not make for a legal overloaded operator. */
return candidates;
default:
......@@ -1845,7 +1874,7 @@ add_builtin_candidate (candidates, code, code2, fnname, type1, type2,
/* If we're dealing with two pointer types, we need candidates
for both of them. */
if (type2 && type1 != type2
if (type2 && !same_type_p (type1, type2)
&& TREE_CODE (type1) == TREE_CODE (type2)
&& (TREE_CODE (type1) == REFERENCE_TYPE
|| (TREE_CODE (type1) == POINTER_TYPE
......@@ -1890,7 +1919,12 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
int flags;
{
int ref1, i;
tree type, argtypes[3], types[2];
tree type, argtypes[3];
/* TYPES[i] is the set of possible builtin-operator parameter types
we will consider for the Ith argument. These are represented as
a TREE_LIST; the TREE_VALUE of each node is the potential
parameter type. */
tree types[2];
for (i = 0; i < 3; ++i)
{
......@@ -2012,6 +2046,8 @@ add_builtin_candidates (candidates, code, code2, fnname, args, flags)
}
}
/* Run through the possible parameter types of both arguments,
creating candidates with those parameter types. */
for (; types[0]; types[0] = TREE_CHAIN (types[0]))
{
if (types[1])
......@@ -2635,6 +2671,374 @@ op_error (code, code2, arg1, arg2, arg3, problem)
}
}
/* Return the implicit conversion sequence that could be used to
convert E1 to E2 in [expr.cond]. */
static tree
conditional_conversion (e1, e2)
tree e1;
tree e2;
{
tree t1 = non_reference (TREE_TYPE (e1));
tree t2 = non_reference (TREE_TYPE (e2));
tree conv;
/* [expr.cond]
If E2 is an lvalue: E1 can be converted to match E2 if E1 can be
implicitly converted (clause _conv_) to the type "reference to
T2", subject to the constraint that in the conversion the
reference must bind directly (_dcl.init.ref_) to E1. */
if (real_lvalue_p (e2))
{
conv = implicit_conversion (build_reference_type (t2),
t1,
e1,
LOOKUP_NO_TEMP_BIND);
if (conv)
return conv;
}
/* [expr.cond]
If E1 and E2 have class type, and the underlying class types are
the same or one is a base class of the other: E1 can be converted
to match E2 if the class of T2 is the same type as, or a base
class of, the class of T1, and the cv-qualification of T2 is the
same cv-qualification as, or a greater cv-qualification than, the
cv-qualification of T1. If the conversion is applied, E1 is
changed to an rvalue of type T2 that still refers to the original
source class object (or the appropriate subobject thereof). */
if (CLASS_TYPE_P (t1) && CLASS_TYPE_P (t2)
&& same_or_base_type_p (TYPE_MAIN_VARIANT (t2),
TYPE_MAIN_VARIANT (t1)))
{
if (at_least_as_qualified_p (t2, t1))
{
conv = build1 (IDENTITY_CONV, t1, e1);
conv = build_conv (BASE_CONV, t2, conv);
return conv;
}
else
return NULL_TREE;
}
/* [expr.cond]
E1 can be converted to match E2 if E1 can be implicitly converted
to the type that expression E2 would have if E2 were converted to
an rvalue (or the type it has, if E2 is an rvalue). */
return implicit_conversion (t2, t1, e1, LOOKUP_NORMAL);
}
/* Implement [expr.cond]. ARG1, ARG2, and ARG3 are the three
arguments to the conditional expression. As an extension, g++
allows users to overload the ?: operator. By the time this
function is called, any suitable candidate functions are included
in CANDIDATES. */
tree
build_conditional_expr (arg1, arg2, arg3)
tree arg1;
tree arg2;
tree arg3;
{
tree arg2_type;
tree arg3_type;
tree result;
tree result_type = NULL_TREE;
int lvalue_p = 1;
struct z_candidate *candidates = 0;
struct z_candidate *cand;
/* As a G++ extension, the second argument to the conditional can be
omitted. (So that `a ? : c' is roughly equivalent to `a ? a :
c'.) If second operand is omitted, make sure it is calculated
only once. */
if (!arg2)
{
if (pedantic)
pedwarn ("ANSI C++ forbids omitting the middle term of a ?: expression");
arg1 = arg2 = save_expr (arg1);
}
/* If something has already gone wrong, just pass that fact up the
tree. */
if (arg1 == error_mark_node
|| arg2 == error_mark_node
|| arg3 == error_mark_node
|| TREE_TYPE (arg1) == error_mark_node
|| TREE_TYPE (arg2) == error_mark_node
|| TREE_TYPE (arg3) == error_mark_node)
return error_mark_node;
/* [expr.cond]
The first expr ession is implicitly converted to bool (clause
_conv_). */
arg1 = cp_convert (boolean_type_node, arg1);
/* [expr.cond]
If either the second or the third operand has type (possibly
cv-qualified) void, then the lvalue-to-rvalue (_conv.lval_),
array-to-pointer (_conv.array_), and function-to-pointer
(_conv.func_) standard conversions are performed on the second
and third operands. */
arg2_type = TREE_TYPE (arg2);
arg3_type = TREE_TYPE (arg3);
if (same_type_p (TYPE_MAIN_VARIANT (arg2_type), void_type_node)
|| same_type_p (TYPE_MAIN_VARIANT (arg3_type), void_type_node))
{
int arg2_void_p;
int arg3_void_p;
/* Do the conversions. We don't these for `void' type arguments
since it can't have any effect and since decay_conversion
does not handle that case gracefully. */
if (!same_type_p (TYPE_MAIN_VARIANT (arg2_type), void_type_node))
arg2 = decay_conversion (arg2);
if (!same_type_p (TYPE_MAIN_VARIANT (arg3_type), void_type_node))
arg3 = decay_conversion (arg3);
arg2_type = TREE_TYPE (arg2);
arg3_type = TREE_TYPE (arg3);
arg2_void_p = same_type_p (TYPE_MAIN_VARIANT (arg2_type),
void_type_node);
arg3_void_p = same_type_p (TYPE_MAIN_VARIANT (arg3_type),
void_type_node);
/* [expr.cond]
One of the following shall hold:
--The second or the third operand (but not both) is a
throw-expression (_except.throw_); the result is of the
type of the other and is an rvalue.
--Both the second and the third operands have type void; the
result is of type void and is an rvalue. */
if ((TREE_CODE (arg2) == THROW_EXPR)
^ (TREE_CODE (arg3) == THROW_EXPR))
result_type = ((TREE_CODE (arg2) == THROW_EXPR)
? arg2_type : arg3_type);
else if (arg2_void_p && arg3_void_p)
result_type = void_type_node;
else
{
cp_error ("`%E' has type `void' and is not a throw-expression",
arg2_void_p ? arg2 : arg3);
return error_mark_node;
}
lvalue_p = 0;
goto valid_operands;
}
/* [expr.cond]
Otherwise, if the second and third operand have different types,
and either has (possibly cv-qualified) class type, an attempt is
made to convert each of those operands to the type of the other. */
else if (!same_type_p (arg2_type, arg3_type)
&& (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type)))
{
tree conv2 = conditional_conversion (arg2, arg3);
tree conv3 = conditional_conversion (arg3, arg2);
/* [expr.cond]
If both can be converted, or one can be converted but the
conversion is ambiguous, the program is ill-formed. If
neither can be converted, the operands are left unchanged and
further checking is performed as described below. If exactly
one conversion is possible, that conversion is applied to the
chosen operand and the converted operand is used in place of
the original operand for the remainder of this section. */
if ((conv2 && !ICS_BAD_FLAG (conv2)
&& conv3 && !ICS_BAD_FLAG (conv3))
|| (conv2 && TREE_CODE (conv2) == AMBIG_CONV)
|| (conv3 && TREE_CODE (conv3) == AMBIG_CONV))
{
cp_error ("operands to ?: have different types");
return error_mark_node;
}
else if (conv2 && !ICS_BAD_FLAG (conv2))
{
arg2 = convert_like (conv2, arg2);
arg2_type = TREE_TYPE (arg2);
}
else if (conv3 && !ICS_BAD_FLAG (conv3))
{
arg3 = convert_like (conv3, arg3);
arg3_type = TREE_TYPE (arg3);
}
}
/* [expr.cond]
If the second and third operands are lvalues and have the same
type, the result is of that type and is an lvalue. */
arg2_type = non_reference (arg2_type);
arg3_type = non_reference (arg3_type);
if (real_lvalue_p (arg2) && real_lvalue_p (arg3) &&
same_type_p (arg2_type, arg3_type))
{
result_type = arg2_type;
goto valid_operands;
}
/* [expr.cond]
Otherwise, the result is an rvalue. If the second and third
operand do not have the same type, and either has (possibly
cv-qualified) class type, overload resolution is used to
determine the conversions (if any) to be applied to the operands
(_over.match.oper_, _over.built_). */
lvalue_p = 0;
if (!same_type_p (arg2_type, arg3_type)
&& (CLASS_TYPE_P (arg2_type) || CLASS_TYPE_P (arg3_type)))
{
tree args[3];
tree conv;
/* Rearrange the arguments so that add_builtin_candidate only has
to know about two args. In build_builtin_candidates, the
arguments are unscrambled. */
args[0] = arg2;
args[1] = arg3;
args[2] = arg1;
candidates = add_builtin_candidates (candidates,
COND_EXPR,
NOP_EXPR,
ansi_opname[COND_EXPR],
args,
LOOKUP_NORMAL);
/* [expr.cond]
If the overload resolution fails, the program is
ill-formed. */
if (!any_viable (candidates))
{
op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
return error_mark_node;
}
candidates = splice_viable (candidates);
cand = tourney (candidates);
if (!cand)
{
op_error (COND_EXPR, NOP_EXPR, arg1, arg2, arg3, "no match");
print_z_candidates (candidates);
return error_mark_node;
}
/* [expr.cond]
Otherwise, the conversions thus determined are applied, and
the converted operands are used in place of the original
operands for the remainder of this section. */
conv = TREE_VEC_ELT (cand->convs, 0);
arg1 = convert_like (conv, arg1);
conv = TREE_VEC_ELT (cand->convs, 1);
arg2 = convert_like (conv, arg2);
conv = TREE_VEC_ELT (cand->convs, 2);
arg3 = convert_like (conv, arg3);
}
/* [expr.cond]
Lvalue-to-rvalue (_conv.lval_), array-to-pointer (_conv.array_),
and function-to-pointer (_conv.func_) standard conversions are
performed on the second and third operands. */
arg2 = decay_conversion (arg2);
arg2_type = TREE_TYPE (arg2);
arg3 = decay_conversion (arg3);
arg3_type = TREE_TYPE (arg3);
/* [expr.cond]
After those conversions, one of the following shall hold:
--The second and third operands have the same type; the result is of
that type. */
if (same_type_p (arg2_type, arg3_type))
result_type = arg2_type;
/* [expr.cond]
--The second and third operands have arithmetic or enumeration
type; the usual arithmetic conversions are performed to bring
them to a common type, and the result is of that type. */
else if ((ARITHMETIC_TYPE_P (arg2_type)
|| TREE_CODE (arg2_type) == ENUMERAL_TYPE)
&& (ARITHMETIC_TYPE_P (arg3_type)
|| TREE_CODE (arg3_type) == ENUMERAL_TYPE))
{
/* In this case, there is always a common type. */
result_type = type_after_usual_arithmetic_conversions (arg2_type,
arg3_type);
arg2 = ncp_convert (result_type, arg2);
arg3 = ncp_convert (result_type, arg3);
}
/* [expr.cond]
--The second and third operands have pointer type, or one has
pointer type and the other is a null pointer constant; pointer
conversions (_conv.ptr_) and qualification conversions
(_conv.qual_) are performed to bring them to their composite
pointer type (_expr.rel_). The result is of the composite
pointer type.
--The second and third operands have pointer to member type, or
one has pointer to member type and the other is a null pointer
constant; pointer to member conversions (_conv.mem_) and
qualification conversions (_conv.qual_) are performed to bring
them to a common type, whose cv-qualification shall match the
cv-qualification of either the second or the third operand.
The result is of the common type. */
else if ((null_ptr_cst_p (arg2)
&& (TYPE_PTR_P (arg3_type) || TYPE_PTRMEM_P (arg3_type)
|| TYPE_PTRMEMFUNC_P (arg3_type)))
|| (null_ptr_cst_p (arg3)
&& (TYPE_PTR_P (arg2_type) || TYPE_PTRMEM_P (arg2_type)
|| TYPE_PTRMEMFUNC_P (arg2_type)))
|| (TYPE_PTR_P (arg2_type) && TYPE_PTR_P (arg3_type))
|| (TYPE_PTRMEM_P (arg2_type) && TYPE_PTRMEM_P (arg3_type))
|| (TYPE_PTRMEMFUNC_P (arg2_type)
&& TYPE_PTRMEMFUNC_P (arg3_type)))
{
result_type = composite_pointer_type (arg2_type, arg3_type, arg2,
arg3, "conditional expression");
arg2 = ncp_convert (result_type, arg2);
arg3 = ncp_convert (result_type, arg3);
}
if (!result_type)
{
cp_error ("operands to ?: have different types");
return error_mark_node;
}
valid_operands:
result = fold (build (COND_EXPR, result_type, arg1, arg2, arg3));
/* Expand both sides into the same slot, hopefully the target of the
?: expression. */
if (TREE_CODE (arg2) == TARGET_EXPR && TREE_CODE (arg3) == TARGET_EXPR)
{
tree slot = build (VAR_DECL, result_type);
layout_decl (slot, 0);
result = build (TARGET_EXPR, result_type,
slot, result, NULL_TREE, NULL_TREE);
}
/* If this expression is an rvalue, but might be mistaken for an
lvalue, we must add a NON_LVALUE_EXPR. */
if (!lvalue_p && real_lvalue_p (result))
result = build1 (NON_LVALUE_EXPR, result_type, result);
return result;
}
tree
build_new_op (code, flags, arg1, arg2, arg3)
enum tree_code code;
......@@ -4660,8 +5064,7 @@ int
can_convert (to, from)
tree to, from;
{
tree t = implicit_conversion (to, from, NULL_TREE, LOOKUP_NORMAL);
return (t && ! ICS_BAD_FLAG (t));
return can_convert_arg (to, from, NULL_TREE);
}
int
......@@ -4672,6 +5075,22 @@ can_convert_arg (to, from, arg)
return (t && ! ICS_BAD_FLAG (t));
}
tree
ncp_convert (type, expr)
tree type;
tree expr;
{
tree conv = implicit_conversion (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);
}
/* Convert EXPR to the indicated reference TYPE, in a way suitable for
initializing a variable of that TYPE. Return the converted
expression. */
......
......@@ -3619,7 +3619,6 @@ finish_struct_1 (t)
{
/* Never let anything with uninheritable virtuals
make it through without complaint. */
if (CLASSTYPE_ABSTRACT_VIRTUALS (type))
abstract_virtuals_error (x, type);
/* Don't let signatures make it through either. */
......
......@@ -1660,7 +1660,24 @@ extern int flag_new_for_scope;
#define INTEGRAL_CODE_P(CODE) \
(CODE == INTEGER_TYPE || CODE == ENUMERAL_TYPE || CODE == BOOLEAN_TYPE)
#define ARITHMETIC_TYPE_P(TYPE) (INTEGRAL_TYPE_P (TYPE) || FLOAT_TYPE_P (TYPE))
/* [basic.fundamental]
Types bool, char, wchar_t, and the signed and unsigned integer types
are collectively called integral types.
Note that INTEGRAL_TYPE_P, as defined in tree.h, allows enumeration
types as well, which is incorrect in C++. */
#define CP_INTEGRAL_TYPE_P(TYPE) \
(TREE_CODE ((TYPE)) == BOOLEAN_TYPE \
|| TREE_CODE ((TYPE)) == INTEGER_TYPE)
/* [basic.fundamental]
Integral and floating types are collectively called arithmetic
types. */
#define ARITHMETIC_TYPE_P(TYPE) \
(CP_INTEGRAL_TYPE_P (TYPE) || TREE_CODE (TYPE) == REAL_TYPE)
/* Mark which labels are explicitly declared.
These may be shadowed, and may be referenced from nested functions. */
......@@ -2767,6 +2784,8 @@ extern tree convert_default_arg PROTO((tree, tree, tree));
extern tree convert_arg_to_ellipsis PROTO((tree));
extern int is_properly_derived_from PROTO((tree, tree));
extern tree initialize_reference PROTO((tree, tree));
extern tree strip_top_quals PROTO((tree));
extern tree ncp_convert PROTO((tree, tree));
/* in class.c */
extern tree build_vbase_path PROTO((enum tree_code, tree, tree, tree, int));
......@@ -3534,12 +3553,14 @@ extern tree build_ptrmemfunc1 PROTO((tree, tree, tree, tree, t
extern void expand_ptrmemfunc_cst PROTO((tree, tree *, tree *, tree *, tree *));
extern tree delta2_from_ptrmemfunc PROTO((tree));
extern tree pfn_from_ptrmemfunc PROTO((tree));
extern tree type_after_usual_arithmetic_conversions PROTO((tree, tree));
extern tree composite_pointer_type PROTO((tree, tree, tree, tree, char*));
/* in typeck2.c */
extern tree error_not_base_type PROTO((tree, tree));
extern tree binfo_or_else PROTO((tree, tree));
extern void readonly_error PROTO((tree, const char *, int));
extern void abstract_virtuals_error PROTO((tree, tree));
extern int abstract_virtuals_error PROTO((tree, tree));
extern void signature_error PROTO((tree, tree));
extern void incomplete_type_error PROTO((tree, tree));
extern void my_friendly_abort PROTO((int))
......
......@@ -826,11 +826,8 @@ ocp_convert (type, expr, convtype, flags)
ctor = e;
if (IS_AGGR_TYPE (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
{
abstract_virtuals_error (NULL_TREE, type);
if (abstract_virtuals_error (NULL_TREE, type))
return error_mark_node;
}
if ((flags & LOOKUP_ONLYCONVERTING)
&& ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
......
......@@ -7857,14 +7857,9 @@ cp_finish_decl (decl, init, asmspec_tree, need_pop, flags)
if (was_temp)
resume_temporary_allocation ();
if (type != error_mark_node
&& TYPE_LANG_SPECIFIC (core_type)
&& CLASSTYPE_ABSTRACT_VIRTUALS (core_type))
abstract_virtuals_error (decl, core_type);
else if ((TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE)
&& TYPE_LANG_SPECIFIC (TREE_TYPE (type))
&& CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (type)))
if (!abstract_virtuals_error (decl, core_type)
&& (TREE_CODE (type) == FUNCTION_TYPE
|| TREE_CODE (type) == METHOD_TYPE))
abstract_virtuals_error (decl, TREE_TYPE (type));
if (TYPE_LANG_SPECIFIC (core_type) && IS_SIGNATURE (core_type))
......@@ -11614,13 +11609,8 @@ grokparms (first_parm, funcdef_flag)
type = build_pointer_type (type);
TREE_TYPE (decl) = type;
}
else if (TREE_CODE (type) == RECORD_TYPE
&& TYPE_LANG_SPECIFIC (type)
&& CLASSTYPE_ABSTRACT_VIRTUALS (type))
{
abstract_virtuals_error (decl, type);
else if (abstract_virtuals_error (decl, type))
any_error = 1; /* Seems like a good idea. */
}
else if (TREE_CODE (type) == RECORD_TYPE
&& TYPE_LANG_SPECIFIC (type)
&& IS_SIGNATURE (type))
......@@ -12033,9 +12023,7 @@ grok_op_properties (decl, virtualp, friendp)
else if (name == ansi_opname[(int) COND_EXPR])
{
/* 13.4.0.3 */
pedwarn ("ANSI C++ prohibits overloading operator ?:");
if (list_length (argtypes) != 4)
cp_error ("`%D' must take exactly three arguments", decl);
cp_error ("ANSI C++ prohibits overloading operator ?:");
}
else if (ambi_op_p (name))
{
......@@ -13113,8 +13101,6 @@ start_function (declspecs, declarator, attrs, pre_parsed_p)
= CP_TYPE_VOLATILE_P (TREE_TYPE (fntype));
}
if (TYPE_LANG_SPECIFIC (TREE_TYPE (fntype))
&& CLASSTYPE_ABSTRACT_VIRTUALS (TREE_TYPE (fntype)))
abstract_virtuals_error (decl1, TREE_TYPE (fntype));
}
......
......@@ -2206,12 +2206,8 @@ build_new_1 (exp)
return error_mark_node;
}
if (TYPE_LANG_SPECIFIC (true_type)
&& CLASSTYPE_ABSTRACT_VIRTUALS (true_type))
{
abstract_virtuals_error (NULL_TREE, true_type);
if (abstract_virtuals_error (NULL_TREE, true_type))
return error_mark_node;
}
if (TYPE_LANG_SPECIFIC (true_type) && IS_SIGNATURE (true_type))
{
......
......@@ -8338,10 +8338,6 @@ unify (tparms, targs, parm, arg, strict)
{
int sub_strict;
if (TREE_CODE (arg) == RECORD_TYPE && TYPE_PTRMEMFUNC_FLAG (arg))
return (unify (tparms, targs, parm,
TYPE_PTRMEMFUNC_FN_TYPE (arg), strict));
if (TREE_CODE (arg) != POINTER_TYPE)
return 1;
......@@ -8361,14 +8357,13 @@ unify (tparms, targs, parm, arg, strict)
this is probably OK. */
sub_strict = strict;
if (TREE_CODE (TREE_TYPE (arg)) != RECORD_TYPE
|| TYPE_PTRMEMFUNC_FLAG (TREE_TYPE (arg)))
if (TREE_CODE (TREE_TYPE (arg)) != RECORD_TYPE)
/* The derived-to-base conversion only persists through one
level of pointers. */
sub_strict &= ~UNIFY_ALLOW_DERIVED;
return unify (tparms, targs, TREE_TYPE (parm), TREE_TYPE
(arg), sub_strict);
return unify (tparms, targs, TREE_TYPE (parm),
TREE_TYPE (arg), sub_strict);
}
case REFERENCE_TYPE:
......@@ -8448,13 +8443,20 @@ unify (tparms, targs, parm, arg, strict)
case RECORD_TYPE:
case UNION_TYPE:
if (TYPE_PTRMEMFUNC_FLAG (parm))
return unify (tparms, targs, TYPE_PTRMEMFUNC_FN_TYPE (parm),
arg, strict);
if (TREE_CODE (arg) != TREE_CODE (parm))
return 1;
if (TYPE_PTRMEMFUNC_P (parm))
{
if (!TYPE_PTRMEMFUNC_P (arg))
return 1;
return unify (tparms, targs,
TYPE_PTRMEMFUNC_FN_TYPE (parm),
TYPE_PTRMEMFUNC_FN_TYPE (arg),
strict);
}
if (CLASSTYPE_TEMPLATE_INFO (parm))
{
tree t = NULL_TREE;
......
......@@ -3130,6 +3130,10 @@ add_conversions (binfo, data)
tree method_vec = CLASSTYPE_METHOD_VEC (BINFO_TYPE (binfo));
tree *conversions = (tree *) data;
/* Some builtin types have no method vector, not even an empty one. */
if (!method_vec)
return NULL_TREE;
for (i = 2; i < TREE_VEC_LENGTH (method_vec); ++i)
{
tree tmp = TREE_VEC_ELT (method_vec, i);
......
......@@ -403,6 +403,191 @@ original_type (t)
return t;
}
/* T1 and T2 are arithmetic or enumeration types. Return the type
that will result from the "usual arithmetic converions" on T1 and
T2 as described in [expr]. */
tree
type_after_usual_arithmetic_conversions (t1, t2)
tree t1;
tree t2;
{
enum tree_code code1 = TREE_CODE (t1);
enum tree_code code2 = TREE_CODE (t2);
tree attributes;
/* FIXME: Attributes. */
my_friendly_assert (ARITHMETIC_TYPE_P (t1)
|| TREE_CODE (t1) == ENUMERAL_TYPE,
19990725);
my_friendly_assert (ARITHMETIC_TYPE_P (t2)
|| TREE_CODE (t2) == ENUMERAL_TYPE,
19990725);
/* In what follows, we slightly generalize the rules given in [expr]
so as to deal with `long long'. First, merge the attributes. */
attributes = merge_machine_type_attributes (t1, t2);
/* If only one is real, use it as the result. */
if (code1 == REAL_TYPE && code2 != REAL_TYPE)
return build_type_attribute_variant (t1, attributes);
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
return build_type_attribute_variant (t2, attributes);
/* Perform the integral promotions. */
if (code1 != REAL_TYPE)
{
t1 = type_promotes_to (t1);
t2 = type_promotes_to (t2);
}
/* Both real or both integers; use the one with greater precision. */
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
return build_type_attribute_variant (t1, attributes);
else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
return build_type_attribute_variant (t2, attributes);
if (code1 != REAL_TYPE)
{
/* If one is unsigned long long, then convert the other to unsigned
long long. */
if (same_type_p (TYPE_MAIN_VARIANT (t1), long_long_unsigned_type_node)
|| same_type_p (TYPE_MAIN_VARIANT (t2), long_long_unsigned_type_node))
return build_type_attribute_variant (long_long_unsigned_type_node,
attributes);
/* If one is a long long, and the other is an unsigned long, and
long long can represent all the values of an unsigned long, then
convert to a long long. Otherwise, convert to an unsigned long
long. Otherwise, if either operand is long long, convert the
other to long long.
Since we're here, we know the TYPE_PRECISION is the same;
therefore converting to long long cannot represent all the values
of an unsigned long, so we choose unsigned long long in that
case. */
if (same_type_p (TYPE_MAIN_VARIANT (t1), long_long_integer_type_node)
|| same_type_p (TYPE_MAIN_VARIANT (t2), long_long_integer_type_node))
{
tree t = ((TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
? long_long_unsigned_type_node
: long_long_integer_type_node);
return build_type_attribute_variant (t, attributes);
}
/* Go through the same procedure, but for longs. */
if (same_type_p (TYPE_MAIN_VARIANT (t1), long_unsigned_type_node)
|| same_type_p (TYPE_MAIN_VARIANT (t2), long_unsigned_type_node))
return build_type_attribute_variant (long_unsigned_type_node,
attributes);
if (same_type_p (TYPE_MAIN_VARIANT (t1), long_integer_type_node)
|| same_type_p (TYPE_MAIN_VARIANT (t2), long_integer_type_node))
{
tree t = ((TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
? long_unsigned_type_node : long_integer_type_node);
return build_type_attribute_variant (t, attributes);
}
/* Otherwise prefer the unsigned one. */
if (TREE_UNSIGNED (t1))
return build_type_attribute_variant (t1, attributes);
else
return build_type_attribute_variant (t2, attributes);
}
else
{
if (same_type_p (TYPE_MAIN_VARIANT (t1), long_double_type_node)
|| same_type_p (TYPE_MAIN_VARIANT (t2), long_double_type_node))
return build_type_attribute_variant (long_double_type_node,
attributes);
if (same_type_p (TYPE_MAIN_VARIANT (t1), double_type_node)
|| same_type_p (TYPE_MAIN_VARIANT (t2), double_type_node))
return build_type_attribute_variant (double_type_node,
attributes);
else
return build_type_attribute_variant (float_type_node,
attributes);
}
}
/* Return the composite pointer type (see [expr.rel]) for T1 and T2.
ARG1 and ARG2 are the values with those types. The LOCATION is a
string describing the current location, in case an error occurs. */
tree
composite_pointer_type (t1, t2, arg1, arg2, location)
tree t1;
tree t2;
tree arg1;
tree arg2;
char* location;
{
tree result_type;
/* [expr.rel]
If one operand is a null pointer constant, the composite pointer
type is the type of the other operand. */
if (null_ptr_cst_p (arg1))
return t2;
if (null_ptr_cst_p (arg2))
return t1;
/* Deal with pointer-to-member functions in the same way as we deal
with pointers to functions. */
if (TYPE_PTRMEMFUNC_P (t1))
t1 = TYPE_PTRMEMFUNC_FN_TYPE (t1);
if (TYPE_PTRMEMFUNC_P (t2))
t2 = TYPE_PTRMEMFUNC_FN_TYPE (t2);
if (comp_target_types (t1, t2, 1))
result_type = common_type (t1, t2);
else if (TYPE_MAIN_VARIANT (TREE_TYPE (t1)) == void_type_node)
{
if (pedantic && TREE_CODE (t2) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids %s between `void *' and function pointer",
location);
result_type = qualify_type (t1, t2);
}
else if (TYPE_MAIN_VARIANT (TREE_TYPE (t2)) == void_type_node)
{
if (pedantic && TREE_CODE (t1) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids %s between `void *' and function pointer",
location);
result_type = qualify_type (t2, t1);
}
/* C++ */
else if (same_or_base_type_p (t2, t1))
result_type = t2;
else if (IS_AGGR_TYPE (TREE_TYPE (t1))
&& IS_AGGR_TYPE (TREE_TYPE (t2))
&& (result_type = common_base_type (TREE_TYPE (t1),
TREE_TYPE (t2))))
{
if (result_type == error_mark_node)
{
cp_error ("common base type of types `%T' and `%T' is ambiguous",
TREE_TYPE (t1), TREE_TYPE (t2));
result_type = ptr_type_node;
}
else
{
if (pedantic
&& result_type != TREE_TYPE (t1)
&& result_type != TREE_TYPE (t2))
cp_pedwarn ("`%T' and `%T' converted to `%T *' in %s",
t1, t2, result_type, location);
result_type = build_pointer_type (result_type);
}
}
else
{
cp_pedwarn ("pointer type mismatch in %s", location);
result_type = ptr_type_node;
}
return result_type;
}
/* Return the common type of two types.
We assume that comptypes has already been done and returned 1;
if that isn't so, this may crash.
......@@ -435,44 +620,13 @@ common_type (t1, t2)
if (t2 == error_mark_node)
return t1;
if ((ARITHMETIC_TYPE_P (t1) || TREE_CODE (t1) == ENUMERAL_TYPE)
&& (ARITHMETIC_TYPE_P (t2) || TREE_CODE (t2) == ENUMERAL_TYPE))
return type_after_usual_arithmetic_conversions (t1, t2);
/* Merge the attributes. */
attributes = merge_machine_type_attributes (t1, t2);
{ register tree a1, a2;
a1 = TYPE_ATTRIBUTES (t1);
a2 = TYPE_ATTRIBUTES (t2);
/* Either one unset? Take the set one. */
if (!(attributes = a1))
attributes = a2;
/* One that completely contains the other? Take it. */
else if (a2 && !attribute_list_contained (a1, a2))
{
if (attribute_list_contained (a2, a1))
attributes = a2;
else
{
/* Pick the longest list, and hang on the other list. */
/* ??? For the moment we punt on the issue of attrs with args. */
if (list_length (a1) < list_length (a2))
attributes = a2, a2 = a1;
for (; a2; a2 = TREE_CHAIN (a2))
if (lookup_attribute (IDENTIFIER_POINTER (TREE_PURPOSE (a2)),
attributes) == NULL_TREE)
{
a1 = copy_node (a2);
TREE_CHAIN (a1) = attributes;
attributes = a1;
}
}
}
}
/* Treat an enum type as the unsigned integer type of the same width. */
if (TREE_CODE (t1) == ENUMERAL_TYPE)
......@@ -510,51 +664,10 @@ common_type (t1, t2)
{
case INTEGER_TYPE:
case REAL_TYPE:
/* If only one is real, use it as the result. */
if (code1 == REAL_TYPE && code2 != REAL_TYPE)
return build_type_attribute_variant (t1, attributes);
if (code2 == REAL_TYPE && code1 != REAL_TYPE)
return build_type_attribute_variant (t2, attributes);
/* Both real or both integers; use the one with greater precision. */
if (TYPE_PRECISION (t1) > TYPE_PRECISION (t2))
return build_type_attribute_variant (t1, attributes);
else if (TYPE_PRECISION (t2) > TYPE_PRECISION (t1))
return build_type_attribute_variant (t2, attributes);
/* Same precision. Prefer longs to ints even when same size. */
if (TYPE_MAIN_VARIANT (t1) == long_unsigned_type_node
|| TYPE_MAIN_VARIANT (t2) == long_unsigned_type_node)
return build_type_attribute_variant (long_unsigned_type_node,
attributes);
if (TYPE_MAIN_VARIANT (t1) == long_integer_type_node
|| TYPE_MAIN_VARIANT (t2) == long_integer_type_node)
{
/* But preserve unsignedness from the other type,
since long cannot hold all the values of an unsigned int. */
if (TREE_UNSIGNED (t1) || TREE_UNSIGNED (t2))
t1 = long_unsigned_type_node;
else
t1 = long_integer_type_node;
return build_type_attribute_variant (t1, attributes);
}
if (TYPE_MAIN_VARIANT (t1) == long_double_type_node
|| TYPE_MAIN_VARIANT (t2) == long_double_type_node)
return build_type_attribute_variant (long_double_type_node,
attributes);
/* Otherwise prefer the unsigned one. */
if (TREE_UNSIGNED (t1))
return build_type_attribute_variant (t1, attributes);
else
return build_type_attribute_variant (t2, attributes);
/* We should have called type_after_usual_arithmetic_conversions
above. */
my_friendly_abort (19990725);
break;
case POINTER_TYPE:
case REFERENCE_TYPE:
......@@ -797,17 +910,16 @@ comp_array_types (cmp, t1, t2, strict)
TYPE_MAX_VALUE (d2)));
}
/* Return 1 if TYPE1 and TYPE2 are compatible types for assignment
or various other operations. STRICT is a bitwise-or of the
COMPARE_* flags. */
/* Return 1 if T1 and T2 are compatible types for assignment or
various other operations. STRICT is a bitwise-or of the COMPARE_*
flags. */
int
comptypes (type1, type2, strict)
tree type1, type2;
comptypes (t1, t2, strict)
tree t1;
tree t2;
int strict;
{
register tree t1 = type1;
register tree t2 = type2;
int attrval, val;
int orig_strict = strict;
......@@ -969,6 +1081,9 @@ comptypes (type1, type2, strict)
return 0;
return same_type_p (TYPE_CONTEXT (t1), TYPE_CONTEXT (t2));
case COMPLEX_TYPE:
return same_type_p (TREE_TYPE (t1), TREE_TYPE (t2));
default:
break;
}
......@@ -3536,11 +3651,9 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
if (result_type == NULL_TREE)
result_type = ptr_type_node;
}
else if (code0 == POINTER_TYPE && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
else if (code0 == POINTER_TYPE && null_ptr_cst_p (op1))
result_type = type0;
else if (code1 == POINTER_TYPE && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
else if (code1 == POINTER_TYPE && null_ptr_cst_p (op0))
result_type = type1;
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
......@@ -3552,15 +3665,13 @@ build_binary_op_nodefault (code, orig_op0, orig_op1, error_code)
result_type = type1;
error ("ANSI C++ forbids comparison between pointer and integer");
}
else if (TYPE_PTRMEMFUNC_P (type0) && TREE_CODE (op1) == INTEGER_CST
&& integer_zerop (op1))
else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
{
op0 = build_component_ref (op0, index_identifier, NULL_TREE, 0);
op1 = integer_zero_node;
result_type = TREE_TYPE (op0);
}
else if (TYPE_PTRMEMFUNC_P (type1) && TREE_CODE (op0) == INTEGER_CST
&& integer_zerop (op0))
else if (TYPE_PTRMEMFUNC_P (type1) && null_ptr_cst_p (op0))
{
op0 = build_component_ref (op1, index_identifier, NULL_TREE, 0);
op1 = integer_zero_node;
......@@ -4967,326 +5078,7 @@ build_x_conditional_expr (ifexp, op1, op2)
if (processing_template_decl)
return build_min_nt (COND_EXPR, ifexp, op1, op2);
return build_new_op (COND_EXPR, LOOKUP_NORMAL, ifexp, op1, op2);
}
tree
build_conditional_expr (ifexp, op1, op2)
tree ifexp, op1, op2;
{
register tree type1;
register tree type2;
register enum tree_code code1;
register enum tree_code code2;
register tree result_type = NULL_TREE;
/* If second operand is omitted, it is the same as the first one;
make sure it is calculated only once. */
if (op1 == 0)
{
if (pedantic)
pedwarn ("ANSI C++ forbids omitting the middle term of a ?: expression");
ifexp = op1 = save_expr (ifexp);
}
type1 = TREE_TYPE (op1);
code1 = TREE_CODE (type1);
type2 = TREE_TYPE (op2);
code2 = TREE_CODE (type2);
if (op1 == error_mark_node || op2 == error_mark_node
|| type1 == error_mark_node || type2 == error_mark_node)
return error_mark_node;
ifexp = cp_convert (boolean_type_node, ifexp);
if (TREE_CODE (ifexp) == ERROR_MARK)
return error_mark_node;
/* C++: REFERENCE_TYPES must be dereferenced. */
if (code1 == REFERENCE_TYPE)
{
op1 = convert_from_reference (op1);
type1 = TREE_TYPE (op1);
code1 = TREE_CODE (type1);
}
if (code2 == REFERENCE_TYPE)
{
op2 = convert_from_reference (op2);
type2 = TREE_TYPE (op2);
code2 = TREE_CODE (type2);
}
/* Don't promote the operands separately if they promote
the same way. Return the unpromoted type and let the combined
value get promoted if necessary. */
if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2)
&& code2 != ARRAY_TYPE
&& code2 != FUNCTION_TYPE
&& code2 != METHOD_TYPE)
{
tree result;
if (TREE_CONSTANT (ifexp)
&& (TREE_CODE (ifexp) == INTEGER_CST
|| TREE_CODE (ifexp) == ADDR_EXPR))
return (integer_zerop (ifexp) ? op2 : op1);
if (TREE_CODE (op1) == CONST_DECL)
op1 = DECL_INITIAL (op1);
else if (TREE_READONLY_DECL_P (op1))
op1 = decl_constant_value (op1);
if (TREE_CODE (op2) == CONST_DECL)
op2 = DECL_INITIAL (op2);
else if (TREE_READONLY_DECL_P (op2))
op2 = decl_constant_value (op2);
if (type1 != type2)
type1 = cp_build_qualified_type
(type1, (CP_TYPE_QUALS (TREE_TYPE (op1))
| CP_TYPE_QUALS (TREE_TYPE (op2))));
/* ??? This is a kludge to deal with the fact that
we don't sort out integers and enums properly, yet. */
result = fold (build (COND_EXPR, type1, ifexp, op1, op2));
if (TREE_TYPE (result) != type1)
result = build1 (NOP_EXPR, type1, result);
/* Expand both sides into the same slot,
hopefully the target of the ?: expression. */
if (TREE_CODE (op1) == TARGET_EXPR && TREE_CODE (op2) == TARGET_EXPR)
{
tree slot = build (VAR_DECL, TREE_TYPE (result));
layout_decl (slot, 0);
result = build (TARGET_EXPR, TREE_TYPE (result),
slot, result, NULL_TREE, NULL_TREE);
}
return result;
}
/* They don't match; promote them both and then try to reconcile them.
But don't permit mismatching enum types. */
if (code1 == ENUMERAL_TYPE)
{
if (code2 == ENUMERAL_TYPE)
{
cp_error ("enumeral mismatch in conditional expression: `%T' vs `%T'",
type1, type2);
return error_mark_node;
}
else if (extra_warnings && ! IS_AGGR_TYPE_CODE (code2)
&& type2 != type_promotes_to (type1))
warning ("enumeral and non-enumeral type in conditional expression");
}
else if (extra_warnings
&& code2 == ENUMERAL_TYPE && ! IS_AGGR_TYPE_CODE (code1)
&& type1 != type_promotes_to (type2))
warning ("enumeral and non-enumeral type in conditional expression");
if (code1 != VOID_TYPE)
{
op1 = default_conversion (op1);
type1 = TREE_TYPE (op1);
if (TYPE_PTRMEMFUNC_P (type1))
type1 = TYPE_PTRMEMFUNC_FN_TYPE (type1);
code1 = TREE_CODE (type1);
}
if (code2 != VOID_TYPE)
{
op2 = default_conversion (op2);
type2 = TREE_TYPE (op2);
if (TYPE_PTRMEMFUNC_P (type2))
type2 = TYPE_PTRMEMFUNC_FN_TYPE (type2);
code2 = TREE_CODE (type2);
}
if (code1 == RECORD_TYPE && code2 == RECORD_TYPE
&& real_lvalue_p (op1) && real_lvalue_p (op2)
&& comptypes (type1, type2, COMPARE_BASE | COMPARE_RELAXED))
{
type1 = build_reference_type (type1);
type2 = build_reference_type (type2);
result_type = common_type (type1, type2);
op1 = convert_to_reference (result_type, op1, CONV_IMPLICIT,
LOOKUP_NORMAL, NULL_TREE);
op2 = convert_to_reference (result_type, op2, CONV_IMPLICIT,
LOOKUP_NORMAL, NULL_TREE);
}
/* Quickly detect the usual case where op1 and op2 have the same type
after promotion. */
else if (TYPE_MAIN_VARIANT (type1) == TYPE_MAIN_VARIANT (type2))
{
if (type1 == type2)
result_type = type1;
else
result_type =
cp_build_qualified_type (type1,
CP_TYPE_QUALS (TREE_TYPE (op1))
| CP_TYPE_QUALS (TREE_TYPE (op2)));
}
else if ((code1 == INTEGER_TYPE || code1 == REAL_TYPE)
&& (code2 == INTEGER_TYPE || code2 == REAL_TYPE))
{
result_type = common_type (type1, type2);
}
else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
{
if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE))
pedwarn ("ANSI C++ forbids conditional expr with only one void side");
result_type = void_type_node;
}
else if (code1 == POINTER_TYPE && null_ptr_cst_p (op2))
result_type = qualify_type (type1, type2);
else if (code2 == POINTER_TYPE && null_ptr_cst_p (op1))
result_type = qualify_type (type2, type1);
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
{
if (comp_target_types (type1, type2, 1))
result_type = common_type (type1, type2);
else if (TYPE_MAIN_VARIANT (TREE_TYPE (type1)) == void_type_node)
{
if (pedantic && TREE_CODE (type2) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids conditional expr between `void *' and function pointer");
result_type = qualify_type (type1, type2);
}
else if (TYPE_MAIN_VARIANT (TREE_TYPE (type2)) == void_type_node)
{
if (pedantic && TREE_CODE (type1) == FUNCTION_TYPE)
pedwarn ("ANSI C++ forbids conditional expr between `void *' and function pointer");
result_type = qualify_type (type2, type1);
}
/* C++ */
else if (same_or_base_type_p (type2, type1))
result_type = type2;
else if (IS_AGGR_TYPE (TREE_TYPE (type1))
&& IS_AGGR_TYPE (TREE_TYPE (type2))
&& (result_type = common_base_type (TREE_TYPE (type1),
TREE_TYPE (type2))))
{
if (result_type == error_mark_node)
{
cp_error ("common base type of types `%T' and `%T' is ambiguous",
TREE_TYPE (type1), TREE_TYPE (type2));
result_type = ptr_type_node;
}
else
{
if (pedantic
&& result_type != TREE_TYPE (type1)
&& result_type != TREE_TYPE (type2))
cp_pedwarn ("`%T' and `%T' converted to `%T *' in conditional expression",
type1, type2, result_type);
result_type = build_pointer_type (result_type);
}
}
else
{
pedwarn ("pointer type mismatch in conditional expression");
result_type = ptr_type_node;
}
}
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
{
pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type1;
}
else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
pedwarn ("pointer/integer type mismatch in conditional expression");
result_type = type2;
}
if (type2 == unknown_type_node)
result_type = type1;
else if (type1 == unknown_type_node)
result_type = type2;
if (!result_type)
{
/* The match does not look good. If either is
an aggregate value, try converting to a scalar type. */
if (code1 == RECORD_TYPE && code2 == RECORD_TYPE)
{
cp_error ("aggregate mismatch in conditional expression: `%T' vs `%T'",
type1, type2);
return error_mark_node;
}
/* Warning: this code assumes that conversion between cv-variants of
a type is done using NOP_EXPRs. */
if (code1 == RECORD_TYPE && TYPE_HAS_CONVERSION (type1))
{
/* There are other types besides pointers and records. */
tree tmp;
if (code2 == POINTER_TYPE)
tmp = build_pointer_type
(cp_build_qualified_type (TREE_TYPE (type2),
TYPE_QUAL_CONST
| TYPE_QUAL_VOLATILE
| TYPE_QUAL_RESTRICT));
else
tmp = type2;
tmp = build_type_conversion (tmp, op1, 0);
if (tmp == NULL_TREE)
{
cp_error ("incompatible types `%T' and `%T' in `?:'",
type1, type2);
return error_mark_node;
}
if (tmp == error_mark_node)
error ("ambiguous pointer conversion");
else
STRIP_NOPS (tmp);
result_type = common_type (type2, TREE_TYPE (tmp));
op1 = tmp;
}
else if (code2 == RECORD_TYPE && TYPE_HAS_CONVERSION (type2))
{
tree tmp;
if (code1 == POINTER_TYPE)
tmp = build_pointer_type
(cp_build_qualified_type (TREE_TYPE (type1),
TYPE_QUAL_CONST
| TYPE_QUAL_VOLATILE
| TYPE_QUAL_RESTRICT));
else
tmp = type1;
tmp = build_type_conversion (tmp, op2, 0);
if (tmp == NULL_TREE)
{
cp_error ("incompatible types `%T' and `%T' in `?:'",
type1, type2);
return error_mark_node;
}
if (tmp == error_mark_node)
error ("ambiguous pointer conversion");
else
STRIP_NOPS (tmp);
result_type = common_type (type1, TREE_TYPE (tmp));
op2 = tmp;
}
else if (flag_cond_mismatch)
result_type = void_type_node;
else
{
error ("type mismatch in conditional expression");
return error_mark_node;
}
}
if (TREE_CODE (result_type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
result_type = build_ptrmemfunc_type (result_type);
if (result_type != TREE_TYPE (op1))
op1 = convert_for_initialization
(NULL_TREE, result_type, op1, LOOKUP_NORMAL, "converting", NULL_TREE, 0);
if (result_type != TREE_TYPE (op2))
op2 = convert_for_initialization
(NULL_TREE, result_type, op2, LOOKUP_NORMAL, "converting", NULL_TREE, 0);
if (TREE_CODE (ifexp) == INTEGER_CST)
return integer_zerop (ifexp) ? op2 : op1;
return convert_from_reference
(fold (build (COND_EXPR, result_type, ifexp, op1, op2)));
return build_conditional_expr (ifexp, op1, op2);
}
/* Handle overloading of the ',' operator when needed. Otherwise,
......@@ -6628,18 +6420,11 @@ pfn_from_ptrmemfunc (t)
pfn_identifier, NULL_TREE, 0));
}
/* Convert value RHS to type TYPE as preparation for an assignment
to an lvalue of type TYPE.
The real work of conversion is done by `convert'.
The purpose of this function is to generate error messages
for assignments that are not allowed in C.
ERRTYPE is a string to use in error messages:
"assignment", "return", etc.
C++: attempts to allow `convert' to find conversions involving
implicit type conversion between aggregate and scalar types
as per 8.5.6 of C++ manual. Does not randomly dereference
pointers to aggregates! */
/* Convert value RHS to type TYPE as preparation for an assignment to
an lvalue of type TYPE. ERRTYPE is a string to use in error
messages: "assignment", "return", etc. If FNDECL is non-NULL, we
are doing the conversion in order to pass the PARMNUMth argument of
FNDECL. */
static tree
convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
......@@ -6662,54 +6447,32 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
if (TREE_CODE (rhs) == NON_LVALUE_EXPR)
rhs = TREE_OPERAND (rhs, 0);
if (rhs == error_mark_node || TREE_TYPE (rhs) == error_mark_node)
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
if (rhs == error_mark_node || rhstype == error_mark_node)
return error_mark_node;
if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node)
return error_mark_node;
if (TREE_CODE (TREE_TYPE (rhs)) == ARRAY_TYPE
|| is_overloaded_fn (rhs))
rhs = default_conversion (rhs);
else if (TREE_CODE (TREE_TYPE (rhs)) == REFERENCE_TYPE)
rhs = convert_from_reference (rhs);
/* If rhs is some sort of overloaded function, ocp_convert will either
do the right thing or complain; we don't need to check anything else.
So just hand off. */
if (type_unknown_p (rhs))
return ocp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
rhstype = TREE_TYPE (rhs);
coder = TREE_CODE (rhstype);
/* Issue warnings about peculiar, but legal, uses of NULL. */
if (ARITHMETIC_TYPE_P (type) && rhs == null_node)
cp_warning ("converting NULL to non-pointer type");
/* This should no longer change types on us. */
if (TREE_CODE (rhs) == CONST_DECL)
rhs = DECL_INITIAL (rhs);
else if (TREE_READONLY_DECL_P (rhs))
rhs = decl_constant_value (rhs);
if (same_type_p (type, rhstype))
{
overflow_warning (rhs);
return rhs;
}
/* The RHS of an assignment cannot have void type. */
if (coder == VOID_TYPE)
{
error ("void value not ignored as it ought to be");
return error_mark_node;
}
/* Arithmetic types all interconvert. */
if ((codel == INTEGER_TYPE || codel == REAL_TYPE || codel == BOOLEAN_TYPE
|| codel == COMPLEX_TYPE)
&& (coder == INTEGER_TYPE || coder == REAL_TYPE || coder == BOOLEAN_TYPE
|| coder == COMPLEX_TYPE))
{
/* But we should warn if assigning REAL_TYPE to INTEGER_TYPE. */
/* Simplify the RHS if possible. */
if (TREE_CODE (rhs) == CONST_DECL)
rhs = DECL_INITIAL (rhs);
else if (TREE_READONLY_DECL_P (rhs))
rhs = decl_constant_value (rhs);
/* Warn about assigning a floating-point type to an integer type. */
if (coder == REAL_TYPE && codel == INTEGER_TYPE)
{
if (fndecl)
......@@ -6718,8 +6481,8 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
else
cp_warning ("%s to `%T' from `%T'", errtype, type, rhstype);
}
/* And we should warn if assigning a negative value to
an unsigned variable. */
/* And warn about assigning a negative value to an unsigned
variable. */
else if (TREE_UNSIGNED (type) && codel != BOOLEAN_TYPE)
{
if (TREE_CODE (rhs) == INTEGER_CST
......@@ -6737,313 +6500,33 @@ convert_for_assignment (type, rhs, errtype, fndecl, parmnum)
rhs = fold (rhs);
}
return convert_and_check (type, rhs);
}
/* Conversions involving enums. */
else if ((codel == ENUMERAL_TYPE
&& (INTEGRAL_CODE_P (coder) || coder == REAL_TYPE))
|| (coder == ENUMERAL_TYPE
&& (INTEGRAL_CODE_P (codel) || codel == REAL_TYPE)))
{
return ocp_convert (type, rhs, CONV_IMPLICIT, LOOKUP_NORMAL);
}
/* Conversions among pointers */
else if (codel == POINTER_TYPE
&& (coder == POINTER_TYPE
|| (coder == RECORD_TYPE
&& (IS_SIGNATURE_POINTER (rhstype)
|| IS_SIGNATURE_REFERENCE (rhstype)))))
{
register tree ttl = TREE_TYPE (type);
register tree ttr;
int ctt = 0;
if (coder == RECORD_TYPE)
{
rhs = build_optr_ref (rhs);
rhstype = TREE_TYPE (rhs);
}
ttr = TREE_TYPE (rhstype);
/* If both pointers are of aggregate type, then we
can give better error messages, and save some work
as well. */
if (TREE_CODE (ttl) == RECORD_TYPE && TREE_CODE (ttr) == RECORD_TYPE)
{
tree binfo;
if (TYPE_MAIN_VARIANT (ttl) == TYPE_MAIN_VARIANT (ttr)
|| type == class_star_type_node
|| rhstype == class_star_type_node)
binfo = TYPE_BINFO (ttl);
else
binfo = get_binfo (ttl, ttr, 1);
if (binfo == error_mark_node)
return error_mark_node;
if (binfo == 0)
return error_not_base_type (ttl, ttr);
if (!at_least_as_qualified_p (ttl, ttr))
{
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' discards qualifiers",
rhstype, parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' discards qualifiers",
errtype, type, rhstype);
}
}
/* Any non-function converts to a [const][volatile] void *
and vice versa; otherwise, targets must be the same.
Meanwhile, the lhs target must have all the qualifiers of the rhs. */
else if (TYPE_MAIN_VARIANT (ttl) == void_type_node
|| TYPE_MAIN_VARIANT (ttr) == void_type_node
|| (ctt = comp_target_types (type, rhstype, 1))
|| (unsigned_type (TYPE_MAIN_VARIANT (ttl))
== unsigned_type (TYPE_MAIN_VARIANT (ttr))))
{
/* ARM $4.8, commentary on p39. */
if (TYPE_MAIN_VARIANT (ttl) == void_type_node
&& TREE_CODE (ttr) == OFFSET_TYPE)
{
cp_error ("no standard conversion from `%T' to `void *'", ttr);
return error_mark_node;
}
if (ctt < 0 && TYPE_MAIN_VARIANT (ttl) != TYPE_MAIN_VARIANT (ttr))
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
rhstype, type);
if (TYPE_MAIN_VARIANT (ttl) != void_type_node
&& TYPE_MAIN_VARIANT (ttr) == void_type_node
&& ! null_ptr_cst_p (rhs))
{
if (coder == RECORD_TYPE)
cp_pedwarn ("implicit conversion of signature pointer to type `%T'",
type);
else
pedwarn ("ANSI C++ forbids implicit conversion from `void *' in %s",
errtype);
}
/* Const and volatile mean something different for function types,
so the usual warnings are not appropriate. */
else if ((TREE_CODE (ttr) != FUNCTION_TYPE && TREE_CODE (ttr) != METHOD_TYPE)
|| (TREE_CODE (ttl) != FUNCTION_TYPE && TREE_CODE (ttl) != METHOD_TYPE))
{
if (TREE_CODE (ttl) == OFFSET_TYPE
&& binfo_member (TYPE_OFFSET_BASETYPE (ttr),
CLASSTYPE_VBASECLASSES (TYPE_OFFSET_BASETYPE (ttl))))
{
error ("%s between pointer to members converting across virtual baseclasses", errtype);
return error_mark_node;
}
else if (!at_least_as_qualified_p (ttl, ttr))
{
if (string_conv_p (type, rhs, 1))
/* converting from string constant to char *, OK. */;
/* [expr.ass]
The expression is implicitly converted (clause _conv_) to the
cv-unqualified type of the left operand. */
if (!can_convert_arg (type, rhstype, rhs))
{
/* When -Wno-pmf-converions is use, we just silently allow
conversions from pointers-to-members to plain pointers. If
the conversion doesn't work, cp_convert will complain. */
if (!warn_pmf2ptr
&& TYPE_PTR_P (type)
&& TYPE_PTRMEMFUNC_P (rhstype))
rhs = cp_convert (strip_top_quals (type), rhs);
/* If the right-hand side has unknown type, then it is an
overloaded function. Call instantiate_type to get error
messages. */
else if (rhstype == unknown_type_node)
instantiate_type (type, rhs, 1);
else if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' discards qualifiers",
rhstype, parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' discards qualifiers",
errtype, type, rhstype);
}
else if (TREE_CODE (ttl) == TREE_CODE (ttr)
&& ! comp_target_types (type, rhstype, 1))
{
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' changes signedness",
rhstype, parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' changes signedness",
errtype, type, rhstype);
}
}
}
else
{
int add_quals = 0;
int drops_quals = 0;
int left_const = 1;
int unsigned_parity;
int nptrs = 0;
/* This code is basically a duplicate of comp_ptr_ttypes_real. */
for (; ; ttl = TREE_TYPE (ttl), ttr = TREE_TYPE (ttr))
{
nptrs -= 1;
drops_quals |= !at_least_as_qualified_p (ttl, ttr);
if (! left_const
&& !at_least_as_qualified_p (ttr, ttl))
add_quals = 1;
left_const &= TYPE_READONLY (ttl);
if (TREE_CODE (ttl) != POINTER_TYPE
|| TREE_CODE (ttr) != POINTER_TYPE)
break;
}
unsigned_parity = TREE_UNSIGNED (ttl) - TREE_UNSIGNED (ttr);
if (unsigned_parity)
{
if (TREE_UNSIGNED (ttl))
ttr = unsigned_type (ttr);
else
ttl = unsigned_type (ttl);
}
if (comp_target_types (ttl, ttr, nptrs) > 0)
{
if (add_quals)
{
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' adds cv-quals without intervening `const'",
rhstype, parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' adds cv-quals without intervening `const'",
errtype, type, rhstype);
}
if (drops_quals)
{
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' discards qualifiers",
rhstype, parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' discards qualifiers",
errtype, type, rhstype);
}
if (unsigned_parity > 0)
{
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' changes signed to unsigned",
rhstype, parmnum, fndecl);
cp_error ("cannot convert `%T' to `%T' for argument `%P' to `%D'",
rhstype, type, parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' changes signed to unsigned",
errtype, type, rhstype);
}
else if (unsigned_parity < 0)
{
if (fndecl)
cp_pedwarn ("passing `%T' as argument %P of `%D' changes unsigned to signed",
rhstype, parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' changes unsigned to signed",
errtype, type, rhstype);
}
/* C++ is not so friendly about converting function and
member function pointers as C. Emit warnings here. */
if (TREE_CODE (ttl) == FUNCTION_TYPE
|| TREE_CODE (ttl) == METHOD_TYPE)
if (!same_or_base_type_p (ttl, ttr))
{
warning ("conflicting function types in %s:", errtype);
cp_warning ("\t`%T' != `%T'", type, rhstype);
}
}
else
{
if (fndecl)
cp_error ("passing `%T' as argument %P of `%D'",
rhstype, parmnum, fndecl);
else
cp_error ("%s to `%T' from `%T'", errtype, type, rhstype);
return error_mark_node;
}
}
return cp_convert (type, rhs);
}
else if (codel == POINTER_TYPE
&& (coder == INTEGER_TYPE
|| coder == BOOLEAN_TYPE))
{
/* An explicit constant 0 can convert to a pointer,
but not a 0 that results from casting or folding. */
if (! (TREE_CODE (rhs) == INTEGER_CST && integer_zerop (rhs)))
{
if (fndecl)
cp_pedwarn ("passing `%T' to argument %P of `%D' lacks a cast",
rhstype, parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' lacks a cast",
errtype, type, rhstype);
}
return cp_convert (type, rhs);
}
else if (codel == INTEGER_TYPE
&& (coder == POINTER_TYPE
|| (coder == RECORD_TYPE
&& (IS_SIGNATURE_POINTER (rhstype)
|| TYPE_PTRMEMFUNC_FLAG (rhstype)
|| IS_SIGNATURE_REFERENCE (rhstype)))))
{
if (fndecl)
cp_pedwarn ("passing `%T' to argument %P of `%D' lacks a cast",
rhstype, parmnum, fndecl);
else
cp_pedwarn ("%s to `%T' from `%T' lacks a cast",
errtype, type, rhstype);
return cp_convert (type, rhs);
}
else if (codel == BOOLEAN_TYPE
&& (coder == POINTER_TYPE
|| (coder == RECORD_TYPE
&& (IS_SIGNATURE_POINTER (rhstype)
|| TYPE_PTRMEMFUNC_FLAG (rhstype)
|| IS_SIGNATURE_REFERENCE (rhstype)))))
return cp_convert (type, rhs);
/* C++ */
else if (((coder == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (rhstype)) == METHOD_TYPE)
|| integer_zerop (rhs)
|| TYPE_PTRMEMFUNC_P (rhstype))
&& TYPE_PTRMEMFUNC_P (type))
{
tree ttl = TYPE_PTRMEMFUNC_FN_TYPE (type);
tree ttr = (TYPE_PTRMEMFUNC_P (rhstype)
? TYPE_PTRMEMFUNC_FN_TYPE (rhstype)
: rhstype);
int ctt = (TREE_CODE (rhstype) == INTEGER_TYPE ? 1
: comp_target_types (ttl, ttr, 1));
if (ctt < 0)
cp_pedwarn ("converting `%T' to `%T' is a contravariance violation",
ttr, ttl);
else if (ctt == 0)
cp_error ("%s to `%T' from `%T'", errtype, ttl, ttr);
/* compatible pointer to member functions. */
return build_ptrmemfunc (ttl, rhs, 0);
}
else if (codel == ERROR_MARK || coder == ERROR_MARK)
cp_error ("cannot convert `%T' to `%T' in %s", rhstype, type,
errtype);
return error_mark_node;
/* This should no longer happen. References are initialized via
`convert_for_initialization'. They should otherwise be
bashed before coming here. */
else if (codel == REFERENCE_TYPE)
my_friendly_abort (317);
else if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (rhs)))
{
tree nrhs = build1 (NOP_EXPR, type, rhs);
TREE_CONSTANT (nrhs) = TREE_CONSTANT (rhs);
return nrhs;
}
else if (TYPE_HAS_CONSTRUCTOR (type) || IS_AGGR_TYPE (TREE_TYPE (rhs)))
return cp_convert (type, rhs);
/* Handle anachronistic conversions from (::*)() to cv void* or (*)(). */
else if (TREE_CODE (type) == POINTER_TYPE
&& (TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
|| TYPE_MAIN_VARIANT (TREE_TYPE (type)) == void_type_node)
&& TREE_TYPE (rhs)
&& TYPE_PTRMEMFUNC_P (TREE_TYPE (rhs)))
return cp_convert (type, rhs);
cp_error ("%s to `%T' from `%T'", errtype, type, rhstype);
return error_mark_node;
return ncp_convert (strip_top_quals (type), rhs);
}
/* Convert RHS to be of type TYPE.
......
......@@ -125,21 +125,27 @@ readonly_error (arg, string, soft)
(*fn) ("%s of read-only location", string);
}
/* Print an error message for invalid use of a type which declares
virtual functions which are not inheritable. */
/* If TYPE has abstract virtual functions, issue an error about trying
to create an object of that type. DECL is the object declared, or
NULL_TREE if the declaration is unavailable. Returns 1 if an error
occurred; zero if all was well. */
void
int
abstract_virtuals_error (decl, type)
tree decl;
tree type;
{
tree u = CLASSTYPE_ABSTRACT_VIRTUALS (type);
tree u;
tree tu;
if (!CLASS_TYPE_P (type) || !CLASSTYPE_ABSTRACT_VIRTUALS (type))
return 0;
u = CLASSTYPE_ABSTRACT_VIRTUALS (type);
if (decl)
{
if (TREE_CODE (decl) == RESULT_DECL)
return;
return 0;
if (TREE_CODE (decl) == VAR_DECL)
cp_error ("cannot declare variable `%D' to be of type `%T'",
......@@ -170,6 +176,8 @@ abstract_virtuals_error (decl, type)
}
else
cp_error (" since type `%T' has abstract virtual functions", type);
return 1;
}
/* Print an error message for invalid use of a signature type.
......@@ -1486,11 +1494,8 @@ build_functional_cast (exp, parms)
cp_error ("type `%T' is not yet defined", type);
return error_mark_node;
}
if (IS_AGGR_TYPE (type) && CLASSTYPE_ABSTRACT_VIRTUALS (type))
{
abstract_virtuals_error (NULL_TREE, type);
if (abstract_virtuals_error (NULL_TREE, type))
return error_mark_node;
}
if (parms && TREE_CHAIN (parms) == NULL_TREE)
return build_c_cast (type, TREE_VALUE (parms));
......
......@@ -1168,8 +1168,8 @@ class dict : public object {
DISPLAYER displayer, STRINGER str_f)
{// ERROR - candidate for bad call
if (799 >= 800 ) cout << "Creating new dictionary..." << '\n'; ;
if (cmp == __null ) cmp = &default_compare;
if (displayer == __null ) displayer = &default_displayer;
if (cmp == __null ) cmp = (COMPARE) &default_compare;
if (displayer == __null ) displayer = (DISPLAYER) &default_displayer;
if (str_f == __null ) str_f = &default_stringer;
compare_f = cmp;
display_f = displayer;
......@@ -1417,7 +1417,7 @@ class queue : public object {
DISPLAYER displayer, STRINGER str_f)
{// ERROR - candidate for bad call
if (799 >= 800 ) cout << "Creating new queue..." << '\n'; ;
if (displayer == __null ) displayer = &default_displayer;
if (displayer == __null ) displayer = (DISPLAYER) &default_displayer;
if (str_f == __null ) str_f = &default_stringer;
display_f = displayer;
destroy_f = destroyer;
......
......@@ -2,8 +2,9 @@
// Bug: g++ misinterprets typedefs of function type in class scope.
// Build don't link:
typedef int (*F1) ();
struct A {
typedef int F();
F *fp;
void* g() { return fp; } // gets bogus error - typing
F1 g() { return fp; } // gets bogus error - typing
};
......@@ -11,11 +11,11 @@ public:
void f1b() { ok += 5; }
void f2a() { ok += 7; } // gets bogus error XFAIL *-*-*
void f2b() { }
const static void (*table[2][2])();
static void (*table[2][2])();
void main();
} a;
const void (*A::table[2][2])()
void (*A::table[2][2])()
= { { PMF2PF(&A::f1a), PMF2PF(&A::f1b) },
{ PMF2PF(&A::f2a), PMF2PF(&A::f1b) },
};
......
// Build don't run:
// Origin: Mark Mitchell <mark@codesourcery.com>
template <class T>
void f (T&) ;
template <>
void f (void (&)())
{
}
void g ()
{
}
void h ()
{
}
bool b;
int main ()
{
f (b ? g : h);
}
......@@ -5,4 +5,4 @@
// Special g++ Options:
int foo();
const int (*bar)() = foo; // ERROR - adding const - XFAIL *-*-*
const int (*bar)() = foo; // ERROR - adding const
// Build don't link:
// Origin: Jason Merrill <jason@cygnus.com>
const char *pc;
enum A { x } a;
int i;
int main()
{
return i ? *pc : a;
}
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