aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-07-26 08:18:19 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-07-26 08:18:19 +0000
commita7a64a77ef33be210374003a0b84dd8d60f75a49 (patch)
treec9b772ea54e12c6cccfb0e0b435dbd04cdf6a698
parent5cabd6f5f4b1c910709ab5beca3ad62e7d38ed7f (diff)
downloadgcc-a7a64a77ef33be210374003a0b84dd8d60f75a49.zip
gcc-a7a64a77ef33be210374003a0b84dd8d60f75a49.tar.gz
gcc-a7a64a77ef33be210374003a0b84dd8d60f75a49.tar.bz2
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
-rw-r--r--gcc/cp/ChangeLog49
-rw-r--r--gcc/cp/call.c503
-rw-r--r--gcc/cp/class.c3
-rw-r--r--gcc/cp/cp-tree.h25
-rw-r--r--gcc/cp/cvt.c7
-rw-r--r--gcc/cp/decl.c28
-rw-r--r--gcc/cp/init.c8
-rw-r--r--gcc/cp/pt.c26
-rw-r--r--gcc/cp/search.c4
-rw-r--r--gcc/cp/typeck.c1053
-rw-r--r--gcc/cp/typeck2.c25
-rw-r--r--gcc/testsuite/g++.old-deja/g++.brendan/crash19.C6
-rw-r--r--gcc/testsuite/g++.old-deja/g++.jason/typedef.C3
-rw-r--r--gcc/testsuite/g++.old-deja/g++.mike/p10769a.C4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/cond1.C26
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/conv5.C2
-rw-r--r--gcc/testsuite/g++.old-deja/g++.other/overload10.C11
17 files changed, 891 insertions, 892 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index b0efd31..4dba902 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,52 @@
+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.
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 6e75e94..cd5e77d 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -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]
+
+ For every pair of promoted arithmetic types L and R, there
+ exist candidate operator functions of the form
- /* Extension: Support ?: of enumeral type. Hopefully this will not
- be an extension for long. */
- if (TREE_CODE (type1) == ENUMERAL_TYPE && type1 == type2)
+ 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;
- else if (TREE_CODE (type1) == ENUMERAL_TYPE
- || TREE_CODE (type2) == ENUMERAL_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 (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)))
+
+ /* 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;
- if (TREE_CODE (type1) == REFERENCE_TYPE
- || TREE_CODE (type2) == REFERENCE_TYPE)
- 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;
- 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. */
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 41f1d79..a4cc5a5 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -3619,8 +3619,7 @@ 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);
+ abstract_virtuals_error (x, type);
/* Don't let signatures make it through either. */
if (IS_SIGNATURE (type))
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 50d28ca..4e13392 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -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))
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index d24dbf1..e5c1064 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -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);
- return error_mark_node;
- }
+ if (abstract_virtuals_error (NULL_TREE, type))
+ return error_mark_node;
if ((flags & LOOKUP_ONLYCONVERTING)
&& ! (IS_AGGR_TYPE (dtype) && DERIVED_FROM_P (type, dtype)))
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 21b1143..1dc070b 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -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);
- any_error = 1; /* Seems like a good idea. */
- }
+ 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,9 +13101,7 @@ 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));
+ abstract_virtuals_error (decl1, TREE_TYPE (fntype));
}
/* Effective C++ rule 15. See also c_expand_return. */
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 8469fe6..b3b9dcb 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -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);
- return error_mark_node;
- }
+ if (abstract_virtuals_error (NULL_TREE, true_type))
+ return error_mark_node;
if (TYPE_LANG_SPECIFIC (true_type) && IS_SIGNATURE (true_type))
{
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 06b6c13..ef84f74 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -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;
diff --git a/gcc/cp/search.c b/gcc/cp/search.c
index 6cde690..b7f3e18 100644
--- a/gcc/cp/search.c
+++ b/gcc/cp/search.c
@@ -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);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index 7add550..c4bb18f 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -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,388 +6447,86 @@ 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. */
- if (coder == REAL_TYPE && codel == INTEGER_TYPE)
- {
- if (fndecl)
- cp_warning ("`%T' used for argument %P of `%D'",
- rhstype, parmnum, fndecl);
- else
- cp_warning ("%s to `%T' from `%T'", errtype, type, rhstype);
- }
- /* And we should warn if assigning a negative value to
- an unsigned variable. */
- else if (TREE_UNSIGNED (type) && codel != BOOLEAN_TYPE)
- {
- if (TREE_CODE (rhs) == INTEGER_CST
- && TREE_NEGATED_INT (rhs))
- {
- if (fndecl)
- cp_warning ("negative value `%E' passed as argument %P of `%D'",
- rhs, parmnum, fndecl);
- else
- cp_warning ("%s of negative value `%E' to `%T'",
- errtype, rhs, type);
- }
- overflow_warning (rhs);
- if (TREE_CONSTANT (rhs))
- 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);
+ /* 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);
- 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. */;
- 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);
- }
- }
- }
+ /* Warn about assigning a floating-point type to an integer type. */
+ if (coder == REAL_TYPE && codel == INTEGER_TYPE)
+ {
+ if (fndecl)
+ cp_warning ("`%T' used for argument %P of `%D'",
+ rhstype, parmnum, fndecl);
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);
- 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);
+ cp_warning ("%s to `%T' from `%T'", errtype, type, rhstype);
}
- else if (codel == POINTER_TYPE
- && (coder == INTEGER_TYPE
- || coder == BOOLEAN_TYPE))
+ /* And warn about assigning a negative value to an unsigned
+ variable. */
+ else if (TREE_UNSIGNED (type) && codel != 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 (TREE_CODE (rhs) == INTEGER_CST
+ && TREE_NEGATED_INT (rhs))
{
if (fndecl)
- cp_pedwarn ("passing `%T' to argument %P of `%D' lacks a cast",
- rhstype, parmnum, fndecl);
+ cp_warning ("negative value `%E' passed as argument %P of `%D'",
+ rhs, parmnum, fndecl);
else
- cp_pedwarn ("%s to `%T' from `%T' lacks a cast",
- errtype, type, rhstype);
+ cp_warning ("%s of negative value `%E' to `%T'",
+ errtype, rhs, type);
}
- 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);
+ overflow_warning (rhs);
+ if (TREE_CONSTANT (rhs))
+ rhs = fold (rhs);
+ }
+
+ /* [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_error ("cannot convert `%T' to `%T' for argument `%P' to `%D'",
+ rhstype, type, 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)
- 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;
+ cp_error ("cannot convert `%T' to `%T' in %s", rhstype, type,
+ errtype);
+ return error_mark_node;
}
- 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.
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index fbd3d27..d1e96ed 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -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);
- return error_mark_node;
- }
+ 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));
diff --git a/gcc/testsuite/g++.old-deja/g++.brendan/crash19.C b/gcc/testsuite/g++.old-deja/g++.brendan/crash19.C
index 1738c73..de46668 100644
--- a/gcc/testsuite/g++.old-deja/g++.brendan/crash19.C
+++ b/gcc/testsuite/g++.old-deja/g++.brendan/crash19.C
@@ -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;
diff --git a/gcc/testsuite/g++.old-deja/g++.jason/typedef.C b/gcc/testsuite/g++.old-deja/g++.jason/typedef.C
index fac78ce..c681c82d 100644
--- a/gcc/testsuite/g++.old-deja/g++.jason/typedef.C
+++ b/gcc/testsuite/g++.old-deja/g++.jason/typedef.C
@@ -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
};
diff --git a/gcc/testsuite/g++.old-deja/g++.mike/p10769a.C b/gcc/testsuite/g++.old-deja/g++.mike/p10769a.C
index f5ff345..3dd5dc2 100644
--- a/gcc/testsuite/g++.old-deja/g++.mike/p10769a.C
+++ b/gcc/testsuite/g++.old-deja/g++.mike/p10769a.C
@@ -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) },
};
diff --git a/gcc/testsuite/g++.old-deja/g++.other/cond1.C b/gcc/testsuite/g++.old-deja/g++.other/cond1.C
new file mode 100644
index 0000000..c025beb
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/cond1.C
@@ -0,0 +1,26 @@
+// 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);
+}
+
diff --git a/gcc/testsuite/g++.old-deja/g++.other/conv5.C b/gcc/testsuite/g++.old-deja/g++.other/conv5.C
index 97bf238..28c8e3b 100644
--- a/gcc/testsuite/g++.old-deja/g++.other/conv5.C
+++ b/gcc/testsuite/g++.old-deja/g++.other/conv5.C
@@ -5,4 +5,4 @@
// Special g++ Options:
int foo();
-const int (*bar)() = foo; // ERROR - adding const - XFAIL *-*-*
+const int (*bar)() = foo; // ERROR - adding const
diff --git a/gcc/testsuite/g++.old-deja/g++.other/overload10.C b/gcc/testsuite/g++.old-deja/g++.other/overload10.C
new file mode 100644
index 0000000..50ae8a9
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.other/overload10.C
@@ -0,0 +1,11 @@
+// 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;
+ }