/* 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.
diagnostic messages in convert_for_assignment. */
enum impl_conv {
ic_argpass,
- ic_argpass_nonproto,
ic_assign,
ic_init,
ic_return
static char *print_spelling (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);
/* 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.
\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) == 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 (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C forbids subscripting %<register%> array");
else if (!flag_isoc99 && !lvalue_p (foo))
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"ISO C90 forbids subscripting non-lvalue 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
/* 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 (TREE_CODE_CLASS (code1) != tcc_comparison)
warn_logical_operator (code, arg1.value, arg2.value);
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;
- pedwarn (input_location, OPT_pedantic,
+ 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;
- pedwarn (input_location, OPT_pedantic,
+ 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 (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 (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"wrong type argument to increment");
else
- pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ 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.
/* 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(LOCATION, OPT, AR, AS, IN, RE) \
- do { \
- switch (errtype) \
- { \
- case ic_argpass: \
- pedwarn (LOCATION, OPT, AR, parmnum, rname); \
- break; \
- case ic_argpass_nonproto: \
- warning (OPT, AR, parmnum, rname); \
- 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 (); \
- } \
+#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;
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",
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 (input_location,
+ WARN_FOR_ASSIGNMENT (input_location, 0,
G_("passing argument %d of %qE discards "
"qualifiers from pointer target type"),
G_("assignment discards qualifiers "
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 ();
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;
}
/* 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);
}
/* 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 (0, "initialized field with side-effects overwritten");
- else if (warn_override_init)
- warning_init (OPT_Woverride_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 (0, "initialized field with side-effects overwritten");
- else if (warn_override_init)
- warning_init (OPT_Woverride_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)
{
}
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;
&& 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 (0, "initialized field with side-effects overwritten");
- else if (warn_override_init)
- warning_init (OPT_Woverride_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;
}
{
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
{
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
{
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);
}
/* 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);
{
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);
{
switch (TREE_CODE (inner))
{
- CASE_CONVERT: case NON_LVALUE_EXPR:
+ CASE_CONVERT:
+ case NON_LVALUE_EXPR:
case PLUS_EXPR:
+ case POINTER_PLUS_EXPR:
inner = TREE_OPERAND (inner, 0);
continue;
&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);
\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 (FLOAT_TYPE_P (type0) || FLOAT_TYPE_P (type1))
- warning (OPT_Wfloat_equal,
- "comparing floating point with == or != is unsafe");
+ 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 (input_location, OPT_pedantic, "ISO C forbids "
+ 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 (input_location, OPT_pedantic, "ISO C forbids "
+ 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 (input_location, 0,
+ pedwarn (location, 0,
"comparison of distinct pointer types lacks a cast");
if (result_type == NULL_TREE)
{
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 (input_location, 0, "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 (input_location, 0, "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 (input_location, 0,
+ pedwarn (location, 0,
"comparison of complete and incomplete pointers");
else if (TREE_CODE (TREE_TYPE (type0)) == FUNCTION_TYPE)
- pedwarn (input_location, OPT_pedantic, "ISO C forbids "
+ pedwarn (location, OPT_pedantic, "ISO C forbids "
"ordered comparisons of pointers to functions");
}
else
{
result_type = ptr_type_node;
- pedwarn (input_location, 0,
+ pedwarn (location, 0,
"comparison of distinct pointer types lacks a cast");
}
}
{
result_type = type0;
if (pedantic)
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (location, OPT_pedantic,
"ordered comparison of pointer with integer zero");
else if (extra_warnings)
- warning (OPT_Wextra,
+ 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;
- pedwarn (input_location, OPT_pedantic,
+ pedwarn (location, OPT_pedantic,
"ordered comparison of pointer with integer zero");
}
else if (code0 == POINTER_TYPE && code1 == INTEGER_TYPE)
{
result_type = type0;
- pedwarn (input_location, 0, "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 (input_location, 0, "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;
}
= 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;
if (warn_sign_compare && !skip_evaluation)
{
- warn_for_sign_compare (orig_op0, orig_op1, op0, op1,
+ 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