summaryrefslogtreecommitdiff
path: root/gcc/c-common.c
diff options
context:
space:
mode:
authorrus <rus@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-09 20:58:24 +0000
committerrus <rus@138bc75d-0d04-0410-961f-82ee72b054a4>2009-11-09 20:58:24 +0000
commit7f4db7c80779ecbc57d1146654daf0acfe18de66 (patch)
tree3af522a3b5e149c3fd498ecb1255994daae2129a /gcc/c-common.c
parent611349f0ec42a37591db2cd02974a11a48d10edb (diff)
downloadgcc-profile-stdlib.tar.gz
merge from trunkprofile-stdlib
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/profile-stdlib@154052 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/c-common.c')
-rw-r--r--gcc/c-common.c171
1 files changed, 119 insertions, 52 deletions
diff --git a/gcc/c-common.c b/gcc/c-common.c
index 4de92d0de95..20b24f0c3c2 100644
--- a/gcc/c-common.c
+++ b/gcc/c-common.c
@@ -710,6 +710,11 @@ const struct c_common_resword c_common_reswords[] =
{ "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 =
@@ -840,6 +845,19 @@ const struct attribute_spec c_common_format_attribute_table[] =
{ 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
@@ -1219,6 +1237,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
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)
@@ -1235,8 +1254,10 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
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);
@@ -1293,6 +1314,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
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
@@ -1304,6 +1326,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
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
@@ -1333,6 +1356,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
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)
@@ -1372,12 +1396,14 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
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)
@@ -1409,12 +1435,15 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
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)
@@ -3790,6 +3819,31 @@ pointer_int_sum (location_t loc, enum tree_code resultcode,
return ret;
}
+/* 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
@@ -3804,10 +3858,7 @@ c_save_expr (tree expr)
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;
}
@@ -4150,6 +4201,15 @@ c_common_get_alias_set (tree t)
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
@@ -5032,44 +5092,6 @@ c_common_nodes_and_builtins (void)
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;
@@ -6455,9 +6477,10 @@ handle_mode_attribute (tree *node, tree name, tree args,
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;
@@ -7802,6 +7825,8 @@ parse_optimize_options (tree args, bool attr_p)
/* 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;
@@ -8186,7 +8211,8 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
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");
@@ -8330,15 +8356,14 @@ fold_offsetof_1 (tree expr, tree stop_ref)
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);
@@ -8371,6 +8396,48 @@ fold_offsetof_1 (tree expr, tree 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:
@@ -8506,7 +8573,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
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