X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-common.c;h=59dd295d3d62f0c3fb3bc18a4c6ae5f22631afc9;hb=fa09122aa24992c512e5e9e492e36fe1f3ebffd8;hp=1ff92920b65bc184eb12eac97be9d232324a0fb2;hpb=8115f0afdaff380da01d555b0584cd0fceb789b8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-common.c b/gcc/c-common.c index 1ff92920b65..59dd295d3d6 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -1,6 +1,6 @@ /* 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 + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 Free Software Foundation, Inc. This file is part of GCC. @@ -30,8 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "c-pragma.h" #include "rtl.h" #include "ggc.h" -#include "varray.h" -#include "expr.h" +#include "expr.h" /* For vector_mode_valid_p */ #include "c-common.h" #include "tm_p.h" #include "obstack.h" @@ -49,7 +48,6 @@ along with GCC; see the file COPYING3. If not see #include "real.h" #include "cgraph.h" #include "target-def.h" -#include "gimple.h" #include "fixed-value.h" #include "libfuncs.h" @@ -280,10 +278,14 @@ int flag_cond_mismatch; int flag_isoc94; -/* Nonzero means use the ISO C99 dialect of C. */ +/* Nonzero means use the ISO C99 (or C1X) dialect of C. */ int flag_isoc99; +/* Nonzero means use the ISO C1X dialect of C. */ + +int flag_isoc1x; + /* Nonzero means that we have builtin functions, and main is an int. */ int flag_hosted = 1; @@ -424,15 +426,11 @@ int flag_threadsafe_statics = 1; int flag_pretty_templates = 1; -/* Nonzero means warn about implicit declarations. */ - -int warn_implicit = 1; - -/* Maximum template instantiation depth. This limit is rather - arbitrary, but it exists to limit the time it takes to notice - infinite template instantiations. */ +/* Maximum template instantiation depth. This limit exists to limit the + time it takes to notice infinite template instantiations; the default + value of 1024 is likely to be in the next C++ standard. */ -int max_tinst_depth = 500; +int max_tinst_depth = 1024; @@ -482,6 +480,7 @@ 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_noinline_attribute (tree *, tree, tree, int, bool *); +static tree handle_noclone_attribute (tree *, tree, tree, int, bool *); static tree handle_always_inline_attribute (tree *, tree, tree, int, bool *); static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *); @@ -529,6 +528,7 @@ static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *); static tree handle_target_attribute (tree *, tree, tree, int, bool *); static tree handle_optimize_attribute (tree *, tree, tree, int, bool *); +static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *); static void check_function_nonnull (tree, int, tree *); static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); @@ -563,6 +563,7 @@ const struct c_common_resword c_common_reswords[] = { "_Fract", RID_FRACT, D_CONLY | D_EXT }, { "_Accum", RID_ACCUM, D_CONLY | D_EXT }, { "_Sat", RID_SAT, D_CONLY | D_EXT }, + { "_Static_assert", RID_STATIC_ASSERT, D_CONLY }, { "__FUNCTION__", RID_FUNCTION_NAME, 0 }, { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 }, { "__alignof", RID_ALIGNOF, 0 }, @@ -598,6 +599,8 @@ const struct c_common_resword c_common_reswords[] = { "__is_enum", RID_IS_ENUM, D_CXXONLY }, { "__is_pod", RID_IS_POD, D_CXXONLY }, { "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY }, + { "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY }, + { "__is_trivial", RID_IS_TRIVIAL, D_CXXONLY }, { "__is_union", RID_IS_UNION, D_CXXONLY }, { "__imag", RID_IMAGPART, 0 }, { "__imag__", RID_IMAGPART, 0 }, @@ -616,6 +619,7 @@ const struct c_common_resword c_common_reswords[] = { "__typeof__", RID_TYPEOF, 0 }, { "__volatile", RID_VOLATILE, 0 }, { "__volatile__", RID_VOLATILE, 0 }, + { "alignof", RID_ALIGNOF, D_CXXONLY | D_CXX0X | D_CXXWARN }, { "asm", RID_ASM, D_ASM }, { "auto", RID_AUTO, 0 }, { "bool", RID_BOOL, D_CXXONLY | D_CXXWARN }, @@ -627,6 +631,7 @@ const struct c_common_resword c_common_reswords[] = { "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 }, @@ -652,6 +657,7 @@ const struct c_common_resword c_common_reswords[] = { "mutable", RID_MUTABLE, D_CXXONLY | D_CXXWARN }, { "namespace", RID_NAMESPACE, D_CXXONLY | D_CXXWARN }, { "new", RID_NEW, D_CXXONLY | D_CXXWARN }, + { "nullptr", RID_NULLPTR, D_CXXONLY | D_CXX0X | D_CXXWARN }, { "operator", RID_OPERATOR, D_CXXONLY | D_CXXWARN }, { "private", RID_PRIVATE, D_CXX_OBJC | D_CXXWARN }, { "protected", RID_PROTECTED, D_CXX_OBJC | D_CXXWARN }, @@ -705,6 +711,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 = @@ -731,6 +742,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_noreturn_attribute }, { "noinline", 0, 0, true, false, false, handle_noinline_attribute }, + { "noclone", 0, 0, true, false, false, + handle_noclone_attribute }, { "always_inline", 0, 0, true, false, false, handle_always_inline_attribute }, { "gnu_inline", 0, 0, true, false, false, @@ -817,6 +830,10 @@ const struct attribute_spec c_common_attribute_table[] = handle_target_attribute }, { "optimize", 1, -1, true, false, false, handle_optimize_attribute }, + /* For internal use (marking of builtins and runtime functions) only. + The name contains space to prevent its usage in source code. */ + { "fn spec", 1, 1, false, true, true, + handle_fnspec_attribute }, { NULL, 0, 0, false, false, false, NULL } }; @@ -833,6 +850,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 @@ -1084,6 +1114,7 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const) tree eptype = NULL_TREE; bool dummy = true; bool maybe_const_itself = true; + location_t loc = EXPR_LOCATION (expr); /* This function is not relevant to C++ because C++ folds while parsing, and may need changes to be correct for C++ when C++ @@ -1101,7 +1132,7 @@ c_fully_fold (tree expr, bool in_init, bool *maybe_const) ret = c_fully_fold_internal (expr, in_init, maybe_const, &maybe_const_itself); if (eptype) - ret = fold_convert (eptype, ret); + ret = fold_convert_loc (loc, eptype, ret); *maybe_const &= maybe_const_itself; return ret; } @@ -1127,6 +1158,7 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, bool op0_const = true, op1_const = true, op2_const = true; bool op0_const_self = true, op1_const_self = true, op2_const_self = true; bool nowarning = TREE_NO_WARNING (expr); + int unused_p; /* This function is not relevant to C++ because C++ folds while parsing, and may need changes to be correct for C++ when C++ @@ -1210,6 +1242,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) @@ -1226,8 +1259,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); @@ -1284,6 +1319,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 @@ -1295,13 +1331,18 @@ 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 - ? fold_build2_initializer (code, TREE_TYPE (expr), op0, op1) - : fold_build2 (code, TREE_TYPE (expr), op0, op1); + ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1) + : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1); else ret = fold (expr); + if (TREE_OVERFLOW_P (ret) + && !TREE_OVERFLOW_P (op0) + && !TREE_OVERFLOW_P (op1)) + overflow_warning (EXPR_LOCATION (expr), ret); goto out; case INDIRECT_REF: @@ -1320,12 +1361,13 @@ 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) ret = in_init - ? fold_build1_initializer (code, TREE_TYPE (expr), op0) - : fold_build1 (code, TREE_TYPE (expr), op0); + ? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0) + : fold_build1_loc (loc, code, TREE_TYPE (expr), op0); else ret = fold (expr); if (code == INDIRECT_REF @@ -1336,6 +1378,20 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr); TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr); } + switch (code) + { + case FIX_TRUNC_EXPR: + case FLOAT_EXPR: + CASE_CONVERT: + /* Don't warn about explicit conversions. We will already + have warned about suspect implicit conversions. */ + break; + + default: + if (TREE_OVERFLOW_P (ret) && !TREE_OVERFLOW_P (op0)) + overflow_warning (EXPR_LOCATION (expr), ret); + break; + } goto out; case TRUTH_ANDIF_EXPR: @@ -1345,11 +1401,20 @@ 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) ret = in_init - ? fold_build2_initializer (code, TREE_TYPE (expr), op0, op1) - : fold_build2 (code, TREE_TYPE (expr), op0, op1); + ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1) + : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1); else ret = fold (expr); *maybe_const_operands &= op0_const; @@ -1374,10 +1439,20 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, orig_op1 = op1 = TREE_OPERAND (expr, 1); 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) - ret = fold_build3 (code, TREE_TYPE (expr), op0, op1, op2); + ret = fold_build3_loc (loc, code, TREE_TYPE (expr), op0, op1, op2); else ret = fold (expr); *maybe_const_operands &= op0_const; @@ -1472,7 +1547,7 @@ decl_constant_value_for_optimization (tree exp) 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 @@ -1515,12 +1590,12 @@ overflow_warning (location_t loc, tree value) 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; @@ -1528,7 +1603,7 @@ overflow_warning (location_t loc, tree value) 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, @@ -1550,7 +1625,7 @@ overflow_warning (location_t loc, tree value) 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); @@ -1607,18 +1682,19 @@ warn_logical_operator (location_t location, enum tree_code code, tree type, 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) && merge_ranges (&in_p, &low, &high, in0_p, low0, high0, in1_p, low1, high1) - && 0 != (tem = build_range_check (type, lhs, in_p, low, high))) + && 0 != (tem = build_range_check (UNKNOWN_LOCATION, + type, lhs, in_p, low, high))) { if (TREE_CODE (tem) != INTEGER_CST) return; @@ -1670,7 +1746,7 @@ strict_aliasing_warning (tree otype, tree type, tree expr) } 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))); @@ -1735,7 +1811,7 @@ check_main_parameter_types (tree decl) { case 1: if (TYPE_MAIN_VARIANT (type) != integer_type_node) - pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %", + pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %", decl); break; @@ -1830,7 +1906,7 @@ vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note) 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) { @@ -1845,13 +1921,13 @@ 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. */ @@ -1866,7 +1942,7 @@ tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise) /* 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) @@ -1875,18 +1951,18 @@ tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise) == 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. */ @@ -1965,7 +2041,7 @@ conversion_warning (tree type, tree expr) /* 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; @@ -1986,7 +2062,7 @@ conversion_warning (tree type, tree expr) && 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"); @@ -2031,7 +2107,7 @@ conversion_warning (tree type, tree expr) 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)) @@ -2058,15 +2134,15 @@ conversion_warning (tree type, tree 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) @@ -2084,13 +2160,13 @@ conversion_warning (tree type, tree 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 @@ -2099,7 +2175,7 @@ conversion_warning (tree type, tree expr) } } /* 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, @@ -2121,12 +2197,17 @@ conversion_warning (tree type, tree expr) else if (TREE_CODE (expr_type) == INTEGER_TYPE && TREE_CODE (type) == REAL_TYPE) { - 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_from_int_cst (0, type_low_bound); - REAL_VALUE_TYPE real_high_bound - = real_value_from_int_cst (0, type_high_bound); + tree type_low_bound, type_high_bound; + REAL_VALUE_TYPE real_low_bound, real_high_bound; + + /* Don't warn about char y = 0xff; float x = (int) y; */ + expr = get_unwidened (expr, 0); + expr_type = TREE_TYPE (expr); + + type_low_bound = TYPE_MIN_VALUE (expr_type); + type_high_bound = TYPE_MAX_VALUE (expr_type); + real_low_bound = real_value_from_int_cst (0, type_low_bound); + real_high_bound = real_value_from_int_cst (0, type_high_bound); if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound) || !exact_real_truncate (TYPE_MODE (type), &real_high_bound)) @@ -2174,7 +2255,7 @@ warnings_for_convert_and_check (tree type, tree expr, tree result) 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. */ @@ -2223,7 +2304,7 @@ convert_and_check (tree type, tree expr) if (TREE_TYPE (expr) == type) return expr; - + result = convert (type, expr); if (c_inhibit_evaluation_warnings == 0 @@ -2529,7 +2610,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp, { 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) { @@ -3614,7 +3695,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, && !(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; @@ -3624,7 +3705,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, && !(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; @@ -3656,7 +3737,8 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, of pointer PTROP and integer INTOP. */ tree -pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop) +pointer_int_sum (location_t loc, enum tree_code resultcode, + tree ptrop, tree intop) { tree size_exp, ret; @@ -3665,19 +3747,19 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop) if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE) { - pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, + pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith, "pointer of type % used in arithmetic"); size_exp = integer_one_node; } else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE) { - pedwarn (input_location, 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 (input_location, 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; } @@ -3729,24 +3811,55 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop) TYPE_UNSIGNED (sizetype)), intop); /* Replace the integer argument with a suitable product by the object size. - Do this multiplication as signed, then convert to the appropriate - type for the pointer operation. */ - intop = convert (sizetype, - build_binary_op (EXPR_LOCATION (intop), - MULT_EXPR, intop, - convert (TREE_TYPE (intop), size_exp), 1)); + Do this multiplication as signed, then convert to the appropriate type + for the pointer operation and disregard an overflow that occured only + because of the sign-extension change in the latter conversion. */ + { + tree t = build_binary_op (loc, + MULT_EXPR, intop, + 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)); + } /* Create the sum or difference. */ if (resultcode == MINUS_EXPR) - intop = fold_build1 (NEGATE_EXPR, sizetype, intop); + intop = fold_build1_loc (loc, NEGATE_EXPR, sizetype, intop); - ret = fold_build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop); + ret = fold_build2_loc (loc, POINTER_PLUS_EXPR, result_type, ptrop, intop); fold_undefer_and_ignore_overflow_warnings (); 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 @@ -3761,10 +3874,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; } @@ -3818,7 +3928,7 @@ c_common_truthvalue_conversion (location_t location, tree 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))); @@ -3911,7 +4021,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) { 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; } @@ -3923,7 +4033,7 @@ c_common_truthvalue_conversion (location_t location, tree expr) /* Distribute the conversion into the arms of a COND_EXPR. */ if (c_dialect_cxx ()) { - expr = fold_build3 (COND_EXPR, truthvalue_type_node, + expr = fold_build3_loc (location, COND_EXPR, truthvalue_type_node, TREE_OPERAND (expr, 0), c_common_truthvalue_conversion (location, TREE_OPERAND (expr, @@ -4107,6 +4217,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 @@ -4258,7 +4377,7 @@ c_sizeof_or_alignof_type (location_t loc, 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 % to a function type"); else if (!complain) return error_mark_node; @@ -4271,7 +4390,7 @@ c_sizeof_or_alignof_type (location_t loc, { 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; @@ -4282,15 +4401,15 @@ c_sizeof_or_alignof_type (location_t loc, if (complain) error_at (loc, "invalid application of %qs to incomplete type %qT ", op_name, type); - value = size_zero_node; + return error_mark_node; } else { if (is_sizeof) /* Convert in case a char is more than one unit. */ - value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), - size_int (TYPE_PRECISION (char_type_node) - / BITS_PER_UNIT)); + value = size_binop_loc (loc, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type), + size_int (TYPE_PRECISION (char_type_node) + / BITS_PER_UNIT)); else value = size_int (TYPE_ALIGN_UNIT (type)); } @@ -4299,7 +4418,7 @@ c_sizeof_or_alignof_type (location_t loc, TYPE_IS_SIZETYPE means that certain things (like overflow) will never happen. However, this node should really have type `size_t', which is just a typedef for an ordinary integer type. */ - value = fold_convert (size_type_node, value); + value = fold_convert_loc (loc, size_type_node, value); gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value))); return value; @@ -4350,7 +4469,7 @@ c_alignof_expr (location_t loc, tree expr) else return c_alignof (loc, TREE_TYPE (expr)); - return fold_convert (size_type_node, t); + return fold_convert_loc (loc, size_type_node, t); } /* Handle C and C++ default attributes. */ @@ -4667,7 +4786,7 @@ c_common_nodes_and_builtins (void) /* 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)) { @@ -4989,44 +5108,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; @@ -5267,7 +5348,7 @@ c_add_case_label (location_t loc, splay_tree cases, tree cond, tree orig_type, /* 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); @@ -5417,13 +5498,15 @@ match_case_to_enum_1 (tree key, tree type, tree label) (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (key)); if (TYPE_NAME (type) == 0) - warning (warn_switch ? OPT_Wswitch : OPT_Wswitch_enum, - "%Jcase value %qs not in enumerated type", - CASE_LABEL (label), buf); + warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)), + warn_switch ? OPT_Wswitch : OPT_Wswitch_enum, + "case value %qs not in enumerated type", + buf); else - warning (warn_switch ? OPT_Wswitch : OPT_Wswitch_enum, - "%Jcase value %qs not in enumerated type %qT", - CASE_LABEL (label), buf, type); + warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)), + warn_switch ? OPT_Wswitch : OPT_Wswitch_enum, + "case value %qs not in enumerated type %qT", + buf, type); } /* Subroutine of c_do_switch_warnings, called via splay_tree_foreach. @@ -5480,8 +5563,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, default_node = splay_tree_lookup (cases, (splay_tree_key) NULL); if (!default_node) - warning (OPT_Wswitch_default, "%Hswitch missing default case", - &switch_location); + warning_at (switch_location, OPT_Wswitch_default, + "switch missing default case"); /* From here on, we only care about about enumerated types. */ if (!type || TREE_CODE (type) != ENUMERAL_TYPE) @@ -5591,7 +5674,7 @@ finish_label_address_expr (tree label, location_t loc) { 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); @@ -5624,11 +5707,11 @@ boolean_increment (enum tree_code code, tree arg) break; case PREDECREMENT_EXPR: val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, - invert_truthvalue (arg)); + invert_truthvalue_loc (input_location, arg)); break; case POSTDECREMENT_EXPR: val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, - invert_truthvalue (arg)); + invert_truthvalue_loc (input_location, arg)); arg = save_expr (arg); val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), val, arg); val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), arg, val); @@ -5731,6 +5814,17 @@ c_init_attributes (void) #undef DEF_ATTR_TREE_LIST } +/* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain + identifier as an argument, so the front end shouldn't look it up. */ + +bool +attribute_takes_identifier_p (tree attr_id) +{ + return (is_attribute_p ("mode", attr_id) + || is_attribute_p ("format", attr_id) + || is_attribute_p ("cleanup", attr_id)); +} + /* Attribute handlers common to C front ends. */ /* Handle a "packed" attribute; arguments as in @@ -5906,6 +6000,23 @@ handle_noinline_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle a "noclone" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_noclone_attribute (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 "always_inline" attribute; arguments as in struct attribute_spec.handler. */ @@ -6032,6 +6143,8 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args), { TREE_USED (node) = 1; DECL_PRESERVE_P (node) = 1; + if (TREE_CODE (node) == VAR_DECL) + DECL_READ_P (node) = 1; } else { @@ -6058,7 +6171,12 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args), || TREE_CODE (decl) == FUNCTION_DECL || TREE_CODE (decl) == LABEL_DECL || TREE_CODE (decl) == TYPE_DECL) - TREE_USED (decl) = 1; + { + TREE_USED (decl) = 1; + if (TREE_CODE (decl) == VAR_DECL + || TREE_CODE (decl) == PARM_DECL) + DECL_READ_P (decl) = 1; + } else { warning (OPT_Wattributes, "%qE attribute ignored", name); @@ -6163,7 +6281,7 @@ handle_transparent_union_attribute (tree *node, tree name, *node = type = build_duplicate_type (type); } - TYPE_TRANSPARENT_UNION (type) = 1; + TYPE_TRANSPARENT_AGGR (type) = 1; return NULL_TREE; } @@ -6185,7 +6303,7 @@ get_priority (tree args, bool is_destructor) if (!args) return DEFAULT_INIT_PRIORITY; - + if (!SUPPORTS_INIT_PRIORITY) { if (is_destructor) @@ -6209,12 +6327,12 @@ get_priority (tree args, bool 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; @@ -6393,9 +6511,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; @@ -6493,8 +6612,9 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args, && current_function_decl != NULL_TREE && !TREE_STATIC (decl)) { - error ("%Jsection attribute cannot be specified for " - "local variables", decl); + error_at (DECL_SOURCE_LOCATION (decl), + "section attribute cannot be specified for " + "local variables"); *no_add_attrs = true; } @@ -6526,7 +6646,8 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args, } else { - error ("%Jsection attributes are not supported for this target", *node); + error_at (DECL_SOURCE_LOCATION (*node), + "section attributes are not supported for this target"); *no_add_attrs = true; } @@ -6573,10 +6694,12 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, } else if (is_type) { + if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + /* OK, modify the type in place. */; /* If we have a TYPE_DECL, then copy the type, so that we don't accidentally modify a builtin type. See pushdecl. */ - if (decl && TREE_TYPE (decl) != error_mark_node - && DECL_ORIGINAL_TYPE (decl) == NULL_TREE) + else if (decl && TREE_TYPE (decl) != error_mark_node + && DECL_ORIGINAL_TYPE (decl) == NULL_TREE) { tree tt = TREE_TYPE (decl); *type = build_variant_type_copy (*type); @@ -6585,7 +6708,7 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, TREE_USED (*type) = TREE_USED (decl); TREE_TYPE (decl) = *type; } - else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE)) + else *type = build_variant_type_copy (*type); TYPE_ALIGN (*type) = (1U << i) * BITS_PER_UNIT; @@ -6657,11 +6780,11 @@ handle_alias_attribute (tree *node, tree name, tree args, *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); @@ -6745,8 +6868,8 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args, else { if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node))) - error ("%Jweakref attribute must appear before alias attribute", - *node); + error_at (DECL_SOURCE_LOCATION (*node), + "weakref attribute must appear before alias attribute"); /* Can't call declare_weak because it wants this to be TREE_PUBLIC, and that isn't supported; and because it wants to add it to @@ -6956,12 +7079,14 @@ handle_no_instrument_function_attribute (tree *node, tree name, if (TREE_CODE (decl) != FUNCTION_DECL) { - error ("%J%qE attribute applies only to functions", decl, name); + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute applies only to functions", name); *no_add_attrs = true; } else if (DECL_INITIAL (decl)) { - error ("%Jcan%'t set %qE attribute after definition", decl, name); + error_at (DECL_SOURCE_LOCATION (decl), + "can%'t set %qE attribute after definition", name); *no_add_attrs = true; } else @@ -7002,11 +7127,11 @@ handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args, 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; @@ -7015,6 +7140,20 @@ handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args, return NULL_TREE; } +/* Handle a "fn spec" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name), + tree args, int ARG_UNUSED (flags), + bool *no_add_attrs ATTRIBUTE_UNUSED) +{ + gcc_assert (args + && TREE_CODE (TREE_VALUE (args)) == STRING_CST + && !TREE_CHAIN (args)); + return NULL_TREE; +} + /* Handle a "returns_twice" attribute; arguments as in struct attribute_spec.handler. */ @@ -7046,12 +7185,14 @@ handle_no_limit_stack_attribute (tree *node, tree name, if (TREE_CODE (decl) != FUNCTION_DECL) { - error ("%J%qE attribute applies only to functions", decl, name); + error_at (DECL_SOURCE_LOCATION (decl), + "%qE attribute applies only to functions", name); *no_add_attrs = true; } else if (DECL_INITIAL (decl)) { - error ("%Jcan%'t set %qE attribute after definition", decl, name); + error_at (DECL_SOURCE_LOCATION (decl), + "can%'t set %qE attribute after definition", name); *no_add_attrs = true; } else @@ -7562,7 +7703,7 @@ handle_sentinel_attribute (tree *node, tree name, tree args, if (TREE_CODE (position) != INTEGER_CST) { - warning (OPT_Wattributes, + warning (OPT_Wattributes, "requested position is not an integer constant"); *no_add_attrs = true; } @@ -7588,10 +7729,10 @@ handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name), 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); @@ -7734,6 +7875,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; @@ -7882,21 +8025,24 @@ check_function_arguments_recurse (void (*callback) (*callback) (ctx, param, param_num); } -/* Checks the number of arguments NARGS against the required number - REQUIRED and issues an error if there is a mismatch. Returns true - if the number of arguments is correct, otherwise false. */ +/* Checks for a builtin function FNDECL that the number of arguments + NARGS against the required number REQUIRED and issues an error if + there is a mismatch. Returns true if the number of arguments is + correct, otherwise false. */ static bool -validate_nargs (tree fndecl, int nargs, int required) +builtin_function_validate_nargs (tree fndecl, int nargs, int required) { if (nargs < required) { - error ("not enough arguments to function %qE", fndecl); + error_at (input_location, + "not enough arguments to function %qE", fndecl); return false; } else if (nargs > required) { - error ("too many arguments to function %qE", fndecl); + error_at (input_location, + "too many arguments to function %qE", fndecl); return false; } return true; @@ -7915,14 +8061,14 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args) switch (DECL_FUNCTION_CODE (fndecl)) { case BUILT_IN_CONSTANT_P: - return validate_nargs (fndecl, nargs, 1); + return builtin_function_validate_nargs (fndecl, nargs, 1); case BUILT_IN_ISFINITE: case BUILT_IN_ISINF: case BUILT_IN_ISINF_SIGN: case BUILT_IN_ISNAN: case BUILT_IN_ISNORMAL: - if (validate_nargs (fndecl, nargs, 1)) + if (builtin_function_validate_nargs (fndecl, nargs, 1)) { if (TREE_CODE (TREE_TYPE (args[0])) != REAL_TYPE) { @@ -7940,7 +8086,7 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args) case BUILT_IN_ISLESSEQUAL: case BUILT_IN_ISLESSGREATER: case BUILT_IN_ISUNORDERED: - if (validate_nargs (fndecl, nargs, 2)) + if (builtin_function_validate_nargs (fndecl, nargs, 2)) { enum tree_code code0, code1; code0 = TREE_CODE (TREE_TYPE (args[0])); @@ -7958,10 +8104,10 @@ check_builtin_function_arguments (tree fndecl, int nargs, tree *args) return false; case BUILT_IN_FPCLASSIFY: - if (validate_nargs (fndecl, nargs, 6)) + if (builtin_function_validate_nargs (fndecl, nargs, 6)) { unsigned i; - + for (i=0; i<5; i++) if (TREE_CODE (args[i]) != INTEGER_CST) { @@ -8073,7 +8219,7 @@ catenate_strings (const char *lhs, const char *rhs_start, int rhs_size) 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)) @@ -8082,8 +8228,8 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type, 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) { @@ -8115,10 +8261,11 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type, 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"); @@ -8151,8 +8298,52 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type, #undef catenate_messages } +/* Mapping for cpp message reasons to the options that enable them. */ + +struct reason_option_codes_t +{ + const int reason; /* cpplib message reason. */ + const int option_code; /* gcc option that controls this message. */ +}; + +static const struct reason_option_codes_t option_codes[] = { + {CPP_W_DEPRECATED, OPT_Wdeprecated}, + {CPP_W_COMMENTS, OPT_Wcomments}, + {CPP_W_TRIGRAPHS, OPT_Wtrigraphs}, + {CPP_W_MULTICHAR, OPT_Wmultichar}, + {CPP_W_TRADITIONAL, OPT_Wtraditional}, + {CPP_W_LONG_LONG, OPT_Wlong_long}, + {CPP_W_ENDIF_LABELS, OPT_Wendif_labels}, + {CPP_W_VARIADIC_MACROS, OPT_Wvariadic_macros}, + {CPP_W_BUILTIN_MACRO_REDEFINED, OPT_Wbuiltin_macro_redefined}, + {CPP_W_UNDEF, OPT_Wundef}, + {CPP_W_UNUSED_MACROS, OPT_Wunused_macros}, + {CPP_W_CXX_OPERATOR_NAMES, OPT_Wc___compat}, + {CPP_W_NORMALIZE, OPT_Wnormalized_}, + {CPP_W_INVALID_PCH, OPT_Winvalid_pch}, + {CPP_W_WARNING_DIRECTIVE, OPT_Wcpp}, + {CPP_W_NONE, 0} +}; + +/* Return the gcc option code associated with the reason for a cpp + message, or 0 if none. */ + +static int +c_option_controlling_cpp_error (int reason) +{ + const struct reason_option_codes_t *entry; + + for (entry = option_codes; entry->reason != CPP_W_NONE; entry++) + { + if (entry->reason == reason) + return entry->option_code; + } + return 0; +} + /* Callback from cpp_error for PFILE to print diagnostics from the - preprocessor. The diagnostic is of type LEVEL, at location + preprocessor. The diagnostic is of type LEVEL, with REASON set + to the reason code if LEVEL is represents a warning, at location LOCATION unless this is after lexing and the compiler's location should be used instead, with column number possibly overridden by COLUMN_OVERRIDE if not zero; MSG is the translated message and AP @@ -8160,7 +8351,7 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token_type, otherwise. */ bool -c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, +c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason, location_t location, unsigned int column_override, const char *msg, va_list *ap) { @@ -8207,74 +8398,14 @@ c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, location, dlevel); if (column_override) diagnostic_override_column (&diagnostic, column_override); + diagnostic_override_option_index (&diagnostic, + c_option_controlling_cpp_error (reason)); ret = report_diagnostic (&diagnostic); if (level == CPP_DL_WARNING_SYSHDR) warn_system_headers = save_warn_system_headers; return ret; } -/* Walk a gimplified function and warn for functions whose return value is - ignored and attribute((warn_unused_result)) is set. This is done before - inlining, so we don't have to worry about that. */ - -void -c_warn_unused_result (gimple_seq seq) -{ - tree fdecl, ftype; - gimple_stmt_iterator i; - - for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i)) - { - gimple g = gsi_stmt (i); - - switch (gimple_code (g)) - { - case GIMPLE_BIND: - c_warn_unused_result (gimple_bind_body (g)); - break; - case GIMPLE_TRY: - c_warn_unused_result (gimple_try_eval (g)); - c_warn_unused_result (gimple_try_cleanup (g)); - break; - case GIMPLE_CATCH: - c_warn_unused_result (gimple_catch_handler (g)); - break; - case GIMPLE_EH_FILTER: - c_warn_unused_result (gimple_eh_filter_failure (g)); - break; - - case GIMPLE_CALL: - if (gimple_call_lhs (g)) - break; - - /* This is a naked call, as opposed to a GIMPLE_CALL with an - LHS. All calls whose value is ignored should be - represented like this. Look for the attribute. */ - fdecl = gimple_call_fndecl (g); - ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g))); - - if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype))) - { - location_t loc = gimple_location (g); - - if (fdecl) - warning (0, "%Hignoring return value of %qD, " - "declared with attribute warn_unused_result", - &loc, fdecl); - else - warning (0, "%Hignoring return value of function " - "declared with attribute warn_unused_result", - &loc); - } - break; - - default: - /* Not a container, not a call, or a call whose value is used. */ - break; - } - } -} - /* Convert a character from the host to the target execution character set. cpplib handles this, mostly. */ @@ -8324,15 +8455,14 @@ fold_offsetof_1 (tree expr, tree stop_ref) error ("cannot apply % when % 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 % 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); @@ -8346,9 +8476,10 @@ fold_offsetof_1 (tree expr, tree stop_ref) "member %qD", t); return error_mark_node; } - off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t), - size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), 1) - / BITS_PER_UNIT)); + off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t), + size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t), + 1) + / BITS_PER_UNIT)); break; case ARRAY_REF: @@ -8360,10 +8491,52 @@ fold_offsetof_1 (tree expr, tree stop_ref) if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0) { code = MINUS_EXPR; - t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t); + t = fold_build1_loc (input_location, NEGATE_EXPR, TREE_TYPE (t), t); } 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: @@ -8453,9 +8626,9 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) bool fold_p = false; if (VEC_index (constructor_elt, v, 0)->index) - maxindex = fold_convert (sizetype, - VEC_index (constructor_elt, - v, 0)->index); + maxindex = fold_convert_loc (input_location, sizetype, + VEC_index (constructor_elt, + v, 0)->index); curindex = maxindex; for (cnt = 1; @@ -8469,7 +8642,8 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) { if (fold_p) curindex = fold_convert (sizetype, curindex); - curindex = size_binop (PLUS_EXPR, curindex, size_one_node); + curindex = size_binop (PLUS_EXPR, curindex, + size_one_node); } if (tree_int_cst_lt (maxindex, curindex)) maxindex = curindex, fold_p = curfold_p; @@ -8498,7 +8672,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 @@ -8510,7 +8684,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) /* 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); @@ -8521,7 +8695,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) 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 @@ -8603,7 +8777,6 @@ sync_resolve_params (tree orig_function, tree function, VEC(tree, gc) *params) { tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (function)); tree ptype; - int number; unsigned int parmnum; /* We've declared the implementation functions to use "volatile void *" @@ -8611,7 +8784,6 @@ sync_resolve_params (tree orig_function, tree function, VEC(tree, gc) *params) call to check_function_arguments what ever type the user used. */ arg_types = TREE_CHAIN (arg_types); ptype = TREE_TYPE (TREE_TYPE (VEC_index (tree, params, 0))); - number = 2; /* 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. */ @@ -8636,7 +8808,6 @@ sync_resolve_params (tree orig_function, tree function, VEC(tree, gc) *params) VEC_replace (tree, params, parmnum, val); arg_types = TREE_CHAIN (arg_types); - number++; } /* The definition of these primitives is variadic, with the remaining @@ -8816,7 +8987,7 @@ warn_about_parentheses (enum tree_code code, || ((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) @@ -8966,16 +9137,16 @@ warn_for_div_by_zero (location_t loc, tree divisor) 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 @@ -9003,10 +9174,10 @@ warn_for_sign_compare (location_t location, 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); @@ -9032,23 +9203,23 @@ warn_for_sign_compare (location_t location, && 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)) { @@ -9063,7 +9234,7 @@ warn_for_sign_compare (location_t location, HOST_WIDE_INT constant, mask; int unsignedp; unsigned int bits; - + if (host_integerp (op0, 0)) { primop = op1; @@ -9076,7 +9247,7 @@ warn_for_sign_compare (location_t location, 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) @@ -9085,10 +9256,10 @@ warn_for_sign_compare (location_t location, 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"); } } @@ -9175,6 +9346,31 @@ is_typedef_decl (tree x) && 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. */