return result_type;
}
-/* Checks if expression EXPR of real/integer type cannot be converted
+/* Checks if expression EXPR of real/integer type cannot be converted
to the real/integer type TYPE. Function returns non-zero when:
- * EXPR is a constant which cannot be exactly converted to TYPE
- * EXPR is not a constant and size of EXPR's type > than size of TYPE,
+ * EXPR is a constant which cannot be exactly converted to TYPE.
+ * EXPR is not a constant and size of EXPR's type > than size of TYPE,
for EXPR type and TYPE being both integers or both real.
- * EXPR is not a constant of real type and TYPE is an integer.
- * EXPR is not a constant of integer type which cannot be
- exactly converted to real type.
+ * EXPR is not a constant of real type and TYPE is an integer.
+ * EXPR is not a constant of integer type which cannot be
+ exactly converted to real type.
Function allows conversions between types of different signedness and
can return SAFE_CONVERSION (zero) in that case. Function can produce
signedness warnings if PRODUCE_WARNS is true. */
+
enum conversion_safety
-unsafe_conversion_p (tree type, tree expr, bool produce_warns)
+unsafe_conversion_p (location_t loc, tree type, tree expr, bool produce_warns)
{
enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */
tree expr_type = TREE_TYPE (expr);
- location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+ loc = expansion_point_location_if_in_system_header (loc);
if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
{
This is a helper function for warnings_for_convert_and_check. */
static void
-conversion_warning (tree type, tree expr)
+conversion_warning (location_t loc, tree type, tree expr)
{
tree expr_type = TREE_TYPE (expr);
- location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
enum conversion_safety conversion_kind;
if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion)
case REAL_CST:
case INTEGER_CST:
- conversion_kind = unsafe_conversion_p (type, expr, true);
+ conversion_kind = unsafe_conversion_p (loc, type, expr, true);
if (conversion_kind == UNSAFE_REAL)
warning_at (loc, OPT_Wfloat_conversion,
"conversion to %qT alters %qT constant value",
tree op1 = TREE_OPERAND (expr, 1);
tree op2 = TREE_OPERAND (expr, 2);
- conversion_warning (type, op1);
- conversion_warning (type, op2);
+ conversion_warning (loc, type, op1);
+ conversion_warning (loc, type, op2);
return;
}
default: /* 'expr' is not a constant. */
- conversion_kind = unsafe_conversion_p (type, expr, true);
+ conversion_kind = unsafe_conversion_p (loc, type, expr, true);
if (conversion_kind == UNSAFE_REAL)
warning_at (loc, OPT_Wfloat_conversion,
"conversion to %qT from %qT may alter its value",
convert_and_check and cp_convert_and_check. */
void
-warnings_for_convert_and_check (tree type, tree expr, tree result)
+warnings_for_convert_and_check (location_t loc, tree type, tree expr,
+ tree result)
{
- location_t loc = EXPR_LOC_OR_LOC (expr, input_location);
+ loc = expansion_point_location_if_in_system_header (loc);
if (TREE_CODE (expr) == INTEGER_CST
&& (TREE_CODE (type) == INTEGER_TYPE
warning_at (loc, OPT_Woverflow,
"large integer implicitly truncated to unsigned type");
else
- conversion_warning (type, expr);
+ conversion_warning (loc, type, expr);
}
else if (!int_fits_type_p (expr, c_common_unsigned_type (type)))
- warning (OPT_Woverflow,
+ warning_at (loc, OPT_Woverflow,
"overflow in implicit constant conversion");
/* No warning for converting 0x80000000 to int. */
else if (pedantic
"overflow in implicit constant conversion");
else
- conversion_warning (type, expr);
+ conversion_warning (loc, type, expr);
}
else if ((TREE_CODE (result) == INTEGER_CST
|| TREE_CODE (result) == FIXED_CST) && TREE_OVERFLOW (result))
warning_at (loc, OPT_Woverflow,
"overflow in implicit constant conversion");
else
- conversion_warning (type, expr);
+ conversion_warning (loc, type, expr);
}
i.e. because of language rules and not because of an explicit cast. */
tree
-convert_and_check (tree type, tree expr)
+convert_and_check (location_t loc, tree type, tree expr)
{
tree result;
tree expr_for_warning;
if (c_inhibit_evaluation_warnings == 0
&& !TREE_OVERFLOW_P (expr)
&& result != error_mark_node)
- warnings_for_convert_and_check (type, expr_for_warning, result);
+ warnings_for_convert_and_check (loc, type, expr_for_warning, result);
return result;
}
if (low_value)
{
low_value = check_case_value (low_value);
- low_value = convert_and_check (type, low_value);
+ low_value = convert_and_check (loc, type, low_value);
if (low_value == error_mark_node)
goto error_out;
}
if (high_value)
{
high_value = check_case_value (high_value);
- high_value = convert_and_check (type, high_value);
+ high_value = convert_and_check (loc, type, high_value);
if (high_value == error_mark_node)
goto error_out;
}
if (TREE_CODE (type0) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
{
- if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+ if (unsafe_conversion_p (loc, TREE_TYPE (type1), op0, false))
{
if (complain)
error_at (loc, "conversion of scalar %qT to vector %qT "
if (TREE_CODE (type0) == INTEGER_TYPE
&& TREE_CODE (TREE_TYPE (type1)) == INTEGER_TYPE)
{
- if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+ if (unsafe_conversion_p (loc, TREE_TYPE (type1), op0, false))
{
if (complain)
error_at (loc, "conversion of scalar %qT to vector %qT "
|| TREE_CODE (type0) == INTEGER_TYPE)
&& SCALAR_FLOAT_TYPE_P (TREE_TYPE (type1)))
{
- if (unsafe_conversion_p (TREE_TYPE (type1), op0, false))
+ if (unsafe_conversion_p (loc, TREE_TYPE (type1), op0, false))
{
if (complain)
error_at (loc, "conversion of scalar %qT to vector %qT "
bool *);
static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
static tree lookup_field (tree, tree);
-static int convert_arguments (tree, vec<tree, va_gc> *, vec<tree, va_gc> *,
- tree, tree);
+static int convert_arguments (location_t, tree, vec<tree, va_gc> *,
+ vec<tree, va_gc> *, tree, tree);
static tree pointer_diff (location_t, tree, tree);
-static tree convert_for_assignment (location_t, tree, tree, tree,
+static tree convert_for_assignment (location_t, location_t, tree, tree, tree,
enum impl_conv, bool, tree, tree, int);
static tree valid_compound_expr_initializer (tree, tree);
static void push_string (const char *);
/* Convert the parameters to the types declared in the
function prototype, or apply default promotions. */
- nargs = convert_arguments (TYPE_ARG_TYPES (fntype), params, origtypes,
+ nargs = convert_arguments (loc, TYPE_ARG_TYPES (fntype), params, origtypes,
function, fundecl);
if (nargs < 0)
return error_mark_node;
failure. */
static int
-convert_arguments (tree typelist, vec<tree, va_gc> *values,
+convert_arguments (location_t loc, tree typelist, vec<tree, va_gc> *values,
vec<tree, va_gc> *origtypes, tree function, tree fundecl)
{
tree typetail, val;
if (type == void_type_node)
{
if (selector)
- error_at (input_location,
- "too many arguments to method %qE", selector);
+ error_at (loc, "too many arguments to method %qE", selector);
else
- error_at (input_location,
- "too many arguments to function %qE", function);
+ error_at (loc, "too many arguments to function %qE", function);
inform_declaration (fundecl);
return parmnum;
}
if (excess_precision)
val = build1 (EXCESS_PRECISION_EXPR, valtype, val);
origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum];
- parmval = convert_for_assignment (input_location, type, val,
- origtype, ic_argpass, npc,
- fundecl, function,
+ parmval = convert_for_assignment (loc, UNKNOWN_LOCATION, type,
+ val, origtype, ic_argpass,
+ npc, fundecl, function,
parmnum + 1);
if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
{
- error_at (input_location,
- "too few arguments to function %qE", function);
+ error_at (loc, "too few arguments to function %qE", function);
inform_declaration (fundecl);
return -1;
}
/* newval = old + val; */
rhs = build_binary_op (loc, modifycode, old, val, 1);
- rhs = convert_for_assignment (loc, nonatomic_lhs_type, rhs, NULL_TREE,
- ic_assign, false, NULL_TREE,
+ rhs = convert_for_assignment (loc, UNKNOWN_LOCATION, nonatomic_lhs_type,
+ rhs, NULL_TREE, ic_assign, false, NULL_TREE,
NULL_TREE, 0);
if (rhs != error_mark_node)
{
the usual ones because of excess precision. */
static tree
-ep_convert_and_check (tree type, tree expr, tree semantic_type)
+ep_convert_and_check (location_t loc, tree type, tree expr,
+ tree semantic_type)
{
if (TREE_TYPE (expr) == type)
return expr;
if (!semantic_type)
- return convert_and_check (type, expr);
+ return convert_and_check (loc, type, expr);
if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
&& TREE_TYPE (expr) != semantic_type)
{
/* For integers, we need to check the real conversion, not
the conversion to the excess precision type. */
- expr = convert_and_check (semantic_type, expr);
+ expr = convert_and_check (loc, semantic_type, expr);
}
/* Result type is the excess precision type, which should be
large enough, so do not check. */
TYPE_READONLY (type1) || TYPE_READONLY (type2),
TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2));
- op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
- op2 = ep_convert_and_check (result_type, op2, semantic_result_type);
+ op1 = ep_convert_and_check (colon_loc, result_type, op1,
+ semantic_result_type);
+ op2 = ep_convert_and_check (colon_loc, result_type, op2,
+ semantic_result_type);
if (ifexp_bcp && ifexp == truthvalue_true_node)
{
newrhs = c_fully_fold (newrhs, false, NULL);
if (rhs_semantic_type)
newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
- newrhs = convert_for_assignment (location, lhstype, newrhs, rhs_origtype,
- ic_assign, npc, NULL_TREE,
- NULL_TREE, 0);
+ newrhs = convert_for_assignment (location, rhs_loc, lhstype, newrhs,
+ rhs_origtype, ic_assign, npc,
+ NULL_TREE, NULL_TREE, 0);
if (TREE_CODE (newrhs) == ERROR_MARK)
return error_mark_node;
}
if (olhstype == TREE_TYPE (result))
goto return_result;
- result = convert_for_assignment (location, olhstype, result, rhs_origtype,
- ic_assign, false, NULL_TREE, NULL_TREE, 0);
+ result = convert_for_assignment (location, rhs_loc, olhstype, result,
+ rhs_origtype, ic_assign, false, NULL_TREE,
+ NULL_TREE, 0);
protected_set_expr_location (result, location);
return_result:
ERRTYPE says whether it is argument passing, assignment,
initialization or return.
- LOCATION is the location of the RHS.
+ LOCATION is the location of the assignment, RHS_LOC is the location of
+ the RHS.
FUNCTION is a tree for the function being called.
PARMNUM is the number of the argument, for printing in error messages. */
static tree
-convert_for_assignment (location_t location, tree type, tree rhs,
- tree origtype, enum impl_conv errtype,
+convert_for_assignment (location_t location, location_t rhs_loc, tree type,
+ tree rhs, tree origtype, enum impl_conv errtype,
bool null_pointer_constant, tree fundecl,
tree function, int parmnum)
{
rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
SET_EXPR_LOCATION (rhs, location);
- rhs = convert_for_assignment (location, build_pointer_type (TREE_TYPE (type)),
- rhs, origtype, errtype, null_pointer_constant,
- fundecl, function, parmnum);
+ rhs = convert_for_assignment (location, rhs_loc,
+ build_pointer_type (TREE_TYPE (type)),
+ rhs, origtype, errtype,
+ null_pointer_constant, fundecl, function,
+ parmnum);
if (rhs == error_mark_node)
return error_mark_node;
bool save = in_late_binary_op;
if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
in_late_binary_op = true;
- ret = convert_and_check (type, orig_rhs);
+ ret = convert_and_check (rhs_loc != UNKNOWN_LOCATION
+ ? rhs_loc : location, type, orig_rhs);
if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
in_late_binary_op = save;
return ret;
if ((codel == RECORD_TYPE || codel == UNION_TYPE)
&& codel == coder
&& comptypes (type, rhstype))
- return convert_and_check (type, rhs);
+ return convert_and_check (rhs_loc != UNKNOWN_LOCATION
+ ? rhs_loc : location, type, rhs);
/* Conversion to a transparent union or record from its member types.
This applies only to function arguments. */
/* Added to enable additional -Wsuggest-attribute=format warnings. */
if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE)
- inside_init = convert_for_assignment (init_loc, type, inside_init,
- origtype,
+ inside_init = convert_for_assignment (init_loc, UNKNOWN_LOCATION,
+ type, inside_init, origtype,
ic_init, null_pointer_constant,
NULL_TREE, NULL_TREE, 0);
return inside_init;
inside_init = build1 (EXCESS_PRECISION_EXPR, semantic_type,
inside_init);
inside_init
- = convert_for_assignment (init_loc, type, inside_init, origtype,
- ic_init, null_pointer_constant,
- NULL_TREE, NULL_TREE, 0);
+ = convert_for_assignment (init_loc, UNKNOWN_LOCATION, type,
+ inside_init, origtype, ic_init,
+ null_pointer_constant, NULL_TREE, NULL_TREE,
+ 0);
/* Check to see if we have already given an error message. */
if (inside_init == error_mark_node)
}
else
{
- tree t = convert_for_assignment (loc, valtype, retval, origtype,
- ic_return,
+ tree t = convert_for_assignment (loc, UNKNOWN_LOCATION, valtype,
+ retval, origtype, ic_return,
npc, NULL_TREE, NULL_TREE, 0);
tree res = DECL_RESULT (current_function_decl);
tree inner;
if (first_complex)
{
if (TREE_TYPE (op0) != result_type)
- op0 = convert_and_check (result_type, op0);
+ op0 = convert_and_check (location, result_type, op0);
if (TREE_TYPE (op1) != real_type)
- op1 = convert_and_check (real_type, op1);
+ op1 = convert_and_check (location, real_type, op1);
}
else
{
if (TREE_TYPE (op0) != real_type)
- op0 = convert_and_check (real_type, op0);
+ op0 = convert_and_check (location, real_type, op0);
if (TREE_TYPE (op1) != result_type)
- op1 = convert_and_check (result_type, op1);
+ op1 = convert_and_check (location, result_type, op1);
}
if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
return error_mark_node;
if (!converted)
{
- op0 = ep_convert_and_check (result_type, op0, semantic_result_type);
- op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
+ op0 = ep_convert_and_check (location, result_type, op0,
+ semantic_result_type);
+ op1 = ep_convert_and_check (location, result_type, op1,
+ semantic_result_type);
/* This can happen if one operand has a vector type, and the other
has a different type. */