/* Subroutines shared by all languages that are variants of C.
- Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
- 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
- Free Software Foundation, Inc.
+ Copyright (C) 1992-2013 Free Software Foundation, Inc.
This file is part of GCC.
#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 "diagnostic.h"
#include "tree-iterator.h"
#include "hashtab.h"
-#include "tree-mudflap.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. */
user's namespace. */
int flag_iso;
-/* Warn about #pragma directives that are not recognized. */
-
-int warn_unknown_pragmas; /* Tri state variable. */
-
-/* Warn about format/argument anomalies in calls to formatted I/O functions
- (*printf, *scanf, strftime, strfmon, etc.). */
-
-int warn_format;
-
/* C/ObjC language option variables. */
static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
+static tree handle_no_sanitize_address_attribute (tree *, tree, tree,
+ int, bool *);
+static tree handle_no_address_safety_analysis_attribute (tree *, tree, tree,
+ int, bool *);
+static tree handle_no_sanitize_undefined_attribute (tree *, tree, tree, int,
+ bool *);
static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
static tree ignore_attribute (tree *, tree, tree, int, bool *);
static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
+static tree handle_warn_unused_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_nonnull_attribute (tree *, tree, tree, int, bool *);
+static tree handle_omp_declare_simd_attribute (tree *, tree, tree, int,
+ bool *);
+static tree handle_omp_declare_target_attribute (tree *, tree, tree, int,
+ bool *);
+static tree handle_bnd_variable_size_attribute (tree *, tree, tree, int, bool *);
+static tree handle_bnd_legacy (tree *, tree, tree, int, bool *);
static void check_function_nonnull (tree, int, tree *);
static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
{
{ "_Alignas", RID_ALIGNAS, D_CONLY },
{ "_Alignof", RID_ALIGNOF, D_CONLY },
+ { "_Atomic", RID_ATOMIC, D_CONLY },
{ "_Bool", RID_BOOL, D_CONLY },
{ "_Complex", RID_COMPLEX, 0 },
+ { "_Cilk_spawn", RID_CILK_SPAWN, 0 },
+ { "_Cilk_sync", RID_CILK_SYNC, 0 },
{ "_Imaginary", RID_IMAGINARY, D_CONLY },
{ "_Decimal32", RID_DFLOAT32, D_CONLY | D_EXT },
{ "_Decimal64", RID_DFLOAT64, D_CONLY | D_EXT },
{ "_Sat", RID_SAT, D_CONLY | D_EXT },
{ "_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 },
handle_cold_attribute, false },
{ "hot", 0, 0, true, false, false,
handle_hot_attribute, false },
+ { "no_address_safety_analysis",
+ 0, 0, true, false, false,
+ handle_no_address_safety_analysis_attribute,
+ false },
+ { "no_sanitize_address", 0, 0, true, false, false,
+ handle_no_sanitize_address_attribute,
+ false },
+ { "no_sanitize_undefined", 0, 0, true, false, false,
+ handle_no_sanitize_undefined_attribute,
+ false },
{ "warning", 1, 1, true, false, false,
handle_error_attribute, false },
{ "error", 1, 1, true, false, false,
The name contains space to prevent its usage in source code. */
{ "fn spec", 1, 1, false, true, true,
handle_fnspec_attribute, false },
+ { "warn_unused", 0, 0, false, false, false,
+ handle_warn_unused_attribute, false },
+ { "returns_nonnull", 0, 0, false, true, true,
+ handle_returns_nonnull_attribute, false },
+ { "omp declare simd", 0, -1, true, false, false,
+ handle_omp_declare_simd_attribute, false },
+ { "omp declare target", 0, 0, true, false, false,
+ handle_omp_declare_target_attribute, false },
+ { "bnd_variable_size", 0, 0, true, false, false,
+ handle_bnd_variable_size_attribute, false },
+ { "bnd_legacy", 0, 0, true, false, false,
+ handle_bnd_legacy, false },
{ NULL, 0, 0, false, false, false, NULL, false }
};
&& !TREE_OVERFLOW_P (op0)
&& !TREE_OVERFLOW_P (op1))
overflow_warning (EXPR_LOCATION (expr), ret);
+ if ((code == LSHIFT_EXPR || code == RSHIFT_EXPR)
+ && TREE_CODE (orig_op1) != INTEGER_CST
+ && TREE_CODE (op1) == INTEGER_CST
+ && (TREE_CODE (TREE_TYPE (orig_op0)) == INTEGER_TYPE
+ || TREE_CODE (TREE_TYPE (orig_op0)) == FIXED_POINT_TYPE)
+ && TREE_CODE (TREE_TYPE (orig_op1)) == INTEGER_TYPE
+ && c_inhibit_evaluation_warnings == 0)
+ {
+ if (tree_int_cst_sgn (op1) < 0)
+ warning_at (loc, 0, (code == LSHIFT_EXPR
+ ? G_("left shift count is negative")
+ : G_("right shift count is negative")));
+ else if (compare_tree_int (op1,
+ TYPE_PRECISION (TREE_TYPE (orig_op0)))
+ >= 0)
+ warning_at (loc, 0, (code == LSHIFT_EXPR
+ ? G_("left shift count >= width of type")
+ : G_("right shift count >= width of type")));
+ }
goto out;
case INDIRECT_REF:
void
sizeof_pointer_memaccess_warning (location_t *sizeof_arg_loc, tree callee,
- VEC(tree, gc) *params, tree *sizeof_arg,
+ vec<tree, va_gc> *params, tree *sizeof_arg,
bool (*comp_types) (tree, tree))
{
tree type, dest = NULL_TREE, src = NULL_TREE, tem;
if (TREE_CODE (callee) != FUNCTION_DECL
|| DECL_BUILT_IN_CLASS (callee) != BUILT_IN_NORMAL
- || VEC_length (tree, params) <= 1)
+ || vec_safe_length (params) <= 1)
return;
switch (DECL_FUNCTION_CODE (callee))
case BUILT_IN_MEMCPY_CHK:
case BUILT_IN_MEMMOVE:
case BUILT_IN_MEMMOVE_CHK:
- if (VEC_length (tree, params) < 3)
+ if (params->length () < 3)
return;
- src = VEC_index (tree, params, 1);
- dest = VEC_index (tree, params, 0);
+ src = (*params)[1];
+ dest = (*params)[0];
idx = 2;
break;
case BUILT_IN_BCOPY:
- if (VEC_length (tree, params) < 3)
+ if (params->length () < 3)
return;
- src = VEC_index (tree, params, 0);
- dest = VEC_index (tree, params, 1);
+ src = (*params)[0];
+ dest = (*params)[1];
idx = 2;
break;
case BUILT_IN_MEMCMP:
case BUILT_IN_BCMP:
- if (VEC_length (tree, params) < 3)
+ if (params->length () < 3)
return;
- src = VEC_index (tree, params, 1);
- dest = VEC_index (tree, params, 0);
+ src = (*params)[1];
+ dest = (*params)[0];
idx = 2;
cmp = true;
break;
case BUILT_IN_MEMSET:
case BUILT_IN_MEMSET_CHK:
- if (VEC_length (tree, params) < 3)
+ if (params->length () < 3)
return;
- dest = VEC_index (tree, params, 0);
+ dest = (*params)[0];
idx = 2;
break;
case BUILT_IN_BZERO:
- dest = VEC_index (tree, params, 0);
+ dest = (*params)[0];
idx = 1;
break;
case BUILT_IN_STRNDUP:
- src = VEC_index (tree, params, 0);
+ src = (*params)[0];
strop = true;
idx = 1;
break;
case BUILT_IN_MEMCHR:
- if (VEC_length (tree, params) < 3)
+ if (params->length () < 3)
return;
- src = VEC_index (tree, params, 0);
+ src = (*params)[0];
idx = 2;
break;
case BUILT_IN_SNPRINTF:
case BUILT_IN_SNPRINTF_CHK:
case BUILT_IN_VSNPRINTF:
case BUILT_IN_VSNPRINTF_CHK:
- dest = VEC_index (tree, params, 0);
+ dest = (*params)[0];
idx = 1;
strop = true;
break;
"%q+D takes only zero or two arguments", decl);
}
+/* vector_targets_convertible_p is used for vector pointer types. The
+ callers perform various checks that the qualifiers are satisfactory,
+ while OTOH vector_targets_convertible_p ignores the number of elements
+ in the vectors. That's fine with vector pointers as we can consider,
+ say, a vector of 8 elements as two consecutive vectors of 4 elements,
+ and that does not require and conversion of the pointer values.
+ In contrast, vector_types_convertible_p and
+ vector_types_compatible_elements_p are used for vector value types. */
/* True if pointers to distinct types T1 and T2 can be converted to
each other without an explicit cast. Only returns true for opaque
vector types. */
return false;
}
+/* vector_types_convertible_p is used for vector value types.
+ It could in principle call vector_targets_convertible_p as a subroutine,
+ but then the check for vector type would be duplicated with its callers,
+ and also the purpose of vector_targets_convertible_p would become
+ muddled.
+ Where vector_types_convertible_p returns true, a conversion might still be
+ needed to make the types match.
+ In contrast, vector_targets_convertible_p is used for vector pointer
+ values, and vector_types_compatible_elements_p is used specifically
+ in the context for binary operators, as a check if use is possible without
+ conversion. */
/* True if vector types T1 and T2 can be converted to each other
without an explicit cast. If EMIT_LAX_NOTE is true, and T1 and T2
can only be converted with -flax-vector-conversions yet that is not
convertible_lax =
(tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
&& (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE ||
- TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
+ TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2))
&& (INTEGRAL_TYPE_P (TREE_TYPE (t1))
== INTEGRAL_TYPE_P (TREE_TYPE (t2))));
an implementation accident and this semantics is not guaranteed to
the user. */
tree
-c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask)
+c_build_vec_perm_expr (location_t loc, tree v0, tree v1, tree mask,
+ bool complain)
{
tree ret;
bool wrap = true;
if (TREE_CODE (TREE_TYPE (mask)) != VECTOR_TYPE
|| TREE_CODE (TREE_TYPE (TREE_TYPE (mask))) != INTEGER_TYPE)
{
- error_at (loc, "__builtin_shuffle last argument must "
- "be an integer vector");
+ if (complain)
+ error_at (loc, "__builtin_shuffle last argument must "
+ "be an integer vector");
return error_mark_node;
}
if (TREE_CODE (TREE_TYPE (v0)) != VECTOR_TYPE
|| TREE_CODE (TREE_TYPE (v1)) != VECTOR_TYPE)
{
- error_at (loc, "__builtin_shuffle arguments must be vectors");
+ if (complain)
+ error_at (loc, "__builtin_shuffle arguments must be vectors");
return error_mark_node;
}
if (TYPE_MAIN_VARIANT (TREE_TYPE (v0)) != TYPE_MAIN_VARIANT (TREE_TYPE (v1)))
{
- error_at (loc, "__builtin_shuffle argument vectors must be of "
- "the same type");
+ if (complain)
+ error_at (loc, "__builtin_shuffle argument vectors must be of "
+ "the same type");
return error_mark_node;
}
&& TYPE_VECTOR_SUBPARTS (TREE_TYPE (v1))
!= TYPE_VECTOR_SUBPARTS (TREE_TYPE (mask)))
{
- error_at (loc, "__builtin_shuffle number of elements of the "
- "argument vector(s) and the mask vector should "
- "be the same");
+ if (complain)
+ error_at (loc, "__builtin_shuffle number of elements of the "
+ "argument vector(s) and the mask vector should "
+ "be the same");
return error_mark_node;
}
if (GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (v0))))
!= GET_MODE_BITSIZE (TYPE_MODE (TREE_TYPE (TREE_TYPE (mask)))))
{
- error_at (loc, "__builtin_shuffle argument vector(s) inner type "
- "must have the same size as inner type of the mask");
+ if (complain)
+ error_at (loc, "__builtin_shuffle argument vector(s) inner type "
+ "must have the same size as inner type of the mask");
return error_mark_node;
}
mask = c_fully_fold (mask, false, &maybe_const);
wrap &= maybe_const;
}
+ else if (two_arguments)
+ v1 = v0 = save_expr (v0);
ret = build3_loc (loc, VEC_PERM_EXPR, TREE_TYPE (v0), v0, v1, mask);
}
/* 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);
case COND_EXPR:
{
- /* In case of COND_EXPR, if both operands are constants or
- COND_EXPR, then we do not care about the type of COND_EXPR,
- only about the conversion of each operand. */
- tree op1 = TREE_OPERAND (expr, 1);
- tree op2 = TREE_OPERAND (expr, 2);
-
- if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST
- || TREE_CODE (op1) == COND_EXPR)
- && (TREE_CODE (op2) == REAL_CST || TREE_CODE (op2) == INTEGER_CST
- || TREE_CODE (op2) == COND_EXPR))
- {
- conversion_warning (type, op1);
- conversion_warning (type, op2);
- return;
- }
- /* Fall through. */
+ /* In case of COND_EXPR, we do not care about the type of
+ COND_EXPR, only about the conversion of each operand. */
+ tree op1 = TREE_OPERAND (expr, 1);
+ tree op2 = TREE_OPERAND (expr, 2);
+
+ conversion_warning (type, op1);
+ conversion_warning (type, op2);
+ return;
}
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);
switch (code)
{
case CONSTRUCTOR:
+ case SIZEOF_EXPR:
return;
case COMPOUND_EXPR:
{
/* 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. */
tree
pointer_int_sum (location_t loc, enum tree_code resultcode,
- tree ptrop, tree intop)
+ tree ptrop, tree intop, bool complain)
{
tree size_exp, ret;
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
{
- pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
- "pointer of type %<void *%> used in arithmetic");
+ if (complain && warn_pointer_arith)
+ pedwarn (loc, OPT_Wpointer_arith,
+ "pointer of type %<void *%> used in arithmetic");
+ else if (!complain)
+ return error_mark_node;
size_exp = integer_one_node;
}
else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
{
- pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
- "pointer to a function used in arithmetic");
- size_exp = integer_one_node;
- }
- else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
- {
- pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
- "pointer to member function used in arithmetic");
+ if (complain && warn_pointer_arith)
+ pedwarn (loc, OPT_Wpointer_arith,
+ "pointer to a function used in arithmetic");
+ else if (!complain)
+ return error_mark_node;
size_exp = integer_one_node;
}
else
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. */
{
if (is_sizeof)
{
- if (complain && (pedantic || warn_pointer_arith))
- pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
+ if (complain && warn_pointer_arith)
+ pedwarn (loc, OPT_Wpointer_arith,
"invalid application of %<sizeof%> to a function type");
else if (!complain)
return error_mark_node;
else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
{
if (type_code == VOID_TYPE
- && complain && (pedantic || warn_pointer_arith))
- pedwarn (loc, pedantic ? OPT_Wpedantic : OPT_Wpointer_arith,
+ && complain && warn_pointer_arith)
+ pedwarn (loc, OPT_Wpointer_arith,
"invalid application of %qs to a void type", op_name);
else if (!complain)
return error_mark_node;
#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME,
#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME,
+#define DEF_FUNCTION_TYPE_8(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7, ARG8) NAME,
#define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
#define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
#define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
#undef DEF_FUNCTION_TYPE_5
#undef DEF_FUNCTION_TYPE_6
#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_8
#undef DEF_FUNCTION_TYPE_VAR_0
#undef DEF_FUNCTION_TYPE_VAR_1
#undef DEF_FUNCTION_TYPE_VAR_2
#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
ARG6, ARG7) \
def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
+#define DEF_FUNCTION_TYPE_8(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+ ARG6, ARG7, ARG8) \
+ def_fn_type (ENUM, RETURN, 0, 8, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, \
+ ARG7, ARG8);
#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
def_fn_type (ENUM, RETURN, 1, 0);
#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
build_common_builtin_nodes ();
- if (flag_mudflap)
- mudflap_init ();
+ if (flag_enable_cilkplus)
+ cilk_init_builtins ();
}
/* Like get_identifier, but avoid warnings about null arguments when
}
/* 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 ();
{
char16_type_node = make_unsigned_type (char16_type_size);
- if (cxx_dialect >= cxx0x)
+ if (cxx_dialect >= cxx11)
record_builtin_type (RID_CHAR16, "char16_t", char16_type_node);
}
{
char32_type_node = make_unsigned_type (char32_type_size);
- if (cxx_dialect >= cxx0x)
+ if (cxx_dialect >= cxx11)
record_builtin_type (RID_CHAR32, "char32_t", char32_type_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)),
return NULL_TREE;
}
+/* Handle a "no_sanitize_address" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_sanitize_address_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "no_address_safety_analysis" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_address_safety_analysis_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ else if (!lookup_attribute ("no_sanitize_address", DECL_ATTRIBUTES (*node)))
+ DECL_ATTRIBUTES (*node)
+ = tree_cons (get_identifier ("no_sanitize_address"),
+ NULL_TREE, DECL_ATTRIBUTES (*node));
+ *no_add_attrs = true;
+ return NULL_TREE;
+}
+
+/* Handle a "no_sanitize_undefined" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_no_sanitize_undefined_attribute (tree *node, tree name, tree, int,
+ bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
/* Handle a "noinline" attribute; arguments as in
struct attribute_spec.handler. */
int ARG_UNUSED (flags), bool *no_add_attrs)
{
if (TREE_CODE (*node) == FUNCTION_DECL
- || TREE_CODE (TREE_VALUE (args)) == STRING_CST)
+ && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
/* Do nothing else, just set the attribute. We'll get at
it later with lookup_attribute. */
;
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;
{
int i;
- if (!INTEGRAL_TYPE_P (TREE_TYPE (align))
- || TREE_CODE (align) != INTEGER_CST)
+ if (TREE_CODE (align) != INTEGER_CST
+ || !INTEGRAL_TYPE_P (TREE_TYPE (align)))
{
error ("requested alignment is not an integer constant");
return -1;
}
else if (allow_zero && integer_zerop (align))
return -1;
- else if ((i = tree_log2 (align)) == -1)
+ else if (tree_int_cst_sgn (align) == -1
+ || (i = tree_log2 (align)) == -1)
{
- error ("requested alignment is not a power of 2");
+ error ("requested alignment is not a positive power of 2");
return -1;
}
else if (i >= HOST_BITS_PER_INT - BITS_PER_UNIT_LOG)
if (TREE_CODE (decl) == FUNCTION_DECL)
DECL_INITIAL (decl) = error_mark_node;
else
- {
- if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
- DECL_EXTERNAL (decl) = 1;
- else
- DECL_EXTERNAL (decl) = 0;
- TREE_STATIC (decl) = 1;
- }
+ TREE_STATIC (decl) = 1;
if (!is_alias)
/* ifuncs are also aliases, so set that attribute too. */
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");
return NULL_TREE;
}
+/* Handle a "bnd_variable_size" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_bnd_variable_size_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FIELD_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "bnd_legacy" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_bnd_legacy (tree *node, tree name, tree ARG_UNUSED (args),
+ int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle a "warn_unused" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_warn_unused_attribute (tree *node, tree name,
+ tree args ATTRIBUTE_UNUSED,
+ int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+ if (TYPE_P (*node))
+ /* Do nothing else, just set the attribute. We'll get at
+ it later with lookup_attribute. */
+ ;
+ else
+ {
+ warning (OPT_Wattributes, "%qE attribute ignored", name);
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
+
+/* Handle an "omp declare simd" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_omp_declare_simd_attribute (tree *, tree, tree, int, bool *)
+{
+ return NULL_TREE;
+}
+
+/* Handle an "omp declare target" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_omp_declare_target_attribute (tree *, tree, tree, int, bool *)
+{
+ return NULL_TREE;
+}
+
/* Handle a "returns_twice" attribute; arguments as in
struct attribute_spec.handler. */
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");
in position >= the number of fixed arguments. */
if ((nargs - 1 - pos) < len)
{
- warning (OPT_Wformat,
+ warning (OPT_Wformat_,
"not enough variable arguments to fit a sentinel");
return;
}
users to cast the NULL they have written there.
We warn with -Wstrict-null-sentinel, though. */
&& (warn_strict_null_sentinel || null_node != sentinel))
- warning (OPT_Wformat, "missing sentinel in function call");
+ warning (OPT_Wformat_, "missing sentinel in function call");
}
}
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
/* Arguments being collected for optimization. */
typedef const char *const_char_p; /* For DEF_VEC_P. */
-DEF_VEC_P(const_char_p);
-DEF_VEC_ALLOC_P(const_char_p, gc);
-static GTY(()) VEC(const_char_p, gc) *optimize_args;
+static GTY(()) vec<const_char_p, va_gc> *optimize_args;
/* Inner function to convert a TREE_LIST to argv string to parse the optimize
/* Build up argv vector. Just in case the string is stored away, use garbage
collected strings. */
- VEC_truncate (const_char_p, optimize_args, 0);
- VEC_safe_push (const_char_p, gc, optimize_args, NULL);
+ vec_safe_truncate (optimize_args, 0);
+ vec_safe_push (optimize_args, (const char *) NULL);
for (ap = args; ap != NULL_TREE; ap = TREE_CHAIN (ap))
{
{
char buffer[20];
sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value));
- VEC_safe_push (const_char_p, gc, optimize_args, ggc_strdup (buffer));
+ vec_safe_push (optimize_args, ggc_strdup (buffer));
}
else if (TREE_CODE (value) == STRING_CST)
memcpy (r, p, len2);
r[len2] = '\0';
- VEC_safe_push (const_char_p, gc, optimize_args, q);
+ vec_safe_push (optimize_args, (const char *) q);
}
}
}
- opt_argc = VEC_length (const_char_p, optimize_args);
+ opt_argc = optimize_args->length ();
opt_argv = (const char **) alloca (sizeof (char *) * (opt_argc + 1));
for (i = 1; i < opt_argc; i++)
- opt_argv[i] = VEC_index (const_char_p, optimize_args, i);
+ opt_argv[i] = (*optimize_args)[i];
saved_flag_strict_aliasing = flag_strict_aliasing;
/* Don't allow changing -fstrict-aliasing. */
flag_strict_aliasing = saved_flag_strict_aliasing;
- VEC_truncate (const_char_p, optimize_args, 0);
+ optimize_args->truncate (0);
return ret;
}
/* Parse options, and update the vector. */
parse_optimize_options (args, true);
DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
- = build_optimization_node ();
+ = build_optimization_node (&global_options);
/* Restore current options. */
cl_optimization_restore (&global_options, &cur_opts);
return NULL_TREE;
}
+
+/* Handle a "returns_nonnull" attribute; arguments as in
+ struct attribute_spec.handler. */
+
+static tree
+handle_returns_nonnull_attribute (tree *node, tree, tree, int,
+ bool *no_add_attrs)
+{
+ // Even without a prototype we still have a return type we can check.
+ if (TREE_CODE (TREE_TYPE (*node)) != POINTER_TYPE)
+ {
+ error ("returns_nonnull attribute on a function not returning a pointer");
+ *no_add_attrs = true;
+ }
+ return NULL_TREE;
+}
+
\f
/* Check for valid arguments being passed to a function with FNTYPE.
There are NARGS arguments in the array ARGARRAY. */
/* 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;
free (message);
message = NULL;
}
+ else if (token_type == CPP_CHAR_USERDEF
+ || token_type == CPP_WCHAR_USERDEF
+ || token_type == CPP_CHAR16_USERDEF
+ || token_type == CPP_CHAR32_USERDEF)
+ message = catenate_messages (gmsgid,
+ " before user-defined character literal");
+ else if (token_type == CPP_STRING_USERDEF
+ || token_type == CPP_WSTRING_USERDEF
+ || token_type == CPP_STRING16_USERDEF
+ || token_type == CPP_STRING32_USERDEF
+ || token_type == CPP_UTF8STRING_USERDEF)
+ message = catenate_messages (gmsgid, " before user-defined string literal");
else if (token_type == CPP_STRING
|| token_type == CPP_WSTRING
|| token_type == CPP_STRING16
{CPP_W_INVALID_PCH, OPT_Winvalid_pch},
{CPP_W_WARNING_DIRECTIVE, OPT_Wcpp},
{CPP_W_LITERAL_SUFFIX, OPT_Wliteral_suffix},
+ {CPP_W_DATE_TIME, OPT_Wdate_time},
{CPP_W_NONE, 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
"invalid type argument of %<->%> (have %qT)",
type);
break;
+ case RO_ARROW_STAR:
+ error_at (loc,
+ "invalid type argument of %<->*%> (have %qT)",
+ type);
+ break;
case RO_IMPLICIT_CONVERSION:
error_at (loc,
"invalid type argument of implicit conversion (have %qT)",
tree maxindex, type, main_type, elt, unqual_elt;
int failure = 0, quals;
hashval_t hashcode = 0;
+ bool overflow_p = false;
maxindex = size_zero_node;
if (initial_value)
}
else if (TREE_CODE (initial_value) == CONSTRUCTOR)
{
- VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value);
+ vec<constructor_elt, va_gc> *v = CONSTRUCTOR_ELTS (initial_value);
- if (VEC_empty (constructor_elt, v))
+ if (vec_safe_is_empty (v))
{
if (pedantic)
failure = 3;
constructor_elt *ce;
bool fold_p = false;
- if (VEC_index (constructor_elt, v, 0).index)
- maxindex = fold_convert_loc (input_location, sizetype,
- VEC_index (constructor_elt,
- v, 0).index);
+ if ((*v)[0].index)
+ maxindex = (*v)[0].index, fold_p = true;
+
curindex = maxindex;
- for (cnt = 1;
- VEC_iterate (constructor_elt, v, cnt, ce);
- cnt++)
+ for (cnt = 1; vec_safe_iterate (v, cnt, &ce); cnt++)
{
bool curfold_p = false;
if (ce->index)
else
{
if (fold_p)
- curindex = fold_convert (sizetype, curindex);
+ {
+ /* Since we treat size types now as ordinary
+ unsigned types, we need an explicit overflow
+ check. */
+ tree orig = curindex;
+ curindex = fold_convert (sizetype, curindex);
+ overflow_p |= tree_int_cst_lt (curindex, orig);
+ }
curindex = size_binop (PLUS_EXPR, curindex,
size_one_node);
}
if (tree_int_cst_lt (maxindex, curindex))
maxindex = curindex, fold_p = curfold_p;
}
- if (fold_p)
- maxindex = fold_convert (sizetype, maxindex);
+ if (fold_p)
+ {
+ tree orig = maxindex;
+ maxindex = fold_convert (sizetype, maxindex);
+ overflow_p |= tree_int_cst_lt (maxindex, orig);
+ }
}
}
else
if (COMPLETE_TYPE_P (type)
&& TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
- && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
+ && (overflow_p || TREE_OVERFLOW (TYPE_SIZE_UNIT (type))))
{
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;
}
Returns 0 if an error is encountered. */
static int
-sync_resolve_size (tree function, VEC(tree,gc) *params)
+sync_resolve_size (tree function, vec<tree, va_gc> *params)
{
tree type;
int size;
- if (VEC_empty (tree, params))
+ if (!params)
{
error ("too few arguments to function %qE", function);
return 0;
}
- type = TREE_TYPE (VEC_index (tree, params, 0));
+ type = TREE_TYPE ((*params)[0]);
if (TREE_CODE (type) != POINTER_TYPE)
goto incompatible;
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;
static bool
sync_resolve_params (location_t loc, tree orig_function, tree function,
- VEC(tree, gc) *params, bool orig_format)
+ vec<tree, va_gc> *params, bool orig_format)
{
function_args_iterator iter;
tree ptype;
as the pointer parameter, so we shouldn't get any complaints from the
call to check_function_arguments what ever type the user used. */
function_args_iter_next (&iter);
- ptype = TREE_TYPE (TREE_TYPE (VEC_index (tree, params, 0)));
+ ptype = TREE_TYPE (TREE_TYPE ((*params)[0]));
+ ptype = TYPE_MAIN_VARIANT (ptype);
/* For the rest of the values, we need to cast these to FTYPE, so that we
don't get warnings for passing pointer types, etc. */
break;
++parmnum;
- if (VEC_length (tree, params) <= parmnum)
+ if (params->length () <= parmnum)
{
error_at (loc, "too few arguments to function %qE", orig_function);
return false;
/* Ideally for the first conversion we'd use convert_for_assignment
so that we get warnings for anything that doesn't match the pointer
type. This isn't portable across the C and C++ front ends atm. */
- val = VEC_index (tree, params, parmnum);
+ val = (*params)[parmnum];
val = convert (ptype, val);
val = convert (arg_type, val);
- VEC_replace (tree, params, parmnum, val);
+ (*params)[parmnum] = val;
}
function_args_iter_next (&iter);
}
/* __atomic routines are not variadic. */
- if (!orig_format && VEC_length (tree, params) != parmnum + 1)
+ if (!orig_format && params->length () != parmnum + 1)
{
error_at (loc, "too many arguments to function %qE", orig_function);
return false;
being "an optional list of variables protected by the memory barrier".
No clue what that's supposed to mean, precisely, but we consider all
call-clobbered variables to be protected so we're safe. */
- VEC_truncate (tree, params, parmnum + 1);
+ params->truncate (parmnum + 1);
return true;
}
0 is returned if the parameters are invalid. */
static int
-get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
+get_atomic_generic_size (location_t loc, tree function,
+ vec<tree, va_gc> *params)
{
unsigned int n_param;
unsigned int n_model;
gcc_unreachable ();
}
- if (VEC_length (tree, params) != n_param)
+ if (vec_safe_length (params) != n_param)
{
error_at (loc, "incorrect number of arguments to function %qE", function);
return 0;
}
/* Get type of first parameter, and determine its size. */
- type_0 = TREE_TYPE (VEC_index (tree, params, 0));
+ type_0 = TREE_TYPE ((*params)[0]);
if (TREE_CODE (type_0) != POINTER_TYPE || VOID_TYPE_P (TREE_TYPE (type_0)))
{
error_at (loc, "argument 1 of %qE must be a non-void pointer type",
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)
for (x = 0; x < n_param - n_model; x++)
{
int size;
- tree type = TREE_TYPE (VEC_index (tree, params, x));
- /* __atomic_compare_exchange has a bool in the 4th postion, skip it. */
+ tree type = TREE_TYPE ((*params)[x]);
+ /* __atomic_compare_exchange has a bool in the 4th position, skip it. */
if (n_param == 6 && x == 3)
continue;
if (!POINTER_TYPE_P (type))
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,
/* Check memory model parameters for validity. */
for (x = n_param - n_model ; x < n_param; x++)
{
- tree p = VEC_index (tree, params, x);
+ tree p = (*params)[x];
if (TREE_CODE (p) == INTEGER_CST)
{
- int i = tree_low_cst (p, 1);
- if (i < 0 || i >= MEMMODEL_LAST)
+ int i = tree_to_uhwi (p);
+ if (i < 0 || (i & MEMMODEL_MASK) >= MEMMODEL_LAST)
{
warning_at (loc, OPT_Winvalid_memory_model,
"invalid memory model argument %d of %qE", x + 1,
static tree
add_atomic_size_parameter (unsigned n, location_t loc, tree function,
- VEC(tree,gc) *params)
+ vec<tree, va_gc> *params)
{
tree size_node;
/* Insert a SIZE_T parameter as the first param. If there isn't
enough space, allocate a new vector and recursively re-build with that. */
- if (!VEC_space (tree, params, 1))
+ if (!params->space (1))
{
unsigned int z, len;
- VEC(tree,gc) *vec;
+ vec<tree, va_gc> *v;
tree f;
- len = VEC_length (tree, params);
- vec = VEC_alloc (tree, gc, len + 1);
+ len = params->length ();
+ vec_alloc (v, len + 1);
for (z = 0; z < len; z++)
- VEC_quick_push (tree, vec, VEC_index (tree, params, z));
- f = build_function_call_vec (loc, function, vec, NULL);
- VEC_free (tree, gc, vec);
+ v->quick_push ((*params)[z]);
+ f = build_function_call_vec (loc, function, v, NULL);
+ vec_free (v);
return f;
}
/* Add the size parameter and leave as a function call for processing. */
size_node = build_int_cst (size_type_node, n);
- VEC_quick_insert (tree, params, 0, size_node);
+ params->quick_insert (0, size_node);
return NULL_TREE;
}
+/* Return whether atomic operations for naturally aligned N-byte
+ arguments are supported, whether inline or through libatomic. */
+static bool
+atomic_size_supported_p (int n)
+{
+ switch (n)
+ {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ return true;
+
+ case 16:
+ return targetm.scalar_mode_supported_p (TImode);
+
+ default:
+ return false;
+ }
+}
+
/* This will process an __atomic_exchange function call, determine whether it
needs to be mapped to the _N variation, or turned into a library call.
LOC is the location of the builtin call.
NEW_RETURN is set to the the return value the result is copied into. */
static bool
resolve_overloaded_atomic_exchange (location_t loc, tree function,
- VEC(tree,gc) *params, tree *new_return)
+ vec<tree, va_gc> *params, tree *new_return)
{
tree p0, p1, p2, p3;
tree I_type, I_type_ptr;
}
/* If not a lock-free size, change to the library generic format. */
- if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+ if (!atomic_size_supported_p (n))
{
*new_return = add_atomic_size_parameter (n, loc, function, params);
return true;
into
*return = (T) (fn (In* mem, (In) *desired, model)) */
- p0 = VEC_index (tree, params, 0);
- p1 = VEC_index (tree, params, 1);
- p2 = VEC_index (tree, params, 2);
- p3 = VEC_index (tree, params, 3);
+ p0 = (*params)[0];
+ p1 = (*params)[1];
+ p2 = (*params)[2];
+ p3 = (*params)[3];
/* Create pointer to appropriate size. */
I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
/* Convert object pointer to required type. */
p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
- VEC_replace (tree, params, 0, p0);
+ (*params)[0] = p0;
/* Convert new value to required type, and dereference it. */
p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
- VEC_replace (tree, params, 1, p1);
+ (*params)[1] = p1;
/* Move memory model to the 3rd position, and end param list. */
- VEC_replace (tree, params, 2, p3);
- VEC_truncate (tree, params, 3);
+ (*params)[2] = p3;
+ params->truncate (3);
/* Convert return pointer and dereference it for later assignment. */
*new_return = build_indirect_ref (loc, p2, RO_UNARY_STAR);
static bool
resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
- VEC(tree,gc) *params,
+ vec<tree, va_gc> *params,
tree *new_return)
{
tree p0, p1, p2;
}
/* If not a lock-free size, change to the library generic format. */
- if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+ if (!atomic_size_supported_p (n))
{
/* The library generic format does not have the weak parameter, so
remove it from the param list. Since a parameter has been removed,
there is no danger this will be done twice. */
if (n > 0)
{
- VEC_replace (tree, params, 3, VEC_index (tree, params, 4));
- VEC_replace (tree, params, 4, VEC_index (tree, params, 5));
- VEC_truncate (tree, params, 5);
+ (*params)[3] = (*params)[4];
+ (*params)[4] = (*params)[5];
+ params->truncate (5);
}
*new_return = add_atomic_size_parameter (n, loc, function, params);
return true;
into
bool fn ((In *)mem, (In *)expected, (In) *desired, weak, succ, fail) */
- p0 = VEC_index (tree, params, 0);
- p1 = VEC_index (tree, params, 1);
- p2 = VEC_index (tree, params, 2);
+ p0 = (*params)[0];
+ p1 = (*params)[1];
+ p2 = (*params)[2];
/* Create pointer to appropriate size. */
I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
/* Convert object pointer to required type. */
p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
- VEC_replace (tree, params, 0, p0);
+ (*params)[0] = p0;
/* Convert expected pointer to required type. */
p1 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1);
- VEC_replace (tree, params, 1, p1);
+ (*params)[1] = p1;
/* Convert desired value to required type, and dereference it. */
p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR);
p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2);
- VEC_replace (tree, params, 2, p2);
+ (*params)[2] = p2;
/* The rest of the parameters are fine. NULL means no special return value
processing.*/
static bool
resolve_overloaded_atomic_load (location_t loc, tree function,
- VEC(tree,gc) *params, tree *new_return)
+ vec<tree, va_gc> *params, tree *new_return)
{
tree p0, p1, p2;
tree I_type, I_type_ptr;
}
/* If not a lock-free size, change to the library generic format. */
- if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+ if (!atomic_size_supported_p (n))
{
*new_return = add_atomic_size_parameter (n, loc, function, params);
return true;
into
*return = (T) (fn ((In *) mem, model)) */
- p0 = VEC_index (tree, params, 0);
- p1 = VEC_index (tree, params, 1);
- p2 = VEC_index (tree, params, 2);
+ p0 = (*params)[0];
+ p1 = (*params)[1];
+ p2 = (*params)[2];
/* Create pointer to appropriate size. */
I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
/* Convert object pointer to required type. */
p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
- VEC_replace (tree, params, 0, p0);
+ (*params)[0] = p0;
/* Move memory model to the 2nd position, and end param list. */
- VEC_replace (tree, params, 1, p2);
- VEC_truncate (tree, params, 2);
+ (*params)[1] = p2;
+ params->truncate (2);
/* Convert return pointer and dereference it for later assignment. */
*new_return = build_indirect_ref (loc, p1, RO_UNARY_STAR);
static bool
resolve_overloaded_atomic_store (location_t loc, tree function,
- VEC(tree,gc) *params, tree *new_return)
+ vec<tree, va_gc> *params, tree *new_return)
{
tree p0, p1;
tree I_type, I_type_ptr;
}
/* If not a lock-free size, change to the library generic format. */
- if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
+ if (!atomic_size_supported_p (n))
{
*new_return = add_atomic_size_parameter (n, loc, function, params);
return true;
into
fn ((In *) mem, (In) *value, model) */
- p0 = VEC_index (tree, params, 0);
- p1 = VEC_index (tree, params, 1);
+ p0 = (*params)[0];
+ p1 = (*params)[1];
/* Create pointer to appropriate size. */
I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
/* Convert object pointer to required type. */
p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
- VEC_replace (tree, params, 0, p0);
+ (*params)[0] = p0;
/* Convert new value to required type, and dereference it. */
p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
- VEC_replace (tree, params, 1, p1);
+ (*params)[1] = p1;
/* The memory model is in the right spot already. Return is void. */
*new_return = NULL_TREE;
continue. */
tree
-resolve_overloaded_builtin (location_t loc, tree function, VEC(tree,gc) *params)
+resolve_overloaded_builtin (location_t loc, tree function,
+ vec<tree, va_gc> *params)
{
enum built_in_function orig_code = DECL_FUNCTION_CODE (function);
bool orig_format = true;
orig_format))
return error_mark_node;
- first_param = VEC_index (tree, params, 0);
+ first_param = (*params)[0];
result = build_function_call_vec (loc, new_function, params, NULL);
if (result == error_mark_node)
return result;
}
}
-/* Ignoring their sign, return true if two scalar types are the same. */
+/* vector_types_compatible_elements_p is used in type checks of vectors
+ values used as operands of binary operators. Where it returns true, and
+ the other checks of the caller succeed (being vector types in he first
+ place, and matching number of elements), we can just treat the types
+ as essentially the same.
+ Contrast with vector_targets_convertible_p, which is used for vector
+ pointer types, and vector_types_convertible_p, which will allow
+ language-specific matches under the control of flag_lax_vector_conversions,
+ and might still require a conversion. */
+/* True if vector types T1 and T2 can be inputs to the same binary
+ operator without conversion.
+ We don't check the overall vector size here because some of our callers
+ want to give different error messages when the vectors are compatible
+ except for the element count. */
+
bool
-same_scalar_type_ignoring_signedness (tree t1, tree t2)
+vector_types_compatible_elements_p (tree t1, tree t2)
{
+ bool opaque = TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2);
+ t1 = TREE_TYPE (t1);
+ t2 = TREE_TYPE (t2);
+
enum tree_code c1 = TREE_CODE (t1), c2 = TREE_CODE (t2);
gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE || c1 == FIXED_POINT_TYPE)
&& (c2 == INTEGER_TYPE || c2 == REAL_TYPE
|| c2 == FIXED_POINT_TYPE));
+ t1 = c_common_signed_type (t1);
+ t2 = c_common_signed_type (t2);
/* Equality works here because c_common_signed_type uses
TYPE_MAIN_VARIANT. */
- return c_common_signed_type (t1)
- == c_common_signed_type (t2);
+ if (t1 == t2)
+ return true;
+ if (opaque && c1 == c2
+ && (c1 == INTEGER_TYPE || c1 == REAL_TYPE)
+ && TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
+ return true;
+ return false;
}
/* Check for missing format attributes on function pointers. LTYPE is
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));
{
gcc_assert (decl && DECL_P (decl) && TREE_STATIC (decl));
- while (!VEC_empty (tree, types_used_by_cur_var_decl))
+ while (types_used_by_cur_var_decl && !types_used_by_cur_var_decl->is_empty ())
{
- tree type = VEC_pop (tree, types_used_by_cur_var_decl);
+ tree type = types_used_by_cur_var_decl->pop ();
types_used_by_var_decl_insert (type, decl);
}
}
return;
l = (struct c_language_function *) cfun->language;
- VEC_safe_push (tree, gc, l->local_typedefs, decl);
+ vec_safe_push (l->local_typedefs, decl);
}
/* If T is a TYPE_DECL declared locally, mark it as used. */
if (warn_unused_local_typedefs
&& errorcount == unused_local_typedefs_warn_count)
{
- FOR_EACH_VEC_ELT (tree, l->local_typedefs, i, decl)
+ FOR_EACH_VEC_SAFE_ELT (l->local_typedefs, i, decl)
if (!TREE_USED (decl))
warning_at (DECL_SOURCE_LOCATION (decl),
OPT_Wunused_local_typedefs,
unused_local_typedefs_warn_count = errorcount;
}
- if (l->local_typedefs)
- {
- VEC_free (tree, gc, l->local_typedefs);
- l->local_typedefs = NULL;
- }
+ vec_free (l->local_typedefs);
}
/* The C and C++ parsers both use vectors to hold function arguments.
For efficiency, we keep a cache of unused vectors. This is the
cache. */
-typedef VEC(tree,gc)* tree_gc_vec;
-DEF_VEC_P(tree_gc_vec);
-DEF_VEC_ALLOC_P(tree_gc_vec,gc);
-static GTY((deletable)) VEC(tree_gc_vec,gc) *tree_vector_cache;
+typedef vec<tree, va_gc> *tree_gc_vec;
+static GTY((deletable)) vec<tree_gc_vec, va_gc> *tree_vector_cache;
/* Return a new vector from the cache. If the cache is empty,
allocate a new vector. These vectors are GC'ed, so it is OK if the
pointer is not released.. */
-VEC(tree,gc) *
+vec<tree, va_gc> *
make_tree_vector (void)
{
- if (!VEC_empty (tree_gc_vec, tree_vector_cache))
- return VEC_pop (tree_gc_vec, tree_vector_cache);
+ if (tree_vector_cache && !tree_vector_cache->is_empty ())
+ return tree_vector_cache->pop ();
else
{
- /* Passing 0 to VEC_alloc returns NULL, and our callers require
+ /* Passing 0 to vec::alloc returns NULL, and our callers require
that we always return a non-NULL value. The vector code uses
4 when growing a NULL vector, so we do too. */
- return VEC_alloc (tree, gc, 4);
+ vec<tree, va_gc> *v;
+ vec_alloc (v, 4);
+ return v;
}
}
/* Release a vector of trees back to the cache. */
void
-release_tree_vector (VEC(tree,gc) *vec)
+release_tree_vector (vec<tree, va_gc> *vec)
{
if (vec != NULL)
{
- VEC_truncate (tree, vec, 0);
- VEC_safe_push (tree_gc_vec, gc, tree_vector_cache, vec);
+ vec->truncate (0);
+ vec_safe_push (tree_vector_cache, vec);
}
}
/* Get a new tree vector holding a single tree. */
-VEC(tree,gc) *
+vec<tree, va_gc> *
make_tree_vector_single (tree t)
{
- VEC(tree,gc) *ret = make_tree_vector ();
- VEC_quick_push (tree, ret, t);
+ vec<tree, va_gc> *ret = make_tree_vector ();
+ ret->quick_push (t);
return ret;
}
/* Get a new tree vector of the TREE_VALUEs of a TREE_LIST chain. */
-VEC(tree,gc) *
+vec<tree, va_gc> *
make_tree_vector_from_list (tree list)
{
- VEC(tree,gc) *ret = make_tree_vector ();
+ vec<tree, va_gc> *ret = make_tree_vector ();
for (; list; list = TREE_CHAIN (list))
- VEC_safe_push (tree, gc, ret, TREE_VALUE (list));
+ vec_safe_push (ret, TREE_VALUE (list));
return ret;
}
/* Get a new tree vector which is a copy of an existing one. */
-VEC(tree,gc) *
-make_tree_vector_copy (const VEC(tree,gc) *orig)
+vec<tree, va_gc> *
+make_tree_vector_copy (const vec<tree, va_gc> *orig)
{
- VEC(tree,gc) *ret;
+ vec<tree, va_gc> *ret;
unsigned int ix;
tree t;
ret = make_tree_vector ();
- VEC_reserve (tree, gc, ret, VEC_length (tree, orig));
- FOR_EACH_VEC_ELT (tree, orig, ix, t)
- VEC_quick_push (tree, ret, t);
+ vec_safe_reserve (ret, vec_safe_length (orig));
+ FOR_EACH_VEC_SAFE_ELT (orig, ix, t)
+ ret->quick_push (t);
return ret;
}
{
switch (keyword)
{
+ case RID_AUTO_TYPE:
case RID_INT:
case RID_CHAR:
case RID_FLOAT:
case RID_CONST:
case RID_VOLATILE:
case RID_RESTRICT:
+ case RID_ATOMIC:
return true;
default:
return false;
{
MARK_TS_TYPED (C_MAYBE_CONST_EXPR);
MARK_TS_TYPED (EXCESS_PRECISION_EXPR);
+ MARK_TS_TYPED (ARRAY_NOTATION_REF);
}
/* Build a user-defined numeric literal out of an integer constant type VALUE
with identifier SUFFIX. */
tree
-build_userdef_literal (tree suffix_id, tree value, tree num_string)
+build_userdef_literal (tree suffix_id, tree value,
+ enum overflow_type overflow, tree num_string)
{
tree literal = make_node (USERDEF_LITERAL);
USERDEF_LITERAL_SUFFIX_ID (literal) = suffix_id;
USERDEF_LITERAL_VALUE (literal) = value;
+ USERDEF_LITERAL_OVERFLOW (literal) = overflow;
USERDEF_LITERAL_NUM_STRING (literal) = num_string;
return literal;
}
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);