diff options
author | rus <rus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-09 20:58:24 +0000 |
---|---|---|
committer | rus <rus@138bc75d-0d04-0410-961f-82ee72b054a4> | 2009-11-09 20:58:24 +0000 |
commit | 7f4db7c80779ecbc57d1146654daf0acfe18de66 (patch) | |
tree | 3af522a3b5e149c3fd498ecb1255994daae2129a /gcc/c-common.c | |
parent | 611349f0ec42a37591db2cd02974a11a48d10edb (diff) | |
download | gcc-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.c | 171 |
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 |