static int joust PARAMS ((struct z_candidate *, struct z_candidate *, int));
static int compare_ics PARAMS ((tree, tree));
static tree build_over_call PARAMS ((struct z_candidate *, tree, int));
-static tree convert_like PARAMS ((tree, tree));
+#define convert_like(CONV, EXPR) convert_like_real (CONV, EXPR, NULL_TREE, 0, 0)
+#define convert_like_with_context(CONV, EXPR, FN, ARGNO) convert_like_real (CONV, EXPR, FN, ARGNO, 0)
+static tree convert_like_real PARAMS ((tree, tree, tree, int, int));
static void op_error PARAMS ((enum tree_code, enum tree_code, tree, tree,
tree, const char *));
static tree build_object_call PARAMS ((tree, tree));
{
if (TREE_CODE (cand->second_conv) == AMBIG_CONV)
return error_mark_node;
- return convert_from_reference (convert_like (cand->second_conv, expr));
+ return convert_from_reference
+ (convert_like_with_context
+ (cand->second_conv, expr, cand->fn, 0));
}
return NULL_TREE;
}
&& DECL_NAME (cand->fn) == ansi_opname [CALL_EXPR])
return build_over_call (cand, mem_args, LOOKUP_NORMAL);
- obj = convert_like (TREE_VEC_ELT (cand->convs, 0), obj);
+ obj = convert_like_with_context
+ (TREE_VEC_ELT (cand->convs, 0), obj, cand->fn, -1);
/* FIXME */
return build_function_call (obj, args);
return 1;
}
-/* Perform the conversions in CONVS on the expression EXPR. */
+/* Perform the conversions in CONVS on the expression EXPR.
+ FN and ARGNUM are used for diagnostics. ARGNUM is zero based, -1
+ indicates the `this' argument of a method. INNER is non-zero when
+ being called to continue a conversion chain. */
static tree
-convert_like (convs, expr)
+convert_like_real (convs, expr, fn, argnum, inner)
tree convs, expr;
+ tree fn;
+ int argnum;
+ int inner;
{
if (ICS_BAD_FLAG (convs)
&& TREE_CODE (convs) != USER_CONV
{
if (TREE_CODE (t) == USER_CONV)
{
- expr = convert_like (t, expr);
+ expr = convert_like_real (t, expr, fn, argnum, 1);
break;
}
else if (TREE_CODE (t) == AMBIG_CONV)
- return convert_like (t, expr);
+ return convert_like_real (t, expr, fn, argnum, 1);
else if (TREE_CODE (t) == IDENTITY_CONV)
break;
}
return convert_for_initialization
(NULL_TREE, TREE_TYPE (convs), expr, LOOKUP_NORMAL,
- "conversion", NULL_TREE, 0);
+ "conversion", fn, argnum);
}
-
+
+ if (!inner)
+ expr = dubious_conversion_warnings
+ (TREE_TYPE (convs), expr, "argument", fn, argnum);
switch (TREE_CODE (convs))
{
case USER_CONV:
break;
};
- expr = convert_like (TREE_OPERAND (convs, 0), expr);
+ expr = convert_like_real (TREE_OPERAND (convs, 0), expr, fn, argnum, 1);
if (expr == error_mark_node)
return error_mark_node;
conversions. Return the converted value. */
tree
-convert_default_arg (type, arg, fn)
+convert_default_arg (type, arg, fn, parmnum)
tree type;
tree arg;
tree fn;
+ int parmnum;
{
if (fn && DECL_TEMPLATE_INFO (fn))
arg = tsubst_default_argument (fn, type, arg);
{
arg = digest_init (type, arg, 0);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- "default argument", 0, 0);
+ "default argument", fn, parmnum);
}
else
{
arg = copy_node (arg);
arg = convert_for_initialization (0, type, arg, LOOKUP_NORMAL,
- "default argument", 0, 0);
+ "default argument", fn, parmnum);
if (PROMOTE_PROTOTYPES
&& (TREE_CODE (type) == INTEGER_TYPE
|| TREE_CODE (type) == ENUMERAL_TYPE)
if (TREE_CODE (t) == USER_CONV
|| TREE_CODE (t) == AMBIG_CONV)
{
- val = convert_like (t, val);
+ val = convert_like_with_context (t, val, fn, i - is_method);
break;
}
else if (TREE_CODE (t) == IDENTITY_CONV)
}
val = convert_for_initialization
(NULL_TREE, type, val, LOOKUP_NORMAL,
- "argument passing", fn, i - is_method);
+ "argument", fn, i - is_method);
}
else
{
- /* Issue warnings about peculiar, but legal, uses of NULL. */
- if (ARITHMETIC_TYPE_P (TREE_VALUE (parm))
- && TREE_VALUE (arg) == null_node)
- cp_warning ("converting NULL to non-pointer type");
-
- val = convert_like (conv, TREE_VALUE (arg));
+ val = TREE_VALUE (arg);
+ val = convert_like_with_context
+ (conv, TREE_VALUE (arg), fn, i - is_method);
}
if (PROMOTE_PROTOTYPES
}
/* Default arguments */
- for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm))
+ for (; parm && parm != void_list_node; parm = TREE_CHAIN (parm), i++)
converted_args
= tree_cons (NULL_TREE,
convert_default_arg (TREE_VALUE (parm),
TREE_PURPOSE (parm),
- fn),
+ fn, i - is_method),
converted_args);
/* Ellipsis */
extern int can_convert PARAMS ((tree, tree));
extern int can_convert_arg PARAMS ((tree, tree, tree));
extern int enforce_access PARAMS ((tree, tree));
-extern tree convert_default_arg PARAMS ((tree, tree, tree));
+extern tree convert_default_arg PARAMS ((tree, tree, tree, int));
extern tree convert_arg_to_ellipsis PARAMS ((tree));
extern tree build_x_va_arg PARAMS ((tree, tree));
extern tree convert_type_from_ellipsis PARAMS ((tree));
extern tree build_c_cast PARAMS ((tree, tree));
extern tree build_x_modify_expr PARAMS ((tree, enum tree_code, tree));
extern tree build_modify_expr PARAMS ((tree, enum tree_code, tree));
+extern tree dubious_conversion_warnings PARAMS ((tree, tree, const char *, tree, int));
extern tree convert_for_initialization PARAMS ((tree, tree, tree, int, const char *, tree, int));
extern void c_expand_asm_operands PARAMS ((tree, tree, tree, tree, int, char *, int));
extern void c_expand_return PARAMS ((tree));
tree parmval
= convert_default_arg (TREE_VALUE (typetail),
TREE_PURPOSE (typetail),
- fndecl);
+ fndecl, i);
if (parmval == error_mark_node)
return error_mark_node;
pfn_identifier, NULL_TREE, 0));
}
+/* Expression EXPR is about to be implicitly converted to TYPE. Warn
+ if this is a potentially dangerous thing to do. Returns a possibly
+ marked EXPR. */
+
+tree
+dubious_conversion_warnings (type, expr, errtype, fndecl, parmnum)
+ tree type;
+ tree expr;
+ const char *errtype;
+ tree fndecl;
+ int parmnum;
+{
+ /* Issue warnings about peculiar, but legal, uses of NULL. */
+ if (ARITHMETIC_TYPE_P (type) && expr == null_node)
+ {
+ if (fndecl)
+ cp_warning ("passing NULL used for non-pointer %s %P of `%D'",
+ errtype, parmnum, fndecl);
+ else
+ cp_warning ("%s to non-pointer type `%T' from NULL", errtype, type);
+ }
+
+ /* Warn about assigning a floating-point type to an integer type. */
+ if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+ && TREE_CODE (type) == INTEGER_TYPE)
+ {
+ if (fndecl)
+ cp_warning ("passing `%T' for %s %P of `%D'",
+ TREE_TYPE (expr), errtype, parmnum, fndecl);
+ else
+ cp_warning ("%s to `%T' from `%T'", errtype, type, TREE_TYPE (expr));
+ }
+ /* And warn about assigning a negative value to an unsigned
+ variable. */
+ else if (TREE_UNSIGNED (type) && TREE_CODE (type) != BOOLEAN_TYPE)
+ {
+ if (TREE_CODE (expr) == INTEGER_CST
+ && TREE_NEGATED_INT (expr))
+ {
+ if (fndecl)
+ cp_warning ("passing negative value `%E' for %s %P of `%D'",
+ expr, errtype, parmnum, fndecl);
+ else
+ cp_warning ("%s of negative value `%E' to `%T'",
+ errtype, expr, type);
+ }
+ overflow_warning (expr);
+ if (TREE_CONSTANT (expr))
+ expr = fold (expr);
+ }
+ return expr;
+}
+
/* 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
if (TREE_CODE (rhs) == TREE_LIST && TREE_VALUE (rhs) == error_mark_node)
return error_mark_node;
- /* Issue warnings about peculiar, but legal, uses of NULL. We
- do this *before* the call to decl_constant_value so as to
- avoid duplicate warnings on code like `const int I = NULL;
- f(I);'. */
- if (ARITHMETIC_TYPE_P (type) && rhs == null_node)
- cp_warning ("converting NULL to non-pointer type");
+ rhs = dubious_conversion_warnings (type, rhs, errtype, fndecl, parmnum);
/* The RHS of an assignment cannot have void type. */
if (coder == VOID_TYPE)
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)
- cp_warning ("`%T' used for argument %P of `%D'",
- rhstype, parmnum, fndecl);
- else
- cp_warning ("%s to `%T' from `%T'", errtype, type, rhstype);
- }
- /* 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
- && 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);
- }
-
/* [expr.ass]
The expression is implicitly converted (clause _conv_) to the