{ "char32_t", RID_CHAR32, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "class", RID_CLASS, D_CXX_OBJC | D_CXXWARN },
{ "const", RID_CONST, 0 },
+ { "constexpr", RID_CONSTEXPR, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "const_cast", RID_CONSTCAST, D_CXXONLY | D_CXXWARN },
{ "continue", RID_CONTINUE, 0 },
{ "decltype", RID_DECLTYPE, D_CXXONLY | D_CXX0X | D_CXXWARN },
{ "inout", RID_INOUT, D_OBJC },
{ "oneway", RID_ONEWAY, D_OBJC },
{ "out", RID_OUT, D_OBJC },
+
+#ifdef TARGET_ADDR_SPACE_KEYWORDS
+ /* Any address space keywords recognized by the target. */
+ TARGET_ADDR_SPACE_KEYWORDS,
+#endif
};
const unsigned int num_c_common_reswords =
{ NULL, 0, 0, false, false, false, NULL }
};
+/* Return identifier for address space AS. */
+const char *
+c_addr_space_name (addr_space_t as)
+{
+ unsigned int i;
+
+ for (i = 0; i < num_c_common_reswords; i++)
+ if (c_common_reswords[i].rid == RID_FIRST_ADDR_SPACE + as)
+ return c_common_reswords[i].word;
+
+ gcc_unreachable ();
+}
+
/* Push current bindings for the function name VAR_DECLS. */
void
op2 = TREE_OPERAND (expr, 2);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
if (op0 != orig_op0)
ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
if (ret != expr)
op3 = TREE_OPERAND (expr, 3);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op1);
op1 = decl_constant_value_for_optimization (op1);
if (op0 != orig_op0 || op1 != orig_op1)
ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
orig_op1 = op1 = TREE_OPERAND (expr, 1);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
if (code != MODIFY_EXPR
&& code != PREDECREMENT_EXPR
&& code != PREINCREMENT_EXPR
if (code != MODIFY_EXPR)
op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op1);
op1 = decl_constant_value_for_optimization (op1);
if (op0 != orig_op0 || op1 != orig_op1 || in_init)
ret = in_init
orig_op0 = op0 = TREE_OPERAND (expr, 0);
op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
maybe_const_itself);
+ STRIP_TYPE_NOPS (op0);
if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR)
op0 = decl_constant_value_for_optimization (op0);
if (op0 != orig_op0 || in_init)
orig_op0 = op0 = TREE_OPERAND (expr, 0);
orig_op1 = op1 = TREE_OPERAND (expr, 1);
op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+ STRIP_TYPE_NOPS (op0);
unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
? truthvalue_false_node
: truthvalue_true_node));
c_inhibit_evaluation_warnings += unused_p;
op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+ STRIP_TYPE_NOPS (op1);
c_inhibit_evaluation_warnings -= unused_p;
if (op0 != orig_op0 || op1 != orig_op1 || in_init)
orig_op2 = op2 = TREE_OPERAND (expr, 2);
op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
+ STRIP_TYPE_NOPS (op0);
c_inhibit_evaluation_warnings += (op0 == truthvalue_false_node);
op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
+ STRIP_TYPE_NOPS (op1);
c_inhibit_evaluation_warnings -= (op0 == truthvalue_false_node);
c_inhibit_evaluation_warnings += (op0 == truthvalue_true_node);
op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self);
+ STRIP_TYPE_NOPS (op2);
c_inhibit_evaluation_warnings -= (op0 == truthvalue_true_node);
if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
void
constant_expression_warning (tree value)
{
- if (warn_overflow && pedantic
+ if (warn_overflow && pedantic
&& (TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
|| TREE_CODE (value) == FIXED_CST
|| TREE_CODE (value) == VECTOR_CST
case INTEGER_CST:
warning_at (loc, OPT_Woverflow, "integer overflow in expression");
break;
-
+
case REAL_CST:
warning_at (loc, OPT_Woverflow,
"floating point overflow in expression");
break;
-
+
case FIXED_CST:
warning_at (loc, OPT_Woverflow, "fixed-point overflow in expression");
break;
case VECTOR_CST:
warning_at (loc, OPT_Woverflow, "vector overflow in expression");
break;
-
+
case COMPLEX_CST:
if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)
warning_at (loc, OPT_Woverflow,
had CODE_LEFT and CODE_RIGHT, into an expression of type TYPE. */
void
warn_logical_operator (location_t location, enum tree_code code, tree type,
- enum tree_code code_left, tree op_left,
+ enum tree_code code_left, tree op_left,
enum tree_code ARG_UNUSED (code_right), tree op_right)
{
int or_op = (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR);
if (rhs && TREE_CODE (rhs) == C_MAYBE_CONST_EXPR)
rhs = C_MAYBE_CONST_EXPR_EXPR (rhs);
-
+
/* If this is an OR operation, invert both sides; we will invert
again at the end. */
if (or_op)
in0_p = !in0_p, in1_p = !in1_p;
-
+
/* If both expressions are the same, if we can merge the ranges, and we
can build the range test, return it or it inverted. */
if (lhs && rhs && operand_equal_p (lhs, rhs, 0)
}
else
{
- /* warn_strict_aliasing >= 3. This includes the default (3).
+ /* warn_strict_aliasing >= 3. This includes the default (3).
Only warn if the cast is dereferenced immediately. */
alias_set_type set1 =
get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
{
case 1:
if (TYPE_MAIN_VARIANT (type) != integer_type_node)
- pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %<int%>",
+ pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %<int%>",
decl);
break;
both args are zero-extended or both are sign-extended.
Otherwise, we might change the result.
Eg, (short)-1 | (unsigned short)-1 is (int)-1
- but calculated in (unsigned short) it would be (unsigned short)-1.
+ but calculated in (unsigned short) it would be (unsigned short)-1.
*/
tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
{
from signed char and that RESULT_TYPE is long long int.
If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
like
-
+
(long long int) (unsigned int) signed_char
which get_narrower would narrow down to
-
+
(unsigned int) signed char
-
+
If we do not cast OP0 first, get_narrower would return
signed_char, which is inconsistent with the case of the
explicit cast. */
/* Handle the case that OP0 (or OP1) does not *contain* a conversion
but it *requires* conversion to FINAL_TYPE. */
-
+
if ((TYPE_PRECISION (TREE_TYPE (op0))
== TYPE_PRECISION (TREE_TYPE (arg0)))
&& TREE_TYPE (op0) != result_type)
== TYPE_PRECISION (TREE_TYPE (arg1)))
&& TREE_TYPE (op1) != result_type)
unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
-
+
/* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE. */
-
+
/* For bitwise operations, signedness of nominal type
does not matter. Consider only how operands were extended. */
if (bitwise)
uns = unsigned0;
-
+
/* Note that in all three cases below we refrain from optimizing
an unsigned operation on sign-extended args.
That would not be valid. */
-
+
/* Both args variable: if both extended in same way
from same width, do it in that width.
Do it unsigned if args were zero-extended. */
/* Conversion from boolean to a signed:1 bit-field (which only
can hold the values 0 and -1) doesn't lose information - but
it does change the value. */
- if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
+ if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
warning (OPT_Wconversion,
"conversion to %qT from boolean expression", type);
return;
&& TREE_CODE (type) == INTEGER_TYPE
&& !int_fits_type_p (expr, type))
{
- if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)
+ if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)
&& tree_int_cst_sgn (expr) < 0)
warning (OPT_Wsign_conversion,
"negative integer implicitly converted to unsigned type");
tree op1 = TREE_OPERAND (expr, 1);
tree op2 = TREE_OPERAND (expr, 2);
- if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST
+ 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))
expr_type = TREE_TYPE (expr);
/* Don't warn for short y; short x = ((int)y & 0xff); */
- if (TREE_CODE (expr) == BIT_AND_EXPR
- || TREE_CODE (expr) == BIT_IOR_EXPR
+ if (TREE_CODE (expr) == BIT_AND_EXPR
+ || TREE_CODE (expr) == BIT_IOR_EXPR
|| TREE_CODE (expr) == BIT_XOR_EXPR)
{
/* If both args were extended from a shortest type,
use that type if that is safe. */
- expr_type = shorten_binary_op (expr_type,
- TREE_OPERAND (expr, 0),
- TREE_OPERAND (expr, 1),
+ expr_type = shorten_binary_op (expr_type,
+ TREE_OPERAND (expr, 0),
+ TREE_OPERAND (expr, 1),
/* bitwise */1);
if (TREE_CODE (expr) == BIT_AND_EXPR)
&& int_fits_type_p (op0, c_common_unsigned_type (type)))
|| (TREE_CODE (op1) == INTEGER_CST
&& int_fits_type_p (op1, c_common_signed_type (type))
- && int_fits_type_p (op1,
+ && int_fits_type_p (op1,
c_common_unsigned_type (type))))
return;
/* If constant is unsigned and fits in the target
type, then the result will also fit. */
else if ((TREE_CODE (op0) == INTEGER_CST
- && unsigned0
+ && unsigned0
&& int_fits_type_p (op0, type))
|| (TREE_CODE (op1) == INTEGER_CST
&& unsigned1
}
}
/* Warn for integer types converted to smaller integer types. */
- if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
+ if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
give_warning = true;
/* When they are the same width but different signedness,
{
tree type_low_bound = TYPE_MIN_VALUE (expr_type);
tree type_high_bound = TYPE_MAX_VALUE (expr_type);
- REAL_VALUE_TYPE real_low_bound
+ REAL_VALUE_TYPE real_low_bound
= real_value_from_int_cst (0, type_low_bound);
- REAL_VALUE_TYPE real_high_bound
+ REAL_VALUE_TYPE real_high_bound
= real_value_from_int_cst (0, type_high_bound);
if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
else
conversion_warning (type, expr);
}
- else if (!int_fits_type_p (expr, c_common_unsigned_type (type)))
+ else if (!int_fits_type_p (expr, c_common_unsigned_type (type)))
warning (OPT_Woverflow,
"overflow in implicit constant conversion");
/* No warning for converting 0x80000000 to int. */
if (TREE_TYPE (expr) == type)
return expr;
-
+
result = convert (type, expr);
if (c_inhibit_evaluation_warnings == 0
{
call_expr_arg_iterator iter;
tree arg;
- tmp_before = tmp_nosp = 0;
+ tmp_before = tmp_nosp = 0;
verify_tree (CALL_EXPR_FN (x), &tmp_before, &tmp_nosp, NULL_TREE);
FOR_EACH_CALL_EXPR_ARG (arg, iter, x)
{
&& !(TREE_CODE (primop0) == INTEGER_CST
&& !TREE_OVERFLOW (convert (c_common_signed_type (type),
primop0))))
- warning (OPT_Wtype_limits,
+ warning (OPT_Wtype_limits,
"comparison of unsigned expression >= 0 is always true");
value = truthvalue_true_node;
break;
&& !(TREE_CODE (primop0) == INTEGER_CST
&& !TREE_OVERFLOW (convert (c_common_signed_type (type),
primop0))))
- warning (OPT_Wtype_limits,
+ warning (OPT_Wtype_limits,
"comparison of unsigned expression < 0 is always false");
value = truthvalue_false_node;
break;
if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
{
- pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"pointer of type %<void *%> used in arithmetic");
size_exp = integer_one_node;
}
else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
{
- pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : 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_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"pointer to member function used in arithmetic");
size_exp = integer_one_node;
}
return ret;
}
\f
+/* Wrap a C_MAYBE_CONST_EXPR around an expression that is fully folded
+ and if NON_CONST is known not to be permitted in an evaluated part
+ of a constant expression. */
+
+tree
+c_wrap_maybe_const (tree expr, bool non_const)
+{
+ bool nowarning = TREE_NO_WARNING (expr);
+ location_t loc = EXPR_LOCATION (expr);
+
+ /* This should never be called for C++. */
+ if (c_dialect_cxx ())
+ gcc_unreachable ();
+
+ /* The result of folding may have a NOP_EXPR to set TREE_NO_WARNING. */
+ STRIP_TYPE_NOPS (expr);
+ expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
+ C_MAYBE_CONST_EXPR_NON_CONST (expr) = non_const;
+ if (nowarning)
+ TREE_NO_WARNING (expr) = 1;
+ protected_set_expr_location (expr, loc);
+
+ return expr;
+}
+
/* Wrap a SAVE_EXPR around EXPR, if appropriate. Like save_expr, but
for C folds the inside expression and wraps a C_MAYBE_CONST_EXPR
around the SAVE_EXPR if needed so that c_fully_fold does not need
expr = c_fully_fold (expr, false, &maybe_const);
expr = save_expr (expr);
if (!maybe_const)
- {
- expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
- C_MAYBE_CONST_EXPR_NON_CONST (expr) = 1;
- }
+ expr = c_wrap_maybe_const (expr, true);
return expr;
}
if (TREE_TYPE (expr) == truthvalue_type_node)
return expr;
expr = build2 (TREE_CODE (expr), truthvalue_type_node,
- c_common_truthvalue_conversion (location,
+ c_common_truthvalue_conversion (location,
TREE_OPERAND (expr, 0)),
c_common_truthvalue_conversion (location,
TREE_OPERAND (expr, 1)));
{
expr = build2 (COMPOUND_EXPR, truthvalue_type_node,
TREE_OPERAND (expr, 1),
- c_common_truthvalue_conversion
+ c_common_truthvalue_conversion
(location, TREE_OPERAND (expr, 0)));
goto ret;
}
tree u;
PTR *slot;
+ /* For VLAs, use the alias set of the element type rather than the
+ default of alias set 0 for types compared structurally. */
+ if (TYPE_P (t) && TYPE_STRUCTURAL_EQUALITY_P (t))
+ {
+ if (TREE_CODE (t) == ARRAY_TYPE)
+ return get_alias_set (TREE_TYPE (t));
+ return -1;
+ }
+
/* Permit type-punning when accessing a union, provided the access
is directly through the union. For example, this code does not
permit taking the address of a union member and then storing
if (is_sizeof)
{
if (complain && (pedantic || warn_pointer_arith))
- pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"invalid application of %<sizeof%> to a function type");
else if (!complain)
return error_mark_node;
{
if (type_code == VOID_TYPE
&& complain && (pedantic || warn_pointer_arith))
- pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
+ pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
"invalid application of %qs to a void type", op_name);
else if (!complain)
return error_mark_node;
targetm.init_builtins ();
- build_common_builtin_nodes (c_dialect_cxx ());
+ build_common_builtin_nodes ();
if (flag_mudflap)
mudflap_init ();
/* Only supported decimal floating point extension if the target
actually supports underlying modes. */
- if (targetm.scalar_mode_supported_p (SDmode)
+ if (targetm.scalar_mode_supported_p (SDmode)
&& targetm.scalar_mode_supported_p (DDmode)
&& targetm.scalar_mode_supported_p (TDmode))
{
memset (builtin_types, 0, sizeof (builtin_types));
}
-/* Look up the function in built_in_decls that corresponds to DECL
- and set ASMSPEC as its user assembler name. DECL must be a
- function decl that declares a builtin. */
-
-void
-set_builtin_user_assembler_name (tree decl, const char *asmspec)
-{
- tree builtin;
- gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
- && asmspec != 0);
-
- builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
- set_user_assembler_name (builtin, asmspec);
- switch (DECL_FUNCTION_CODE (decl))
- {
- case BUILT_IN_MEMCPY:
- init_block_move_fn (asmspec);
- memcpy_libfunc = set_user_assembler_libfunc ("memcpy", asmspec);
- break;
- case BUILT_IN_MEMSET:
- init_block_clear_fn (asmspec);
- memset_libfunc = set_user_assembler_libfunc ("memset", asmspec);
- break;
- case BUILT_IN_MEMMOVE:
- memmove_libfunc = set_user_assembler_libfunc ("memmove", asmspec);
- break;
- case BUILT_IN_MEMCMP:
- memcmp_libfunc = set_user_assembler_libfunc ("memcmp", asmspec);
- break;
- case BUILT_IN_ABORT:
- abort_libfunc = set_user_assembler_libfunc ("abort", asmspec);
- break;
- default:
- break;
- }
-}
-
/* The number of named compound-literals generated thus far. */
static GTY(()) int compound_literal_number;
/* Case ranges are a GNU extension. */
if (high_value)
- pedwarn (loc, OPT_pedantic,
+ pedwarn (loc, OPT_pedantic,
"range expressions in switch statements are non-standard");
type = TREE_TYPE (cond);
{
TREE_USED (label) = 1;
result = build1 (ADDR_EXPR, ptr_type_node, label);
- /* The current function in not necessarily uninlinable.
+ /* The current function is not necessarily uninlinable.
Computed gotos are incompatible with inlining, but the value
here could be used only in a diagnostic, for example. */
protected_set_expr_location (result, loc);
*node = type = build_duplicate_type (type);
}
- TYPE_TRANSPARENT_UNION (type) = 1;
+ TYPE_TRANSPARENT_AGGR (type) = 1;
return NULL_TREE;
}
if (!args)
return DEFAULT_INIT_PRIORITY;
-
+
if (!SUPPORTS_INIT_PRIORITY)
{
if (is_destructor)
if (is_destructor)
warning (0,
"destructor priorities from 0 to %d are reserved "
- "for the implementation",
+ "for the implementation",
MAX_RESERVED_INIT_PRIORITY);
else
warning (0,
"constructor priorities from 0 to %d are reserved "
- "for the implementation",
+ "for the implementation",
MAX_RESERVED_INIT_PRIORITY);
}
return pri;
if (POINTER_TYPE_P (type))
{
+ addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
tree (*fn)(tree, enum machine_mode, bool);
- if (!targetm.valid_pointer_mode (mode))
+ if (!targetm.addr_space.valid_pointer_mode (mode, as))
{
error ("invalid pointer mode %qs", p);
return NULL_TREE;
&& current_function_decl != NULL_TREE
&& !TREE_STATIC (decl))
{
- error_at (DECL_SOURCE_LOCATION (decl),
+ error_at (DECL_SOURCE_LOCATION (decl),
"section attribute cannot be specified for "
"local variables");
*no_add_attrs = true;
*no_add_attrs = true;
}
else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
- || (TREE_CODE (decl) != FUNCTION_DECL
+ || (TREE_CODE (decl) != FUNCTION_DECL
&& TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
/* A static variable declaration is always a tentative definition,
but the alias is a non-tentative definition which overrides. */
- || (TREE_CODE (decl) != FUNCTION_DECL
+ || (TREE_CODE (decl) != FUNCTION_DECL
&& ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
{
error ("%q+D defined both normally and as an alias", decl);
tree position = TREE_VALUE (args);
if (TREE_CODE (position) != INTEGER_CST
- || TREE_INT_CST_HIGH (position)
+ || TREE_INT_CST_HIGH (position)
|| TREE_INT_CST_LOW (position) < 1
|| TREE_INT_CST_LOW (position) > arg_count )
{
- warning (OPT_Wattributes,
+ warning (OPT_Wattributes,
"alloc_size parameter outside range");
*no_add_attrs = true;
return NULL_TREE;
if (TREE_CODE (position) != INTEGER_CST)
{
- warning (OPT_Wattributes,
+ warning (OPT_Wattributes,
"requested position is not an integer constant");
*no_add_attrs = true;
}
bool * ARG_UNUSED (no_add_attrs))
{
tree params;
-
+
/* Ensure we have a function type. */
gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
-
+
params = TYPE_ARG_TYPES (*node);
while (params && ! VOID_TYPE_P (TREE_VALUE (params)))
params = TREE_CHAIN (params);
/* Now parse the options. */
decode_options (opt_argc, opt_argv);
+ targetm.override_options_after_change();
+
/* Don't allow changing -fstrict-aliasing. */
flag_strict_aliasing = saved_flag_strict_aliasing;
if (validate_nargs (fndecl, nargs, 6))
{
unsigned i;
-
+
for (i=0; i<5; i++)
if (TREE_CODE (args[i]) != INTEGER_CST)
{
TOKEN, which had the associated VALUE. */
void
-c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
+c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
tree value, unsigned char token_flags)
{
#define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
if (token_type == CPP_EOF)
message = catenate_messages (gmsgid, " at end of input");
- else if (token_type == CPP_CHAR
- || token_type == CPP_WCHAR
+ else if (token_type == CPP_CHAR
+ || token_type == CPP_WCHAR
|| token_type == CPP_CHAR16
|| token_type == CPP_CHAR32)
{
free (message);
message = NULL;
}
- else if (token_type == CPP_STRING
- || token_type == CPP_WSTRING
+ else if (token_type == CPP_STRING
+ || token_type == CPP_WSTRING
|| token_type == CPP_STRING16
- || token_type == CPP_STRING32)
+ || token_type == CPP_STRING32
+ || token_type == CPP_UTF8STRING)
message = catenate_messages (gmsgid, " before string constant");
else if (token_type == CPP_NUMBER)
message = catenate_messages (gmsgid, " before numeric constant");
error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
return error_mark_node;
- case INTEGER_CST:
- gcc_assert (integer_zerop (expr));
- return size_zero_node;
-
case NOP_EXPR:
case INDIRECT_REF:
- base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
- gcc_assert (base == error_mark_node || base == size_zero_node);
- return base;
+ if (!integer_zerop (TREE_OPERAND (expr, 0)))
+ {
+ error ("cannot apply %<offsetof%> to a non constant address");
+ return error_mark_node;
+ }
+ return size_zero_node;
case COMPONENT_REF:
base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
}
t = convert (sizetype, t);
off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
+
+ /* Check if the offset goes beyond the upper bound of the array. */
+ if (code == PLUS_EXPR && TREE_CODE (t) == INTEGER_CST)
+ {
+ tree upbound = array_ref_up_bound (expr);
+ if (upbound != NULL_TREE
+ && TREE_CODE (upbound) == INTEGER_CST
+ && !tree_int_cst_equal (upbound,
+ TYPE_MAX_VALUE (TREE_TYPE (upbound))))
+ {
+ upbound = size_binop (PLUS_EXPR, upbound,
+ build_int_cst (TREE_TYPE (upbound), 1));
+ if (tree_int_cst_lt (upbound, t))
+ {
+ tree v;
+
+ for (v = TREE_OPERAND (expr, 0);
+ TREE_CODE (v) == COMPONENT_REF;
+ v = TREE_OPERAND (v, 0))
+ if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
+ == RECORD_TYPE)
+ {
+ tree fld_chain = TREE_CHAIN (TREE_OPERAND (v, 1));
+ for (; fld_chain; fld_chain = TREE_CHAIN (fld_chain))
+ if (TREE_CODE (fld_chain) == FIELD_DECL)
+ break;
+
+ if (fld_chain)
+ break;
+ }
+ /* Don't warn if the array might be considered a poor
+ man's flexible array member with a very permissive
+ definition thereof. */
+ if (TREE_CODE (v) == ARRAY_REF
+ || TREE_CODE (v) == COMPONENT_REF)
+ warning (OPT_Warray_bounds,
+ "index %E denotes an offset "
+ "greater than size of %qT",
+ t, TREE_TYPE (TREE_OPERAND (expr, 0)));
+ }
+ }
+ }
break;
case COMPOUND_EXPR:
if (quals == 0)
unqual_elt = elt;
else
- unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+ unqual_elt = c_build_qualified_type (elt, KEEP_QUAL_ADDR_SPACE (quals));
/* Using build_distinct_type_copy and modifying things afterward instead
of using build_array_type to create a new type preserves all of the
/* Make sure we have the canonical MAIN_TYPE. */
hashcode = iterative_hash_object (TYPE_HASH (unqual_elt), hashcode);
- hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (main_type)),
+ hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (main_type)),
hashcode);
main_type = type_hash_canon (hashcode, main_type);
else if (TYPE_CANONICAL (TREE_TYPE (main_type)) != TREE_TYPE (main_type)
|| (TYPE_CANONICAL (TYPE_DOMAIN (main_type))
!= TYPE_DOMAIN (main_type)))
- TYPE_CANONICAL (main_type)
+ TYPE_CANONICAL (main_type)
= build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)),
TYPE_CANONICAL (TYPE_DOMAIN (main_type)));
else
|| ((CODE) != INTEGER_CST \
&& (integer_onep (ARG) || integer_zerop (ARG))))
- switch (code)
+ switch (code)
{
case LSHIFT_EXPR:
if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
The arguments of this function map directly to local variables
of build_binary_op. */
-void
+void
warn_for_sign_compare (location_t location,
- tree orig_op0, tree orig_op1,
- tree op0, tree op1,
+ tree orig_op0, tree orig_op1,
+ tree op0, tree op1,
tree result_type, enum tree_code resultcode)
{
int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
int unsignedp0, unsignedp1;
-
+
/* In C++, check for comparison of different enum types. */
if (c_dialect_cxx()
&& TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
if (op0_signed)
sop = orig_op0, uop = orig_op1;
- else
+ else
sop = orig_op1, uop = orig_op0;
- STRIP_TYPE_NOPS (sop);
+ STRIP_TYPE_NOPS (sop);
STRIP_TYPE_NOPS (uop);
base_type = (TREE_CODE (result_type) == COMPLEX_TYPE
? TREE_TYPE (result_type) : result_type);
&& int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE (uop)),
c_common_signed_type (base_type)))
/* OK */;
- else
+ else
warning_at (location,
- OPT_Wsign_compare,
+ OPT_Wsign_compare,
"comparison between signed and unsigned integer expressions");
}
-
+
/* Warn if two unsigned values are being compared in a size larger
than their original size, and one (and only one) is the result of
a `~' operator. This comparison will always fail.
-
+
Also warn if one operand is a constant, and the constant does not
have all bits set that are set in the ~ operand when it is
extended. */
op0 = get_narrower (op0, &unsignedp0);
op1 = get_narrower (op1, &unsignedp1);
-
+
if ((TREE_CODE (op0) == BIT_NOT_EXPR)
^ (TREE_CODE (op1) == BIT_NOT_EXPR))
{
HOST_WIDE_INT constant, mask;
int unsignedp;
unsigned int bits;
-
+
if (host_integerp (op0, 0))
{
primop = op1;
unsignedp = unsignedp0;
constant = tree_low_cst (op1, 0);
}
-
+
bits = TYPE_PRECISION (TREE_TYPE (primop));
if (bits < TYPE_PRECISION (result_type)
&& bits < HOST_BITS_PER_LONG && unsignedp)
if ((mask & constant) != mask)
{
if (constant == 0)
- warning (OPT_Wsign_compare,
+ warning (OPT_Wsign_compare,
"promoted ~unsigned is always non-zero");
else
- warning_at (location, OPT_Wsign_compare,
+ warning_at (location, OPT_Wsign_compare,
"comparison of promoted ~unsigned with constant");
}
}
&& DECL_ORIGINAL_TYPE (x) != NULL_TREE);
}
+/* Record the types used by the current global variable declaration
+ being parsed, so that we can decide later to emit their debug info.
+ Those types are in types_used_by_cur_var_decl, and we are going to
+ store them in the types_used_by_vars_hash hash table.
+ DECL is the declaration of the global variable that has been parsed. */
+
+void
+record_types_used_by_current_var_decl (tree decl)
+{
+ gcc_assert (decl && DECL_P (decl) && TREE_STATIC (decl));
+
+ if (types_used_by_cur_var_decl)
+ {
+ tree node;
+ for (node = types_used_by_cur_var_decl;
+ node;
+ node = TREE_CHAIN (node))
+ {
+ tree type = TREE_PURPOSE (node);
+ types_used_by_var_decl_insert (type, decl);
+ }
+ types_used_by_cur_var_decl = NULL;
+ }
+}
+
/* 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. */