#include "tm.h"
#include "intl.h"
#include "tree.h"
+#include "fold-const.h"
+#include "stor-layout.h"
+#include "calls.h"
+#include "stringpool.h"
+#include "attribs.h"
+#include "varasm.h"
+#include "trans-mem.h"
#include "flags.h"
#include "c-pragma.h"
#include "ggc.h"
#include "opts.h"
#include "cgraph.h"
#include "target-def.h"
+#include "gimple.h"
+#include "gimplify.h"
+#include "wide-int-print.h"
cpp_reader *parse_in; /* Declared in c-pragma.h. */
{ "_Static_assert", RID_STATIC_ASSERT, D_CONLY },
{ "_Noreturn", RID_NORETURN, D_CONLY },
{ "_Generic", RID_GENERIC, D_CONLY },
+ { "_Thread_local", RID_THREAD, D_CONLY },
{ "__FUNCTION__", RID_FUNCTION_NAME, 0 },
{ "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
{ "__alignof", RID_ALIGNOF, 0 },
{ "__asm__", RID_ASM, 0 },
{ "__attribute", RID_ATTRIBUTE, 0 },
{ "__attribute__", RID_ATTRIBUTE, 0 },
+ { "__auto_type", RID_AUTO_TYPE, D_CONLY },
{ "__bases", RID_BASES, D_CXXONLY },
{ "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
{ "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
}
/* Checks if expression EXPR of real/integer type cannot be converted
- to the real/integer type TYPE. Function returns true when:
+ to the real/integer type TYPE. Function returns non-zero when:
* EXPR is a constant which cannot be exactly converted to TYPE
* EXPR is not a constant and size of EXPR's type > than size of TYPE,
for EXPR type and TYPE being both integers or both real.
* EXPR is not a constant of integer type which cannot be
exactly converted to real type.
Function allows conversions between types of different signedness and
- does not return true in that case. Function can produce signedness
- warnings if PRODUCE_WARNS is true. */
-bool
+ can return SAFE_CONVERSION (zero) in that case. Function can produce
+ signedness warnings if PRODUCE_WARNS is true. */
+enum conversion_safety
unsafe_conversion_p (tree type, tree expr, bool produce_warns)
{
- bool give_warning = false;
+ enum conversion_safety give_warning = SAFE_CONVERSION; /* is 0 or false */
tree expr_type = TREE_TYPE (expr);
location_t loc = EXPR_LOC_OR_HERE (expr);
&& TREE_CODE (type) == INTEGER_TYPE)
{
if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type)))
- give_warning = true;
+ give_warning = UNSAFE_REAL;
}
/* Warn for an integer constant that does not fit into integer type. */
else if (TREE_CODE (expr_type) == INTEGER_TYPE
" constant value to negative integer");
}
else
- give_warning = true;
+ give_warning = UNSAFE_OTHER;
}
else if (TREE_CODE (type) == REAL_TYPE)
{
{
REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
if (!exact_real_truncate (TYPE_MODE (type), &a))
- give_warning = true;
+ give_warning = UNSAFE_REAL;
}
/* Warn for a real constant that does not fit into a smaller
real type. */
{
REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
if (!exact_real_truncate (TYPE_MODE (type), &a))
- give_warning = true;
+ give_warning = UNSAFE_REAL;
}
}
}
/* Warn for real types converted to integer types. */
if (TREE_CODE (expr_type) == REAL_TYPE
&& TREE_CODE (type) == INTEGER_TYPE)
- give_warning = true;
+ give_warning = UNSAFE_REAL;
else if (TREE_CODE (expr_type) == INTEGER_TYPE
&& TREE_CODE (type) == INTEGER_TYPE)
&& int_fits_type_p (op1, c_common_signed_type (type))
&& int_fits_type_p (op1,
c_common_unsigned_type (type))))
- return false;
+ return SAFE_CONVERSION;
/* If constant is unsigned and fits in the target
type, then the result will also fit. */
else if ((TREE_CODE (op0) == INTEGER_CST
|| (TREE_CODE (op1) == INTEGER_CST
&& unsigned1
&& int_fits_type_p (op1, type)))
- return false;
+ return SAFE_CONVERSION;
}
}
/* Warn for integer types converted to smaller integer types. */
if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
- give_warning = true;
+ give_warning = UNSAFE_OTHER;
/* When they are the same width but different signedness,
then the value may change. */
if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
|| !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
- give_warning = true;
+ give_warning = UNSAFE_OTHER;
}
/* Warn for real types converted to smaller real types. */
else if (TREE_CODE (expr_type) == REAL_TYPE
&& TREE_CODE (type) == REAL_TYPE
&& TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
- give_warning = true;
+ give_warning = UNSAFE_REAL;
}
return give_warning;
{
tree expr_type = TREE_TYPE (expr);
location_t loc = EXPR_LOC_OR_HERE (expr);
+ enum conversion_safety conversion_kind;
- if (!warn_conversion && !warn_sign_conversion)
+ if (!warn_conversion && !warn_sign_conversion && !warn_float_conversion)
return;
switch (TREE_CODE (expr))
case REAL_CST:
case INTEGER_CST:
- if (unsafe_conversion_p (type, expr, true))
+ conversion_kind = unsafe_conversion_p (type, expr, true);
+ if (conversion_kind == UNSAFE_REAL)
+ warning_at (loc, OPT_Wfloat_conversion,
+ "conversion to %qT alters %qT constant value",
+ type, expr_type);
+ else if (conversion_kind)
warning_at (loc, OPT_Wconversion,
"conversion to %qT alters %qT constant value",
type, expr_type);
}
default: /* 'expr' is not a constant. */
- if (unsafe_conversion_p (type, expr, true))
+ conversion_kind = unsafe_conversion_p (type, expr, true);
+ if (conversion_kind == UNSAFE_REAL)
+ warning_at (loc, OPT_Wfloat_conversion,
+ "conversion to %qT from %qT may alter its value",
+ type, expr_type);
+ else if (conversion_kind)
warning_at (loc, OPT_Wconversion,
"conversion to %qT from %qT may alter its value",
type, expr_type);
{
/* Convert primop1 to target type, but do not introduce
additional overflow. We know primop1 is an int_cst. */
- primop1 = force_fit_type_double (*restype_ptr,
- tree_to_double_int (primop1),
- 0, TREE_OVERFLOW (primop1));
+ primop1 = force_fit_type (*restype_ptr,
+ wide_int::from
+ (primop1,
+ TYPE_PRECISION (*restype_ptr),
+ TYPE_SIGN (TREE_TYPE (primop1))),
+ 0, TREE_OVERFLOW (primop1));
}
if (type != *restype_ptr)
{
maxval = convert (*restype_ptr, maxval);
}
- if (unsignedp && unsignedp0)
- {
- min_gt = INT_CST_LT_UNSIGNED (primop1, minval);
- max_gt = INT_CST_LT_UNSIGNED (primop1, maxval);
- min_lt = INT_CST_LT_UNSIGNED (minval, primop1);
- max_lt = INT_CST_LT_UNSIGNED (maxval, primop1);
- }
- else
- {
- min_gt = INT_CST_LT (primop1, minval);
- max_gt = INT_CST_LT (primop1, maxval);
- min_lt = INT_CST_LT (minval, primop1);
- max_lt = INT_CST_LT (maxval, primop1);
- }
+ min_gt = INT_CST_LT (primop1, minval);
+ max_gt = INT_CST_LT (primop1, maxval);
+ min_lt = INT_CST_LT (minval, primop1);
+ max_lt = INT_CST_LT (maxval, primop1);
val = 0;
/* This used to be a switch, but Genix compiler can't handle that. */
convert (TREE_TYPE (intop), size_exp), 1);
intop = convert (sizetype, t);
if (TREE_OVERFLOW_P (intop) && !TREE_OVERFLOW (t))
- intop = build_int_cst_wide (TREE_TYPE (intop), TREE_INT_CST_LOW (intop),
- TREE_INT_CST_HIGH (intop));
+ intop = wide_int_to_tree (TREE_TYPE (intop), intop);
}
/* Create the sum or difference. */
}
/* This node must not be shared. */
- void_zero_node = make_node (INTEGER_CST);
+ void_zero_node = make_int_cst (1, 1);
TREE_TYPE (void_zero_node) = void_type_node;
void_list_node = build_void_list_node ();
/* Create the built-in __null node. It is important that this is
not shared. */
- null_node = make_node (INTEGER_CST);
+ null_node = make_int_cst (1, 1);
TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
/* Since builtin_types isn't gc'ed, don't export these nodes. */
static void
match_case_to_enum_1 (tree key, tree type, tree label)
{
- char buf[2 + 2*HOST_BITS_PER_WIDE_INT/4 + 1];
-
- /* ??? Not working too hard to print the double-word value.
- Should perhaps be done with %lwd in the diagnostic routines? */
- if (TREE_INT_CST_HIGH (key) == 0)
- snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_UNSIGNED,
- TREE_INT_CST_LOW (key));
- else if (!TYPE_UNSIGNED (type)
- && TREE_INT_CST_HIGH (key) == -1
- && TREE_INT_CST_LOW (key) != 0)
- snprintf (buf, sizeof (buf), "-" HOST_WIDE_INT_PRINT_UNSIGNED,
- -TREE_INT_CST_LOW (key));
+ char buf[WIDE_INT_PRINT_BUFFER_SIZE];
+
+ if (tree_fits_uhwi_p (key))
+ print_dec (key, buf, UNSIGNED);
+ else if (tree_fits_shwi_p (key))
+ print_dec (key, buf, SIGNED);
else
- snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_DOUBLE_HEX,
- (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (key),
- (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (key));
+ print_hex (key, buf);
if (TYPE_NAME (type) == 0)
warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
arg = TREE_VALUE (args);
arg = default_conversion (arg);
- if (!host_integerp (arg, /*pos=*/0)
+ if (!tree_fits_shwi_p (arg)
|| !INTEGRAL_TYPE_P (TREE_TYPE (arg)))
goto invalid;
- pri = tree_low_cst (arg, /*pos=*/0);
+ pri = tree_to_shwi (arg);
if (pri < 0 || pri > MAX_INIT_PRIORITY)
goto invalid;
tree position = TREE_VALUE (args);
if (TREE_CODE (position) != INTEGER_CST
- || TREE_INT_CST_HIGH (position)
- || TREE_INT_CST_LOW (position) < 1
- || TREE_INT_CST_LOW (position) > arg_count )
+ || wi::ltu_p (position, 1)
+ || wi::gtu_p (position, arg_count))
{
warning (OPT_Wattributes,
"alloc_size parameter outside range");
size = TREE_VALUE (args);
- if (!host_integerp (size, 1))
+ if (!tree_fits_uhwi_p (size))
{
warning (OPT_Wattributes, "%qE attribute ignored", name);
return NULL_TREE;
}
/* Get the vector size (in bytes). */
- vecsize = tree_low_cst (size, 1);
+ vecsize = tree_to_uhwi (size);
/* We need to provide for vector pointers, vector arrays, and
functions returning vectors. For example:
|| (!SCALAR_FLOAT_MODE_P (orig_mode)
&& GET_MODE_CLASS (orig_mode) != MODE_INT
&& !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
- || !host_integerp (TYPE_SIZE_UNIT (type), 1)
+ || !tree_fits_uhwi_p (TYPE_SIZE_UNIT (type))
|| TREE_CODE (type) == BOOLEAN_TYPE)
{
error ("invalid vector type for attribute %qE", name);
return NULL_TREE;
}
- if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1))
+ if (vecsize % tree_to_uhwi (TYPE_SIZE_UNIT (type)))
{
error ("vector size not an integral multiple of component size");
return NULL;
}
/* Calculate how many units fit in the vector. */
- nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+ nunits = vecsize / tree_to_uhwi (TYPE_SIZE_UNIT (type));
if (nunits & (nunits - 1))
{
error ("number of components of the vector not a power of two");
static bool
get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
{
- /* Verify the arg number is a constant. */
- if (TREE_CODE (arg_num_expr) != INTEGER_CST
- || TREE_INT_CST_HIGH (arg_num_expr) != 0)
+ /* Verify the arg number is a small constant. */
+ if (cst_fits_uhwi_p (arg_num_expr))
+ {
+ *valp = TREE_INT_CST_LOW (arg_num_expr);
+ return true;
+ }
+ else
return false;
-
- *valp = TREE_INT_CST_LOW (arg_num_expr);
- return true;
}
/* Handle a "nothrow" attribute; arguments as in
/* Extract the argument number, which was previously checked
to be valid. */
format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
-
- gcc_assert (TREE_CODE (format_num_expr) == INTEGER_CST
- && !TREE_INT_CST_HIGH (format_num_expr));
-
- format_num = TREE_INT_CST_LOW (format_num_expr);
+
+ format_num = tree_to_uhwi (format_num_expr);
for (inner_arg = first_call_expr_arg (param, &iter), i = 1;
inner_arg != 0;
return error_mark_node;
}
off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
- size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t),
- 1)
+ size_int (tree_to_uhwi (DECL_FIELD_BIT_OFFSET (t))
/ BITS_PER_UNIT));
break;
how ARG was being used. */
void
-readonly_error (tree arg, enum lvalue_use use)
+readonly_error (location_t loc, tree arg, enum lvalue_use use)
{
gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
|| use == lv_asm);
if (TREE_CODE (arg) == COMPONENT_REF)
{
if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
- error (READONLY_MSG (G_("assignment of member "
- "%qD in read-only object"),
- G_("increment of member "
- "%qD in read-only object"),
- G_("decrement of member "
- "%qD in read-only object"),
- G_("member %qD in read-only object "
- "used as %<asm%> output")),
- TREE_OPERAND (arg, 1));
+ error_at (loc, READONLY_MSG (G_("assignment of member "
+ "%qD in read-only object"),
+ G_("increment of member "
+ "%qD in read-only object"),
+ G_("decrement of member "
+ "%qD in read-only object"),
+ G_("member %qD in read-only object "
+ "used as %<asm%> output")),
+ TREE_OPERAND (arg, 1));
else
- error (READONLY_MSG (G_("assignment of read-only member %qD"),
- G_("increment of read-only member %qD"),
- G_("decrement of read-only member %qD"),
- G_("read-only member %qD used as %<asm%> output")),
- TREE_OPERAND (arg, 1));
+ error_at (loc, READONLY_MSG (G_("assignment of read-only member %qD"),
+ G_("increment of read-only member %qD"),
+ G_("decrement of read-only member %qD"),
+ G_("read-only member %qD used as %<asm%> output")),
+ TREE_OPERAND (arg, 1));
}
else if (TREE_CODE (arg) == VAR_DECL)
- error (READONLY_MSG (G_("assignment of read-only variable %qD"),
- G_("increment of read-only variable %qD"),
- G_("decrement of read-only variable %qD"),
- G_("read-only variable %qD used as %<asm%> output")),
- arg);
+ error_at (loc, READONLY_MSG (G_("assignment of read-only variable %qD"),
+ G_("increment of read-only variable %qD"),
+ G_("decrement of read-only variable %qD"),
+ G_("read-only variable %qD used as %<asm%> output")),
+ arg);
else if (TREE_CODE (arg) == PARM_DECL)
- error (READONLY_MSG (G_("assignment of read-only parameter %qD"),
- G_("increment of read-only parameter %qD"),
- G_("decrement of read-only parameter %qD"),
- G_("read-only parameter %qD use as %<asm%> output")),
- arg);
+ error_at (loc, READONLY_MSG (G_("assignment of read-only parameter %qD"),
+ G_("increment of read-only parameter %qD"),
+ G_("decrement of read-only parameter %qD"),
+ G_("read-only parameter %qD use as %<asm%> output")),
+ arg);
else if (TREE_CODE (arg) == RESULT_DECL)
{
gcc_assert (c_dialect_cxx ());
- error (READONLY_MSG (G_("assignment of "
- "read-only named return value %qD"),
- G_("increment of "
- "read-only named return value %qD"),
- G_("decrement of "
- "read-only named return value %qD"),
- G_("read-only named return value %qD "
- "used as %<asm%>output")),
- arg);
+ error_at (loc, READONLY_MSG (G_("assignment of "
+ "read-only named return value %qD"),
+ G_("increment of "
+ "read-only named return value %qD"),
+ G_("decrement of "
+ "read-only named return value %qD"),
+ G_("read-only named return value %qD "
+ "used as %<asm%>output")),
+ arg);
}
else if (TREE_CODE (arg) == FUNCTION_DECL)
- error (READONLY_MSG (G_("assignment of function %qD"),
- G_("increment of function %qD"),
- G_("decrement of function %qD"),
- G_("function %qD used as %<asm%> output")),
- arg);
+ error_at (loc, READONLY_MSG (G_("assignment of function %qD"),
+ G_("increment of function %qD"),
+ G_("decrement of function %qD"),
+ G_("function %qD used as %<asm%> output")),
+ arg);
else
- error (READONLY_MSG (G_("assignment of read-only location %qE"),
- G_("increment of read-only location %qE"),
- G_("decrement of read-only location %qE"),
- G_("read-only location %qE used as %<asm%> output")),
- arg);
+ error_at (loc, READONLY_MSG (G_("assignment of read-only location %qE"),
+ G_("increment of read-only location %qE"),
+ G_("decrement of read-only location %qE"),
+ G_("read-only location %qE used as %<asm%> output")),
+ arg);
}
/* Print an error message for an invalid lvalue. USE says
{
error ("size of array is too large");
/* If we proceed with the array type as it is, we'll eventually
- crash in tree_low_cst(). */
+ crash in tree_to_[su]hwi(). */
type = error_mark_node;
}
if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
goto incompatible;
- size = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+ size = tree_to_uhwi (TYPE_SIZE_UNIT (type));
if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
return size;
return 0;
}
- size_0 = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type_0)), 1);
+ size_0 = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type_0)));
/* Zero size objects are not allowed. */
if (size_0 == 0)
function);
return 0;
}
- size = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1);
+ size = tree_to_uhwi (TYPE_SIZE_UNIT (TREE_TYPE (type)));
if (size != size_0)
{
error_at (loc, "size mismatch in argument %d of %qE", x + 1,
tree p = (*params)[x];
if (TREE_CODE (p) == INTEGER_CST)
{
- int i = tree_low_cst (p, 1);
+ int i = tree_to_uhwi (p);
if (i < 0 || (i & MEMMODEL_MASK) >= MEMMODEL_LAST)
{
warning_at (loc, OPT_Winvalid_memory_model,
if (TREE_CODE (op1) == BIT_NOT_EXPR)
op1 = c_common_get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
- if (host_integerp (op0, 0) || host_integerp (op1, 0))
+ if (tree_fits_shwi_p (op0) || tree_fits_shwi_p (op1))
{
tree primop;
HOST_WIDE_INT constant, mask;
int unsignedp;
unsigned int bits;
- if (host_integerp (op0, 0))
+ if (tree_fits_shwi_p (op0))
{
primop = op1;
unsignedp = unsignedp1;
- constant = tree_low_cst (op0, 0);
+ constant = tree_to_shwi (op0);
}
else
{
primop = op0;
unsignedp = unsignedp0;
- constant = tree_low_cst (op1, 0);
+ constant = tree_to_shwi (op1);
}
bits = TYPE_PRECISION (TREE_TYPE (primop));
{
switch (keyword)
{
+ case RID_AUTO_TYPE:
case RID_INT:
case RID_CHAR:
case RID_FLOAT:
tree type1;
if (TREE_CODE (index) == INTEGER_CST)
- if (!host_integerp (index, 1)
- || ((unsigned HOST_WIDE_INT) tree_low_cst (index, 1)
- >= TYPE_VECTOR_SUBPARTS (type)))
+ if (!tree_fits_uhwi_p (index)
+ || tree_to_uhwi (index) >= TYPE_VECTOR_SUBPARTS (type))
warning_at (loc, OPT_Warray_bounds, "index value is out of bound");
c_common_mark_addressable_vec (*vecp);