aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/cvt.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/cvt.c')
-rw-r--r--gcc/cp/cvt.c330
1 files changed, 203 insertions, 127 deletions
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index ce01c66..e87b168 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -903,6 +903,7 @@ convert_to_aggr (type, expr, msgp, protect)
parmlist = tree_cons (NULL_TREE, integer_zero_node, parmlist);
parmtypes = tree_cons (NULL_TREE, TYPE_POINTER_TO (basetype), parmtypes);
+#if 0
method_name = build_decl_overload (name, parmtypes, 1);
/* constructors are up front. */
@@ -936,6 +937,7 @@ convert_to_aggr (type, expr, msgp, protect)
}
fndecl = DECL_CHAIN (fndecl);
}
+#endif
/* No exact conversion was found. See if an approximate
one will do. */
@@ -1548,7 +1550,7 @@ build_type_conversion (code, xtype, expr, for_sure)
{
cp_error ("ambiguous conversion from `%T' to `%T'", basetype,
xtype);
- cp_error (" candidate conversion functions include `%T' and `%T'",
+ cp_error (" candidate conversions include `%T' and `%T'",
TREE_VALUE (winner), TREE_VALUE (conv));
return NULL_TREE;
}
@@ -1564,154 +1566,228 @@ build_type_conversion (code, xtype, expr, for_sure)
return NULL_TREE;
}
-/* Must convert two aggregate types to non-aggregate type.
- Attempts to find a non-ambiguous, "best" type conversion.
-
- Return 1 on success, 0 on failure.
+/* Convert the given EXPR to one of a group of types suitable for use in an
+ expression. DESIRES is a combination of various WANT_* flags (q.v.)
+ which indicates which types are suitable. If COMPLAIN is 1, complain
+ about ambiguity; otherwise, the caller will deal with it. */
- @@ What are the real semantics of this supposed to be??? */
-int
-build_default_binary_type_conversion (code, arg1, arg2)
- enum tree_code code;
- tree *arg1, *arg2;
+tree
+build_expr_type_conversion (desires, expr, complain)
+ int desires;
+ tree expr;
+ int complain;
{
- tree type1 = TREE_TYPE (*arg1);
- tree type2 = TREE_TYPE (*arg2);
-
- if (TREE_CODE (type1) == REFERENCE_TYPE
- || TREE_CODE (type1) == POINTER_TYPE)
- type1 = TREE_TYPE (type1);
- if (TREE_CODE (type2) == REFERENCE_TYPE
- || TREE_CODE (type2) == POINTER_TYPE)
- type2 = TREE_TYPE (type2);
+ tree basetype = TREE_TYPE (expr);
+ tree conv;
+ tree winner = NULL_TREE;
- if (TREE_CODE (TYPE_NAME (type1)) != TYPE_DECL)
+ if (TREE_CODE (basetype) == OFFSET_TYPE)
{
- tree decl = typedecl_for_tag (type1);
- if (decl)
- error ("type conversion nonexistent for type `%s'",
- IDENTIFIER_POINTER (DECL_NAME (decl)));
- else
- error ("type conversion nonexistent for non-C++ type");
- return 0;
- }
- if (TREE_CODE (TYPE_NAME (type2)) != TYPE_DECL)
- {
- tree decl = typedecl_for_tag (type2);
- if (decl)
- error ("type conversion nonexistent for type `%s'",
- IDENTIFIER_POINTER (decl));
- else
- error ("type conversion nonexistent for non-C++ type");
- return 0;
+ expr = resolve_offset_ref (expr);
+ basetype = TREE_TYPE (expr);
}
- if (!IS_AGGR_TYPE (type1) || !TYPE_HAS_CONVERSION (type1))
- {
- if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2))
- cp_error ("no conversion from `%T' and `%T' to types with default `%O' ",
- type1, type2, code);
- else
- cp_error ("no conversion from `%T' to type with default `%O'",
- type1, code);
- return 0;
- }
- else if (!IS_AGGR_TYPE (type2) || !TYPE_HAS_CONVERSION (type2))
- {
- cp_error ("no conversion from `%T' to type with default `%O'",
- type2, code);
- return 0;
- }
+ if (! IS_AGGR_TYPE (basetype))
+ switch (TREE_CODE (basetype))
+ {
+ case INTEGER_TYPE:
+ if ((desires & WANT_NULL) && TREE_CODE (expr) == INTEGER_CST
+ && integer_zerop (expr))
+ return expr;
+ /* else fall through... */
+
+ case BOOLEAN_TYPE:
+ return (desires & WANT_INT) ? expr : NULL_TREE;
+ case ENUMERAL_TYPE:
+ return (desires & WANT_ENUM) ? expr : NULL_TREE;
+ case REAL_TYPE:
+ return (desires & WANT_FLOAT) ? expr : NULL_TREE;
+ case POINTER_TYPE:
+ return (desires & WANT_POINTER) ? expr : NULL_TREE;
+
+ case FUNCTION_TYPE:
+ case ARRAY_TYPE:
+ return (desires & WANT_POINTER) ? default_conversion (expr)
+ : NULL_TREE;
+ default:
+ return NULL_TREE;
+ }
- if (code == TRUTH_ANDIF_EXPR
- || code == TRUTH_ORIF_EXPR)
- {
- *arg1 = convert (boolean_type_node, *arg1);
- *arg2 = convert (boolean_type_node, *arg2);
- }
- else if (TYPE_HAS_INT_CONVERSION (type1))
- {
- if (TYPE_HAS_REAL_CONVERSION (type1))
- cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int",
- type1);
- *arg1 = build_type_conversion (code, integer_type_node, *arg1, 1);
- *arg2 = build_type_conversion (code, integer_type_node, *arg2, 1);
- }
- else if (TYPE_HAS_REAL_CONVERSION (type1))
- {
- *arg1 = build_type_conversion (code, double_type_node, *arg1, 1);
- *arg2 = build_type_conversion (code, double_type_node, *arg2, 1);
- }
- else
- {
- *arg1 = build_type_conversion (code, ptr_type_node, *arg1, 1);
- if (*arg1 == error_mark_node)
- error ("ambiguous pointer conversion");
- *arg2 = build_type_conversion (code, ptr_type_node, *arg2, 1);
- if (*arg1 != error_mark_node && *arg2 == error_mark_node)
- error ("ambiguous pointer conversion");
- }
- if (*arg1 == 0)
- {
- if (*arg2 == 0 && type1 != type2)
- cp_error ("default type conversion for types `%T' and `%T' failed",
- type1, type2);
- else
- cp_error ("default type conversion for type `%T' failed", type1);
- return 0;
- }
- else if (*arg2 == 0)
+ if (! TYPE_HAS_CONVERSION (basetype))
+ return NULL_TREE;
+
+ for (conv = lookup_conversions (basetype); conv; conv = TREE_CHAIN (conv))
{
- cp_error ("default type conversion for type `%T' failed", type2);
- return 0;
+ int win = 0;
+
+ if (winner && TREE_PURPOSE (winner) == TREE_PURPOSE (conv))
+ continue;
+
+ switch (TREE_CODE (TREE_VALUE (conv)))
+ {
+ case BOOLEAN_TYPE:
+ case INTEGER_TYPE:
+ win = (desires & WANT_INT); break;
+ case ENUMERAL_TYPE:
+ win = (desires & WANT_ENUM); break;
+ case REAL_TYPE:
+ win = (desires & WANT_FLOAT); break;
+ case POINTER_TYPE:
+ win = (desires & WANT_POINTER); break;
+ }
+
+ if (win)
+ {
+ if (winner)
+ {
+ if (complain)
+ {
+ cp_error ("ambiguous default type conversion from `%T'",
+ basetype);
+ cp_error (" candidate conversions include `%T' and `%T'",
+ TREE_VALUE (winner), TREE_VALUE (conv));
+ }
+ return error_mark_node;
+ }
+ else
+ winner = conv;
+ }
}
- return 1;
+
+ if (winner)
+ return build_type_conversion_1 (TREE_VALUE (winner), basetype, expr,
+ TREE_PURPOSE (winner), 1);
+
+ return NULL_TREE;
}
-/* Must convert an aggregate type to non-aggregate type.
+/* Must convert two aggregate types to non-aggregate type.
Attempts to find a non-ambiguous, "best" type conversion.
Return 1 on success, 0 on failure.
- The type of the argument is expected to be of aggregate type here.
-
@@ What are the real semantics of this supposed to be??? */
int
-build_default_unary_type_conversion (code, arg)
+build_default_binary_type_conversion (code, arg1, arg2)
enum tree_code code;
- tree *arg;
+ tree *arg1, *arg2;
{
- tree type = TREE_TYPE (*arg);
-
- if (! TYPE_HAS_CONVERSION (type))
+ switch (code)
{
- cp_error ("type conversion required for type `%T'", type);
- return 0;
- }
+ case MULT_EXPR:
+ case TRUNC_DIV_EXPR:
+ case CEIL_DIV_EXPR:
+ case FLOOR_DIV_EXPR:
+ case ROUND_DIV_EXPR:
+ case EXACT_DIV_EXPR:
+ *arg1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
+ *arg2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
+ break;
- if (code == TRUTH_NOT_EXPR)
- *arg = convert (boolean_type_node, *arg);
- else if (TYPE_HAS_INT_CONVERSION (type))
- {
- if (TYPE_HAS_REAL_CONVERSION (type))
- cp_pedwarn ("ambiguous type conversion for type `%T', defaulting to int",
- type);
- *arg = build_type_conversion (code, integer_type_node, *arg, 1);
- }
- else if (TYPE_HAS_REAL_CONVERSION (type))
- *arg = build_type_conversion (code, double_type_node, *arg, 1);
- else
- {
- *arg = build_type_conversion (code, ptr_type_node, *arg, 1);
- if (*arg == error_mark_node)
- error ("ambiguous pointer conversion");
- }
- if (*arg == NULL_TREE)
- {
- cp_error ("default type conversion for type `%T' failed", type);
- return 0;
+ case TRUNC_MOD_EXPR:
+ case FLOOR_MOD_EXPR:
+ case LSHIFT_EXPR:
+ case RSHIFT_EXPR:
+ case BIT_AND_EXPR:
+ case BIT_XOR_EXPR:
+ case BIT_IOR_EXPR:
+ *arg1 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg1, 0);
+ *arg2 = build_expr_type_conversion (WANT_INT | WANT_ENUM, *arg2, 0);
+ break;
+
+ case PLUS_EXPR:
+ {
+ tree a1, a2, p1, p2;
+ int wins;
+
+ a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
+ a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
+ p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0);
+ p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0);
+
+ wins = (a1 && a2) + (a1 && p2) + (p1 && a2);
+
+ if (wins > 1)
+ error ("ambiguous default type conversion for `operator +'");
+
+ if (a1 && a2)
+ *arg1 = a1, *arg2 = a2;
+ else if (a1 && p2)
+ *arg1 = a1, *arg2 = p2;
+ else
+ *arg1 = p1, *arg2 = a2;
+ break;
+ }
+
+ case MINUS_EXPR:
+ {
+ tree a1, a2, p1, p2;
+ int wins;
+
+ a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
+ a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
+ p1 = build_expr_type_conversion (WANT_POINTER, *arg1, 0);
+ p2 = build_expr_type_conversion (WANT_POINTER, *arg2, 0);
+
+ wins = (a1 && a2) + (p1 && p2) + (p1 && a2);
+
+ if (wins > 1)
+ error ("ambiguous default type conversion for `operator -'");
+
+ if (a1 && a2)
+ *arg1 = a1, *arg2 = a2;
+ else if (p1 && p2)
+ *arg1 = p1, *arg2 = p2;
+ else
+ *arg1 = p1, *arg2 = a2;
+ break;
+ }
+
+ case GT_EXPR:
+ case LT_EXPR:
+ case GE_EXPR:
+ case LE_EXPR:
+ case EQ_EXPR:
+ case NE_EXPR:
+ {
+ tree a1, a2, p1, p2;
+ int wins;
+
+ a1 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg1, 0);
+ a2 = build_expr_type_conversion (WANT_ARITH | WANT_ENUM, *arg2, 0);
+ p1 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg1, 0);
+ p2 = build_expr_type_conversion (WANT_POINTER | WANT_NULL, *arg2, 0);
+
+ wins = (a1 && a2) + (p1 && p2);
+
+ if (wins > 1)
+ cp_error ("ambiguous default type conversion for `%O'", code);
+
+ if (a1 && a2)
+ *arg1 = a1, *arg2 = a2;
+ else
+ *arg1 = p1, *arg2 = p2;
+ break;
+ }
+
+ case TRUTH_ANDIF_EXPR:
+ case TRUTH_ORIF_EXPR:
+ *arg1 = convert (boolean_type_node, *arg1);
+ *arg2 = convert (boolean_type_node, *arg2);
+ break;
+
+ default:
+ *arg1 = NULL_TREE;
+ *arg2 = NULL_TREE;
}
- return 1;
+
+ if (*arg1 == error_mark_node || *arg2 == error_mark_node)
+ cp_error ("ambiguous default type conversion for `%O'", code);
+
+ if (*arg1 && *arg2)
+ return 1;
+
+ return 0;
}
/* Implements integral promotion (4.1) and float->double promotion. */