/* 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, 2007, 2008
+ 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GCC.
#include "ggc.h"
#include "target.h"
#include "tree-iterator.h"
-#include "tree-gimple.h"
+#include "gimple.h"
#include "tree-flow.h"
/* Possible cases of implicit bad conversions. Used to select
diagnostic messages in convert_for_assignment. */
enum impl_conv {
ic_argpass,
- ic_argpass_nonproto,
ic_assign,
ic_init,
ic_return
static void push_member_name (tree);
static int spelling_length (void);
static char *print_spelling (char *);
-static void warning_init (const char *);
+static void warning_init (int, const char *);
static tree digest_init (tree, tree, bool, int);
-static void output_init_element (tree, bool, tree, tree, int);
+static void output_init_element (tree, bool, tree, tree, int, bool);
static void output_pending_init_elements (int);
static int set_designator (int);
static void push_range_stack (tree);
-static void add_pending_init (tree, tree);
+static void add_pending_init (tree, tree, bool);
static void set_nonincremental_init (void);
static void set_nonincremental_init_from_string (tree);
static tree find_init_member (tree);
{
TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
TREE_VALUE (p2));
- if (pedantic)
- pedwarn ("function types not truly compatible in ISO C");
+ pedwarn (input_location, OPT_pedantic,
+ "function types not truly compatible in ISO C");
goto parm_done;
}
}
{
TREE_VALUE (n) = composite_type (TREE_TYPE (memb),
TREE_VALUE (p1));
- if (pedantic)
- pedwarn ("function types not truly compatible in ISO C");
+ pedwarn (input_location, OPT_pedantic,
+ "function types not truly compatible in ISO C");
goto parm_done;
}
}
signed type. */
if (code1 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t1))
{
- unsigned char mclass = 0;
+ enum mode_class mclass = (enum mode_class) 0;
if (GET_MODE_CLASS (m1) == MODE_UFRACT)
mclass = MODE_FRACT;
else if (GET_MODE_CLASS (m1) == MODE_UACCUM)
}
if (code2 == FIXED_POINT_TYPE && TYPE_UNSIGNED (t2))
{
- unsigned char mclass = 0;
+ enum mode_class mclass = (enum mode_class) 0;
if (GET_MODE_CLASS (m2) == MODE_UFRACT)
mclass = MODE_FRACT;
else if (GET_MODE_CLASS (m2) == MODE_UACCUM)
mvr = TYPE_MAIN_VARIANT (mvr);
val = comptypes (mvl, mvr);
- if (val == 2 && pedantic)
- pedwarn ("types are not quite compatible");
+ if (val == 2)
+ pedwarn (input_location, OPT_pedantic, "types are not quite compatible");
return val;
}
\f
/* 'volatile' qualifiers on a function's return type used to mean
the function is noreturn. */
if (TYPE_VOLATILE (ret1) != TYPE_VOLATILE (ret2))
- pedwarn ("function return types not compatible due to %<volatile%>");
+ pedwarn (input_location, 0, "function return types not compatible due to %<volatile%>");
if (TYPE_VOLATILE (ret1))
ret1 = build_qualified_type (TYPE_MAIN_VARIANT (ret1),
TYPE_QUALS (ret1) & ~TYPE_QUAL_VOLATILE);
/* This way is better for a COMPONENT_REF since it can
simplify the offset for a component. */
- adr = build_unary_op (ADDR_EXPR, exp, 1);
+ adr = build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 1);
return convert (ptrtype, adr);
}
if (TREE_NO_WARNING (orig_exp))
TREE_NO_WARNING (exp) = 1;
- return build_unary_op (ADDR_EXPR, exp, 0);
+ return build_unary_op (EXPR_LOCATION (exp), ADDR_EXPR, exp, 0);
}
/* Perform the default conversion of arrays and functions to pointers.
bool lvalue_array_p;
while ((TREE_CODE (exp.value) == NON_LVALUE_EXPR
- || TREE_CODE (exp.value) == NOP_EXPR
- || TREE_CODE (exp.value) == CONVERT_EXPR)
+ || CONVERT_EXPR_P (exp.value))
&& TREE_TYPE (TREE_OPERAND (exp.value, 0)) == type)
{
if (TREE_CODE (exp.value) == NON_LVALUE_EXPR)
\f
/* Given an expression PTR for a pointer, return an expression
for the value pointed to.
- ERRORSTRING is the name of the operator to appear in error messages. */
+ ERRORSTRING is the name of the operator to appear in error messages.
+
+ LOC is the location to use for the generated tree. */
tree
-build_indirect_ref (tree ptr, const char *errorstring)
+build_indirect_ref (location_t loc, tree ptr, const char *errorstring)
{
tree pointer = default_conversion (ptr);
tree type = TREE_TYPE (pointer);
+ tree ref;
if (TREE_CODE (type) == POINTER_TYPE)
{
- if (TREE_CODE (pointer) == CONVERT_EXPR
- || TREE_CODE (pointer) == NOP_EXPR
+ if (CONVERT_EXPR_P (pointer)
|| TREE_CODE (pointer) == VIEW_CONVERT_EXPR)
{
/* If a warning is issued, mark it to avoid duplicates from
if (TREE_CODE (pointer) == ADDR_EXPR
&& (TREE_TYPE (TREE_OPERAND (pointer, 0))
== TREE_TYPE (type)))
- return TREE_OPERAND (pointer, 0);
+ {
+ ref = TREE_OPERAND (pointer, 0);
+ protected_set_expr_location (ref, loc);
+ return ref;
+ }
else
{
tree t = TREE_TYPE (type);
- tree ref;
ref = build1 (INDIRECT_REF, t, pointer);
if (!COMPLETE_OR_VOID_TYPE_P (t) && TREE_CODE (t) != ARRAY_TYPE)
{
- error ("dereferencing pointer to incomplete type");
+ error_at (loc, "dereferencing pointer to incomplete type");
return error_mark_node;
}
if (VOID_TYPE_P (t) && skip_evaluation == 0)
- warning (0, "dereferencing %<void *%> pointer");
+ warning_at (loc, 0, "dereferencing %<void *%> pointer");
/* We *must* set TREE_READONLY when dereferencing a pointer to const,
so that we get the proper error message if the result is used
TREE_SIDE_EFFECTS (ref)
= TYPE_VOLATILE (t) || TREE_SIDE_EFFECTS (pointer);
TREE_THIS_VOLATILE (ref) = TYPE_VOLATILE (t);
+ protected_set_expr_location (ref, loc);
return ref;
}
}
else if (TREE_CODE (pointer) != ERROR_MARK)
- error ("invalid type argument of %qs (have %qT)", errorstring, type);
+ error_at (loc,
+ "invalid type argument of %qs (have %qT)", errorstring, type);
return error_mark_node;
}
If A is a variable or a member, we generate a primitive ARRAY_REF.
This avoids forcing the array out of registers, and can work on
arrays that are not lvalues (for example, members of structures returned
- by functions). */
+ by functions).
+
+ LOC is the location to use for the returned expression. */
tree
-build_array_ref (tree array, tree index)
+build_array_ref (tree array, tree index, location_t loc)
{
+ tree ret;
bool swapped = false;
if (TREE_TYPE (array) == error_mark_node
|| TREE_TYPE (index) == error_mark_node)
if (TREE_CODE (TREE_TYPE (index)) != ARRAY_TYPE
&& TREE_CODE (TREE_TYPE (index)) != POINTER_TYPE)
{
- error ("subscripted value is neither array nor pointer");
+ error_at (loc, "subscripted value is neither array nor pointer");
return error_mark_node;
}
temp = array;
if (!INTEGRAL_TYPE_P (TREE_TYPE (index)))
{
- error ("array subscript is not an integer");
+ error_at (loc, "array subscript is not an integer");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (TREE_TYPE (array))) == FUNCTION_TYPE)
{
- error ("subscripted value is pointer to function");
+ error_at (loc, "subscripted value is pointer to function");
return error_mark_node;
}
while (TREE_CODE (foo) == COMPONENT_REF)
foo = TREE_OPERAND (foo, 0);
if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
- pedwarn ("ISO C forbids subscripting %<register%> array");
+ pedwarn (loc, OPT_pedantic,
+ "ISO C forbids subscripting %<register%> array");
else if (!flag_isoc99 && !lvalue_p (foo))
- pedwarn ("ISO C90 forbids subscripting non-lvalue array");
+ pedwarn (loc, OPT_pedantic,
+ "ISO C90 forbids subscripting non-lvalue array");
}
type = TREE_TYPE (TREE_TYPE (array));
in an inline function.
Hope it doesn't break something else. */
| TREE_THIS_VOLATILE (array));
- return require_complete_type (fold (rval));
+ ret = require_complete_type (fold (rval));
+ protected_set_expr_location (ret, loc);
+ return ret;
}
else
{
gcc_assert (TREE_CODE (TREE_TYPE (ar)) == POINTER_TYPE);
gcc_assert (TREE_CODE (TREE_TYPE (TREE_TYPE (ar))) != FUNCTION_TYPE);
- return build_indirect_ref (build_binary_op (PLUS_EXPR, ar, index, 0),
- "array indexing");
+ return build_indirect_ref
+ (loc, build_binary_op (loc, PLUS_EXPR, ar, index, 0),
+ "array indexing");
}
}
\f
/* Recursive call does not count as usage. */
if (ref != current_function_decl)
{
- if (!skip_evaluation)
- assemble_external (ref);
TREE_USED (ref) = 1;
}
used_types_insert (TREE_TYPE (ref));
ref = DECL_INITIAL (ref);
TREE_CONSTANT (ref) = 1;
- TREE_INVARIANT (ref) = 1;
}
else if (current_function_decl != 0
&& !DECL_FILE_SCOPE_P (current_function_decl)
&& (TREE_CODE (ref) != VAR_DECL || TREE_STATIC (ref))
&& ! TREE_PUBLIC (ref)
&& DECL_CONTEXT (ref) != current_function_decl)
- pedwarn ("%H%qD is static but used in inline function %qD "
- "which is not static", &loc, ref, current_function_decl);
+ pedwarn (loc, 0, "%qD is static but used in inline function %qD "
+ "which is not static", ref, current_function_decl);
return ref;
}
expression if necessary. This has the nice side-effect to prevent
the tree-inliner from generating invalid assignment trees which may
blow up in the RTL expander later. */
- if ((TREE_CODE (function) == NOP_EXPR
- || TREE_CODE (function) == CONVERT_EXPR)
+ if (CONVERT_EXPR_P (function)
&& TREE_CODE (tem = TREE_OPERAND (function, 0)) == ADDR_EXPR
&& TREE_CODE (tem = TREE_OPERAND (tem, 0)) == FUNCTION_DECL
&& !comptypes (fntype, TREE_TYPE (tem)))
/* This situation leads to run-time undefined behavior. We can't,
therefore, simply error unless we can prove that all possible
executions of the program must execute the code. */
- warning (0, "function called through a non-compatible type");
-
- /* We can, however, treat "undefined" any way we please.
- Call abort to encourage the user to fix the program. */
- inform ("if this code is reached, the program will abort");
+ if (warning (0, "function called through a non-compatible type"))
+ /* We can, however, treat "undefined" any way we please.
+ Call abort to encourage the user to fix the program. */
+ inform (input_location, "if this code is reached, the program will abort");
if (VOID_TYPE_P (return_type))
return trap;
if (nargs < 0)
return error_mark_node;
- /* Check that the arguments to the function are valid. */
+ /* Check that arguments to builtin functions match the expectations. */
+ if (fundecl
+ && DECL_BUILT_IN (fundecl)
+ && DECL_BUILT_IN_CLASS (fundecl) == BUILT_IN_NORMAL
+ && !check_builtin_function_arguments (fundecl, nargs, argarray))
+ return error_mark_node;
+ /* Check that the arguments to the function are valid. */
check_function_arguments (TYPE_ATTRIBUTES (fntype), nargs, argarray,
TYPE_ARG_TYPES (fntype));
if (TREE_CONSTANT (result)
&& (name == NULL_TREE
|| strncmp (IDENTIFIER_POINTER (name), "__builtin_", 10) != 0))
- pedwarn_init ("initializer element is not constant");
+ pedwarn_init (input_location, 0, "initializer element is not constant");
}
else
result = fold_build_call_array (TREE_TYPE (fntype),
/* This is the entry point used by the parser to build unary operators
in the input. CODE, a tree_code, specifies the unary operator, and
ARG is the operand. For unary plus, the C parser currently uses
- CONVERT_EXPR for code. */
+ CONVERT_EXPR for code.
+
+ LOC is the location to use for the tree generated.
+*/
struct c_expr
-parser_build_unary_op (enum tree_code code, struct c_expr arg)
+parser_build_unary_op (enum tree_code code, struct c_expr arg, location_t loc)
{
struct c_expr result;
- result.original_code = ERROR_MARK;
- result.value = build_unary_op (code, arg.value, 0);
+ result.value = build_unary_op (loc, code, arg.value, 0);
+ result.original_code = code;
if (TREE_OVERFLOW_P (result.value) && !TREE_OVERFLOW_P (arg.value))
overflow_warning (result.value);
in the input. CODE, a tree_code, specifies the binary operator, and
ARG1 and ARG2 are the operands. In addition to constructing the
expression, we check for operands that were written with other binary
- operators in a way that is likely to confuse the user. */
+ operators in a way that is likely to confuse the user.
+
+ LOCATION is the location of the binary operator. */
struct c_expr
-parser_build_binary_op (enum tree_code code, struct c_expr arg1,
- struct c_expr arg2)
+parser_build_binary_op (location_t location, enum tree_code code,
+ struct c_expr arg1, struct c_expr arg2)
{
struct c_expr result;
enum tree_code code1 = arg1.original_code;
enum tree_code code2 = arg2.original_code;
- result.value = build_binary_op (code, arg1.value, arg2.value, 1);
+ result.value = build_binary_op (location, code,
+ arg1.value, arg2.value, 1);
result.original_code = code;
if (TREE_CODE (result.value) == ERROR_MARK)
return result;
+ if (location != UNKNOWN_LOCATION)
+ protected_set_expr_location (result.value, location);
+
/* Check for cases such as x+y<<z which users are likely
to misinterpret. */
if (warn_parentheses)
- warn_about_parentheses (code, code1, code2);
+ warn_about_parentheses (code, code1, arg1.value, code2, arg2.value);
- if (code1 != tcc_comparison)
+ if (TREE_CODE_CLASS (code1) != tcc_comparison)
warn_logical_operator (code, arg1.value, arg2.value);
/* Warn about comparisons against string literals, with the exception
tree con0, con1, lit0, lit1;
tree orig_op1 = op1;
- if (pedantic || warn_pointer_arith)
- {
- if (TREE_CODE (target_type) == VOID_TYPE)
- pedwarn ("pointer of type %<void *%> used in subtraction");
- if (TREE_CODE (target_type) == FUNCTION_TYPE)
- pedwarn ("pointer to a function used in subtraction");
- }
+ if (TREE_CODE (target_type) == VOID_TYPE)
+ pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ "pointer of type %<void *%> used in subtraction");
+ if (TREE_CODE (target_type) == FUNCTION_TYPE)
+ pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ "pointer to a function used in subtraction");
/* If the conversion to ptrdiff_type does anything like widening or
converting a partial to an integral mode, we get a convert_expression
different mode in place.)
So first try to find a common term here 'by hand'; we want to cover
at least the cases that occur in legal static initializers. */
- if ((TREE_CODE (op0) == NOP_EXPR || TREE_CODE (op0) == CONVERT_EXPR)
+ if (CONVERT_EXPR_P (op0)
&& (TYPE_PRECISION (TREE_TYPE (op0))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op0, 0)))))
con0 = TREE_OPERAND (op0, 0);
else
con0 = op0;
- if ((TREE_CODE (op1) == NOP_EXPR || TREE_CODE (op1) == CONVERT_EXPR)
+ if (CONVERT_EXPR_P (op1)
&& (TYPE_PRECISION (TREE_TYPE (op1))
== TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
con1 = TREE_OPERAND (op1, 0);
Do not do default conversions on the minus operator
in case restype is a short type. */
- op0 = build_binary_op (MINUS_EXPR, convert (restype, op0),
+ op0 = build_binary_op (input_location,
+ MINUS_EXPR, convert (restype, op0),
convert (restype, op1), 0);
/* This generates an error if op1 is pointer to incomplete type. */
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
the default promotions (such as from short to int).
For ADDR_EXPR, the default promotions are not applied; FLAG nonzero
allows non-lvalues; this is only used to handle conversion of non-lvalue
- arrays to pointers in C99. */
+ arrays to pointers in C99.
+
+ LOCATION is the location of the operator. */
tree
-build_unary_op (enum tree_code code, tree xarg, int flag)
+build_unary_op (location_t location,
+ enum tree_code code, tree xarg, int flag)
{
/* No default_conversion here. It causes trouble for ADDR_EXPR. */
tree arg = xarg;
tree argtype = 0;
enum tree_code typecode;
tree val;
+ tree ret = error_mark_node;
int noconvert = flag;
const char *invalid_op_diag;
if ((invalid_op_diag
= targetm.invalid_unary_op (code, TREE_TYPE (xarg))))
{
- error (invalid_op_diag);
+ error_at (location, invalid_op_diag);
return error_mark_node;
}
|| typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
|| typecode == VECTOR_TYPE))
{
- error ("wrong type argument to unary plus");
+ error_at (location, "wrong type argument to unary plus");
return error_mark_node;
}
else if (!noconvert)
|| typecode == FIXED_POINT_TYPE || typecode == COMPLEX_TYPE
|| typecode == VECTOR_TYPE))
{
- error ("wrong type argument to unary minus");
+ error_at (location, "wrong type argument to unary minus");
return error_mark_node;
}
else if (!noconvert)
else if (typecode == COMPLEX_TYPE)
{
code = CONJ_EXPR;
- if (pedantic)
- pedwarn ("ISO C does not support %<~%> for complex conjugation");
+ pedwarn (location, OPT_pedantic,
+ "ISO C does not support %<~%> for complex conjugation");
if (!noconvert)
arg = default_conversion (arg);
}
else
{
- error ("wrong type argument to bit-complement");
+ error_at (location, "wrong type argument to bit-complement");
return error_mark_node;
}
break;
case ABS_EXPR:
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE))
{
- error ("wrong type argument to abs");
+ error_at (location, "wrong type argument to abs");
return error_mark_node;
}
else if (!noconvert)
if (!(typecode == INTEGER_TYPE || typecode == REAL_TYPE
|| typecode == COMPLEX_TYPE))
{
- error ("wrong type argument to conjugation");
+ error_at (location, "wrong type argument to conjugation");
return error_mark_node;
}
else if (!noconvert)
&& typecode != REAL_TYPE && typecode != POINTER_TYPE
&& typecode != COMPLEX_TYPE)
{
- error ("wrong type argument to unary exclamation mark");
+ error_at (location,
+ "wrong type argument to unary exclamation mark");
return error_mark_node;
}
- arg = c_objc_common_truthvalue_conversion (arg);
- return invert_truthvalue (arg);
+ arg = c_objc_common_truthvalue_conversion (location, arg);
+ ret = invert_truthvalue (arg);
+ goto return_build_unary_op;
case REALPART_EXPR:
if (TREE_CODE (arg) == COMPLEX_CST)
- return TREE_REALPART (arg);
+ ret = TREE_REALPART (arg);
else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
- return fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+ ret = fold_build1 (REALPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
else
- return arg;
+ ret = arg;
+ goto return_build_unary_op;
case IMAGPART_EXPR:
if (TREE_CODE (arg) == COMPLEX_CST)
- return TREE_IMAGPART (arg);
+ ret = TREE_IMAGPART (arg);
else if (TREE_CODE (TREE_TYPE (arg)) == COMPLEX_TYPE)
- return fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
+ ret = fold_build1 (IMAGPART_EXPR, TREE_TYPE (TREE_TYPE (arg)), arg);
else
- return convert (TREE_TYPE (arg), integer_zero_node);
+ ret = omit_one_operand (TREE_TYPE (arg), integer_zero_node, arg);
+ goto return_build_unary_op;
case PREINCREMENT_EXPR:
case POSTINCREMENT_EXPR:
{
tree real, imag;
- if (pedantic)
- pedwarn ("ISO C does not support %<++%> and %<--%>"
- " on complex types");
+ pedwarn (location, OPT_pedantic,
+ "ISO C does not support %<++%> and %<--%> on complex types");
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);
+ real = build_unary_op (EXPR_LOCATION (arg), REALPART_EXPR, arg, 1);
+ imag = build_unary_op (EXPR_LOCATION (arg), IMAGPART_EXPR, arg, 1);
+ real = build_unary_op (EXPR_LOCATION (arg), code, real, 1);
if (real == error_mark_node || imag == error_mark_node)
return error_mark_node;
- return build2 (COMPLEX_EXPR, TREE_TYPE (arg),
- real, imag);
+ ret = build2 (COMPLEX_EXPR, TREE_TYPE (arg),
+ real, imag);
+ goto return_build_unary_op;
}
/* Report invalid types. */
&& typecode != INTEGER_TYPE && typecode != REAL_TYPE)
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
- error ("wrong type argument to increment");
+ error_at (location, "wrong type argument to increment");
else
- error ("wrong type argument to decrement");
+ error_at (location, "wrong type argument to decrement");
return error_mark_node;
}
{
tree inc;
- tree result_type = TREE_TYPE (arg);
- arg = get_unwidened (arg, 0);
argtype = TREE_TYPE (arg);
/* Compute the increment. */
{
/* If pointer target is an undefined struct,
we just cannot know how to do the arithmetic. */
- if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (result_type)))
+ if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype)))
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
- error ("increment of pointer to unknown structure");
+ error_at (location,
+ "increment of pointer to unknown structure");
else
- error ("decrement of pointer to unknown structure");
+ error_at (location,
+ "decrement of pointer to unknown structure");
}
- else if ((pedantic || warn_pointer_arith)
- && (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE
- || TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE))
+ else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE
+ || TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
- pedwarn ("wrong type argument to increment");
+ pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ "wrong type argument to increment");
else
- pedwarn ("wrong type argument to decrement");
+ pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ "wrong type argument to decrement");
}
- inc = c_size_in_bytes (TREE_TYPE (result_type));
+ inc = c_size_in_bytes (TREE_TYPE (argtype));
inc = fold_convert (sizetype, inc);
}
- else if (FRACT_MODE_P (TYPE_MODE (result_type)))
+ else if (FRACT_MODE_P (TYPE_MODE (argtype)))
{
/* For signed fract types, we invert ++ to -- or
-- to ++, and change inc from 1 to -1, because
else
val = build2 (code, TREE_TYPE (arg), arg, inc);
TREE_SIDE_EFFECTS (val) = 1;
- val = convert (result_type, val);
if (TREE_CODE (val) != code)
TREE_NO_WARNING (val) = 1;
- return val;
+ ret = val;
+ goto return_build_unary_op;
}
case ADDR_EXPR:
/* Don't let this be an lvalue. */
if (lvalue_p (TREE_OPERAND (arg, 0)))
return non_lvalue (TREE_OPERAND (arg, 0));
- return TREE_OPERAND (arg, 0);
+ ret = TREE_OPERAND (arg, 0);
+ goto return_build_unary_op;
}
/* For &x[y], return x+y */
tree op0 = TREE_OPERAND (arg, 0);
if (!c_mark_addressable (op0))
return error_mark_node;
- return build_binary_op (PLUS_EXPR,
+ return build_binary_op (location, PLUS_EXPR,
(TREE_CODE (TREE_TYPE (op0)) == ARRAY_TYPE
? array_to_pointer_conversion (op0)
: op0),
tree op0 = fold_convert (sizetype, fold_offsetof (arg, val)), op1;
op1 = fold_convert (argtype, TREE_OPERAND (val, 0));
- return fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
+ ret = fold_build2 (POINTER_PLUS_EXPR, argtype, op1, op0);
+ goto return_build_unary_op;
}
val = build1 (ADDR_EXPR, argtype, arg);
- return val;
+ ret = val;
+ goto return_build_unary_op;
default:
gcc_unreachable ();
if (argtype == 0)
argtype = TREE_TYPE (arg);
- return require_constant_value ? fold_build1_initializer (code, argtype, arg)
- : fold_build1 (code, argtype, arg);
+ ret = require_constant_value ? fold_build1_initializer (code, argtype, arg)
+ : fold_build1 (code, argtype, arg);
+ return_build_unary_op:
+ gcc_assert (ret != error_mark_node);
+ protected_set_expr_location (ret, location);
+ return ret;
}
/* Return nonzero if REF is an lvalue valid for this language.
("global register variable %qD used in nested function", x);
return false;
}
- pedwarn ("register variable %qD used in nested function", x);
+ pedwarn (input_location, 0, "register variable %qD used in nested function", x);
}
else if (C_DECL_REGISTER (x))
{
}
else if (code1 == VOID_TYPE || code2 == VOID_TYPE)
{
- if (pedantic && (code1 != VOID_TYPE || code2 != VOID_TYPE))
- pedwarn ("ISO C forbids conditional expr with only one void side");
+ if (code1 != VOID_TYPE || code2 != VOID_TYPE)
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids conditional expr with only one void side");
result_type = void_type_node;
}
else if (code1 == POINTER_TYPE && code2 == POINTER_TYPE)
result_type = qualify_type (type1, type2);
else if (VOID_TYPE_P (TREE_TYPE (type1)))
{
- if (pedantic && TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
- pedwarn ("ISO C forbids conditional expr between "
+ if (TREE_CODE (TREE_TYPE (type2)) == FUNCTION_TYPE)
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids conditional expr between "
"%<void *%> and function pointer");
result_type = build_pointer_type (qualify_type (TREE_TYPE (type1),
TREE_TYPE (type2)));
}
else if (VOID_TYPE_P (TREE_TYPE (type2)))
{
- if (pedantic && TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
- pedwarn ("ISO C forbids conditional expr between "
+ if (TREE_CODE (TREE_TYPE (type1)) == FUNCTION_TYPE)
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids conditional expr between "
"%<void *%> and function pointer");
result_type = build_pointer_type (qualify_type (TREE_TYPE (type2),
TREE_TYPE (type1)));
}
else
{
- pedwarn ("pointer type mismatch in conditional expression");
+ pedwarn (input_location, 0,
+ "pointer type mismatch in conditional expression");
result_type = build_pointer_type (void_type_node);
}
}
else if (code1 == POINTER_TYPE && code2 == INTEGER_TYPE)
{
if (!null_pointer_constant_p (orig_op2))
- pedwarn ("pointer/integer type mismatch in conditional expression");
+ pedwarn (input_location, 0,
+ "pointer/integer type mismatch in conditional expression");
else
{
op2 = null_pointer_node;
else if (code2 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
if (!null_pointer_constant_p (orig_op1))
- pedwarn ("pointer/integer type mismatch in conditional expression");
+ pedwarn (input_location, 0,
+ "pointer/integer type mismatch in conditional expression");
else
{
op1 = null_pointer_node;
if (warn_unused_value)
{
if (VOID_TYPE_P (TREE_TYPE (expr1))
- && (TREE_CODE (expr1) == NOP_EXPR
- || TREE_CODE (expr1) == CONVERT_EXPR))
+ && CONVERT_EXPR_P (expr1))
; /* (void) a, b */
else if (VOID_TYPE_P (TREE_TYPE (expr1))
&& TREE_CODE (expr1) == COMPOUND_EXPR
- && (TREE_CODE (TREE_OPERAND (expr1, 1)) == CONVERT_EXPR
- || TREE_CODE (TREE_OPERAND (expr1, 1)) == NOP_EXPR))
+ && CONVERT_EXPR_P (TREE_OPERAND (expr1, 1)))
; /* (void) a, (void) b, c */
else
warning (OPT_Wunused_value,
if (type == TYPE_MAIN_VARIANT (TREE_TYPE (value)))
{
- if (pedantic)
- {
- if (TREE_CODE (type) == RECORD_TYPE
- || TREE_CODE (type) == UNION_TYPE)
- pedwarn ("ISO C forbids casting nonscalar to the same type");
- }
+ if (TREE_CODE (type) == RECORD_TYPE
+ || TREE_CODE (type) == UNION_TYPE)
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids casting nonscalar to the same type");
}
else if (TREE_CODE (type) == UNION_TYPE)
{
tree field;
for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field))
- if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
- TYPE_MAIN_VARIANT (TREE_TYPE (value))))
+ if (TREE_TYPE (field) != error_mark_node
+ && comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (field)),
+ TYPE_MAIN_VARIANT (TREE_TYPE (value))))
break;
if (field)
{
tree t;
- if (pedantic)
- pedwarn ("ISO C forbids casts to union type");
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C forbids casts to union type");
t = digest_init (type,
build_constructor_single (type, field, value),
true, 0);
TREE_CONSTANT (t) = TREE_CONSTANT (value);
- TREE_INVARIANT (t) = TREE_INVARIANT (value);
return t;
}
error ("cast to union type from type not present in union");
&& TREE_CODE (otype) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (otype)) == FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (type)) != FUNCTION_TYPE)
- pedwarn ("ISO C forbids conversion of function pointer to object pointer type");
+ pedwarn (input_location, OPT_pedantic, "ISO C forbids "
+ "conversion of function pointer to object pointer type");
if (pedantic
&& TREE_CODE (type) == POINTER_TYPE
&& TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE
&& TREE_CODE (TREE_TYPE (otype)) != FUNCTION_TYPE
&& !null_pointer_constant_p (value))
- pedwarn ("ISO C forbids conversion of object pointer to function pointer type");
+ pedwarn (input_location, OPT_pedantic, "ISO C forbids "
+ "conversion of object pointer to function pointer type");
ovalue = value;
value = convert (type, value);
/* Build an assignment expression of lvalue LHS from value RHS.
MODIFYCODE is the code for a binary operator that we use
to combine the old value of LHS with RHS to get the new value.
- Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment. */
+ Or else MODIFYCODE is NOP_EXPR meaning do a simple assignment.
+
+ LOCATION is the location of the MODIFYCODE operator. */
tree
-build_modify_expr (tree lhs, enum tree_code modifycode, tree rhs)
+build_modify_expr (location_t location,
+ tree lhs, enum tree_code modifycode, tree rhs)
{
tree result;
tree newrhs;
if (modifycode != NOP_EXPR)
{
lhs = stabilize_reference (lhs);
- newrhs = build_binary_op (modifycode, lhs, rhs, 1);
+ newrhs = build_binary_op (location,
+ modifycode, lhs, rhs, 1);
}
/* Give an error for storing in something that is 'const'. */
{
result = objc_generate_write_barrier (lhs, modifycode, newrhs);
if (result)
- return result;
+ {
+ protected_set_expr_location (result, location);
+ return result;
+ }
}
/* Scan operands. */
result = build2 (MODIFY_EXPR, lhstype, lhs, newrhs);
TREE_SIDE_EFFECTS (result) = 1;
+ protected_set_expr_location (result, location);
/* If we got the LHS in a different type for storing in,
convert the result back to the nominal type of LHS
if (olhstype == TREE_TYPE (result))
return result;
- return convert_for_assignment (olhstype, result, ic_assign,
- NULL_TREE, NULL_TREE, 0);
+
+ result = convert_for_assignment (olhstype, result, ic_assign,
+ NULL_TREE, NULL_TREE, 0);
+ protected_set_expr_location (result, location);
+ return result;
}
\f
/* Convert value RHS to type TYPE as preparation for an assignment
tree rname = NULL_TREE;
bool objc_ok = false;
- if (errtype == ic_argpass || errtype == ic_argpass_nonproto)
+ if (errtype == ic_argpass)
{
tree selector;
/* Change pointer to function to the function itself for
/* This macro is used to emit diagnostics to ensure that all format
strings are complete sentences, visible to gettext and checked at
compile time. */
-#define WARN_FOR_ASSIGNMENT(AR, AS, IN, RE) \
- do { \
- switch (errtype) \
- { \
- case ic_argpass: \
- pedwarn (AR, parmnum, rname); \
- break; \
- case ic_argpass_nonproto: \
- warning (0, AR, parmnum, rname); \
- break; \
- case ic_assign: \
- pedwarn (AS); \
- break; \
- case ic_init: \
- pedwarn (IN); \
- break; \
- case ic_return: \
- pedwarn (RE); \
- break; \
- default: \
- gcc_unreachable (); \
- } \
+#define WARN_FOR_ASSIGNMENT(LOCATION, OPT, AR, AS, IN, RE) \
+ do { \
+ switch (errtype) \
+ { \
+ case ic_argpass: \
+ if (pedwarn (LOCATION, OPT, AR, parmnum, rname)) \
+ inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
+ ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \
+ "expected %qT but argument is of type %qT", \
+ type, rhstype); \
+ break; \
+ case ic_assign: \
+ pedwarn (LOCATION, OPT, AS); \
+ break; \
+ case ic_init: \
+ pedwarn (LOCATION, OPT, IN); \
+ break; \
+ case ic_return: \
+ pedwarn (LOCATION, OPT, RE); \
+ break; \
+ default: \
+ gcc_unreachable (); \
+ } \
} while (0)
STRIP_TYPE_NOPS (rhs);
/* Conversion to a transparent union from its member types.
This applies only to function arguments. */
if (codel == UNION_TYPE && TYPE_TRANSPARENT_UNION (type)
- && (errtype == ic_argpass || errtype == ic_argpass_nonproto))
+ && errtype == ic_argpass)
{
tree memb, marginal_memb = NULL_TREE;
function where an ordinary one is wanted, but not
vice-versa. */
if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
- WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE "
+ WARN_FOR_ASSIGNMENT (input_location, 0,
+ G_("passing argument %d of %qE "
"makes qualified function "
"pointer from unqualified"),
G_("assignment makes qualified "
"pointer from unqualified"));
}
else if (TYPE_QUALS (ttr) & ~TYPE_QUALS (ttl))
- WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards "
+ WARN_FOR_ASSIGNMENT (input_location, 0,
+ G_("passing argument %d of %qE discards "
"qualifiers from pointer target type"),
G_("assignment discards qualifiers "
"from pointer target type"),
memb = marginal_memb;
}
- if (pedantic && (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl)))
- pedwarn ("ISO C prohibits argument conversion to union type");
+ if (!fundecl || !DECL_IN_SYSTEM_HEADER (fundecl))
+ pedwarn (input_location, OPT_pedantic,
+ "ISO C prohibits argument conversion to union type");
rhs = fold_convert (TREE_TYPE (memb), rhs);
return build_constructor_single (type, memb, rhs);
if (TREE_CODE (mvr) != ARRAY_TYPE)
mvr = TYPE_MAIN_VARIANT (mvr);
/* Opaque pointers are treated like void pointers. */
- is_opaque_pointer = (targetm.vector_opaque_p (type)
- || targetm.vector_opaque_p (rhstype))
- && TREE_CODE (ttl) == VECTOR_TYPE
- && TREE_CODE (ttr) == VECTOR_TYPE;
+ is_opaque_pointer = vector_targets_convertible_p (ttl, ttr);
/* C++ does not allow the implicit conversion void* -> T*. However,
for the purpose of reducing the number of false positives, we
switch (errtype)
{
case ic_argpass:
- case ic_argpass_nonproto:
warning (OPT_Wmissing_format_attribute,
"argument %d of %qE might be "
"a candidate for a format attribute",
(VOID_TYPE_P (ttr)
&& !null_pointer_constant_p (rhs)
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
- WARN_FOR_ASSIGNMENT (G_("ISO C forbids passing argument %d of "
+ WARN_FOR_ASSIGNMENT (input_location, OPT_pedantic,
+ G_("ISO C forbids passing argument %d of "
"%qE between function pointer "
"and %<void *%>"),
G_("ISO C forbids assignment between "
qualifier are acceptable if the 'volatile' has been added
in by the Objective-C EH machinery. */
if (!objc_type_quals_match (ttl, ttr))
- WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE discards "
+ WARN_FOR_ASSIGNMENT (input_location, 0,
+ G_("passing argument %d of %qE discards "
"qualifiers from pointer target type"),
G_("assignment discards qualifiers "
"from pointer target type"),
;
/* If there is a mismatch, do warn. */
else if (warn_pointer_sign)
- WARN_FOR_ASSIGNMENT (G_("pointer targets in passing argument "
+ WARN_FOR_ASSIGNMENT (input_location, OPT_Wpointer_sign,
+ G_("pointer targets in passing argument "
"%d of %qE differ in signedness"),
G_("pointer targets in assignment "
"differ in signedness"),
it is okay to use a const or volatile function
where an ordinary one is wanted, but not vice-versa. */
if (TYPE_QUALS (ttl) & ~TYPE_QUALS (ttr))
- WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
+ WARN_FOR_ASSIGNMENT (input_location, 0,
+ G_("passing argument %d of %qE makes "
"qualified function pointer "
"from unqualified"),
G_("assignment makes qualified function "
else
/* Avoid warning about the volatile ObjC EH puts on decls. */
if (!objc_ok)
- WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE from "
+ WARN_FOR_ASSIGNMENT (input_location, 0,
+ G_("passing argument %d of %qE from "
"incompatible pointer type"),
G_("assignment from incompatible pointer type"),
G_("initialization from incompatible "
or one that results from arithmetic, even including
a cast to integer type. */
if (!null_pointer_constant_p (rhs))
- WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes "
+ WARN_FOR_ASSIGNMENT (input_location, 0,
+ G_("passing argument %d of %qE makes "
"pointer from integer without a cast"),
G_("assignment makes pointer from integer "
"without a cast"),
}
else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
{
- WARN_FOR_ASSIGNMENT (G_("passing argument %d of %qE makes integer "
+ WARN_FOR_ASSIGNMENT (input_location, 0,
+ G_("passing argument %d of %qE makes integer "
"from pointer without a cast"),
G_("assignment makes integer from pointer "
"without a cast"),
switch (errtype)
{
case ic_argpass:
- case ic_argpass_nonproto:
- /* ??? This should not be an error when inlining calls to
- unprototyped functions. */
error ("incompatible type for argument %d of %qE", parmnum, rname);
+ inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
+ ? DECL_SOURCE_LOCATION (fundecl) : input_location,
+ "expected %qT but argument is of type %qT", type, rhstype);
break;
case ic_assign:
- error ("incompatible types in assignment");
+ error ("incompatible types when assigning to type %qT from type %qT",
+ type, rhstype);
break;
case ic_init:
- error ("incompatible types in initialization");
+ error ("incompatible types when initializing type %qT using type %qT",
+ type, rhstype);
break;
case ic_return:
- error ("incompatible types in return");
+ error ("incompatible types when returning type %qT but %qT was expected",
+ rhstype, type);
break;
default:
gcc_unreachable ();
error ("(near initialization for %qs)", ofwhat);
}
-/* Issue a pedantic warning for a bad initializer component.
- MSGID identifies the message.
- The component name is taken from the spelling stack. */
+/* Issue a pedantic warning for a bad initializer component. OPT is
+ the option OPT_* (from options.h) controlling this warning or 0 if
+ it is unconditionally given. MSGID identifies the message. The
+ component name is taken from the spelling stack. */
void
-pedwarn_init (const char *msgid)
+pedwarn_init (location_t location, int opt, const char *msgid)
{
char *ofwhat;
- pedwarn ("%s", _(msgid));
+ pedwarn (location, opt, "%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
- pedwarn ("(near initialization for %qs)", ofwhat);
+ pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
}
-/* Issue a warning for a bad initializer component.
- MSGID identifies the message.
- The component name is taken from the spelling stack. */
+/* Issue a warning for a bad initializer component.
+
+ OPT is the OPT_W* value corresponding to the warning option that
+ controls this warning. MSGID identifies the message. The
+ component name is taken from the spelling stack. */
static void
-warning_init (const char *msgid)
+warning_init (int opt, const char *msgid)
{
char *ofwhat;
- warning (0, "%s", _(msgid));
+ warning (opt, "%s", _(msgid));
ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
if (*ofwhat)
- warning (0, "(near initialization for %qs)", ofwhat);
+ warning (opt, "(near initialization for %qs)", ofwhat);
}
\f
/* If TYPE is an array type and EXPR is a parenthesized string
&& TREE_CODE (type) == ARRAY_TYPE
&& TREE_CODE (expr.value) == STRING_CST
&& expr.original_code != STRING_CST)
- pedwarn_init ("array initialized from parenthesized string constant");
+ pedwarn_init (input_location, OPT_pedantic,
+ "array initialized from parenthesized string constant");
}
/* Digest the parser output INIT as an initializer for type TYPE.
|| typ1 == signed_char_type_node
|| typ1 == unsigned_char_type_node);
bool wchar_array = !!comptypes (typ1, wchar_type_node);
- if (char_array || wchar_array)
+ bool char16_array = !!comptypes (typ1, char16_type_node);
+ bool char32_array = !!comptypes (typ1, char32_type_node);
+
+ if (char_array || wchar_array || char16_array || char32_array)
{
struct c_expr expr;
- bool char_string;
+ tree typ2 = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)));
expr.value = inside_init;
expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
maybe_warn_string_init (type, expr);
- char_string
- = (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (inside_init)))
- == char_type_node);
-
if (comptypes (TYPE_MAIN_VARIANT (TREE_TYPE (inside_init)),
TYPE_MAIN_VARIANT (type)))
return inside_init;
- if (!wchar_array && !char_string)
+ if (char_array)
{
- error_init ("char-array initialized from wide string");
- return error_mark_node;
+ if (typ2 != char_type_node)
+ {
+ error_init ("char-array initialized from wide string");
+ return error_mark_node;
+ }
}
- if (char_string && !char_array)
+ else
{
- error_init ("wchar_t-array initialized from non-wide string");
- return error_mark_node;
+ if (typ2 == char_type_node)
+ {
+ error_init ("wide character array initialized from non-wide "
+ "string");
+ return error_mark_node;
+ }
+ else if (!comptypes(typ1, typ2))
+ {
+ error_init ("wide character array initialized from "
+ "incompatible wide string");
+ return error_mark_node;
+ }
}
TREE_TYPE (inside_init) = type;
if (TYPE_DOMAIN (type) != 0
&& TYPE_SIZE (type) != 0
&& TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
- /* Subtract 1 (or sizeof (wchar_t))
+ /* Subtract the size of a single (possibly wide) character
because it's ok to ignore the terminating null char
that is counted in the length of the constant. */
&& 0 > compare_tree_int (TYPE_SIZE_UNIT (type),
TREE_STRING_LENGTH (inside_init)
- - ((TYPE_PRECISION (typ1)
- != TYPE_PRECISION (char_type_node))
- ? (TYPE_PRECISION (wchar_type_node)
- / BITS_PER_UNIT)
- : 1)))
- pedwarn_init ("initializer-string for array of chars is too long");
+ - (TYPE_PRECISION (typ1)
+ / BITS_PER_UNIT)))
+ pedwarn_init (input_location, 0,
+ "initializer-string for array of chars is too long");
return inside_init;
}
}
}
+ if (warn_sequence_point)
+ verify_sequence_points (inside_init);
+
/* Any type can be initialized
from an expression of the same type, optionally with braces. */
if (inside_init == error_mark_node)
error_init ("initializer element is not constant");
else
- pedwarn_init ("initializer element is not constant");
+ pedwarn_init (input_location, OPT_pedantic,
+ "initializer element is not constant");
if (flag_pedantic_errors)
inside_init = error_mark_node;
}
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
- process_init_element (pop_init_level (1));
+ process_init_element (pop_init_level (1), true);
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& constructor_max_index
&& tree_int_cst_lt (constructor_max_index,
constructor_index))
- process_init_element (pop_init_level (1));
+ process_init_element (pop_init_level (1), true);
else
break;
}
if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
{
missing_braces_mentioned = 1;
- warning_init ("missing braces around initializer");
+ warning_init (OPT_Wmissing_braces, "missing braces around initializer");
}
if (TREE_CODE (constructor_type) == RECORD_TYPE
else
{
if (constructor_type != error_mark_node)
- warning_init ("braces around scalar initializer");
+ warning_init (0, "braces around scalar initializer");
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
/* When we come to an explicit close brace,
pop any inner levels that didn't have explicit braces. */
while (constructor_stack->implicit)
- process_init_element (pop_init_level (1));
+ process_init_element (pop_init_level (1), true);
gcc_assert (!constructor_range_stack);
}
if (constructor_depth > 2)
error_init ("initialization of flexible array member in a nested context");
- else if (pedantic)
- pedwarn_init ("initialization of a flexible array member");
+ else
+ pedwarn_init (input_location, OPT_pedantic,
+ "initialization of a flexible array member");
/* We have already issued an error message for the existence
of a flexible array member not at the end of the structure.
if (constructor_unfilled_fields && !constructor_designated)
{
push_member_name (constructor_unfilled_fields);
- warning_init ("missing initializer");
+ warning_init (OPT_Wmissing_field_initializers,
+ "missing initializer");
RESTORE_SPELLING_DEPTH (constructor_depth);
}
}
ret.value = build_constructor (constructor_type,
constructor_elements);
if (constructor_constant)
- TREE_CONSTANT (ret.value) = TREE_INVARIANT (ret.value) = 1;
+ TREE_CONSTANT (ret.value) = 1;
if (constructor_constant && constructor_simple)
TREE_STATIC (ret.value) = 1;
}
/* Designator list starts at the level of closest explicit
braces. */
while (constructor_stack->implicit)
- process_init_element (pop_init_level (1));
+ process_init_element (pop_init_level (1), true);
constructor_designated = 1;
return 0;
}
\f
/* Add a new initializer to the tree of pending initializers. PURPOSE
identifies the initializer, either array index or field in a structure.
- VALUE is the value of that index or field. */
+ VALUE is the value of that index or field.
+
+ IMPLICIT is true if value comes from pop_init_level (1),
+ the new initializer has been merged with the existing one
+ and thus no warnings should be emitted about overriding an
+ existing initializer. */
static void
-add_pending_init (tree purpose, tree value)
+add_pending_init (tree purpose, tree value, bool implicit)
{
struct init_node *p, **q, *r;
q = &p->right;
else
{
- if (TREE_SIDE_EFFECTS (p->value))
- warning_init ("initialized field with side-effects overwritten");
- else if (warn_override_init)
- warning_init ("initialized field overwritten");
+ if (!implicit)
+ {
+ if (TREE_SIDE_EFFECTS (p->value))
+ warning_init (0, "initialized field with side-effects overwritten");
+ else if (warn_override_init)
+ warning_init (OPT_Woverride_init, "initialized field overwritten");
+ }
p->value = value;
return;
}
q = &p->right;
else
{
- if (TREE_SIDE_EFFECTS (p->value))
- warning_init ("initialized field with side-effects overwritten");
- else if (warn_override_init)
- warning_init ("initialized field overwritten");
+ if (!implicit)
+ {
+ if (TREE_SIDE_EFFECTS (p->value))
+ warning_init (0, "initialized field with side-effects overwritten");
+ else if (warn_override_init)
+ warning_init (OPT_Woverride_init, "initialized field overwritten");
+ }
p->value = value;
return;
}
return;
FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
- add_pending_init (index, value);
+ add_pending_init (index, value, false);
constructor_elements = 0;
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
gcc_assert (TREE_CODE (constructor_type) == ARRAY_TYPE);
- if (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
- == TYPE_PRECISION (char_type_node))
- wchar_bytes = 1;
- else
- {
- gcc_assert (TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str)))
- == TYPE_PRECISION (wchar_type_node));
- wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
- }
+ wchar_bytes = TYPE_PRECISION (TREE_TYPE (TREE_TYPE (str))) / BITS_PER_UNIT;
charwidth = TYPE_PRECISION (char_type_node);
type = TREE_TYPE (constructor_type);
p = TREE_STRING_POINTER (str);
}
value = build_int_cst_wide (type, val[1], val[0]);
- add_pending_init (purpose, value);
+ add_pending_init (purpose, value, false);
}
constructor_incremental = 0;
PENDING if non-nil means output pending elements that belong
right after this element. (PENDING is normally 1;
- it is 0 while outputting pending elements, to avoid recursion.) */
+ it is 0 while outputting pending elements, to avoid recursion.)
+
+ IMPLICIT is true if value comes from pop_init_level (1),
+ the new initializer has been merged with the existing one
+ and thus no warnings should be emitted about overriding an
+ existing initializer. */
static void
output_init_element (tree value, bool strict_string, tree type, tree field,
- int pending)
+ int pending, bool implicit)
{
constructor_elt *celt;
value = error_mark_node;
}
else if (require_constant_elements)
- pedwarn ("initializer element is not computable at load time");
+ pedwarn (input_location, 0,
+ "initializer element is not computable at load time");
}
/* If this field is empty (and not at the end of structure),
&& tree_int_cst_lt (field, constructor_unfilled_index))
set_nonincremental_init ();
- add_pending_init (field, value);
+ add_pending_init (field, value, implicit);
return;
}
else if (TREE_CODE (constructor_type) == RECORD_TYPE
}
}
- add_pending_init (field, value);
+ add_pending_init (field, value, implicit);
return;
}
else if (TREE_CODE (constructor_type) == UNION_TYPE
&& !VEC_empty (constructor_elt, constructor_elements))
{
- if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
- constructor_elements)->value))
- warning_init ("initialized field with side-effects overwritten");
- else if (warn_override_init)
- warning_init ("initialized field overwritten");
+ if (!implicit)
+ {
+ if (TREE_SIDE_EFFECTS (VEC_last (constructor_elt,
+ constructor_elements)->value))
+ warning_init (0,
+ "initialized field with side-effects overwritten");
+ else if (warn_override_init)
+ warning_init (OPT_Woverride_init, "initialized field overwritten");
+ }
/* We can have just one union field set. */
constructor_elements = 0;
constructor_unfilled_index))
output_init_element (elt->value, true,
TREE_TYPE (constructor_type),
- constructor_unfilled_index, 0);
+ constructor_unfilled_index, 0, false);
else if (tree_int_cst_lt (constructor_unfilled_index,
elt->purpose))
{
{
constructor_unfilled_fields = elt->purpose;
output_init_element (elt->value, true, TREE_TYPE (elt->purpose),
- elt->purpose, 0);
+ elt->purpose, 0, false);
}
else if (tree_int_cst_lt (ctor_unfilled_bitpos, elt_bitpos))
{
to handle a partly-braced initializer.
Once this has found the correct level for the new element,
- it calls output_init_element. */
+ it calls output_init_element.
+
+ IMPLICIT is true if value comes from pop_init_level (1),
+ the new initializer has been merged with the existing one
+ and thus no warnings should be emitted about overriding an
+ existing initializer. */
void
-process_init_element (struct c_expr value)
+process_init_element (struct c_expr value, bool implicit)
{
tree orig_value = value.value;
int string_flag = orig_value != 0 && TREE_CODE (orig_value) == STRING_CST;
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
- process_init_element (pop_init_level (1));
+ process_init_element (pop_init_level (1), true);
else if (TREE_CODE (constructor_type) == ARRAY_TYPE
&& (constructor_max_index == 0
|| tree_int_cst_lt (constructor_max_index,
constructor_index)))
- process_init_element (pop_init_level (1));
+ process_init_element (pop_init_level (1), true);
else
break;
}
if (constructor_fields == 0)
{
- pedwarn_init ("excess elements in struct initializer");
+ pedwarn_init (input_location, 0,
+ "excess elements in struct initializer");
break;
}
{
push_member_name (constructor_fields);
output_init_element (value.value, strict_string,
- fieldtype, constructor_fields, 1);
+ fieldtype, constructor_fields, 1, implicit);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
else
if (constructor_fields == 0)
{
- pedwarn_init ("excess elements in union initializer");
+ pedwarn_init (input_location, 0,
+ "excess elements in union initializer");
break;
}
{
push_member_name (constructor_fields);
output_init_element (value.value, strict_string,
- fieldtype, constructor_fields, 1);
+ fieldtype, constructor_fields, 1, implicit);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
else
&& (tree_int_cst_lt (constructor_max_index, constructor_index)
|| integer_all_onesp (constructor_max_index)))
{
- pedwarn_init ("excess elements in array initializer");
+ pedwarn_init (input_location, 0,
+ "excess elements in array initializer");
break;
}
{
push_array_bounds (tree_low_cst (constructor_index, 1));
output_init_element (value.value, strict_string,
- elttype, constructor_index, 1);
+ elttype, constructor_index, 1, implicit);
RESTORE_SPELLING_DEPTH (constructor_depth);
}
always have a fixed size derived from their type. */
if (tree_int_cst_lt (constructor_max_index, constructor_index))
{
- pedwarn_init ("excess elements in vector initializer");
+ pedwarn_init (input_location, 0,
+ "excess elements in vector initializer");
break;
}
/* Now output the actual element. */
if (value.value)
output_init_element (value.value, strict_string,
- elttype, constructor_index, 1);
+ elttype, constructor_index, 1, implicit);
constructor_index
= size_binop (PLUS_EXPR, constructor_index, bitsize_one_node);
else if (constructor_type != error_mark_node
&& constructor_fields == 0)
{
- pedwarn_init ("excess elements in scalar initializer");
+ pedwarn_init (input_location, 0,
+ "excess elements in scalar initializer");
break;
}
else
{
if (value.value)
output_init_element (value.value, strict_string,
- constructor_type, NULL_TREE, 1);
+ constructor_type, NULL_TREE, 1, implicit);
constructor_fields = 0;
}
while (constructor_stack != range_stack->stack)
{
gcc_assert (constructor_stack->implicit);
- process_init_element (pop_init_level (1));
+ process_init_element (pop_init_level (1), true);
}
for (p = range_stack;
!p->range_end || tree_int_cst_equal (p->index, p->range_end);
p = p->prev)
{
gcc_assert (constructor_stack->implicit);
- process_init_element (pop_init_level (1));
+ process_init_element (pop_init_level (1), true);
}
p->index = size_binop (PLUS_EXPR, p->index, bitsize_one_node);
tree
c_finish_goto_ptr (tree expr)
{
- if (pedantic)
- pedwarn ("ISO C forbids %<goto *expr;%>");
+ pedwarn (input_location, OPT_pedantic, "ISO C forbids %<goto *expr;%>");
expr = convert (ptr_type_node, expr);
return add_stmt (build1 (GOTO_EXPR, void_type_node, expr));
}
if ((warn_return_type || flag_isoc99)
&& valtype != 0 && TREE_CODE (valtype) != VOID_TYPE)
{
- pedwarn_c99 ("%<return%> with no value, in "
+ pedwarn_c99 (input_location, flag_isoc99 ? 0 : OPT_Wreturn_type,
+ "%<return%> with no value, in "
"function returning non-void");
no_warning = true;
}
{
current_function_returns_null = 1;
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");
+ pedwarn (input_location, 0,
+ "%<return%> with a value, in function returning void");
+ else
+ pedwarn (input_location, OPT_pedantic, "ISO C forbids "
+ "%<return%> with expression, in function returning void");
}
else
{
{
switch (TREE_CODE (inner))
{
- case NOP_EXPR: case NON_LVALUE_EXPR: case CONVERT_EXPR:
+ CASE_CONVERT:
+ case NON_LVALUE_EXPR:
case PLUS_EXPR:
+ case POINTER_PLUS_EXPR:
inner = TREE_OPERAND (inner, 0);
continue;
tree op1 = TREE_OPERAND (inner, 1);
while (!POINTER_TYPE_P (TREE_TYPE (op1))
- && (TREE_CODE (op1) == NOP_EXPR
- || TREE_CODE (op1) == NON_LVALUE_EXPR
- || TREE_CODE (op1) == CONVERT_EXPR))
+ && (CONVERT_EXPR_P (op1)
+ || TREE_CODE (op1) == NON_LVALUE_EXPR))
op1 = TREE_OPERAND (op1, 0);
if (POINTER_TYPE_P (TREE_TYPE (op1)))
}
retval = build2 (MODIFY_EXPR, TREE_TYPE (res), res, t);
+
+ if (warn_sequence_point)
+ verify_sequence_points (retval);
}
ret_stmt = build_stmt (RETURN_EXPR, retval);
"converted to %<int%> in ISO C");
exp = default_conversion (exp);
+
+ if (warn_sequence_point)
+ verify_sequence_points (exp);
}
}
&if_locus);
}
- 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);
add_stmt (stmt);
if (skip)
return NULL_TREE;
+ if (!is_break)
+ add_stmt (build_predict_expr (PRED_CONTINUE, NOT_TAKEN));
+
return add_stmt (build1 (GOTO_EXPR, void_type_node, label));
}
\f
/* Build a binary-operation expression without default conversions.
CODE is the kind of expression to build.
+ LOCATION is the operator's location.
This function differs from `build' in several ways:
the data type of the result is computed and recorded in it,
warnings are generated if arg data types are invalid,
the arithmetic is to be done. */
tree
-build_binary_op (enum tree_code code, tree orig_op0, tree orig_op1,
- int convert_p)
+build_binary_op (location_t location, enum tree_code code,
+ tree orig_op0, tree orig_op1, int convert_p)
{
tree type0, type1;
enum tree_code code0, code1;
tree op0, op1;
+ tree ret = error_mark_node;
const char *invalid_op_diag;
/* Expression code to give to the expression when it is built.
/* True means types are compatible as far as ObjC is concerned. */
bool objc_ok;
+ if (location == UNKNOWN_LOCATION)
+ location = input_location;
+
if (convert_p)
{
op0 = default_conversion (orig_op0);
if ((invalid_op_diag
= targetm.invalid_binary_op (code, type0, type1)))
{
- error (invalid_op_diag);
+ error_at (location, invalid_op_diag);
return error_mark_node;
}
case PLUS_EXPR:
/* Handle the pointer + int case. */
if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
- return pointer_int_sum (PLUS_EXPR, op0, op1);
+ {
+ ret = pointer_int_sum (PLUS_EXPR, op0, op1);
+ goto return_build_binary_op;
+ }
else if (code1 == POINTER_TYPE && code0 == INTEGER_TYPE)
- return pointer_int_sum (PLUS_EXPR, op1, op0);
+ {
+ ret = pointer_int_sum (PLUS_EXPR, op1, op0);
+ goto return_build_binary_op;
+ }
else
common = 1;
break;
We must subtract them as integers, then divide by object size. */
if (code0 == POINTER_TYPE && code1 == POINTER_TYPE
&& comp_target_types (type0, type1))
- return pointer_diff (op0, op1);
+ {
+ ret = pointer_diff (op0, op1);
+ goto return_build_binary_op;
+ }
/* Handle pointer minus int. Just like pointer plus int. */
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
- return pointer_int_sum (MINUS_EXPR, op0, op1);
+ {
+ ret = pointer_int_sum (MINUS_EXPR, op0, op1);
+ goto return_build_binary_op;
+ }
else
common = 1;
break;
case FLOOR_DIV_EXPR:
case ROUND_DIV_EXPR:
case EXACT_DIV_EXPR:
- warn_for_div_by_zero (op1);
+ warn_for_div_by_zero (location, op1);
if ((code0 == INTEGER_TYPE || code0 == REAL_TYPE
|| code0 == FIXED_POINT_TYPE
case TRUNC_MOD_EXPR:
case FLOOR_MOD_EXPR:
- warn_for_div_by_zero (op1);
+ warn_for_div_by_zero (location, op1);
if (code0 == INTEGER_TYPE && code1 == INTEGER_TYPE)
{
but that does not mean the operands should be
converted to ints! */
result_type = integer_type_node;
- op0 = c_common_truthvalue_conversion (op0);
- op1 = c_common_truthvalue_conversion (op1);
+ op0 = c_common_truthvalue_conversion (location, op0);
+ op1 = c_common_truthvalue_conversion (location, op1);
converted = 1;
}
break;
case EQ_EXPR:
case NE_EXPR:
- if (code0 == REAL_TYPE || code1 == REAL_TYPE)
- warning (OPT_Wfloat_equal,
- "comparing floating point with == or != is unsafe");
+ if (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
+ warning_at (location,
+ OPT_Wfloat_equal,
+ "comparing floating point with == or != is unsafe");
/* Result of comparison is always int,
but don't convert the args to int! */
build_type = integer_type_node;
whose value is 0 but which isn't a valid null ptr const. */
if (pedantic && !null_pointer_constant_p (orig_op0)
&& TREE_CODE (tt1) == FUNCTION_TYPE)
- pedwarn ("ISO C forbids comparison of %<void *%>"
- " with function pointer");
+ pedwarn (location, OPT_pedantic, "ISO C forbids "
+ "comparison of %<void *%> with function pointer");
}
else if (VOID_TYPE_P (tt1))
{
if (pedantic && !null_pointer_constant_p (orig_op1)
&& TREE_CODE (tt0) == FUNCTION_TYPE)
- pedwarn ("ISO C forbids comparison of %<void *%>"
- " with function pointer");
+ pedwarn (location, OPT_pedantic, "ISO C forbids "
+ "comparison of %<void *%> with function pointer");
}
else
/* Avoid warning about the volatile ObjC EH puts on decls. */
if (!objc_ok)
- pedwarn ("comparison of distinct pointer types lacks a cast");
+ pedwarn (location, 0,
+ "comparison of distinct pointer types lacks a cast");
if (result_type == NULL_TREE)
result_type = ptr_type_node;
{
if (TREE_CODE (op0) == ADDR_EXPR
&& decl_with_nonnull_addr_p (TREE_OPERAND (op0, 0)))
- warning (OPT_Waddress, "the address of %qD will never be NULL",
- TREE_OPERAND (op0, 0));
+ warning_at (location,
+ 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_with_nonnull_addr_p (TREE_OPERAND (op1, 0)))
- warning (OPT_Waddress, "the address of %qD will never be NULL",
- TREE_OPERAND (op1, 0));
+ warning_at (location,
+ OPT_Waddress, "the address of %qD will never be NULL",
+ TREE_OPERAND (op1, 0));
result_type = type1;
}
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- pedwarn ("comparison between pointer and integer");
+ pedwarn (location, 0, "comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
- pedwarn ("comparison between pointer and integer");
+ pedwarn (location, 0, "comparison between pointer and integer");
}
break;
result_type = common_pointer_type (type0, type1);
if (!COMPLETE_TYPE_P (TREE_TYPE (type0))
!= !COMPLETE_TYPE_P (TREE_TYPE (type1)))
- pedwarn ("comparison of complete and incomplete pointers");
- else if (pedantic
- && TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
- pedwarn ("ISO C forbids ordered comparisons of pointers to functions");
+ pedwarn (location, 0,
+ "comparison of complete and incomplete pointers");
+ else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
+ pedwarn (location, OPT_pedantic, "ISO C forbids "
+ "ordered comparisons of pointers to functions");
}
else
{
result_type = ptr_type_node;
- pedwarn ("comparison of distinct pointer types lacks a cast");
+ pedwarn (location, 0,
+ "comparison of distinct pointer types lacks a cast");
}
}
else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
{
result_type = type0;
- if (pedantic || extra_warnings)
- pedwarn ("ordered comparison of pointer with integer zero");
+ if (pedantic)
+ pedwarn (location, OPT_pedantic,
+ "ordered comparison of pointer with integer zero");
+ else if (extra_warnings)
+ warning_at (location, OPT_Wextra,
+ "ordered comparison of pointer with integer zero");
}
else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
{
result_type = type1;
- if (pedantic)
- pedwarn ("ordered comparison of pointer with integer zero");
+ pedwarn (location, OPT_pedantic,
+ "ordered comparison of pointer with integer zero");
}
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- pedwarn ("comparison between pointer and integer");
+ pedwarn (location, 0, "comparison between pointer and integer");
}
else if (code0 == INTEGER_TYPE && code1 == POINTER_TYPE)
{
result_type = type1;
- pedwarn ("comparison between pointer and integer");
+ pedwarn (location, 0, "comparison between pointer and integer");
}
break;
|| !same_scalar_type_ignoring_signedness (TREE_TYPE (type0),
TREE_TYPE (type1))))
{
- binary_op_error (code, type0, type1);
+ binary_op_error (location, code, type0, type1);
return error_mark_node;
}
if (shorten && none_complex)
{
- int unsigned0, unsigned1;
- tree arg0, arg1;
- int uns;
- tree type;
-
- /* Cast OP0 and OP1 to RESULT_TYPE. Doing so prevents
- excessive narrowing when we call get_narrower below. For
- example, suppose that OP0 is of unsigned int extended
- from signed char and that RESULT_TYPE is long long int.
- If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
- like
-
- (long long int) (unsigned int) signed_char
-
- which get_narrower would narrow down to
-
- (unsigned int) signed char
-
- If we do not cast OP0 first, get_narrower would return
- signed_char, which is inconsistent with the case of the
- explicit cast. */
- op0 = convert (result_type, op0);
- op1 = convert (result_type, op1);
-
- arg0 = get_narrower (op0, &unsigned0);
- arg1 = get_narrower (op1, &unsigned1);
-
- /* UNS is 1 if the operation to be done is an unsigned one. */
- uns = TYPE_UNSIGNED (result_type);
-
final_type = result_type;
-
- /* Handle the case that OP0 (or OP1) does not *contain* a conversion
- but it *requires* conversion to FINAL_TYPE. */
-
- if ((TYPE_PRECISION (TREE_TYPE (op0))
- == TYPE_PRECISION (TREE_TYPE (arg0)))
- && TREE_TYPE (op0) != final_type)
- unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
- if ((TYPE_PRECISION (TREE_TYPE (op1))
- == TYPE_PRECISION (TREE_TYPE (arg1)))
- && TREE_TYPE (op1) != final_type)
- unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
-
- /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE. */
-
- /* For bitwise operations, signedness of nominal type
- does not matter. Consider only how operands were extended. */
- if (shorten == -1)
- uns = unsigned0;
-
- /* Note that in all three cases below we refrain from optimizing
- an unsigned operation on sign-extended args.
- That would not be valid. */
-
- /* Both args variable: if both extended in same way
- from same width, do it in that width.
- Do it unsigned if args were zero-extended. */
- if ((TYPE_PRECISION (TREE_TYPE (arg0))
- < TYPE_PRECISION (result_type))
- && (TYPE_PRECISION (TREE_TYPE (arg1))
- == TYPE_PRECISION (TREE_TYPE (arg0)))
- && unsigned0 == unsigned1
- && (unsigned0 || !uns))
- result_type
- = c_common_signed_or_unsigned_type
- (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
- else if (TREE_CODE (arg0) == INTEGER_CST
- && (unsigned1 || !uns)
- && (TYPE_PRECISION (TREE_TYPE (arg1))
- < TYPE_PRECISION (result_type))
- && (type
- = c_common_signed_or_unsigned_type (unsigned1,
- TREE_TYPE (arg1)))
- && !POINTER_TYPE_P (type)
- && int_fits_type_p (arg0, type))
- result_type = type;
- else if (TREE_CODE (arg1) == INTEGER_CST
- && (unsigned0 || !uns)
- && (TYPE_PRECISION (TREE_TYPE (arg0))
- < TYPE_PRECISION (result_type))
- && (type
- = c_common_signed_or_unsigned_type (unsigned0,
- TREE_TYPE (arg0)))
- && !POINTER_TYPE_P (type)
- && int_fits_type_p (arg1, type))
- result_type = type;
+ result_type = shorten_binary_op (result_type, op0, op1,
+ shorten == -1);
}
/* Shifts can be shortened if shifting right. */
= shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
if (val != 0)
- return val;
+ {
+ ret = val;
+ goto return_build_binary_op;
+ }
op0 = xop0, op1 = xop1;
converted = 1;
resultcode = xresultcode;
- if (warn_sign_compare && skip_evaluation == 0)
- {
- int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
- int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
- int unsignedp0, unsignedp1;
- tree primop0 = get_narrower (op0, &unsignedp0);
- tree primop1 = get_narrower (op1, &unsignedp1);
-
- xop0 = orig_op0;
- xop1 = orig_op1;
- STRIP_TYPE_NOPS (xop0);
- STRIP_TYPE_NOPS (xop1);
-
- /* Give warnings for comparisons between signed and unsigned
- quantities that may fail.
-
- Do the checking based on the original operand trees, so that
- casts will be considered, but default promotions won't be.
-
- Do not warn if the comparison is being done in a signed type,
- since the signed type will only be chosen if it can represent
- all the values of the unsigned type. */
- if (!TYPE_UNSIGNED (result_type))
- /* OK */;
- /* Do not warn if both operands are the same signedness. */
- else if (op0_signed == op1_signed)
- /* OK */;
- else
- {
- tree sop, uop;
- bool ovf;
-
- if (op0_signed)
- sop = xop0, uop = xop1;
- else
- sop = xop1, uop = xop0;
-
- /* Do not warn if the signed quantity is an
- unsuffixed integer literal (or some static
- constant expression involving such literals or a
- conditional expression involving such literals)
- and it is non-negative. */
- 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
- would fit in the result if the result were signed. */
- else if (TREE_CODE (uop) == INTEGER_CST
- && (resultcode == EQ_EXPR || resultcode == NE_EXPR)
- && int_fits_type_p
- (uop, c_common_signed_type (result_type)))
- /* OK */;
- /* Do not warn if the unsigned quantity is an enumeration
- constant and its maximum value would fit in the result
- if the result were signed. */
- else if (TREE_CODE (uop) == INTEGER_CST
- && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
- && int_fits_type_p
- (TYPE_MAX_VALUE (TREE_TYPE (uop)),
- c_common_signed_type (result_type)))
- /* OK */;
- else
- warning (OPT_Wsign_compare, "comparison between signed and unsigned");
- }
-
- /* Warn if two unsigned values are being compared in a size
- larger than their original size, and one (and only one) is the
- result of a `~' operator. This comparison will always fail.
-
- Also warn if one operand is a constant, and the constant
- does not have all bits set that are set in the ~ operand
- when it is extended. */
-
- if ((TREE_CODE (primop0) == BIT_NOT_EXPR)
- != (TREE_CODE (primop1) == BIT_NOT_EXPR))
- {
- if (TREE_CODE (primop0) == BIT_NOT_EXPR)
- primop0 = get_narrower (TREE_OPERAND (primop0, 0),
- &unsignedp0);
- else
- primop1 = get_narrower (TREE_OPERAND (primop1, 0),
- &unsignedp1);
-
- if (host_integerp (primop0, 0) || host_integerp (primop1, 0))
- {
- tree primop;
- HOST_WIDE_INT constant, mask;
- int unsignedp, bits;
-
- if (host_integerp (primop0, 0))
- {
- primop = primop1;
- unsignedp = unsignedp1;
- constant = tree_low_cst (primop0, 0);
- }
- else
- {
- primop = primop0;
- unsignedp = unsignedp0;
- constant = tree_low_cst (primop1, 0);
- }
-
- bits = TYPE_PRECISION (TREE_TYPE (primop));
- if (bits < TYPE_PRECISION (result_type)
- && bits < HOST_BITS_PER_WIDE_INT && unsignedp)
- {
- mask = (~(HOST_WIDE_INT) 0) << bits;
- if ((mask & constant) != mask)
- warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with constant");
- }
- }
- else if (unsignedp0 && unsignedp1
- && (TYPE_PRECISION (TREE_TYPE (primop0))
- < TYPE_PRECISION (result_type))
- && (TYPE_PRECISION (TREE_TYPE (primop1))
- < TYPE_PRECISION (result_type)))
- warning (OPT_Wsign_compare, "comparison of promoted ~unsigned with unsigned");
- }
+ if (warn_sign_compare && !skip_evaluation)
+ {
+ warn_for_sign_compare (location, orig_op0, orig_op1, op0, op1,
+ result_type, resultcode);
}
}
}
if (!result_type)
{
- binary_op_error (code, TREE_TYPE (op0), TREE_TYPE (op1));
+ binary_op_error (location, code, TREE_TYPE (op0), TREE_TYPE (op1));
return error_mark_node;
}
if (build_type == NULL_TREE)
build_type = result_type;
- {
- /* Treat expressions in initializers specially as they can't trap. */
- tree result = require_constant_value ? fold_build2_initializer (resultcode,
- build_type,
- op0, op1)
- : fold_build2 (resultcode, build_type,
- op0, op1);
-
- if (final_type != 0)
- result = convert (final_type, result);
- return result;
- }
+ /* Treat expressions in initializers specially as they can't trap. */
+ ret = require_constant_value ? fold_build2_initializer (resultcode,
+ build_type,
+ op0, op1)
+ : fold_build2 (resultcode, build_type,
+ op0, op1);
+ if (final_type != 0)
+ ret = convert (final_type, ret);
+
+ return_build_binary_op:
+ gcc_assert (ret != error_mark_node);
+ protected_set_expr_location (ret, location);
+ return ret;
}
/* Convert EXPR to be a truth-value, validating its type for this
- purpose. */
+ purpose. LOCATION is the source location for the expression. */
tree
-c_objc_common_truthvalue_conversion (tree expr)
+c_objc_common_truthvalue_conversion (location_t location, tree expr)
{
switch (TREE_CODE (TREE_TYPE (expr)))
{
case ARRAY_TYPE:
- error ("used array that cannot be converted to pointer where scalar is required");
+ error_at (location, "used array that cannot be converted to pointer where scalar is required");
return error_mark_node;
case RECORD_TYPE:
- error ("used struct type value where scalar is required");
+ error_at (location, "used struct type value where scalar is required");
return error_mark_node;
case UNION_TYPE:
- error ("used union type value where scalar is required");
+ error_at (location, "used union type value where scalar is required");
return error_mark_node;
case FUNCTION_TYPE:
/* ??? Should we also give an error for void and vectors rather than
leaving those to give errors later? */
- return c_common_truthvalue_conversion (expr);
+ return c_common_truthvalue_conversion (location, expr);
}
\f
required. */
tree
-c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED,
- bool *ti ATTRIBUTE_UNUSED, bool *se)
+c_expr_to_decl (tree expr, bool *tc ATTRIBUTE_UNUSED, bool *se)
{
if (TREE_CODE (expr) == COMPOUND_LITERAL_EXPR)
{
return block;
}
+/* Generate OMP_PARALLEL, with CLAUSES and BLOCK as its compound statement. */
+
tree
c_finish_omp_parallel (tree clauses, tree block)
{
return add_stmt (stmt);
}
+/* Like c_begin_compound_stmt, except force the retention of the BLOCK. */
+
+tree
+c_begin_omp_task (void)
+{
+ tree block;
+
+ keep_next_level ();
+ block = c_begin_compound_stmt (true);
+
+ return block;
+}
+
+/* Generate OMP_TASK, with CLAUSES and BLOCK as its compound statement. */
+
+tree
+c_finish_omp_task (tree clauses, tree block)
+{
+ tree stmt;
+
+ block = c_end_compound_stmt (block, true);
+
+ stmt = make_node (OMP_TASK);
+ TREE_TYPE (stmt) = void_type_node;
+ OMP_TASK_CLAUSES (stmt) = clauses;
+ OMP_TASK_BODY (stmt) = block;
+
+ return add_stmt (stmt);
+}
+
/* For all elements of CLAUSES, validate them vs OpenMP constraints.
Remove any elements from the list that are invalid. */
case OMP_CLAUSE_NOWAIT:
case OMP_CLAUSE_ORDERED:
case OMP_CLAUSE_DEFAULT:
+ case OMP_CLAUSE_UNTIED:
+ case OMP_CLAUSE_COLLAPSE:
pc = &OMP_CLAUSE_CHAIN (c);
continue;