/* Build expressions with type checking for C compiler.
Copyright (C) 1987, 1988, 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998,
- 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
Free Software Foundation, Inc.
This file is part of GCC.
static int type_lists_compatible_p (tree, tree);
static tree decl_constant_value_for_broken_optimization (tree);
static tree lookup_field (tree, tree);
-static tree convert_arguments (tree, tree, tree, tree);
+static int convert_arguments (int, tree *, tree, tree, tree, tree);
static tree pointer_diff (tree, tree);
static tree convert_for_assignment (tree, tree, enum impl_conv, tree, tree,
int);
yet available everywhere required. */
tree type = TREE_TYPE (expr);
return (TREE_CODE (expr) == INTEGER_CST
- && !TREE_CONSTANT_OVERFLOW (expr)
+ && !TREE_OVERFLOW (expr)
&& integer_zerop (expr)
&& (INTEGRAL_TYPE_P (type)
|| (TREE_CODE (type) == POINTER_TYPE
if (TREE_CODE (type) == POINTER_TYPE)
{
+ if (TREE_CODE (pointer) == CONVERT_EXPR
+ || TREE_CODE (pointer) == NOP_EXPR
+ || TREE_CODE (pointer) == VIEW_CONVERT_EXPR)
+ {
+ /* If a warning is issued, mark it to avoid duplicates from
+ the backend. This only needs to be done at
+ warn_strict_aliasing > 2. */
+ if (warn_strict_aliasing > 2)
+ if (strict_aliasing_warning (TREE_TYPE (TREE_OPERAND (pointer, 0)),
+ type, TREE_OPERAND (pointer, 0)))
+ TREE_NO_WARNING (pointer) = 1;
+ }
+
if (TREE_CODE (pointer) == ADDR_EXPR
&& (TREE_TYPE (TREE_OPERAND (pointer, 0))
== TREE_TYPE (type)))
}
}
else if (TREE_CODE (pointer) != ERROR_MARK)
- error ("invalid type argument of %qs", errorstring);
+ error ("invalid type argument of %qs (have %qT)", errorstring, type);
return error_mark_node;
}
if (TREE_DEPRECATED (ref))
warn_deprecated_use (ref);
- if (!skip_evaluation)
- assemble_external (ref);
- TREE_USED (ref) = 1;
+ /* Recursive call does not count as usage. */
+ if (ref != current_function_decl)
+ {
+ if (!skip_evaluation)
+ assemble_external (ref);
+ TREE_USED (ref) = 1;
+ }
if (TREE_CODE (ref) == FUNCTION_DECL && !in_alignof)
{
if (context != 0 && context != current_function_decl)
DECL_NONLOCAL (ref) = 1;
}
+ /* C99 6.7.4p3: An inline definition of a function with external
+ linkage ... shall not contain a reference to an identifier with
+ internal linkage. */
+ else if (current_function_decl != 0
+ && DECL_DECLARED_INLINE_P (current_function_decl)
+ && DECL_EXTERNAL (current_function_decl)
+ && VAR_OR_FUNCTION_DECL_P (ref)
+ && (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
+ && ! TREE_PUBLIC (ref))
+ pedwarn ("%H%qD is static but used in inline function %qD "
+ "which is not static", &loc, ref, current_function_decl);
return ref;
}
build_function_call (tree function, tree params)
{
tree fntype, fundecl = 0;
- tree coerced_params;
tree name = NULL_TREE, result;
tree tem;
+ int nargs;
+ tree *argarray;
+
/* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
STRIP_TYPE_NOPS (function);
/* Convert the parameters to the types declared in the
function prototype, or apply default promotions. */
- coerced_params
- = convert_arguments (TYPE_ARG_TYPES (fntype), params, function, fundecl);
-
- if (coerced_params == error_mark_node)
+ nargs = list_length (params);
+ argarray = (tree *) alloca (nargs * sizeof (tree));
+ nargs = convert_arguments (nargs, argarray, TYPE_ARG_TYPES (fntype),
+ params, function, fundecl);
+ if (nargs < 0)
return error_mark_node;
/* Check that the arguments to the function are valid. */
- check_function_arguments (TYPE_ATTRIBUTES (fntype), coerced_params,
+ check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
TYPE_ARG_TYPES (fntype));
if (require_constant_value)
{
- result = fold_build3_initializer (CALL_EXPR, TREE_TYPE (fntype),
- function, coerced_params, NULL_TREE);
-
+ result = fold_build_call_array_initializer (TREE_TYPE (fntype),
+ function, nargs, argarray);
if (TREE_CONSTANT (result)
&& (name == NULL_TREE
|| strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0))
pedwarn_init ("initializer element is not constant");
}
else
- result = fold_build3 (CALL_EXPR, TREE_TYPE (fntype),
- function, coerced_params, NULL_TREE);
+ result = fold_build_call_array (TREE_TYPE (fntype),
+ function, nargs, argarray);
if (VOID_TYPE_P (TREE_TYPE (result)))
return result;
}
\f
/* Convert the argument expressions in the list VALUES
- to the types in the list TYPELIST. The result is a list of converted
- argument expressions, unless there are too few arguments in which
- case it is error_mark_node.
+ to the types in the list TYPELIST. The resulting arguments are
+ stored in the array ARGARRAY which has size NARGS.
If TYPELIST is exhausted, or when an element has NULL as its type,
perform the default conversions.
This is also where warnings about wrong number of args are generated.
- Both VALUES and the returned value are chains of TREE_LIST nodes
- with the elements of the list in the TREE_VALUE slots of those nodes. */
+ VALUES is a chain of TREE_LIST nodes with the elements of the list
+ in the TREE_VALUE slots of those nodes.
-static tree
-convert_arguments (tree typelist, tree values, tree function, tree fundecl)
+ Returns the actual number of arguments processed (which may be less
+ than NARGS in some error situations), or -1 on failure. */
+
+static int
+convert_arguments (int nargs, tree *argarray,
+ tree typelist, tree values, tree function, tree fundecl)
{
tree typetail, valtail;
- tree result = NULL;
int parmnum;
+ const bool type_generic = fundecl
+ && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
tree selector;
/* Change pointer to function to the function itself for
selector = objc_message_selector ();
/* Scan the given expressions and types, producing individual
- converted arguments and pushing them on RESULT in reverse order. */
+ converted arguments and storing them in ARGARRAY. */
for (valtail = values, typetail = typelist, parmnum = 0;
valtail;
if (type == void_type_node)
{
error ("too many arguments to function %qE", function);
- break;
+ return parmnum;
}
if (selector && argnum > 2)
{
/* Optionally warn about conversions that
differ from the default conversions. */
- if (warn_conversion || warn_traditional)
+ if (warn_traditional_conversion || warn_traditional)
{
unsigned int formal_prec = TYPE_PRECISION (type);
}
/* Detect integer changing in width or signedness.
These warnings are only activated with
- -Wconversion, not with -Wtraditional. */
- else if (warn_conversion && INTEGRAL_TYPE_P (type)
+ -Wtraditional-conversion, not with -Wtraditional. */
+ else if (warn_traditional_conversion && INTEGRAL_TYPE_P (type)
&& INTEGRAL_TYPE_P (TREE_TYPE (val)))
{
tree would_have_been = default_conversion (val);
and the actual arg is that enum type. */
;
else if (formal_prec != TYPE_PRECISION (type1))
- warning (OPT_Wconversion, "passing argument %d of %qE "
+ warning (OPT_Wtraditional_conversion, "passing argument %d of %qE "
"with different width due to prototype",
argnum, rname);
else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
&& TYPE_UNSIGNED (TREE_TYPE (val)))
;
else if (TYPE_UNSIGNED (type))
- warning (OPT_Wconversion, "passing argument %d of %qE "
+ warning (OPT_Wtraditional_conversion, "passing argument %d of %qE "
"as unsigned due to prototype",
argnum, rname);
else
- warning (OPT_Wconversion, "passing argument %d of %qE "
+ warning (OPT_Wtraditional_conversion, "passing argument %d of %qE "
"as signed due to prototype", argnum, rname);
}
}
&& (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
parmval = default_conversion (parmval);
}
- result = tree_cons (NULL_TREE, parmval, result);
+ argarray[parmnum] = parmval;
}
else if (TREE_CODE (TREE_TYPE (val)) == REAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (val))
< TYPE_PRECISION (double_type_node))
&& !DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (val))))
- /* Convert `float' to `double'. */
- result = tree_cons (NULL_TREE, convert (double_type_node, val), result);
+ {
+ if (type_generic)
+ argarray[parmnum] = val;
+ else
+ /* Convert `float' to `double'. */
+ argarray[parmnum] = convert (double_type_node, val);
+ }
else if ((invalid_func_diag =
targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
{
error (invalid_func_diag);
- return error_mark_node;
+ return -1;
}
else
/* Convert `short' and `char' to full-size `int'. */
- result = tree_cons (NULL_TREE, default_conversion (val), result);
+ argarray[parmnum] = default_conversion (val);
if (typetail)
typetail = TREE_CHAIN (typetail);
}
+ gcc_assert (parmnum == nargs);
+
if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
{
error ("too few arguments to function %qE", function);
- return error_mark_node;
+ return -1;
}
- return nreverse (result);
+ return parmnum;
}
\f
/* This is the entry point used by the parser to build unary operators
result.original_code = ERROR_MARK;
result.value = build_unary_op (code, arg.value, 0);
- overflow_warning (result.value);
+
+ if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
+ overflow_warning (result.value);
+
return result;
}
/* Check for cases such as x+y<<z which users are likely
to misinterpret. */
if (warn_parentheses)
- {
- if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
- {
- if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
- || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
- warning (OPT_Wparentheses,
- "suggest parentheses around + or - inside shift");
- }
-
- if (code == TRUTH_ORIF_EXPR)
- {
- if (code1 == TRUTH_ANDIF_EXPR
- || code2 == TRUTH_ANDIF_EXPR)
- warning (OPT_Wparentheses,
- "suggest parentheses around && within ||");
- }
-
- if (code == BIT_IOR_EXPR)
- {
- if (code1 == BIT_AND_EXPR || code1 == BIT_XOR_EXPR
- || code1 == PLUS_EXPR || code1 == MINUS_EXPR
- || code2 == BIT_AND_EXPR || code2 == BIT_XOR_EXPR
- || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
- warning (OPT_Wparentheses,
- "suggest parentheses around arithmetic in operand of |");
- /* Check cases like x|y==z */
- if (TREE_CODE_CLASS (code1) == tcc_comparison
- || TREE_CODE_CLASS (code2) == tcc_comparison)
- warning (OPT_Wparentheses,
- "suggest parentheses around comparison in operand of |");
- }
-
- if (code == BIT_XOR_EXPR)
- {
- if (code1 == BIT_AND_EXPR
- || code1 == PLUS_EXPR || code1 == MINUS_EXPR
- || code2 == BIT_AND_EXPR
- || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
- warning (OPT_Wparentheses,
- "suggest parentheses around arithmetic in operand of ^");
- /* Check cases like x^y==z */
- if (TREE_CODE_CLASS (code1) == tcc_comparison
- || TREE_CODE_CLASS (code2) == tcc_comparison)
- warning (OPT_Wparentheses,
- "suggest parentheses around comparison in operand of ^");
- }
+ warn_about_parentheses (code, code1, code2);
- if (code == BIT_AND_EXPR)
- {
- if (code1 == PLUS_EXPR || code1 == MINUS_EXPR
- || code2 == PLUS_EXPR || code2 == MINUS_EXPR)
- warning (OPT_Wparentheses,
- "suggest parentheses around + or - in operand of &");
- /* Check cases like x&y==z */
- if (TREE_CODE_CLASS (code1) == tcc_comparison
- || TREE_CODE_CLASS (code2) == tcc_comparison)
- warning (OPT_Wparentheses,
- "suggest parentheses around comparison in operand of &");
- }
- /* Similarly, check for cases like 1<=i<=10 that are probably errors. */
- if (TREE_CODE_CLASS (code) == tcc_comparison
- && (TREE_CODE_CLASS (code1) == tcc_comparison
- || TREE_CODE_CLASS (code2) == tcc_comparison))
- warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not "
- "have their mathematical meaning");
-
- }
+ if (code1 != tcc_comparison)
+ warn_logical_operator (code, arg1.value, arg2.value);
/* Warn about comparisons against string literals, with the exception
of testing for equality or inequality of a string literal with NULL. */
{
if ((code1 == STRING_CST && !integer_zerop (arg2.value))
|| (code2 == STRING_CST && !integer_zerop (arg1.value)))
- warning (OPT_Wstring_literal_comparison,
- "comparison with string literal");
+ warning (OPT_Waddress, "comparison with string literal results in unspecified behavior");
}
else if (TREE_CODE_CLASS (code) == tcc_comparison
&& (code1 == STRING_CST || code2 == STRING_CST))
- warning (OPT_Wstring_literal_comparison,
- "comparison with string literal");
+ warning (OPT_Waddress, "comparison with string literal results in unspecified behavior");
- overflow_warning (result.value);
+ if (TREE_OVERFLOW_P (result.value)
+ && !TREE_OVERFLOW_P (arg1.value)
+ && !TREE_OVERFLOW_P (arg2.value))
+ overflow_warning (result.value);
return result;
}
arg = stabilize_reference (arg);
real = build_unary_op (REALPART_EXPR, arg, 1);
imag = build_unary_op (IMAGPART_EXPR, arg, 1);
+ real = build_unary_op (code, real, 1);
+ if (real == error_mark_node || imag == error_mark_node)
+ return error_mark_node;
return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
- build_unary_op (code, real, 1), imag);
+ real, imag);
}
/* Report invalid types. */
}
inc = c_size_in_bytes (TREE_TYPE (result_type));
+ inc = fold_convert (sizetype, inc);
}
else
- inc = integer_one_node;
-
- inc = convert (argtype, inc);
+ {
+ inc = integer_one_node;
+ inc = convert (argtype, inc);
+ }
/* Complain about anything else that is not a true lvalue. */
if (!lvalue_or_else (arg, ((code == PREINCREMENT_EXPR
if (val && TREE_CODE (val) == INDIRECT_REF
&& TREE_CONSTANT (TREE_OPERAND (val, 0)))
{
- tree op0 = fold_convert (argtype, fold_offsetof (arg, val)), op1;
+ tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1;
op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
- return fold_build2 (PLUS_EXPR, argtype, op0, op1);
+ return fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
}
val = build1 (ADDR_EXPR, argtype, arg);
if (unsigned_op1 ^ unsigned_op2)
{
+ bool ovf;
+
/* Do not warn if the result type is signed, since the
signed type will only be chosen if it can represent
all the values of the unsigned type. */
/* Do not warn if the signed quantity is an unsuffixed
integer literal (or some static constant expression
involving such literals) and it is non-negative. */
- else if ((unsigned_op2 && tree_expr_nonnegative_p (op1))
- || (unsigned_op1 && tree_expr_nonnegative_p (op2)))
+ else if ((unsigned_op2
+ && tree_expr_nonnegative_warnv_p (op1, &ovf))
+ || (unsigned_op1
+ && tree_expr_nonnegative_warnv_p (op2, &ovf)))
/* OK */;
else
warning (0, "signed and unsigned type in conditional expression");
|| TREE_CODE (TREE_OPERAND (expr1, 1)) == NOP_EXPR))
; /* (void) a, (void) b, c */
else
- warning (0, "left-hand operand of comma expression has no effect");
+ warning (OPT_Wunused_value,
+ "left-hand operand of comma expression has no effect");
}
}
warning (OPT_Wint_to_pointer_cast, "cast to pointer from integer "
"of different size");
- strict_aliasing_warning (otype, type, expr);
+ if (warn_strict_aliasing <= 2)
+ strict_aliasing_warning (otype, type, expr);
/* If pedantic, warn for conversions between function and object
pointer types, except for converting a null pointer constant
/* Ignore any integer overflow caused by the cast. */
if (TREE_CODE (value) == INTEGER_CST)
{
- if (CONSTANT_CLASS_P (ovalue)
- && (TREE_OVERFLOW (ovalue) || TREE_CONSTANT_OVERFLOW (ovalue)))
+ if (CONSTANT_CLASS_P (ovalue) && TREE_OVERFLOW (ovalue))
{
- /* Avoid clobbering a shared constant. */
- value = copy_node (value);
- TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
- TREE_CONSTANT_OVERFLOW (value) = TREE_CONSTANT_OVERFLOW (ovalue);
+ if (!TREE_OVERFLOW (value))
+ {
+ /* Avoid clobbering a shared constant. */
+ value = copy_node (value);
+ TREE_OVERFLOW (value) = TREE_OVERFLOW (ovalue);
+ }
}
- else if (TREE_OVERFLOW (value) || TREE_CONSTANT_OVERFLOW (value))
+ else if (TREE_OVERFLOW (value))
/* Reset VALUE's overflow flags, ensuring constant sharing. */
value = build_int_cst_wide (TREE_TYPE (value),
TREE_INT_CST_LOW (value),
}
if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (rhstype))
- {
- overflow_warning (rhs);
- return rhs;
- }
+ return rhs;
if (coder == VOID_TYPE)
{
}
/* Some types can interconvert without explicit casts. */
else if (codel == VECTOR_TYPE && coder == VECTOR_TYPE
- && vector_types_convertible_p (type, TREE_TYPE (rhs)))
+ && vector_types_convertible_p (type, TREE_TYPE (rhs), true))
return convert (type, rhs);
/* Arithmetic types all interconvert, and enum is treated like int. */
else if ((codel == INTEGER_TYPE || codel == REAL_TYPE
|| coder == BOOLEAN_TYPE))
return convert_and_check (type, rhs);
+ /* Aggregates in different TUs might need conversion. */
+ if ((codel == RECORD_TYPE || codel == UNION_TYPE)
+ && codel == coder
+ && comptypes (type, rhstype))
+ return convert_and_check (type, rhs);
+
/* Conversion to a transparent union from its member types.
This applies only to function arguments. */
- else if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
- && (errtype == ic_argpass || errtype == ic_argpass_nonproto))
+ if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
+ && (errtype == ic_argpass || errtype == ic_argpass_nonproto))
{
tree memb, marginal_memb = NULL_TREE;
return error_mark_node;
}
-
-/* Convert VALUE for assignment into inlined parameter PARM. ARGNUM
- is used for error and warning reporting and indicates which argument
- is being processed. */
-
-tree
-c_convert_parm_for_inlining (tree parm, tree value, tree fn, int argnum)
-{
- tree ret, type;
-
- /* If FN was prototyped at the call site, the value has been converted
- already in convert_arguments.
- However, we might see a prototype now that was not in place when
- the function call was seen, so check that the VALUE actually matches
- PARM before taking an early exit. */
- if (!value
- || (TYPE_ARG_TYPES (TREE_TYPE (fn))
- && (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
- == TYPE_MAIN_VARIANT (TREE_TYPE (value)))))
- return value;
-
- type = TREE_TYPE (parm);
- ret = convert_for_assignment (type, value,
- ic_argpass_nonproto, fn,
- fn, argnum);
- if (targetm.calls.promote_prototypes (TREE_TYPE (fn))
- && INTEGRAL_TYPE_P (type)
- && (TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node)))
- ret = default_conversion (ret);
- return ret;
-}
\f
/* If VALUE is a compound expr all of whose expressions are constant, then
return its value. Otherwise, return error_mark_node.
/* ANSI wants warnings about out-of-range constant initializers. */
STRIP_TYPE_NOPS (value);
- constant_expression_warning (value);
+ if (TREE_STATIC (decl))
+ constant_expression_warning (value);
/* Check if we need to set array size from compound literal size. */
if (TREE_CODE (type) == ARRAY_TYPE
below and handle as a constructor. */
if (code == VECTOR_TYPE
&& TREE_CODE (TREE_TYPE (inside_init)) == VECTOR_TYPE
- && vector_types_convertible_p (TREE_TYPE (inside_init), type)
+ && vector_types_convertible_p (TREE_TYPE (inside_init), type, true)
&& TREE_CONSTANT (inside_init))
{
if (TREE_CODE (inside_init) == VECTOR_CST
conversion. */
inside_init = convert (type, inside_init);
- if (require_constant && !flag_isoc99
+ if (require_constant
+ && (code == VECTOR_TYPE || !flag_isoc99)
&& TREE_CODE (inside_init) == COMPOUND_LITERAL_EXPR)
{
/* As an extension, allow initializing objects with static storage
duration with compound literals (which are then treated just as
- the brace enclosed list they contain). */
+ the brace enclosed list they contain). Also allow this for
+ vectors, as we can only assign them with compound literals. */
tree decl = COMPOUND_LITERAL_EXPR_DECL (inside_init);
inside_init = DECL_INITIAL (decl);
}
else if (valtype == 0 || TREE_CODE (valtype) == VOID_TYPE)
{
current_function_returns_null = 1;
- if (pedantic || TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
+ if (TREE_CODE (TREE_TYPE (retval)) != VOID_TYPE)
pedwarn ("%<return%> with a value, in function returning void");
+ else if (pedantic)
+ pedwarn ("ISO C forbids %<return%> with expression, in function returning void");
}
else
{
&if_locus);
}
- empty_body_warning (then_block, else_block);
+ empty_if_body_warning (then_block, else_block);
stmt = build3 (COND_EXPR, void_type_node, cond, then_block, else_block);
SET_EXPR_LOCATION (stmt, if_locus);
else if (!TREE_SIDE_EFFECTS (expr))
{
if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
- warning (0, "%Hstatement with no effect",
+ warning (OPT_Wunused_value, "%Hstatement with no effect",
EXPR_HAS_LOCATION (expr) ? EXPR_LOCUS (expr) : &input_location);
}
- else if (warn_unused_value)
+ else
warn_if_unused_value (expr, input_location);
}
Warnings for statement expressions will be emitted later, once we figure
out which is the result. */
if (!STATEMENT_LIST_STMT_EXPR (cur_stmt_list)
- && (extra_warnings || warn_unused_value))
+ && warn_unused_value)
emit_side_effect_warnings (expr);
/* If the expression is not of a type to which we cannot assign a line
if (DECL_P (expr) || CONSTANT_CLASS_P (expr))
expr = build1 (NOP_EXPR, TREE_TYPE (expr), expr);
- if (EXPR_P (expr))
+ if (CAN_HAVE_LOCATION_P (expr))
SET_EXPR_LOCATION (expr, input_location);
return expr;
/* If we're supposed to generate side effects warnings, process
all of the statements except the last. */
- if (extra_warnings || warn_unused_value)
+ if (warn_unused_value)
{
for (i = tsi_start (last); !tsi_one_before_end_p (i); tsi_next (&i))
emit_side_effect_warnings (tsi_stmt (i));
{
/* Do not warn if the return value of a statement expression is
unused. */
- if (EXPR_P (last))
+ if (CAN_HAVE_LOCATION_P (last))
TREE_NO_WARNING (last) = 1;
return last;
}
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
- /* Floating point division by zero is a legitimate way to obtain
- infinities and NaNs. */
- if (skip_evaluation == 0 && integer_zerop (op1))
- warning (OPT_Wdiv_by_zero, "division by zero");
+ warn_for_div_by_zero (op1);
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|| code0 == COMPLEX_TYPE || code0 == VECTOR_TYPE)
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
- if (skip_evaluation == 0 && integer_zerop (op1))
- warning (OPT_Wdiv_by_zero, "division by zero");
+ warn_for_div_by_zero (op1);
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
{
if (TREE_CODE (op0) == ADDR_EXPR
- && DECL_P (TREE_OPERAND (op0, 0))
- && (TREE_CODE (TREE_OPERAND (op0, 0)) == PARM_DECL
- || TREE_CODE (TREE_OPERAND (op0, 0)) == LABEL_DECL
- || !DECL_WEAK (TREE_OPERAND (op0, 0))))
- warning (OPT_Walways_true, "the address of %qD will never be NULL",
+ && decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
+ warning (OPT_Waddress, "the address of %qD will never be NULL",
TREE_OPERAND (op0, 0));
result_type = type0;
}
else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
{
if (TREE_CODE (op1) == ADDR_EXPR
- && DECL_P (TREE_OPERAND (op1, 0))
- && (TREE_CODE (TREE_OPERAND (op1, 0)) == PARM_DECL
- || TREE_CODE (TREE_OPERAND (op1, 0)) == LABEL_DECL
- || !DECL_WEAK (TREE_OPERAND (op1, 0))))
- warning (OPT_Walways_true, "the address of %qD will never be NULL",
+ && decl_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
+ warning (OPT_Waddress, "the address of %qD will never be NULL",
TREE_OPERAND (op1, 0));
result_type = type1;
}
|| !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
TREE_TYPE (type1))))
{
- binary_op_error (code);
+ binary_op_error (code, type0, type1);
return error_mark_node;
}
int none_complex = (code0 != COMPLEX_TYPE && code1 != COMPLEX_TYPE);
if (shorten || common || short_compare)
- result_type = c_common_type (type0, type1);
+ {
+ result_type = c_common_type (type0, type1);
+ if (result_type == error_mark_node)
+ return error_mark_node;
+ }
/* For certain operations (which identify themselves by shorten != 0)
if both args were extended from the same smaller type,
else
{
tree sop, uop;
+ bool ovf;
if (op0_signed)
sop = xop0, uop = xop1;
constant expression involving such literals or a
conditional expression involving such literals)
and it is non-negative. */
- if (tree_expr_nonnegative_p (sop))
+ if (tree_expr_nonnegative_warnv_p (sop, &ovf))
/* OK */;
/* Do not warn if the comparison is an equality operation,
the unsigned quantity is an integral constant, and it
if (!result_type)
{
- binary_op_error (code);
+ binary_op_error (code, TREE_TYPE (op0), TREE_TYPE (op1));
return error_mark_node;
}