#include "target.h"
#include "tree-iterator.h"
#include "bitmap.h"
-#include "pointer-set.h"
#include "basic-block.h"
#include "gimple-expr.h"
#include "gimplify.h"
#include "c-family/c-common.h"
#include "c-family/c-ubsan.h"
#include "cilk.h"
+#include "wide-int.h"
/* Possible cases of implicit bad conversions. Used to select
diagnostic messages in convert_for_assignment. */
if expr.original_code == SIZEOF_EXPR. */
tree c_last_sizeof_arg;
-/* Nonzero if we've already printed a "missing braces around initializer"
- message within this initializer. */
-static int missing_braces_mentioned;
+/* Nonzero if we might need to print a "missing braces around
+ initializer" message within this initializer. */
+static int found_missing_braces;
static int require_constant_value;
static int require_constant_elements;
bool *);
static int type_lists_compatible_p (const_tree, const_tree, bool *, bool *);
static tree lookup_field (tree, tree);
-static int convert_arguments (tree, vec<tree, va_gc> *, vec<tree, va_gc> *,
- tree, tree);
+static int convert_arguments (location_t, vec<location_t>, tree,
+ vec<tree, va_gc> *, vec<tree, va_gc> *, tree,
+ tree);
static tree pointer_diff (location_t, tree, tree);
-static tree convert_for_assignment (location_t, tree, tree, tree,
+static tree convert_for_assignment (location_t, location_t, tree, tree, tree,
enum impl_conv, bool, tree, tree, int);
static tree valid_compound_expr_initializer (tree, tree);
static void push_string (const char *);
static void push_member_name (tree);
static int spelling_length (void);
static char *print_spelling (char *);
-static void warning_init (int, const char *);
+static void warning_init (location_t, int, const char *);
static tree digest_init (location_t, tree, tree, tree, bool, bool, int);
-static void output_init_element (tree, tree, bool, tree, tree, int, bool,
- struct obstack *);
+static void output_init_element (location_t, tree, tree, bool, tree, tree, int,
+ bool, struct obstack *);
static void output_pending_init_elements (int, struct obstack *);
-static int set_designator (int, struct obstack *);
+static int set_designator (location_t, int, struct obstack *);
static void push_range_stack (tree, struct obstack *);
-static void add_pending_init (tree, tree, tree, bool, struct obstack *);
+static void add_pending_init (location_t, tree, tree, tree, bool,
+ struct obstack *);
static void set_nonincremental_init (struct obstack *);
static void set_nonincremental_init_from_string (tree, struct obstack *);
static tree find_init_member (tree, struct obstack *);
}
}
\f
-/* Compute the size to increment a pointer by. */
+/* Compute the size to increment a pointer by. When a function type or void
+ type or incomplete type is passed, size_one_node is returned.
+ This function does not emit any diagnostics; the caller is responsible
+ for that. */
static tree
c_size_in_bytes (const_tree type)
{
enum tree_code code = TREE_CODE (type);
- if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK)
+ if (code == FUNCTION_TYPE || code == VOID_TYPE || code == ERROR_MARK
+ || !COMPLETE_TYPE_P (type))
return size_one_node;
- if (!COMPLETE_OR_VOID_TYPE_P (type))
- {
- error ("arithmetic on pointer to an incomplete type");
- return size_one_node;
- }
-
/* Convert in case a char is more than one unit. */
return size_binop_loc (input_location, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
size_int (TYPE_PRECISION (char_type_node)
tmp = create_tmp_var (nonatomic_type, NULL);
tmp_addr = build_unary_op (loc, ADDR_EXPR, tmp, 0);
TREE_ADDRESSABLE (tmp) = 1;
+ TREE_NO_WARNING (tmp) = 1;
/* Issue __atomic_load (&expr, &tmp, SEQ_CST); */
fndecl = builtin_decl_explicit (BUILT_IN_ATOMIC_LOAD);
params->quick_push (expr_addr);
params->quick_push (tmp_addr);
params->quick_push (seq_cst);
- func_call = build_function_call_vec (loc, fndecl, params, NULL);
+ func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
+
+ /* EXPR is always read. */
+ mark_exp_read (exp.value);
/* Return tmp which contains the value loaded. */
exp.value = build2 (COMPOUND_EXPR, nonatomic_type, func_call, tmp);
if (code == VOID_TYPE)
{
- error ("void value not ignored as it ought to be");
+ error_at (EXPR_LOC_OR_LOC (exp, input_location),
+ "void value not ignored as it ought to be");
return error_mark_node;
}
|| TREE_TYPE (index) == error_mark_node)
return error_mark_node;
- if (flag_enable_cilkplus && contains_array_notation_expr (index))
+ if (flag_cilkplus && contains_array_notation_expr (index))
{
size_t rank = 0;
if (!find_rank (loc, index, index, true, &rank))
return error_mark_node;
}
- if (pedantic)
+ if (pedantic || warn_c90_c99_compat)
{
tree foo = array;
while (TREE_CODE (foo) == COMPONENT_REF)
if (TREE_CODE (foo) == VAR_DECL && C_DECL_REGISTER (foo))
pedwarn (loc, OPT_Wpedantic,
"ISO C forbids subscripting %<register%> array");
- else if (!flag_isoc99 && !lvalue_p (foo))
- pedwarn (loc, OPT_Wpedantic,
- "ISO C90 forbids subscripting non-lvalue array");
+ else if (!lvalue_p (foo))
+ pedwarn_c90 (loc, OPT_Wpedantic,
+ "ISO C90 forbids subscripting non-lvalue "
+ "array");
}
type = TREE_TYPE (TREE_TYPE (array));
else
{
bool expr_const_operands = true;
+
+ if (TREE_CODE (expr.value) == PARM_DECL
+ && C_ARRAY_PARAMETER (expr.value))
+ {
+ if (warning_at (loc, OPT_Wsizeof_array_argument,
+ "%<sizeof%> on array function parameter %qE will "
+ "return size of %qT", expr.value,
+ expr.original_type))
+ inform (DECL_SOURCE_LOCATION (expr.value), "declared here");
+ }
tree folded_expr = c_fully_fold (expr.value, require_constant_value,
&expr_const_operands);
ret.value = c_sizeof (loc, TREE_TYPE (folded_expr));
vec_alloc (v, list_length (params));
for (; params; params = TREE_CHAIN (params))
v->quick_push (TREE_VALUE (params));
- ret = build_function_call_vec (loc, function, v, NULL);
+ ret = c_build_function_call_vec (loc, vNULL, function, v, NULL);
vec_free (v);
return ret;
}
PARAMS. */
tree
-build_function_call_vec (location_t loc, tree function,
- vec<tree, va_gc> *params,
+build_function_call_vec (location_t loc, vec<location_t> arg_loc,
+ tree function, vec<tree, va_gc> *params,
vec<tree, va_gc> *origtypes)
{
tree fntype, fundecl = 0;
/* Convert anything with function type to a pointer-to-function. */
if (TREE_CODE (function) == FUNCTION_DECL)
{
- /* Implement type-directed function overloading for builtins.
- resolve_overloaded_builtin and targetm.resolve_overloaded_builtin
- handle all the type checking. The result is a complete expression
- that implements this function call. */
- tem = resolve_overloaded_builtin (loc, function, params);
- if (tem)
- return tem;
-
name = DECL_NAME (function);
if (flag_tm)
if (name && !strncmp (IDENTIFIER_POINTER (name), "__atomic_", 9))
origtypes = NULL;
- if (flag_enable_cilkplus
+ if (flag_cilkplus
&& is_cilkplus_reduce_builtin (function))
origtypes = NULL;
}
/* Convert the parameters to the types declared in the
function prototype, or apply default promotions. */
- nargs = convert_arguments (TYPE_ARG_TYPES (fntype), params, origtypes,
- function, fundecl);
+ nargs = convert_arguments (loc, arg_loc, TYPE_ARG_TYPES (fntype), params,
+ origtypes, function, fundecl);
if (nargs < 0)
return error_mark_node;
/* Check that the function is called through a compatible prototype.
- If it is not, replace the call by a trap, wrapped up in a compound
- 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 it is not, warn. */
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)))
{
tree return_type = TREE_TYPE (fntype);
- tree trap = build_function_call (loc,
- builtin_decl_explicit (BUILT_IN_TRAP),
- NULL_TREE);
- int i;
/* 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. */
- if (warning_at (loc, 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 (loc, "if this code is reached, the program will abort");
- /* Before the abort, allow the function arguments to exit or
- call longjmp. */
- for (i = 0; i < nargs; i++)
- trap = build2 (COMPOUND_EXPR, void_type_node, (*params)[i], trap);
-
- if (VOID_TYPE_P (return_type))
- {
- if (TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
- pedwarn (loc, 0,
- "function with qualified void return type called");
- return trap;
- }
- else
- {
- tree rhs;
+ warning_at (loc, 0, "function called through a non-compatible type");
- if (AGGREGATE_TYPE_P (return_type))
- rhs = build_compound_literal (loc, return_type,
- build_constructor (return_type,
- NULL),
- false);
- else
- rhs = build_zero_cst (return_type);
-
- return require_complete_type (build2 (COMPOUND_EXPR, return_type,
- trap, rhs));
- }
- }
+ if (VOID_TYPE_P (return_type)
+ && TYPE_QUALS (return_type) != TYPE_UNQUALIFIED)
+ pedwarn (loc, 0,
+ "function with qualified void return type called");
+ }
argarray = vec_safe_address (params);
}
return require_complete_type (result);
}
+
+/* Like build_function_call_vec, but call also resolve_overloaded_builtin. */
+
+tree
+c_build_function_call_vec (location_t loc, vec<location_t> arg_loc,
+ tree function, vec<tree, va_gc> *params,
+ vec<tree, va_gc> *origtypes)
+{
+ /* Strip NON_LVALUE_EXPRs, etc., since we aren't using as an lvalue. */
+ STRIP_TYPE_NOPS (function);
+
+ /* Convert anything with function type to a pointer-to-function. */
+ if (TREE_CODE (function) == FUNCTION_DECL)
+ {
+ /* Implement type-directed function overloading for builtins.
+ resolve_overloaded_builtin and targetm.resolve_overloaded_builtin
+ handle all the type checking. The result is a complete expression
+ that implements this function call. */
+ tree tem = resolve_overloaded_builtin (loc, function, params);
+ if (tem)
+ return tem;
+ }
+ return build_function_call_vec (loc, arg_loc, function, params, origtypes);
+}
\f
/* Convert the argument expressions in the vector VALUES
to the types in the list TYPELIST.
This is also where warnings about wrong number of args are generated.
+ ARG_LOC are locations of function arguments (if any).
+
Returns the actual number of arguments processed (which may be less
than the length of VALUES in some error situations), or -1 on
failure. */
static int
-convert_arguments (tree typelist, vec<tree, va_gc> *values,
- vec<tree, va_gc> *origtypes, tree function, tree fundecl)
+convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
+ vec<tree, va_gc> *values, vec<tree, va_gc> *origtypes,
+ tree function, tree fundecl)
{
tree typetail, val;
unsigned int parmnum;
bool error_args = false;
const bool type_generic = fundecl
- && lookup_attribute ("type generic", TYPE_ATTRIBUTES(TREE_TYPE (fundecl)));
+ && lookup_attribute ("type generic", TYPE_ATTRIBUTES (TREE_TYPE (fundecl)));
bool type_generic_remove_excess_precision = false;
tree selector;
break;
}
}
- if (flag_enable_cilkplus && fundecl && is_cilkplus_reduce_builtin (fundecl))
+ if (flag_cilkplus && fundecl && is_cilkplus_reduce_builtin (fundecl))
return vec_safe_length (values);
/* Scan the given expressions and types, producing individual
bool excess_precision = false;
bool npc;
tree parmval;
+ /* Some __atomic_* builtins have additional hidden argument at
+ position 0. */
+ location_t ploc
+ = !arg_loc.is_empty () && values->length () == arg_loc.length ()
+ ? expansion_point_location_if_in_system_header (arg_loc[parmnum])
+ : input_location;
if (type == void_type_node)
{
if (selector)
- error_at (input_location,
- "too many arguments to method %qE", selector);
+ error_at (loc, "too many arguments to method %qE", selector);
else
- error_at (input_location,
- "too many arguments to function %qE", function);
+ error_at (loc, "too many arguments to function %qE", function);
inform_declaration (fundecl);
return parmnum;
}
if (type == error_mark_node || !COMPLETE_TYPE_P (type))
{
- error ("type of formal parameter %d is incomplete", parmnum + 1);
+ error_at (ploc, "type of formal parameter %d is incomplete",
+ parmnum + 1);
parmval = val;
}
else
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (valtype) == REAL_TYPE)
- warning (0, "passing argument %d of %qE as integer "
- "rather than floating due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as integer rather "
+ "than floating due to prototype",
+ argnum, rname);
if (INTEGRAL_TYPE_P (type)
&& TREE_CODE (valtype) == COMPLEX_TYPE)
- warning (0, "passing argument %d of %qE as integer "
- "rather than complex due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as integer rather "
+ "than complex due to prototype",
+ argnum, rname);
else if (TREE_CODE (type) == COMPLEX_TYPE
&& TREE_CODE (valtype) == REAL_TYPE)
- warning (0, "passing argument %d of %qE as complex "
- "rather than floating due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as complex rather "
+ "than floating due to prototype",
+ argnum, rname);
else if (TREE_CODE (type) == REAL_TYPE
&& INTEGRAL_TYPE_P (valtype))
- warning (0, "passing argument %d of %qE as floating "
- "rather than integer due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as floating rather "
+ "than integer due to prototype",
+ argnum, rname);
else if (TREE_CODE (type) == COMPLEX_TYPE
&& INTEGRAL_TYPE_P (valtype))
- warning (0, "passing argument %d of %qE as complex "
- "rather than integer due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as complex rather "
+ "than integer due to prototype",
+ argnum, rname);
else if (TREE_CODE (type) == REAL_TYPE
&& TREE_CODE (valtype) == COMPLEX_TYPE)
- warning (0, "passing argument %d of %qE as floating "
- "rather than complex due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE as floating rather "
+ "than complex due to prototype",
+ argnum, rname);
/* ??? At some point, messages should be written about
conversions between complex types, but that's too messy
to do now. */
since without a prototype it would be `double'. */
if (formal_prec == TYPE_PRECISION (float_type_node)
&& type != dfloat32_type_node)
- warning (0, "passing argument %d of %qE as %<float%> "
- "rather than %<double%> due to prototype",
- argnum, rname);
+ warning_at (ploc, 0,
+ "passing argument %d of %qE as %<float%> "
+ "rather than %<double%> due to prototype",
+ argnum, rname);
/* Warn if mismatch between argument and prototype
for decimal float types. Warn of conversions with
|| (type == dfloat64_type_node
&& (valtype
!= dfloat32_type_node))))
- warning (0, "passing argument %d of %qE as %qT "
- "rather than %qT due to prototype",
- argnum, rname, type, valtype);
+ warning_at (ploc, 0,
+ "passing argument %d of %qE as %qT "
+ "rather than %qT due to prototype",
+ argnum, rname, type, valtype);
}
/* Detect integer changing in width or signedness.
and the actual arg is that enum type. */
;
else if (formal_prec != TYPE_PRECISION (type1))
- warning (OPT_Wtraditional_conversion,
- "passing argument %d of %qE "
- "with different width due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE "
+ "with different width due to prototype",
+ argnum, rname);
else if (TYPE_UNSIGNED (type) == TYPE_UNSIGNED (type1))
;
/* Don't complain if the formal parameter type
&& TYPE_UNSIGNED (valtype))
;
else if (TYPE_UNSIGNED (type))
- warning (OPT_Wtraditional_conversion,
- "passing argument %d of %qE "
- "as unsigned due to prototype",
- argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE "
+ "as unsigned due to prototype",
+ argnum, rname);
else
- warning (OPT_Wtraditional_conversion,
- "passing argument %d of %qE "
- "as signed due to prototype", argnum, rname);
+ warning_at (ploc, OPT_Wtraditional_conversion,
+ "passing argument %d of %qE "
+ "as signed due to prototype",
+ argnum, rname);
}
}
if (excess_precision)
val = build1 (EXCESS_PRECISION_EXPR, valtype, val);
origtype = (!origtypes) ? NULL_TREE : (*origtypes)[parmnum];
- parmval = convert_for_assignment (input_location, type, val,
- origtype, ic_argpass, npc,
- fundecl, function,
+ parmval = convert_for_assignment (loc, ploc, type,
+ val, origtype, ic_argpass,
+ npc, fundecl, function,
parmnum + 1);
if (targetm.calls.promote_prototypes (fundecl ? TREE_TYPE (fundecl) : 0)
{
/* Convert `float' to `double'. */
if (warn_double_promotion && !c_inhibit_evaluation_warnings)
- warning (OPT_Wdouble_promotion,
- "implicit conversion from %qT to %qT when passing "
- "argument to function",
- valtype, double_type_node);
+ warning_at (ploc, OPT_Wdouble_promotion,
+ "implicit conversion from %qT to %qT when passing "
+ "argument to function",
+ valtype, double_type_node);
parmval = convert (double_type_node, val);
}
}
if (typetail != 0 && TREE_VALUE (typetail) != void_type_node)
{
- error_at (input_location,
- "too few arguments to function %qE", function);
+ error_at (loc, "too few arguments to function %qE", function);
inform_declaration (fundecl);
return -1;
}
/* Check for cases such as x+y<<z which users are likely
to misinterpret. */
if (warn_parentheses)
- warn_about_parentheses (input_location, code,
- code1, arg1.value, code2, arg2.value);
+ warn_about_parentheses (location, code, code1, arg1.value, code2,
+ arg2.value);
if (warn_logical_op)
- warn_logical_operator (input_location, code, TREE_TYPE (result.value),
+ warn_logical_operator (location, code, TREE_TYPE (result.value),
code1, arg1.value, code2, arg2.value);
+ if (warn_logical_not_paren
+ && code1 == TRUTH_NOT_EXPR
+ && code2 != TRUTH_NOT_EXPR)
+ warn_logical_not_parentheses (location, code, arg1.value, arg2.value);
+
/* Warn about comparisons against string literals, with the exception
of testing for equality or inequality of a string literal with NULL. */
if (code == EQ_EXPR || code == NE_EXPR)
addr_space_t as0 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op0)));
addr_space_t as1 = TYPE_ADDR_SPACE (TREE_TYPE (TREE_TYPE (op1)));
tree target_type = TREE_TYPE (TREE_TYPE (op0));
- tree con0, con1, lit0, lit1;
tree orig_op1 = op1;
/* If the operands point into different address spaces, we need to
else
inttype = restype;
-
if (TREE_CODE (target_type) == VOID_TYPE)
pedwarn (loc, OPT_Wpointer_arith,
"pointer of type %<void *%> used in subtraction");
pedwarn (loc, 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
- that is in the way to do any simplifications.
- (fold-const.c doesn't know that the extra bits won't be needed.
- split_tree uses STRIP_SIGN_NOPS, which leaves conversions to a
- 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 (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 (CONVERT_EXPR_P (op1)
- && (TYPE_PRECISION (TREE_TYPE (op1))
- == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (op1, 0)))))
- con1 = TREE_OPERAND (op1, 0);
- else
- con1 = op1;
-
- if (TREE_CODE (con0) == POINTER_PLUS_EXPR)
- {
- lit0 = TREE_OPERAND (con0, 1);
- con0 = TREE_OPERAND (con0, 0);
- }
- else
- lit0 = integer_zero_node;
-
- if (TREE_CODE (con1) == POINTER_PLUS_EXPR)
- {
- lit1 = TREE_OPERAND (con1, 1);
- con1 = TREE_OPERAND (con1, 0);
- }
- else
- lit1 = integer_zero_node;
-
- if (operand_equal_p (con0, con1, 0))
- {
- op0 = lit0;
- op1 = lit1;
- }
-
-
/* First do the subtraction as integers;
then drop through to build the divide operator.
Do not do default conversions on the minus operator
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (TREE_TYPE (orig_op1))))
error_at (loc, "arithmetic on pointer to an incomplete type");
- /* This generates an error if op0 is pointer to incomplete type. */
op1 = c_size_in_bytes (target_type);
+ if (pointer_to_zero_sized_aggr_p (TREE_TYPE (orig_op1)))
+ error_at (loc, "arithmetic on pointer to an empty aggregate");
+
/* Divide by the size, in easiest possible way. */
result = fold_build2_loc (loc, EXACT_DIV_EXPR, inttype,
op0, convert (inttype, op1));
nonatomic_rhs_type = build_qualified_type (rhs_type, TYPE_UNQUALIFIED);
val = create_tmp_var (nonatomic_rhs_type, NULL);
TREE_ADDRESSABLE (val) = 1;
+ TREE_NO_WARNING (val) = 1;
rhs = build2 (MODIFY_EXPR, nonatomic_rhs_type, val, rhs);
SET_EXPR_LOCATION (rhs, loc);
add_stmt (rhs);
params->quick_push (lhs_addr);
params->quick_push (rhs);
params->quick_push (seq_cst);
- func_call = build_function_call_vec (loc, fndecl, params, NULL);
+ func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
add_stmt (func_call);
/* Finish the compound statement. */
/* Create the variables and labels required for the op= form. */
old = create_tmp_var (nonatomic_lhs_type, NULL);
old_addr = build_unary_op (loc, ADDR_EXPR, old, 0);
- TREE_ADDRESSABLE (val) = 1;
+ TREE_ADDRESSABLE (old) = 1;
+ TREE_NO_WARNING (old) = 1;
newval = create_tmp_var (nonatomic_lhs_type, NULL);
newval_addr = build_unary_op (loc, ADDR_EXPR, newval, 0);
params->quick_push (lhs_addr);
params->quick_push (old_addr);
params->quick_push (seq_cst);
- func_call = build_function_call_vec (loc, fndecl, params, NULL);
+ func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
add_stmt (func_call);
params->truncate (0);
/* newval = old + val; */
rhs = build_binary_op (loc, modifycode, old, val, 1);
- rhs = convert_for_assignment (loc, nonatomic_lhs_type, rhs, NULL_TREE,
- ic_assign, false, NULL_TREE,
+ rhs = convert_for_assignment (loc, UNKNOWN_LOCATION, nonatomic_lhs_type,
+ rhs, NULL_TREE, ic_assign, false, NULL_TREE,
NULL_TREE, 0);
if (rhs != error_mark_node)
{
params->quick_push (integer_zero_node);
params->quick_push (seq_cst);
params->quick_push (seq_cst);
- func_call = build_function_call_vec (loc, fndecl, params, NULL);
+ func_call = c_build_function_call_vec (loc, vNULL, fndecl, params, NULL);
goto_stmt = build1 (GOTO_EXPR, void_type_node, done_decl);
SET_EXPR_LOCATION (goto_stmt, loc);
if (typecode == POINTER_TYPE)
{
- /* If pointer target is an undefined struct,
+ /* If pointer target is an incomplete type,
we just cannot know how to do the arithmetic. */
if (!COMPLETE_OR_VOID_TYPE_P (TREE_TYPE (argtype)))
{
if (code == PREINCREMENT_EXPR || code == POSTINCREMENT_EXPR)
error_at (location,
- "increment of pointer to unknown structure");
+ "increment of pointer to an incomplete type %qT",
+ TREE_TYPE (argtype));
else
error_at (location,
- "decrement of pointer to unknown structure");
+ "decrement of pointer to an incomplete type %qT",
+ TREE_TYPE (argtype));
}
else if (TREE_CODE (TREE_TYPE (argtype)) == FUNCTION_TYPE
|| TREE_CODE (TREE_TYPE (argtype)) == VOID_TYPE)
the usual ones because of excess precision. */
static tree
-ep_convert_and_check (tree type, tree expr, tree semantic_type)
+ep_convert_and_check (location_t loc, tree type, tree expr,
+ tree semantic_type)
{
if (TREE_TYPE (expr) == type)
return expr;
if (!semantic_type)
- return convert_and_check (type, expr);
+ return convert_and_check (loc, type, expr);
if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
&& TREE_TYPE (expr) != semantic_type)
{
/* For integers, we need to check the real conversion, not
the conversion to the excess precision type. */
- expr = convert_and_check (semantic_type, expr);
+ expr = convert_and_check (loc, semantic_type, expr);
}
/* Result type is the excess precision type, which should be
large enough, so do not check. */
TYPE_READONLY (type1) || TYPE_READONLY (type2),
TYPE_VOLATILE (type1) || TYPE_VOLATILE (type2));
- op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
- op2 = ep_convert_and_check (result_type, op2, semantic_result_type);
+ op1 = ep_convert_and_check (colon_loc, result_type, op1,
+ semantic_result_type);
+ op2 = ep_convert_and_check (colon_loc, result_type, op2,
+ semantic_result_type);
if (ifexp_bcp && ifexp == truthvalue_true_node)
{
tree eptype = NULL_TREE;
tree ret;
- if (flag_enable_cilkplus
+ if (flag_cilkplus
&& (TREE_CODE (expr1) == CILK_SPAWN_STMT
|| TREE_CODE (expr2) == CILK_SPAWN_STMT))
{
"left-hand operand of comma expression has no effect");
}
}
+ else if (TREE_CODE (expr1) == COMPOUND_EXPR
+ && warn_unused_value)
+ {
+ tree r = expr1;
+ location_t cloc = loc;
+ while (TREE_CODE (r) == COMPOUND_EXPR)
+ {
+ if (EXPR_HAS_LOCATION (r))
+ cloc = EXPR_LOCATION (r);
+ r = TREE_OPERAND (r, 1);
+ }
+ if (!TREE_SIDE_EFFECTS (r)
+ && !VOID_TYPE_P (TREE_TYPE (r))
+ && !CONVERT_EXPR_P (r))
+ warning_at (cloc, OPT_Wunused_value,
+ "right-hand operand of comma expression has no effect");
+ }
/* With -Wunused, we should also warn if the left-hand operand does have
side-effects, but computes a value which is not used. For example, in
/* There are qualifiers present in IN_OTYPE that are not present
in IN_TYPE. */
warning_at (loc, OPT_Wcast_qual,
- "cast discards %q#v qualifier from pointer target type",
+ "cast discards %qv qualifier from pointer target type",
discarded);
if (added || discarded)
}
else if (TREE_OVERFLOW (value))
/* Reset VALUE's overflow flags, ensuring constant sharing. */
- value = build_int_cst_wide (TREE_TYPE (value),
- TREE_INT_CST_LOW (value),
- TREE_INT_CST_HIGH (value));
+ value = wide_int_to_tree (TREE_TYPE (value), value);
}
}
newrhs = c_fully_fold (newrhs, false, NULL);
if (rhs_semantic_type)
newrhs = build1 (EXCESS_PRECISION_EXPR, rhs_semantic_type, newrhs);
- newrhs = convert_for_assignment (location, lhstype, newrhs, rhs_origtype,
- ic_assign, npc, NULL_TREE,
- NULL_TREE, 0);
+ newrhs = convert_for_assignment (location, rhs_loc, lhstype, newrhs,
+ rhs_origtype, ic_assign, npc,
+ NULL_TREE, NULL_TREE, 0);
if (TREE_CODE (newrhs) == ERROR_MARK)
return error_mark_node;
}
if (olhstype == TREE_TYPE (result))
goto return_result;
- result = convert_for_assignment (location, olhstype, result, rhs_origtype,
- ic_assign, false, NULL_TREE, NULL_TREE, 0);
+ result = convert_for_assignment (location, rhs_loc, olhstype, result,
+ rhs_origtype, ic_assign, false, NULL_TREE,
+ NULL_TREE, 0);
protected_set_expr_location (result, location);
return_result:
return ret;
}
+/* Issue an error message for a bad initializer component.
+ GMSGID identifies the message.
+ The component name is taken from the spelling stack. */
+
+static void
+error_init (location_t loc, const char *gmsgid)
+{
+ char *ofwhat;
+
+ /* The gmsgid may be a format string with %< and %>. */
+ error_at (loc, gmsgid);
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+ if (*ofwhat)
+ inform (loc, "(near initialization for %qs)", ofwhat);
+}
+
+/* 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. GMSGID identifies the message. The
+ component name is taken from the spelling stack. */
+
+static void
+pedwarn_init (location_t location, int opt, const char *gmsgid)
+{
+ char *ofwhat;
+ bool warned;
+
+ /* The gmsgid may be a format string with %< and %>. */
+ warned = pedwarn (location, opt, gmsgid);
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+ if (*ofwhat && warned)
+ inform (location, "(near initialization for %qs)", ofwhat);
+}
+
+/* Issue a warning for a bad initializer component.
+
+ OPT is the OPT_W* value corresponding to the warning option that
+ controls this warning. GMSGID identifies the message. The
+ component name is taken from the spelling stack. */
+
+static void
+warning_init (location_t loc, int opt, const char *gmsgid)
+{
+ char *ofwhat;
+ bool warned;
+
+ /* The gmsgid may be a format string with %< and %>. */
+ warned = warning_at (loc, opt, gmsgid);
+ ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
+ if (*ofwhat && warned)
+ inform (loc, "(near initialization for %qs)", ofwhat);
+}
+\f
+/* If TYPE is an array type and EXPR is a parenthesized string
+ constant, warn if pedantic that EXPR is being used to initialize an
+ object of type TYPE. */
+
+void
+maybe_warn_string_init (location_t loc, tree type, struct c_expr expr)
+{
+ if (pedantic
+ && TREE_CODE (type) == ARRAY_TYPE
+ && TREE_CODE (expr.value) == STRING_CST
+ && expr.original_code != STRING_CST)
+ pedwarn_init (loc, OPT_Wpedantic,
+ "array initialized from parenthesized string constant");
+}
+
/* Convert value RHS to type TYPE as preparation for an assignment to
an lvalue of type TYPE. If ORIGTYPE is not NULL_TREE, it is the
original type of RHS; this differs from TREE_TYPE (RHS) for enum
ERRTYPE says whether it is argument passing, assignment,
initialization or return.
- LOCATION is the location of the RHS.
+ LOCATION is the location of the assignment, EXPR_LOC is the location of
+ the RHS or, for a function, location of an argument.
FUNCTION is a tree for the function being called.
PARMNUM is the number of the argument, for printing in error messages. */
static tree
-convert_for_assignment (location_t location, tree type, tree rhs,
- tree origtype, enum impl_conv errtype,
+convert_for_assignment (location_t location, location_t expr_loc, tree type,
+ tree rhs, tree origtype, enum impl_conv errtype,
bool null_pointer_constant, tree fundecl,
tree function, int parmnum)
{
/* 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) \
+#define WARN_FOR_ASSIGNMENT(LOCATION, PLOC, OPT, AR, AS, IN, RE) \
do { \
switch (errtype) \
{ \
case ic_argpass: \
- if (pedwarn (LOCATION, OPT, AR, parmnum, rname)) \
+ if (pedwarn (PLOC, OPT, AR, parmnum, rname)) \
inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
- ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \
+ ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
"expected %qT but argument is of type %qT", \
type, rhstype); \
break; \
pedwarn_init (LOCATION, OPT, IN); \
break; \
case ic_return: \
- pedwarn (LOCATION, OPT, RE); \
+ pedwarn (LOCATION, OPT, RE); \
break; \
default: \
gcc_unreachable (); \
compile time. It is the same as WARN_FOR_ASSIGNMENT but with an
extra parameter to enumerate qualifiers. */
-#define WARN_FOR_QUALIFIERS(LOCATION, OPT, AR, AS, IN, RE, QUALS) \
+#define WARN_FOR_QUALIFIERS(LOCATION, PLOC, OPT, AR, AS, IN, RE, QUALS) \
do { \
switch (errtype) \
{ \
case ic_argpass: \
- if (pedwarn (LOCATION, OPT, AR, parmnum, rname, QUALS)) \
+ if (pedwarn (PLOC, OPT, AR, parmnum, rname, QUALS)) \
inform ((fundecl && !DECL_IS_BUILTIN (fundecl)) \
- ? DECL_SOURCE_LOCATION (fundecl) : LOCATION, \
+ ? DECL_SOURCE_LOCATION (fundecl) : PLOC, \
"expected %qT but argument is of type %qT", \
type, rhstype); \
break; \
case ic_assign: \
- pedwarn (LOCATION, OPT, AS, QUALS); \
+ pedwarn (LOCATION, OPT, AS, QUALS); \
break; \
case ic_init: \
- pedwarn (LOCATION, OPT, IN, QUALS); \
+ pedwarn (LOCATION, OPT, IN, QUALS); \
break; \
case ic_return: \
- pedwarn (LOCATION, OPT, RE, QUALS); \
+ pedwarn (LOCATION, OPT, RE, QUALS); \
break; \
default: \
gcc_unreachable (); \
&& TREE_CODE (type) == ENUMERAL_TYPE
&& TYPE_MAIN_VARIANT (checktype) != TYPE_MAIN_VARIANT (type))
{
- WARN_FOR_ASSIGNMENT (input_location, OPT_Wc___compat,
+ WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wc___compat,
G_("enum conversion when passing argument "
"%d of %qE is invalid in C++"),
G_("enum conversion in assignment is "
rhs = build1 (ADDR_EXPR, build_pointer_type (TREE_TYPE (rhs)), rhs);
SET_EXPR_LOCATION (rhs, location);
- rhs = convert_for_assignment (location, build_pointer_type (TREE_TYPE (type)),
- rhs, origtype, errtype, null_pointer_constant,
- fundecl, function, parmnum);
+ rhs = convert_for_assignment (location, expr_loc,
+ build_pointer_type (TREE_TYPE (type)),
+ rhs, origtype, errtype,
+ null_pointer_constant, fundecl, function,
+ parmnum);
if (rhs == error_mark_node)
return error_mark_node;
bool save = in_late_binary_op;
if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
in_late_binary_op = true;
- ret = convert_and_check (type, orig_rhs);
+ ret = convert_and_check (expr_loc != UNKNOWN_LOCATION
+ ? expr_loc : location, type, orig_rhs);
if (codel == BOOLEAN_TYPE || codel == COMPLEX_TYPE)
in_late_binary_op = save;
return ret;
if ((codel == RECORD_TYPE || codel == UNION_TYPE)
&& codel == coder
&& comptypes (type, rhstype))
- return convert_and_check (type, rhs);
+ return convert_and_check (expr_loc != UNKNOWN_LOCATION
+ ? expr_loc : location, type, rhs);
/* Conversion to a transparent union or record from its member types.
This applies only to function arguments. */
vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- WARN_FOR_QUALIFIERS (location, 0,
+ WARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE "
"makes %q#v qualified function "
"pointer from unqualified"),
}
else if (TYPE_QUALS_NO_ADDR_SPACE (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttl))
- WARN_FOR_QUALIFIERS (location, 0,
+ WARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE discards "
"%qv qualifier from pointer target type"),
G_("assignment discards %qv qualifier "
where NULL is typically defined in C to be '(void *) 0'. */
if (VOID_TYPE_P (ttr) && rhs != null_pointer_node && !VOID_TYPE_P (ttl))
- warning_at (location, OPT_Wc___compat,
- "request for implicit conversion "
+ warning_at (errtype == ic_argpass ? expr_loc : location,
+ OPT_Wc___compat,
+ "request for implicit conversion "
"from %qT to %qT not permitted in C++", rhstype, type);
/* See if the pointers point to incompatible address spaces. */
switch (errtype)
{
case ic_argpass:
- error_at (location, "passing argument %d of %qE from pointer to "
+ error_at (expr_loc, "passing argument %d of %qE from pointer to "
"non-enclosed address space", parmnum, rname);
break;
case ic_assign:
switch (errtype)
{
case ic_argpass:
- warning_at (location, OPT_Wsuggest_attribute_format,
+ warning_at (expr_loc, OPT_Wsuggest_attribute_format,
"argument %d of %qE might be "
"a candidate for a format attribute",
parmnum, rname);
(VOID_TYPE_P (ttr)
&& !null_pointer_constant
&& TREE_CODE (ttl) == FUNCTION_TYPE)))
- WARN_FOR_ASSIGNMENT (location, OPT_Wpedantic,
+ WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpedantic,
G_("ISO C forbids passing argument %d of "
"%qE between function pointer "
"and %<void *%>"),
if (TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttr)
& ~TYPE_QUALS_NO_ADDR_SPACE_NO_ATOMIC (ttl))
{
- WARN_FOR_QUALIFIERS (location, 0,
+ WARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE discards "
"%qv qualifier from pointer target type"),
G_("assignment discards %qv qualifier "
;
/* If there is a mismatch, do warn. */
else if (warn_pointer_sign)
- WARN_FOR_ASSIGNMENT (location, OPT_Wpointer_sign,
+ WARN_FOR_ASSIGNMENT (location, expr_loc, OPT_Wpointer_sign,
G_("pointer targets in passing argument "
"%d of %qE differ in signedness"),
G_("pointer targets in assignment "
where an ordinary one is wanted, but not vice-versa. */
if (TYPE_QUALS_NO_ADDR_SPACE (ttl)
& ~TYPE_QUALS_NO_ADDR_SPACE (ttr))
- WARN_FOR_QUALIFIERS (location, 0,
+ WARN_FOR_QUALIFIERS (location, expr_loc,
+ OPT_Wdiscarded_qualifiers,
G_("passing argument %d of %qE makes "
"%q#v qualified function pointer "
"from unqualified"),
else
/* Avoid warning about the volatile ObjC EH puts on decls. */
if (!objc_ok)
- WARN_FOR_ASSIGNMENT (location, 0,
+ WARN_FOR_ASSIGNMENT (location, expr_loc,
+ OPT_Wincompatible_pointer_types,
G_("passing argument %d of %qE from "
"incompatible pointer type"),
G_("assignment from incompatible pointer type"),
or one that results from arithmetic, even including
a cast to integer type. */
if (!null_pointer_constant)
- WARN_FOR_ASSIGNMENT (location, 0,
+ WARN_FOR_ASSIGNMENT (location, expr_loc,
+ OPT_Wint_conversion,
G_("passing argument %d of %qE makes "
"pointer from integer without a cast"),
G_("assignment makes pointer from integer "
}
else if (codel == INTEGER_TYPE && coder == POINTER_TYPE)
{
- WARN_FOR_ASSIGNMENT (location, 0,
+ WARN_FOR_ASSIGNMENT (location, expr_loc,
+ OPT_Wint_conversion,
G_("passing argument %d of %qE makes integer "
"from pointer without a cast"),
G_("assignment makes integer from pointer "
switch (errtype)
{
case ic_argpass:
- error_at (location, "incompatible type for argument %d of %qE", parmnum, rname);
+ error_at (expr_loc, "incompatible type for argument %d of %qE", parmnum,
+ rname);
inform ((fundecl && !DECL_IS_BUILTIN (fundecl))
- ? DECL_SOURCE_LOCATION (fundecl) : input_location,
+ ? DECL_SOURCE_LOCATION (fundecl) : expr_loc,
"expected %qT but argument is of type %qT", type, rhstype);
break;
case ic_assign:
break;
case ic_init:
error_at (location,
- "incompatible types when initializing type %qT using type %qT",
+ "incompatible types when initializing type %qT using type %qT",
type, rhstype);
break;
case ic_return:
error_at (location,
- "incompatible types when returning type %qT but %qT was "
+ "incompatible types when returning type %qT but %qT was "
"expected", rhstype, type);
break;
default:
return buffer;
}
-/* Issue an error message for a bad initializer component.
- GMSGID identifies the message.
- The component name is taken from the spelling stack. */
-
-void
-error_init (const char *gmsgid)
-{
- char *ofwhat;
-
- /* The gmsgid may be a format string with %< and %>. */
- error (gmsgid);
- ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
- if (*ofwhat)
- error ("(near initialization for %qs)", ofwhat);
-}
-
-/* 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. GMSGID identifies the message. The
- component name is taken from the spelling stack. */
-
-void
-pedwarn_init (location_t location, int opt, const char *gmsgid)
-{
- char *ofwhat;
-
- /* The gmsgid may be a format string with %< and %>. */
- pedwarn (location, opt, gmsgid);
- ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
- if (*ofwhat)
- pedwarn (location, opt, "(near initialization for %qs)", ofwhat);
-}
-
-/* Issue a warning for a bad initializer component.
-
- OPT is the OPT_W* value corresponding to the warning option that
- controls this warning. GMSGID identifies the message. The
- component name is taken from the spelling stack. */
-
-static void
-warning_init (int opt, const char *gmsgid)
-{
- char *ofwhat;
-
- /* The gmsgid may be a format string with %< and %>. */
- warning (opt, gmsgid);
- ofwhat = print_spelling ((char *) alloca (spelling_length () + 1));
- if (*ofwhat)
- warning (opt, "(near initialization for %qs)", ofwhat);
-}
-\f
-/* If TYPE is an array type and EXPR is a parenthesized string
- constant, warn if pedantic that EXPR is being used to initialize an
- object of type TYPE. */
-
-void
-maybe_warn_string_init (tree type, struct c_expr expr)
-{
- if (pedantic
- && TREE_CODE (type) == ARRAY_TYPE
- && TREE_CODE (expr.value) == STRING_CST
- && expr.original_code != STRING_CST)
- pedwarn_init (input_location, OPT_Wpedantic,
- "array initialized from parenthesized string constant");
-}
-
/* Digest the parser output INIT as an initializer for type TYPE.
Return a C expression of type TYPE to represent the initial value.
expr.value = inside_init;
expr.original_code = (strict_string ? STRING_CST : ERROR_MARK);
expr.original_type = NULL;
- maybe_warn_string_init (type, expr);
+ maybe_warn_string_init (init_loc, type, expr);
if (TYPE_DOMAIN (type) && !TYPE_MAX_VALUE (TYPE_DOMAIN (type)))
pedwarn_init (init_loc, OPT_Wpedantic,
{
if (typ2 != char_type_node)
{
- error_init ("char-array initialized from wide string");
+ error_init (init_loc, "char-array initialized from wide "
+ "string");
return error_mark_node;
}
}
{
if (typ2 == char_type_node)
{
- error_init ("wide character array initialized from non-wide "
- "string");
+ error_init (init_loc, "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");
+ error_init (init_loc, "wide character array initialized "
+ "from incompatible wide string");
return error_mark_node;
}
}
}
else if (INTEGRAL_TYPE_P (typ1))
{
- error_init ("array of inappropriate type initialized "
+ error_init (init_loc, "array of inappropriate type initialized "
"from string constant");
return error_mark_node;
}
(init_loc, inside_init);
else
{
- error_init ("invalid use of non-lvalue array");
+ error_init (init_loc, "invalid use of non-lvalue array");
return error_mark_node;
}
}
if (code == ARRAY_TYPE && TREE_CODE (inside_init) != STRING_CST
&& TREE_CODE (inside_init) != CONSTRUCTOR)
{
- error_init ("array initialized from non-constant array expression");
+ error_init (init_loc, "array initialized from non-constant array "
+ "expression");
return error_mark_node;
}
= valid_compound_expr_initializer (inside_init,
TREE_TYPE (inside_init));
if (inside_init == error_mark_node)
- error_init ("initializer element is not constant");
+ error_init (init_loc, "initializer element is not constant");
else
pedwarn_init (init_loc, OPT_Wpedantic,
"initializer element is not constant");
&& !initializer_constant_valid_p (inside_init,
TREE_TYPE (inside_init)))
{
- error_init ("initializer element is not constant");
+ error_init (init_loc, "initializer element is not constant");
inside_init = error_mark_node;
}
else if (require_constant && !maybe_const)
/* Added to enable additional -Wsuggest-attribute=format warnings. */
if (TREE_CODE (TREE_TYPE (inside_init)) == POINTER_TYPE)
- inside_init = convert_for_assignment (init_loc, type, inside_init,
- origtype,
+ inside_init = convert_for_assignment (init_loc, UNKNOWN_LOCATION,
+ type, inside_init, origtype,
ic_init, null_pointer_constant,
NULL_TREE, NULL_TREE, 0);
return inside_init;
inside_init = build1 (EXCESS_PRECISION_EXPR, semantic_type,
inside_init);
inside_init
- = convert_for_assignment (init_loc, type, inside_init, origtype,
- ic_init, null_pointer_constant,
- NULL_TREE, NULL_TREE, 0);
+ = convert_for_assignment (init_loc, UNKNOWN_LOCATION, type,
+ inside_init, origtype, ic_init,
+ null_pointer_constant, NULL_TREE, NULL_TREE,
+ 0);
/* Check to see if we have already given an error message. */
if (inside_init == error_mark_node)
;
else if (require_constant && !TREE_CONSTANT (inside_init))
{
- error_init ("initializer element is not constant");
+ error_init (init_loc, "initializer element is not constant");
inside_init = error_mark_node;
}
else if (require_constant
&& !initializer_constant_valid_p (inside_init,
TREE_TYPE (inside_init)))
{
- error_init ("initializer element is not computable at load time");
+ error_init (init_loc, "initializer element is not computable at "
+ "load time");
inside_init = error_mark_node;
}
else if (require_constant && !maybe_const)
if (COMPLETE_TYPE_P (type) && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
{
- error_init ("variable-sized object may not be initialized");
+ error_init (init_loc, "variable-sized object may not be initialized");
return error_mark_node;
}
- error_init ("invalid initializer");
+ error_init (init_loc, "invalid initializer");
return error_mark_node;
}
\f
/* 1 if this constructor is erroneous so far. */
static int constructor_erroneous;
+/* 1 if this constructor is the universal zero initializer { 0 }. */
+static int constructor_zeroinit;
+
/* Structure for managing pending initializer elements, organized as an
AVL tree. */
char outer;
char incremental;
char designated;
+ int designator_depth;
};
static struct constructor_stack *constructor_stack;
constructor_stack = 0;
constructor_range_stack = 0;
- missing_braces_mentioned = 0;
+ found_missing_braces = 0;
spelling_base = 0;
spelling_size = 0;
p->outer = 0;
p->incremental = constructor_incremental;
p->designated = constructor_designated;
+ p->designator_depth = designator_depth;
p->next = 0;
constructor_stack = p;
constructor_type = type;
constructor_incremental = 1;
constructor_designated = 0;
+ constructor_zeroinit = 1;
designator_depth = 0;
designator_erroneous = 0;
IMPLICIT is 1 (or 2 if the push is because of designator list). */
void
-push_init_level (int implicit, struct obstack * braced_init_obstack)
+push_init_level (location_t loc, int implicit,
+ struct obstack *braced_init_obstack)
{
struct constructor_stack *p;
tree value = NULL_TREE;
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
- process_init_element (pop_init_level (1, braced_init_obstack),
+ process_init_element (input_location,
+ pop_init_level (loc, 1, braced_init_obstack),
true, braced_init_obstack);
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, braced_init_obstack),
+ process_init_element (input_location,
+ pop_init_level (loc, 1, braced_init_obstack),
true, braced_init_obstack);
else
break;
p->outer = 0;
p->incremental = constructor_incremental;
p->designated = constructor_designated;
+ p->designator_depth = designator_depth;
p->next = constructor_stack;
p->range_stack = 0;
constructor_stack = p;
push_member_name (constructor_fields);
constructor_depth++;
}
+ /* If upper initializer is designated, then mark this as
+ designated too to prevent bogus warnings. */
+ constructor_designated = p->designated;
}
else if (TREE_CODE (constructor_type) == ARRAY_TYPE)
{
if (constructor_type == 0)
{
- error_init ("extra brace group at end of initializer");
+ error_init (loc, "extra brace group at end of initializer");
constructor_fields = 0;
constructor_unfilled_fields = 0;
return;
set_nonincremental_init (braced_init_obstack);
}
- if (implicit == 1 && warn_missing_braces && !missing_braces_mentioned)
- {
- missing_braces_mentioned = 1;
- warning_init (OPT_Wmissing_braces, "missing braces around initializer");
- }
+ if (implicit == 1)
+ found_missing_braces = 1;
if (TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
else
{
if (constructor_type != error_mark_node)
- warning_init (0, "braces around scalar initializer");
+ warning_init (input_location, 0, "braces around scalar initializer");
constructor_fields = constructor_type;
constructor_unfilled_fields = constructor_type;
}
Otherwise, return a CONSTRUCTOR expression as the value. */
struct c_expr
-pop_init_level (int implicit, struct obstack * braced_init_obstack)
+pop_init_level (location_t loc, int implicit,
+ struct obstack *braced_init_obstack)
{
struct constructor_stack *p;
struct c_expr ret;
/* 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, braced_init_obstack),
- true, braced_init_obstack);
- }
+ process_init_element (input_location,
+ pop_init_level (loc, 1, braced_init_obstack),
+ true, braced_init_obstack);
gcc_assert (!constructor_range_stack);
}
gcc_assert (!TYPE_SIZE (constructor_type));
if (constructor_depth > 2)
- error_init ("initialization of flexible array member in a nested context");
+ error_init (loc, "initialization of flexible array member in a nested context");
else
- pedwarn_init (input_location, OPT_Wpedantic,
+ pedwarn_init (loc, OPT_Wpedantic,
"initialization of a flexible array member");
/* We have already issued an error message for the existence
}
}
+ if (vec_safe_length (constructor_elements) != 1)
+ constructor_zeroinit = 0;
+
+ /* Warn when some structs are initialized with direct aggregation. */
+ if (!implicit && found_missing_braces && warn_missing_braces
+ && !constructor_zeroinit)
+ {
+ warning_init (loc, OPT_Wmissing_braces,
+ "missing braces around initializer");
+ }
+
/* Warn when some struct elements are implicitly initialized to zero. */
if (warn_missing_field_initializers
&& constructor_type
&& TREE_CODE (constructor_type) == RECORD_TYPE
&& constructor_unfilled_fields)
{
- bool constructor_zeroinit =
- (vec_safe_length (constructor_elements) == 1
- && integer_zerop ((*constructor_elements)[0].value));
-
/* Do not warn for flexible array members or zero-length arrays. */
while (constructor_unfilled_fields
&& (!DECL_SIZE (constructor_unfilled_fields)
if (vec_safe_is_empty (constructor_elements))
{
if (!constructor_erroneous)
- error_init ("empty scalar initializer");
+ error_init (loc, "empty scalar initializer");
ret.value = error_mark_node;
}
else if (vec_safe_length (constructor_elements) != 1)
{
- error_init ("extra elements in scalar initializer");
+ error_init (loc, "extra elements in scalar initializer");
ret.value = (*constructor_elements)[0].value;
}
else
constructor_erroneous = p->erroneous;
constructor_incremental = p->incremental;
constructor_designated = p->designated;
+ designator_depth = p->designator_depth;
constructor_pending_elts = p->pending_elts;
constructor_depth = p->depth;
if (!p->implicit)
ARRAY argument is nonzero for array ranges. Returns zero for success. */
static int
-set_designator (int array, struct obstack * braced_init_obstack)
+set_designator (location_t loc, int array,
+ struct obstack *braced_init_obstack)
{
tree subtype;
enum tree_code subcode;
/* Designator list starts at the level of closest explicit
braces. */
while (constructor_stack->implicit)
- {
- process_init_element (pop_init_level (1, braced_init_obstack),
- true, braced_init_obstack);
- }
+ process_init_element (input_location,
+ pop_init_level (loc, 1, braced_init_obstack),
+ true, braced_init_obstack);
constructor_designated = 1;
return 0;
}
subcode = TREE_CODE (subtype);
if (array && subcode != ARRAY_TYPE)
{
- error_init ("array index in non-array initializer");
+ error_init (loc, "array index in non-array initializer");
return 1;
}
else if (!array && subcode != RECORD_TYPE && subcode != UNION_TYPE)
{
- error_init ("field name not in record or union initializer");
+ error_init (loc, "field name not in record or union initializer");
return 1;
}
constructor_designated = 1;
- push_init_level (2, braced_init_obstack);
+ push_init_level (loc, 2, braced_init_obstack);
return 0;
}
of indices, running from FIRST through LAST. */
void
-set_init_index (tree first, tree last,
- struct obstack * braced_init_obstack)
+set_init_index (location_t loc, tree first, tree last,
+ struct obstack *braced_init_obstack)
{
- if (set_designator (1, braced_init_obstack))
+ if (set_designator (loc, 1, braced_init_obstack))
return;
designator_erroneous = 1;
if (!INTEGRAL_TYPE_P (TREE_TYPE (first))
|| (last && !INTEGRAL_TYPE_P (TREE_TYPE (last))))
{
- error_init ("array index in initializer not of integer type");
+ error_init (loc, "array index in initializer not of integer type");
return;
}
{
first = c_fully_fold (first, false, NULL);
if (TREE_CODE (first) == INTEGER_CST)
- pedwarn_init (input_location, OPT_Wpedantic,
+ pedwarn_init (loc, OPT_Wpedantic,
"array index in initializer is not "
"an integer constant expression");
}
{
last = c_fully_fold (last, false, NULL);
if (TREE_CODE (last) == INTEGER_CST)
- pedwarn_init (input_location, OPT_Wpedantic,
+ pedwarn_init (loc, OPT_Wpedantic,
"array index in initializer is not "
"an integer constant expression");
}
if (TREE_CODE (first) != INTEGER_CST)
- error_init ("nonconstant array index in initializer");
+ error_init (loc, "nonconstant array index in initializer");
else if (last != 0 && TREE_CODE (last) != INTEGER_CST)
- error_init ("nonconstant array index in initializer");
+ error_init (loc, "nonconstant array index in initializer");
else if (TREE_CODE (constructor_type) != ARRAY_TYPE)
- error_init ("array index in non-array initializer");
+ error_init (loc, "array index in non-array initializer");
else if (tree_int_cst_sgn (first) == -1)
- error_init ("array index in initializer exceeds array bounds");
+ error_init (loc, "array index in initializer exceeds array bounds");
else if (constructor_max_index
&& tree_int_cst_lt (constructor_max_index, first))
- error_init ("array index in initializer exceeds array bounds");
+ error_init (loc, "array index in initializer exceeds array bounds");
else
{
constant_expression_warning (first);
last = 0;
else if (tree_int_cst_lt (last, first))
{
- error_init ("empty index range in initializer");
+ error_init (loc, "empty index range in initializer");
last = 0;
}
else
if (constructor_max_index != 0
&& tree_int_cst_lt (constructor_max_index, last))
{
- error_init ("array index range in initializer exceeds array bounds");
+ error_init (loc, "array index range in initializer exceeds "
+ "array bounds");
last = 0;
}
}
/* Within a struct initializer, specify the next field to be initialized. */
void
-set_init_label (tree fieldname, struct obstack * braced_init_obstack)
+set_init_label (location_t loc, tree fieldname,
+ struct obstack *braced_init_obstack)
{
tree field;
- if (set_designator (0, braced_init_obstack))
+ if (set_designator (loc, 0, braced_init_obstack))
return;
designator_erroneous = 1;
if (TREE_CODE (constructor_type) != RECORD_TYPE
&& TREE_CODE (constructor_type) != UNION_TYPE)
{
- error_init ("field name not in record or union initializer");
+ error_init (loc, "field name not in record or union initializer");
return;
}
field = TREE_CHAIN (field);
if (field)
{
- if (set_designator (0, braced_init_obstack))
+ if (set_designator (loc, 0, braced_init_obstack))
return;
}
}
existing initializer. */
static void
-add_pending_init (tree purpose, tree value, tree origtype, bool implicit,
- struct obstack * braced_init_obstack)
+add_pending_init (location_t loc, tree purpose, tree value, tree origtype,
+ bool implicit, struct obstack *braced_init_obstack)
{
struct init_node *p, **q, *r;
if (!implicit)
{
if (TREE_SIDE_EFFECTS (p->value))
- warning_init (0, "initialized field with side-effects overwritten");
+ warning_init (loc, 0,
+ "initialized field with side-effects "
+ "overwritten");
else if (warn_override_init)
- warning_init (OPT_Woverride_init, "initialized field overwritten");
+ warning_init (loc, OPT_Woverride_init,
+ "initialized field overwritten");
}
p->value = value;
p->origtype = origtype;
if (!implicit)
{
if (TREE_SIDE_EFFECTS (p->value))
- warning_init (0, "initialized field with side-effects overwritten");
+ warning_init (loc, 0,
+ "initialized field with side-effects "
+ "overwritten");
else if (warn_override_init)
- warning_init (OPT_Woverride_init, "initialized field overwritten");
+ warning_init (loc, OPT_Woverride_init,
+ "initialized field overwritten");
}
p->value = value;
p->origtype = origtype;
return;
FOR_EACH_CONSTRUCTOR_ELT (constructor_elements, ix, index, value)
- {
- add_pending_init (index, value, NULL_TREE, true,
- braced_init_obstack);
- }
+ add_pending_init (input_location, index, value, NULL_TREE, true,
+ braced_init_obstack);
constructor_elements = NULL;
if (TREE_CODE (constructor_type) == RECORD_TYPE)
{
{
if (wchar_bytes == 1)
{
- val[1] = (unsigned char) *p++;
- val[0] = 0;
+ val[0] = (unsigned char) *p++;
+ val[1] = 0;
}
else
{
- val[0] = 0;
val[1] = 0;
+ val[0] = 0;
for (byte = 0; byte < wchar_bytes; byte++)
{
if (BYTES_BIG_ENDIAN)
bitpos = (wchar_bytes - byte - 1) * charwidth;
else
bitpos = byte * charwidth;
- val[bitpos < HOST_BITS_PER_WIDE_INT]
+ val[bitpos % HOST_BITS_PER_WIDE_INT]
|= ((unsigned HOST_WIDE_INT) ((unsigned char) *p++))
<< (bitpos % HOST_BITS_PER_WIDE_INT);
}
bitpos = ((wchar_bytes - 1) * charwidth) + HOST_BITS_PER_CHAR;
if (bitpos < HOST_BITS_PER_WIDE_INT)
{
- if (val[1] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
+ if (val[0] & (((HOST_WIDE_INT) 1) << (bitpos - 1)))
{
- val[1] |= ((HOST_WIDE_INT) -1) << bitpos;
- val[0] = -1;
+ val[0] |= ((HOST_WIDE_INT) -1) << bitpos;
+ val[1] = -1;
}
}
else if (bitpos == HOST_BITS_PER_WIDE_INT)
{
- if (val[1] < 0)
- val[0] = -1;
+ if (val[0] < 0)
+ val[1] = -1;
}
- else if (val[0] & (((HOST_WIDE_INT) 1)
+ else if (val[1] & (((HOST_WIDE_INT) 1)
<< (bitpos - 1 - HOST_BITS_PER_WIDE_INT)))
- val[0] |= ((HOST_WIDE_INT) -1)
+ val[1] |= ((HOST_WIDE_INT) -1)
<< (bitpos - HOST_BITS_PER_WIDE_INT);
}
- value = build_int_cst_wide (type, val[1], val[0]);
- add_pending_init (purpose, value, NULL_TREE, true,
+ value = wide_int_to_tree (type,
+ wide_int::from_array (val, 2,
+ HOST_BITS_PER_WIDE_INT * 2));
+ add_pending_init (input_location, purpose, value, NULL_TREE, true,
braced_init_obstack);
}
existing initializer. */
static void
-output_init_element (tree value, tree origtype, bool strict_string, tree type,
- tree field, int pending, bool implicit,
- struct obstack * braced_init_obstack)
+output_init_element (location_t loc, tree value, tree origtype,
+ bool strict_string, tree type, tree field, int pending,
+ bool implicit, struct obstack * braced_init_obstack)
{
tree semantic_type = NULL_TREE;
bool maybe_const = true;
{
if (require_constant_value)
{
- error_init ("initializer element is not constant");
+ error_init (loc, "initializer element is not constant");
value = error_mark_node;
}
else if (require_constant_elements)
- pedwarn (input_location, 0,
+ pedwarn (loc, OPT_Wpedantic,
"initializer element is not computable at load time");
}
else if (!maybe_const
&& (require_constant_value || require_constant_elements))
- pedwarn_init (input_location, 0,
+ pedwarn_init (loc, OPT_Wpedantic,
"initializer element is not a constant expression");
/* Issue -Wc++-compat warnings about initializing a bitfield with
if (checktype != error_mark_node
&& (TYPE_MAIN_VARIANT (checktype)
!= TYPE_MAIN_VARIANT (DECL_BIT_FIELD_TYPE (field))))
- warning_init (OPT_Wc___compat,
+ warning_init (loc, OPT_Wc___compat,
"enum conversion in initialization is invalid in C++");
}
if (semantic_type)
value = build1 (EXCESS_PRECISION_EXPR, semantic_type, value);
- value = digest_init (input_location, type, value, origtype, npc,
- strict_string, require_constant_value);
+ value = digest_init (loc, type, value, origtype, npc, strict_string,
+ require_constant_value);
if (value == error_mark_node)
{
constructor_erroneous = 1;
&& tree_int_cst_lt (field, constructor_unfilled_index))
set_nonincremental_init (braced_init_obstack);
- add_pending_init (field, value, origtype, implicit,
+ add_pending_init (loc, field, value, origtype, implicit,
braced_init_obstack);
return;
}
}
}
- add_pending_init (field, value, origtype, implicit,
+ add_pending_init (loc, field, value, origtype, implicit,
braced_init_obstack);
return;
}
if (!implicit)
{
if (TREE_SIDE_EFFECTS (constructor_elements->last ().value))
- warning_init (0,
+ warning_init (loc, 0,
"initialized field with side-effects overwritten");
else if (warn_override_init)
- warning_init (OPT_Woverride_init, "initialized field overwritten");
+ warning_init (loc, OPT_Woverride_init,
+ "initialized field overwritten");
}
/* We can have just one union field set. */
{
if (tree_int_cst_equal (elt->purpose,
constructor_unfilled_index))
- output_init_element (elt->value, elt->origtype, true,
- TREE_TYPE (constructor_type),
+ output_init_element (input_location, elt->value, elt->origtype,
+ true, TREE_TYPE (constructor_type),
constructor_unfilled_index, 0, false,
braced_init_obstack);
else if (tree_int_cst_lt (constructor_unfilled_index,
if (tree_int_cst_equal (elt_bitpos, ctor_unfilled_bitpos))
{
constructor_unfilled_fields = elt->purpose;
- output_init_element (elt->value, elt->origtype, true,
- TREE_TYPE (elt->purpose),
+ output_init_element (input_location, elt->value, elt->origtype,
+ true, TREE_TYPE (elt->purpose),
elt->purpose, 0, false,
braced_init_obstack);
}
existing initializer. */
void
-process_init_element (struct c_expr value, bool implicit,
+process_init_element (location_t loc, struct c_expr value, bool implicit,
struct obstack * braced_init_obstack)
{
tree orig_value = value.value;
designator_depth = 0;
designator_erroneous = 0;
+ if (!implicit && value.value && !integer_zerop (value.value))
+ constructor_zeroinit = 0;
+
/* Handle superfluous braces around string cst as in
char x[] = {"foo"}; */
if (string_flag
&& integer_zerop (constructor_unfilled_index))
{
if (constructor_stack->replacement_value.value)
- error_init ("excess elements in char array initializer");
+ error_init (loc, "excess elements in char array initializer");
constructor_stack->replacement_value = value;
return;
}
if (constructor_stack->replacement_value.value != 0)
{
- error_init ("excess elements in struct initializer");
+ error_init (loc, "excess elements in struct initializer");
return;
}
if (constructor_type == 0)
return;
+ if (!implicit && warn_designated_init && !was_designated
+ && TREE_CODE (constructor_type) == RECORD_TYPE
+ && lookup_attribute ("designated_init",
+ TYPE_ATTRIBUTES (constructor_type)))
+ warning_init (loc,
+ OPT_Wdesignated_init,
+ "positional initialization of field "
+ "in %<struct%> declared with %<designated_init%> attribute");
+
/* If we've exhausted any levels that didn't have braces,
pop them now. */
while (constructor_stack->implicit)
if ((TREE_CODE (constructor_type) == RECORD_TYPE
|| TREE_CODE (constructor_type) == UNION_TYPE)
&& constructor_fields == 0)
- process_init_element (pop_init_level (1, braced_init_obstack),
+ process_init_element (loc,
+ pop_init_level (loc, 1, braced_init_obstack),
true, braced_init_obstack);
else if ((TREE_CODE (constructor_type) == ARRAY_TYPE
|| TREE_CODE (constructor_type) == VECTOR_TYPE)
&& constructor_max_index
&& tree_int_cst_lt (constructor_max_index,
constructor_index))
- process_init_element (pop_init_level (1, braced_init_obstack),
+ process_init_element (loc,
+ pop_init_level (loc, 1, braced_init_obstack),
true, braced_init_obstack);
else
break;
if (constructor_fields == 0)
{
- pedwarn_init (input_location, 0,
- "excess elements in struct initializer");
+ pedwarn_init (loc, 0, "excess elements in struct initializer");
break;
}
&& TYPE_SIZE (fieldtype) == NULL_TREE
&& DECL_CHAIN (constructor_fields) == NULL_TREE)
{
- error_init ("non-static initialization of a flexible array member");
+ error_init (loc, "non-static initialization of a flexible "
+ "array member");
break;
}
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
{
- push_init_level (1, braced_init_obstack);
+ push_init_level (loc, 1, braced_init_obstack);
continue;
}
if (value.value)
{
push_member_name (constructor_fields);
- output_init_element (value.value, value.original_type,
+ output_init_element (loc, value.value, value.original_type,
strict_string, fieldtype,
constructor_fields, 1, implicit,
braced_init_obstack);
if (constructor_fields == 0)
{
- pedwarn_init (input_location, 0,
+ pedwarn_init (loc, 0,
"excess elements in union initializer");
break;
}
&& (fieldcode == RECORD_TYPE || fieldcode == ARRAY_TYPE
|| fieldcode == UNION_TYPE || fieldcode == VECTOR_TYPE))
{
- push_init_level (1, braced_init_obstack);
+ push_init_level (loc, 1, braced_init_obstack);
continue;
}
if (value.value)
{
push_member_name (constructor_fields);
- output_init_element (value.value, value.original_type,
+ output_init_element (loc, value.value, value.original_type,
strict_string, fieldtype,
constructor_fields, 1, implicit,
braced_init_obstack);
&& (eltcode == RECORD_TYPE || eltcode == ARRAY_TYPE
|| eltcode == UNION_TYPE || eltcode == VECTOR_TYPE))
{
- push_init_level (1, braced_init_obstack);
+ push_init_level (loc, 1, braced_init_obstack);
continue;
}
&& (tree_int_cst_lt (constructor_max_index, constructor_index)
|| integer_all_onesp (constructor_max_index)))
{
- pedwarn_init (input_location, 0,
+ pedwarn_init (loc, 0,
"excess elements in array initializer");
break;
}
if (value.value)
{
push_array_bounds (tree_to_uhwi (constructor_index));
- output_init_element (value.value, value.original_type,
+ output_init_element (loc, value.value, value.original_type,
strict_string, elttype,
constructor_index, 1, implicit,
braced_init_obstack);
always have a fixed size derived from their type. */
if (tree_int_cst_lt (constructor_max_index, constructor_index))
{
- pedwarn_init (input_location, 0,
+ pedwarn_init (loc, 0,
"excess elements in vector initializer");
break;
}
{
if (TREE_CODE (value.value) == VECTOR_CST)
elttype = TYPE_MAIN_VARIANT (constructor_type);
- output_init_element (value.value, value.original_type,
+ output_init_element (loc, value.value, value.original_type,
strict_string, elttype,
constructor_index, 1, implicit,
braced_init_obstack);
else if (constructor_type != error_mark_node
&& constructor_fields == 0)
{
- pedwarn_init (input_location, 0,
+ pedwarn_init (loc, 0,
"excess elements in scalar initializer");
break;
}
else
{
if (value.value)
- output_init_element (value.value, value.original_type,
+ output_init_element (loc, value.value, value.original_type,
strict_string, constructor_type,
NULL_TREE, 1, implicit,
braced_init_obstack);
while (constructor_stack != range_stack->stack)
{
gcc_assert (constructor_stack->implicit);
- process_init_element (pop_init_level (1,
+ process_init_element (loc,
+ pop_init_level (loc, 1,
braced_init_obstack),
true, braced_init_obstack);
}
p = p->prev)
{
gcc_assert (constructor_stack->implicit);
- process_init_element (pop_init_level (1, braced_init_obstack),
+ process_init_element (loc,
+ pop_init_level (loc, 1,
+ braced_init_obstack),
true, braced_init_obstack);
}
p = p->next;
if (!p)
break;
- push_init_level (2, braced_init_obstack);
+ push_init_level (loc, 2, braced_init_obstack);
p->stack = constructor_stack;
if (p->range_end && tree_int_cst_equal (p->index, p->range_end))
p->index = p->range_start;
/* Generate a C `return' statement. RETVAL is the expression for what
to return, or a null pointer for `return;' with no value. LOC is
- the location of the return statement. If ORIGTYPE is not NULL_TREE, it
+ the location of the return statement, or the location of the expression,
+ if the statement has any. If ORIGTYPE is not NULL_TREE, it
is the original type of RETVAL. */
tree
warning_at (loc, 0,
"function declared %<noreturn%> has a %<return%> statement");
- if (flag_enable_cilkplus && contains_array_notation_expr (retval))
+ if (flag_cilkplus && contains_array_notation_expr (retval))
{
/* Array notations are allowed in a return statement if it is inside a
built-in array notation reduction function. */
return error_mark_node;
}
}
- if (flag_enable_cilkplus && retval && TREE_CODE (retval) == CILK_SPAWN_STMT)
+ if (flag_cilkplus && retval && contains_cilk_spawn_stmt (retval))
{
error_at (loc, "use of %<_Cilk_spawn%> in a return statement is not "
"allowed");
}
else
{
- tree t = convert_for_assignment (loc, valtype, retval, origtype,
- ic_return,
+ tree t = convert_for_assignment (loc, UNKNOWN_LOCATION, valtype,
+ retval, origtype, ic_return,
npc, NULL_TREE, NULL_TREE, 0);
tree res = DECL_RESULT (current_function_decl);
tree inner;
&& !DECL_EXTERNAL (inner)
&& !TREE_STATIC (inner)
&& DECL_CONTEXT (inner) == current_function_decl)
- warning_at (loc,
- OPT_Wreturn_local_addr, "function returns address "
- "of local variable");
+ {
+ if (TREE_CODE (inner) == LABEL_DECL)
+ warning_at (loc, OPT_Wreturn_local_addr,
+ "function returns address of label");
+ else
+ {
+ warning_at (loc, OPT_Wreturn_local_addr,
+ "function returns address of local variable");
+ tree zero = build_zero_cst (TREE_TYPE (res));
+ t = build2 (COMPOUND_EXPR, TREE_TYPE (res), t, zero);
+ }
+ }
break;
default:
/* Start a C switch statement, testing expression EXP. Return the new
SWITCH_EXPR. SWITCH_LOC is the location of the `switch'.
- SWITCH_COND_LOC is the location of the switch's condition. */
+ SWITCH_COND_LOC is the location of the switch's condition.
+ EXPLICIT_CAST_P is true if the expression EXP has explicit cast. */
tree
c_start_case (location_t switch_loc,
location_t switch_cond_loc,
- tree exp)
+ tree exp, bool explicit_cast_p)
{
tree orig_type = error_mark_node;
struct c_switch *cs;
else
{
tree type = TYPE_MAIN_VARIANT (orig_type);
+ tree e = exp;
+
+ /* Warn if the condition has boolean value. */
+ while (TREE_CODE (e) == COMPOUND_EXPR)
+ e = TREE_OPERAND (e, 1);
+
+ if ((TREE_CODE (type) == BOOLEAN_TYPE
+ || truth_value_p (TREE_CODE (e)))
+ /* Explicit cast to int suppresses this warning. */
+ && !(TREE_CODE (type) == INTEGER_TYPE
+ && explicit_cast_p))
+ warning_at (switch_cond_loc, OPT_Wswitch_bool,
+ "switch condition has boolean value");
if (!in_system_header_at (input_location)
&& (type == long_integer_type_node
{
low_value = c_fully_fold (low_value, false, NULL);
if (TREE_CODE (low_value) == INTEGER_CST)
- pedwarn (input_location, OPT_Wpedantic,
+ pedwarn (loc, OPT_Wpedantic,
"case label is not an integer constant expression");
}
else_block must be either 0 or be equal to the rank of the condition. If
the condition does not have array notations then break them up as it is
broken up in a normal expression. */
- if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+ if (flag_cilkplus && contains_array_notation_expr (cond))
{
size_t then_rank = 0, cond_rank = 0, else_rank = 0;
if (!find_rank (if_locus, cond, cond, true, &cond_rank))
{
tree entry = NULL, exit = NULL, t;
- if (flag_enable_cilkplus && contains_array_notation_expr (cond))
+ if (flag_cilkplus && contains_array_notation_expr (cond))
{
error_at (start_locus, "array notation expression cannot be used in a "
"loop%'s condition");
if (!VOID_TYPE_P (TREE_TYPE (expr)) && !TREE_NO_WARNING (expr))
warning_at (loc, OPT_Wunused_value, "statement with no effect");
}
+ else if (TREE_CODE (expr) == COMPOUND_EXPR)
+ {
+ tree r = expr;
+ location_t cloc = loc;
+ while (TREE_CODE (r) == COMPOUND_EXPR)
+ {
+ if (EXPR_HAS_LOCATION (r))
+ cloc = EXPR_LOCATION (r);
+ r = TREE_OPERAND (r, 1);
+ }
+ if (!TREE_SIDE_EFFECTS (r)
+ && !VOID_TYPE_P (TREE_TYPE (r))
+ && !CONVERT_EXPR_P (r)
+ && !TREE_NO_WARNING (r)
+ && !TREE_NO_WARNING (expr))
+ warning_at (cloc, OPT_Wunused_value,
+ "right-hand operand of comma expression has no effect");
+ }
else
warn_if_unused_value (expr, loc);
}
/* When Cilk Plus is enabled and there are array notations inside op0, then
we check to see if there are builtin array notation functions. If
so, then we take on the type of the array notation inside it. */
- if (flag_enable_cilkplus && contains_array_notation_expr (op0))
+ if (flag_cilkplus && contains_array_notation_expr (op0))
orig_type0 = type0 = find_correct_array_notation_type (op0);
else
orig_type0 = type0 = TREE_TYPE (op0);
- if (flag_enable_cilkplus && contains_array_notation_expr (op1))
+ if (flag_cilkplus && contains_array_notation_expr (op1))
orig_type1 = type1 = find_correct_array_notation_type (op1);
else
orig_type1 = type1 = TREE_TYPE (op1);
{
int_const = false;
if (c_inhibit_evaluation_warnings == 0)
- warning (0, "right shift count is negative");
+ warning_at (location, 0, "right shift count is negative");
}
else
{
{
int_const = false;
if (c_inhibit_evaluation_warnings == 0)
- warning (0, "right shift count >= width of type");
+ warning_at (location, 0, "right shift count >= width "
+ "of type");
}
}
}
{
int_const = false;
if (c_inhibit_evaluation_warnings == 0)
- warning (0, "left shift count is negative");
+ warning_at (location, 0, "left shift count is negative");
}
else if (compare_tree_int (op1, TYPE_PRECISION (type0)) >= 0)
{
int_const = false;
if (c_inhibit_evaluation_warnings == 0)
- warning (0, "left shift count >= width of type");
+ warning_at (location, 0, "left shift count >= width of "
+ "type");
}
}
if (first_complex)
{
if (TREE_TYPE (op0) != result_type)
- op0 = convert_and_check (result_type, op0);
+ op0 = convert_and_check (location, result_type, op0);
if (TREE_TYPE (op1) != real_type)
- op1 = convert_and_check (real_type, op1);
+ op1 = convert_and_check (location, real_type, op1);
}
else
{
if (TREE_TYPE (op0) != real_type)
- op0 = convert_and_check (real_type, op0);
+ op0 = convert_and_check (location, real_type, op0);
if (TREE_TYPE (op1) != result_type)
- op1 = convert_and_check (result_type, op1);
+ op1 = convert_and_check (location, result_type, op1);
}
if (TREE_CODE (op0) == ERROR_MARK || TREE_CODE (op1) == ERROR_MARK)
return error_mark_node;
tree xop0 = op0, xop1 = op1, xresult_type = result_type;
enum tree_code xresultcode = resultcode;
tree val
- = shorten_compare (&xop0, &xop1, &xresult_type, &xresultcode);
+ = shorten_compare (location, &xop0, &xop1, &xresult_type,
+ &xresultcode);
if (val != 0)
{
if (!converted)
{
- op0 = ep_convert_and_check (result_type, op0, semantic_result_type);
- op1 = ep_convert_and_check (result_type, op1, semantic_result_type);
+ op0 = ep_convert_and_check (location, result_type, op0,
+ semantic_result_type);
+ op1 = ep_convert_and_check (location, result_type, op1,
+ semantic_result_type);
/* This can happen if one operand has a vector type, and the other
has a different type. */
return error_mark_node;
}
- if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE))
+ if ((flag_sanitize & (SANITIZE_SHIFT | SANITIZE_DIVIDE
+ | SANITIZE_FLOAT_DIVIDE))
&& current_function_decl != 0
&& !lookup_attribute ("no_sanitize_undefined",
DECL_ATTRIBUTES (current_function_decl))
op1 = c_save_expr (op1);
op0 = c_fully_fold (op0, false, NULL);
op1 = c_fully_fold (op1, false, NULL);
- if (doing_div_or_mod && (flag_sanitize & SANITIZE_DIVIDE))
+ if (doing_div_or_mod && (flag_sanitize & (SANITIZE_DIVIDE
+ | SANITIZE_FLOAT_DIVIDE)))
instrument_expr = ubsan_instrument_division (location, op0, op1);
else if (doing_shift && (flag_sanitize & SANITIZE_SHIFT))
instrument_expr = ubsan_instrument_shift (location, code, op0, op1);
tree decl, tree placeholder)
{
copy_body_data id;
- struct pointer_map_t *decl_map = pointer_map_create ();
+ hash_map<tree, tree> decl_map;
- *pointer_map_insert (decl_map, omp_decl1) = placeholder;
- *pointer_map_insert (decl_map, omp_decl2) = decl;
+ decl_map.put (omp_decl1, placeholder);
+ decl_map.put (omp_decl2, decl);
memset (&id, 0, sizeof (id));
id.src_fn = DECL_CONTEXT (omp_decl1);
id.dst_fn = current_function_decl;
id.src_cfun = DECL_STRUCT_FUNCTION (id.src_fn);
- id.decl_map = decl_map;
+ id.decl_map = &decl_map;
id.copy_decl = copy_decl_no_change;
id.transform_call_graph_edges = CB_CGE_DUPLICATE;
id.transform_lang_insert_block = NULL;
id.eh_lp_nr = 0;
walk_tree (&stmt, copy_tree_body_r, &id, NULL);
- pointer_map_destroy (decl_map);
return stmt;
}
{
bitmap_head generic_head, firstprivate_head, lastprivate_head;
bitmap_head aligned_head;
- tree c, t, *pc = &clauses;
+ tree c, t, *pc;
bool branch_seen = false;
bool copyprivate_seen = false;
tree *nowait_clause = NULL;
need_implicitly_determined = true;
t = OMP_CLAUSE_DECL (c);
if (OMP_CLAUSE_REDUCTION_PLACEHOLDER (c) == NULL_TREE
- && FLOAT_TYPE_P (TREE_TYPE (t)))
+ && (FLOAT_TYPE_P (TREE_TYPE (t))
+ || TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE))
{
enum tree_code r_code = OMP_CLAUSE_REDUCTION_CODE (c);
const char *r_name = NULL;
case PLUS_EXPR:
case MULT_EXPR:
case MINUS_EXPR:
+ break;
case MIN_EXPR:
+ if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
+ r_name = "min";
+ break;
case MAX_EXPR:
+ if (TREE_CODE (TREE_TYPE (t)) == COMPLEX_TYPE)
+ r_name = "max";
break;
case BIT_AND_EXPR:
r_name = "&";
r_name = "|";
break;
case TRUTH_ANDIF_EXPR:
- r_name = "&&";
+ if (FLOAT_TYPE_P (TREE_TYPE (t)))
+ r_name = "&&";
break;
case TRUTH_ORIF_EXPR:
- r_name = "||";
+ if (FLOAT_TYPE_P (TREE_TYPE (t)))
+ r_name = "||";
break;
default:
gcc_unreachable ();
s = size_one_node;
OMP_CLAUSE_LINEAR_STEP (c) = s;
}
+ else
+ OMP_CLAUSE_LINEAR_STEP (c)
+ = fold_convert (TREE_TYPE (t), OMP_CLAUSE_LINEAR_STEP (c));
goto check_dup_generic;
check_dup_generic:
else
{
t = OMP_CLAUSE_DECL (c);
- if (!COMPLETE_TYPE_P (TREE_TYPE (t)))
+ if (!lang_hooks.types.omp_mappable_type (TREE_TYPE (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"array section does not have mappable type "
}
else if (!c_mark_addressable (t))
remove = true;
- else if (!COMPLETE_TYPE_P (TREE_TYPE (t))
- && !(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
- && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER))
+ else if (!(OMP_CLAUSE_CODE (c) == OMP_CLAUSE_MAP
+ && OMP_CLAUSE_MAP_KIND (c) == OMP_CLAUSE_MAP_POINTER)
+ && !lang_hooks.types.omp_mappable_type (TREE_TYPE (t)))
{
error_at (OMP_CLAUSE_LOCATION (c),
"%qD does not have a mappable type in %qs clause", t,
switch (code1)
{
case INTEGER_CST:
- return TREE_INT_CST_LOW (t1) == TREE_INT_CST_LOW (t2)
- && TREE_INT_CST_HIGH (t1) == TREE_INT_CST_HIGH (t2);
+ return wi::eq_p (t1, t2);
case REAL_CST:
return REAL_VALUES_EQUAL (TREE_REAL_CST (t1), TREE_REAL_CST (t2));