X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fc-common.c;h=351c62831d397eb9350e01ab96c9b2e7b19d9bd6;hb=0c8e56a848b9ad7a1008870b974b017c59efc2a4;hp=d9a826d1d96980c5ce19a012ff4cb43b067b81c3;hpb=c2f47e150f3c68a813f92460462c2e70155f2c67;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/c-common.c b/gcc/c-common.c index d9a826d1d96..351c62831d3 100644 --- a/gcc/c-common.c +++ b/gcc/c-common.c @@ -1,12 +1,12 @@ /* 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 Free Software Foundation, Inc. + 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free -Software Foundation; either version 2, or (at your option) any later +Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY @@ -15,9 +15,8 @@ FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GCC; see the file COPYING. If not, write to the Free -Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA -02110-1301, USA. */ +along with GCC; see the file COPYING3. If not see +. */ #include "config.h" #include "system.h" @@ -48,6 +47,8 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA #include "opts.h" #include "real.h" #include "cgraph.h" +#include "target-def.h" +#include "fixed-value.h" cpp_reader *parse_in; /* Declared in c-pragma.h. */ @@ -65,6 +66,14 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */ #define PID_TYPE "int" #endif +#ifndef CHAR16_TYPE +#define CHAR16_TYPE "short unsigned int" +#endif + +#ifndef CHAR32_TYPE +#define CHAR32_TYPE "unsigned int" +#endif + #ifndef WCHAR_TYPE #define WCHAR_TYPE "int" #endif @@ -122,6 +131,9 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */ tree signed_wchar_type_node; tree unsigned_wchar_type_node; + tree char16_type_node; + tree char32_type_node; + tree float_type_node; tree double_type_node; tree long_double_type_node; @@ -173,6 +185,16 @@ cpp_reader *parse_in; /* Declared in c-pragma.h. */ tree wchar_array_type_node; + Type `char16_t[SOMENUMBER]' or something like it. + Used when a UTF-16 string literal is created. + + tree char16_array_type_node; + + Type `char32_t[SOMENUMBER]' or something like it. + Used when a UTF-32 string literal is created. + + tree char32_array_type_node; + Type `int ()' -- used for implicit declaration of functions. tree default_function_type; @@ -405,10 +427,9 @@ int flag_access_control = 1; int flag_check_new; -/* Nonzero if we want to allow the use of experimental features that - are likely to become part of C++0x. */ +/* The C++ dialect being used. C++98 is the default. */ -int flag_cpp0x = 0; +enum cxx_dialect cxx_dialect = cxx98; /* Nonzero if we want the new ISO rules for pushing a new scope for `for' initialization variables. @@ -443,11 +464,6 @@ int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT; int flag_use_cxa_get_exception_ptr = 2; -/* Nonzero means make the default pedwarns warnings instead of errors. - The value of this flag is ignored if -pedantic is specified. */ - -int flag_permissive; - /* Nonzero means to implement standard semantics for exception specifications, calling unexpected if an exception is thrown that doesn't match the specification. Zero means to treat them as @@ -510,12 +526,15 @@ static tree handle_packed_attribute (tree *, tree, tree, int, bool *); static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *); static tree handle_common_attribute (tree *, tree, tree, int, bool *); 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_always_inline_attribute (tree *, tree, tree, int, bool *); -static tree handle_gnu_inline_attribute (tree *, tree, tree, int, - bool *); +static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *); +static tree handle_artificial_attribute (tree *, tree, tree, int, bool *); static tree handle_flatten_attribute (tree *, tree, tree, int, bool *); +static tree handle_error_attribute (tree *, tree, tree, int, bool *); static tree handle_used_attribute (tree *, tree, tree, int, bool *); static tree handle_unused_attribute (tree *, tree, tree, int, bool *); static tree handle_externally_visible_attribute (tree *, tree, tree, int, @@ -553,8 +572,10 @@ static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *); static tree handle_warn_unused_result_attribute (tree *, tree, tree, int, bool *); static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *); +static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *); +static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *); -static void check_function_nonnull (tree, tree); +static void check_function_nonnull (tree, int, tree *); static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT); static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT); static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *); @@ -585,6 +606,8 @@ const struct attribute_spec c_common_attribute_table[] = handle_always_inline_attribute }, { "gnu_inline", 0, 0, true, false, false, handle_gnu_inline_attribute }, + { "artificial", 0, 0, true, false, false, + handle_artificial_attribute }, { "flatten", 0, 0, true, false, false, handle_flatten_attribute }, { "used", 0, 0, true, false, false, @@ -598,9 +621,9 @@ const struct attribute_spec c_common_attribute_table[] = handle_const_attribute }, { "transparent_union", 0, 0, false, false, false, handle_transparent_union_attribute }, - { "constructor", 0, 0, true, false, false, + { "constructor", 0, 1, true, false, false, handle_constructor_attribute }, - { "destructor", 0, 0, true, false, false, + { "destructor", 0, 1, true, false, false, handle_destructor_attribute }, { "mode", 1, 1, false, true, false, handle_mode_attribute }, @@ -647,6 +670,20 @@ const struct attribute_spec c_common_attribute_table[] = handle_warn_unused_result_attribute }, { "sentinel", 0, 1, false, true, true, handle_sentinel_attribute }, + /* For internal use (marking of builtins) only. The name contains space + to prevent its usage in source code. */ + { "type generic", 0, 0, false, true, true, + handle_type_generic_attribute }, + { "alloc_size", 1, 2, false, true, true, + handle_alloc_size_attribute }, + { "cold", 0, 0, true, false, false, + handle_cold_attribute }, + { "hot", 0, 0, true, false, false, + handle_hot_attribute }, + { "warning", 1, 1, true, false, false, + handle_error_attribute }, + { "error", 1, 1, true, false, false, + handle_error_attribute }, { NULL, 0, 0, false, false, false, NULL } }; @@ -742,7 +779,8 @@ fname_as_string (int pretty_p) { const char *name = "top level"; char *namep; - int vrb = 2; + int vrb = 2, len; + cpp_string cstr = { 0, 0 }, strname; if (!pretty_p) { @@ -753,24 +791,18 @@ fname_as_string (int pretty_p) if (current_function_decl) name = lang_hooks.decl_printable_name (current_function_decl, vrb); - if (c_lex_string_translate) - { - int len = strlen (name) + 3; /* Two for '"'s. One for NULL. */ - cpp_string cstr = { 0, 0 }, strname; + len = strlen (name) + 3; /* Two for '"'s. One for NULL. */ - namep = XNEWVEC (char, len); - snprintf (namep, len, "\"%s\"", name); - strname.text = (unsigned char *) namep; - strname.len = len - 1; + namep = XNEWVEC (char, len); + snprintf (namep, len, "\"%s\"", name); + strname.text = (unsigned char *) namep; + strname.len = len - 1; - if (cpp_interpret_string (parse_in, &strname, 1, &cstr, false)) - { - XDELETEVEC (namep); - return (char *) cstr.text; - } + if (cpp_interpret_string (parse_in, &strname, 1, &cstr, CPP_STRING)) + { + XDELETEVEC (namep); + return (const char *) cstr.text; } - else - namep = xstrdup (name); return namep; } @@ -824,11 +856,7 @@ fname_decl (unsigned int rid, tree id) it from appearing in the RTL. */ tree stmts; location_t saved_location = input_location; -#ifdef USE_MAPPED_LOCATION input_location = UNKNOWN_LOCATION; -#else - input_line = 0; -#endif stmts = push_stmt_list (); decl = (*make_fname_decl) (id, fname_vars[ix].pretty); @@ -850,14 +878,31 @@ fname_decl (unsigned int rid, tree id) tree fix_string_type (tree value) { - const int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT; - const int wide_flag = TREE_TYPE (value) == wchar_array_type_node; int length = TREE_STRING_LENGTH (value); int nchars; tree e_type, i_type, a_type; /* Compute the number of elements, for the array type. */ - nchars = wide_flag ? length / wchar_bytes : length; + if (TREE_TYPE (value) == char_array_type_node || !TREE_TYPE (value)) + { + nchars = length; + e_type = char_type_node; + } + else if (TREE_TYPE (value) == char16_array_type_node) + { + nchars = length / (TYPE_PRECISION (char16_type_node) / BITS_PER_UNIT); + e_type = char16_type_node; + } + else if (TREE_TYPE (value) == char32_array_type_node) + { + nchars = length / (TYPE_PRECISION (char32_type_node) / BITS_PER_UNIT); + e_type = char32_type_node; + } + else + { + nchars = length / (TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT); + e_type = wchar_type_node; + } /* C89 2.2.4.1, C99 5.2.4.1 (Translation limits). The analogous limit in C++98 Annex B is very large (65536) and is not normative, @@ -892,7 +937,6 @@ fix_string_type (tree value) construct the matching unqualified array type first. The C front end does not require this, but it does no harm, so we do it unconditionally. */ - e_type = wide_flag ? wchar_type_node : char_type_node; i_type = build_index_type (build_int_cst (NULL_TREE, nchars - 1)); a_type = build_array_type (e_type, i_type); if (c_dialect_cxx() || warn_write_strings) @@ -915,13 +959,25 @@ fix_string_type (tree value) void constant_expression_warning (tree value) { + if (warn_overflow && pedantic + && (TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST + || TREE_CODE (value) == FIXED_CST + || TREE_CODE (value) == VECTOR_CST + || TREE_CODE (value) == COMPLEX_CST) + && TREE_OVERFLOW (value)) + pedwarn ("overflow in constant expression"); +} + +/* The same as above but print an unconditional error. */ +void +constant_expression_error (tree value) +{ if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST + || TREE_CODE (value) == FIXED_CST || TREE_CODE (value) == VECTOR_CST || TREE_CODE (value) == COMPLEX_CST) - && TREE_OVERFLOW (value) - && warn_overflow - && pedantic) - pedwarn ("overflow in constant expression"); + && TREE_OVERFLOW (value)) + error ("overflow in constant expression"); } /* Print a warning if an expression had overflow in folding and its @@ -950,6 +1006,10 @@ overflow_warning (tree value) warning (OPT_Woverflow, "floating point overflow in expression"); break; + case FIXED_CST: + warning (OPT_Woverflow, "fixed-point overflow in expression"); + break; + case VECTOR_CST: warning (OPT_Woverflow, "vector overflow in expression"); break; @@ -966,40 +1026,108 @@ overflow_warning (tree value) } } + +/* Warn about use of a logical || / && operator being used in a + context where it is likely that the bitwise equivalent was intended + by the programmer. CODE is the TREE_CODE of the operator, ARG1 + and ARG2 the arguments. */ + +void +warn_logical_operator (enum tree_code code, tree arg1, tree + arg2) +{ + switch (code) + { + case TRUTH_ANDIF_EXPR: + case TRUTH_ORIF_EXPR: + case TRUTH_OR_EXPR: + case TRUTH_AND_EXPR: + if (!TREE_NO_WARNING (arg1) + && INTEGRAL_TYPE_P (TREE_TYPE (arg1)) + && !CONSTANT_CLASS_P (arg1) + && TREE_CODE (arg2) == INTEGER_CST + && !integer_zerop (arg2)) + { + warning (OPT_Wlogical_op, + "logical %<%s%> with non-zero constant " + "will always evaluate as true", + ((code == TRUTH_ANDIF_EXPR) + || (code == TRUTH_AND_EXPR)) ? "&&" : "||"); + TREE_NO_WARNING (arg1) = true; + } + break; + default: + break; + } +} + + /* Print a warning about casts that might indicate violation of strict aliasing rules if -Wstrict-aliasing is used and strict aliasing mode is in effect. OTYPE is the original TREE_TYPE of EXPR, and TYPE the type we're casting to. */ -void +bool strict_aliasing_warning (tree otype, tree type, tree expr) { - if (flag_strict_aliasing && warn_strict_aliasing - && POINTER_TYPE_P (type) && POINTER_TYPE_P (otype) - && TREE_CODE (expr) == ADDR_EXPR + if (!(flag_strict_aliasing && POINTER_TYPE_P (type) + && POINTER_TYPE_P (otype) && !VOID_TYPE_P (TREE_TYPE (type)))) + return false; + + if ((warn_strict_aliasing > 1) && TREE_CODE (expr) == ADDR_EXPR && (DECL_P (TREE_OPERAND (expr, 0)) - || handled_component_p (TREE_OPERAND (expr, 0))) - && !VOID_TYPE_P (TREE_TYPE (type))) + || handled_component_p (TREE_OPERAND (expr, 0)))) { /* Casting the address of an object to non void pointer. Warn if the cast breaks type based aliasing. */ - if (!COMPLETE_TYPE_P (TREE_TYPE (type))) - warning (OPT_Wstrict_aliasing, "type-punning to incomplete type " - "might break strict-aliasing rules"); + if (!COMPLETE_TYPE_P (TREE_TYPE (type)) && warn_strict_aliasing == 2) + { + warning (OPT_Wstrict_aliasing, "type-punning to incomplete type " + "might break strict-aliasing rules"); + return true; + } else { - HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0))); - HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type)); + /* 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))); + alias_set_type set2 = get_alias_set (TREE_TYPE (type)); if (!alias_sets_conflict_p (set1, set2)) - warning (OPT_Wstrict_aliasing, "dereferencing type-punned " - "pointer will break strict-aliasing rules"); - else if (warn_strict_aliasing > 1 - && !alias_sets_might_conflict_p (set1, set2)) - warning (OPT_Wstrict_aliasing, "dereferencing type-punned " - "pointer might break strict-aliasing rules"); + { + warning (OPT_Wstrict_aliasing, "dereferencing type-punned " + "pointer will break strict-aliasing rules"); + return true; + } + else if (warn_strict_aliasing == 2 + && !alias_sets_must_conflict_p (set1, set2)) + { + warning (OPT_Wstrict_aliasing, "dereferencing type-punned " + "pointer might break strict-aliasing rules"); + return true; + } } } + else + if ((warn_strict_aliasing == 1) && !VOID_TYPE_P (TREE_TYPE (otype))) + { + /* At this level, warn for any conversions, even if an address is + not taken in the same statement. This will likely produce many + false positives, but could be useful to pinpoint problems that + are not revealed at higher levels. */ + alias_set_type set1 = get_alias_set (TREE_TYPE (otype)); + alias_set_type set2 = get_alias_set (TREE_TYPE (type)); + if (!COMPLETE_TYPE_P (type) + || !alias_sets_must_conflict_p (set1, set2)) + { + warning (OPT_Wstrict_aliasing, "dereferencing type-punned " + "pointer might break strict-aliasing rules"); + return true; + } + } + + return false; } /* Print a warning about if (); or if () .. else; constructs @@ -1008,26 +1136,23 @@ strict_aliasing_warning (tree otype, tree type, tree expr) block. */ void -empty_body_warning (tree inner_then, tree inner_else) +empty_if_body_warning (tree inner_then, tree inner_else) { - if (warn_empty_body) - { - if (TREE_CODE (inner_then) == STATEMENT_LIST - && STATEMENT_LIST_TAIL (inner_then)) - inner_then = STATEMENT_LIST_TAIL (inner_then)->stmt; + if (TREE_CODE (inner_then) == STATEMENT_LIST + && STATEMENT_LIST_TAIL (inner_then)) + inner_then = STATEMENT_LIST_TAIL (inner_then)->stmt; - if (inner_else && TREE_CODE (inner_else) == STATEMENT_LIST - && STATEMENT_LIST_TAIL (inner_else)) - inner_else = STATEMENT_LIST_TAIL (inner_else)->stmt; + if (inner_else && TREE_CODE (inner_else) == STATEMENT_LIST + && STATEMENT_LIST_TAIL (inner_else)) + inner_else = STATEMENT_LIST_TAIL (inner_else)->stmt; - if (IS_EMPTY_STMT (inner_then) && !inner_else) - warning (OPT_Wempty_body, "%Hempty body in an if-statement", - EXPR_LOCUS (inner_then)); + if (IS_EMPTY_STMT (inner_then) && !inner_else) + warning (OPT_Wempty_body, "%Hsuggest braces around empty body " + "in an % statement", EXPR_LOCUS (inner_then)); - if (inner_else && IS_EMPTY_STMT (inner_else)) - warning (OPT_Wempty_body, "%Hempty body in an else-statement", - EXPR_LOCUS (inner_else)); - } + else if (inner_else && IS_EMPTY_STMT (inner_else)) + warning (OPT_Wempty_body, "%Hsuggest braces around empty body " + "in an % statement", EXPR_LOCUS (inner_else)); } /* Warn for unlikely, improbable, or stupid DECL declarations @@ -1088,7 +1213,7 @@ check_main_parameter_types (tree decl) in effect, emit a note telling the user about that option if such a note has not previously been emitted. */ bool -vector_types_convertible_p (tree t1, tree t2, bool emit_lax_note) +vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note) { static bool emitted_lax_note = false; bool convertible_lax; @@ -1108,7 +1233,7 @@ vector_types_convertible_p (tree t1, tree t2, bool emit_lax_note) return convertible_lax; if (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2) - && comptypes (TREE_TYPE (t1), TREE_TYPE (t2))) + && lang_hooks.types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2))) return true; if (emit_lax_note && !emitted_lax_note) @@ -1123,7 +1248,7 @@ vector_types_convertible_p (tree t1, tree t2, bool emit_lax_note) } /* Warns if the conversion of EXPR to TYPE may alter a value. - This function is called from convert_and_check. */ + This is a helper function for warnings_for_convert_and_check. */ static void conversion_warning (tree type, tree expr) @@ -1132,6 +1257,9 @@ conversion_warning (tree type, tree expr) unsigned int formal_prec = TYPE_PRECISION (type); + if (!warn_conversion && !warn_sign_conversion) + return; + if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST) { /* Warn for real constant that is not an exact integer converted @@ -1148,10 +1276,13 @@ conversion_warning (tree type, tree expr) && !int_fits_type_p (expr, type)) { if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr))) - warning (OPT_Wconversion, - "negative integer implicitly converted to unsigned type"); - else - give_warning = true; + warning (OPT_Wsign_conversion, + "negative integer implicitly converted to unsigned type"); + else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (TREE_TYPE (expr))) + warning (OPT_Wsign_conversion, + "conversion of unsigned constant value to negative integer"); + else + give_warning = true; } else if (TREE_CODE (type) == REAL_TYPE) { @@ -1188,17 +1319,24 @@ conversion_warning (tree type, tree expr) else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE && TREE_CODE (type) == INTEGER_TYPE) { + /* Don't warn about unsigned char y = 0xff, x = (int) y; */ + expr = get_unwidened (expr, 0); + /* Warn for integer types converted to smaller integer types. */ - if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr)) - /* When they are the same width but different signedness, - then the value may change. */ - || (formal_prec == TYPE_PRECISION (TREE_TYPE (expr)) - && TYPE_UNSIGNED (TREE_TYPE (expr)) != TYPE_UNSIGNED (type)) - /* Even when converted to a bigger type, if the type is - unsigned but expr is signed, then negative values - will be changed. */ - || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr)))) - give_warning = true; + if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr))) + give_warning = true; + + /* When they are the same width but different signedness, + then the value may change. */ + else if ((formal_prec == TYPE_PRECISION (TREE_TYPE (expr)) + && TYPE_UNSIGNED (TREE_TYPE (expr)) != TYPE_UNSIGNED (type)) + /* Even when converted to a bigger type, if the type is + unsigned but expr is signed, then negative values + will be changed. */ + || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr)))) + warning (OPT_Wsign_conversion, + "conversion to %qT from %qT may change the sign of the result", + type, TREE_TYPE (expr)); } /* Warn for integer types converted to real types if and only if @@ -1231,24 +1369,13 @@ conversion_warning (tree type, tree expr) } } -/* Convert EXPR to TYPE, warning about conversion problems with constants. - Invoke this function on every expression that is converted implicitly, - i.e. because of language rules and not because of an explicit cast. */ +/* Produce warnings after a conversion. RESULT is the result of + converting EXPR to TYPE. This is a helper function for + convert_and_check and cp_convert_and_check. */ -tree -convert_and_check (tree type, tree expr) +void +warnings_for_convert_and_check (tree type, tree expr, tree result) { - tree result; - - if (TREE_TYPE (expr) == type) - return expr; - - result = convert (type, expr); - - if (skip_evaluation) - return result; - - if (TREE_CODE (expr) == INTEGER_CST && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == ENUMERAL_TYPE) @@ -1266,31 +1393,49 @@ convert_and_check (tree type, tree expr) if (!int_fits_type_p (expr, c_common_signed_type (type))) warning (OPT_Woverflow, "large integer implicitly truncated to unsigned type"); - else if (warn_conversion) + else conversion_warning (type, expr); } + 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. */ + else if (pedantic + && (TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE + || TYPE_PRECISION (TREE_TYPE (expr)) + != TYPE_PRECISION (type))) + warning (OPT_Woverflow, + "overflow in implicit constant conversion"); + 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. */ - else if (pedantic - && (TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE - || TYPE_PRECISION (TREE_TYPE (expr)) - != TYPE_PRECISION (type))) - warning (OPT_Woverflow, - "overflow in implicit constant conversion"); - else if (warn_conversion) - conversion_warning (type, expr); - } + conversion_warning (type, expr); } - else if (TREE_CODE (result) == INTEGER_CST && TREE_OVERFLOW (result)) + else if ((TREE_CODE (result) == INTEGER_CST + || TREE_CODE (result) == FIXED_CST) && TREE_OVERFLOW (result)) warning (OPT_Woverflow, "overflow in implicit constant conversion"); - else if (warn_conversion) + else conversion_warning (type, expr); +} + + +/* Convert EXPR to TYPE, warning about conversion problems with constants. + Invoke this function on every expression that is converted implicitly, + i.e. because of language rules and not because of an explicit cast. */ + +tree +convert_and_check (tree type, tree expr) +{ + tree result; + + if (TREE_TYPE (expr) == type) + return expr; + result = convert (type, expr); + + if (!skip_evaluation && !TREE_OVERFLOW_P (expr) && result != error_mark_node) + warnings_for_convert_and_check (type, expr, result); + return result; } @@ -1422,7 +1567,8 @@ warn_for_collisions_1 (tree written, tree writer, struct tlist *list, && DECL_NAME (list->expr)) { warned_ids = new_tlist (warned_ids, written, NULL_TREE); - warning (0, "operation on %qE may be undefined", list->expr); + warning (OPT_Wsequence_point, "operation on %qE may be undefined", + list->expr); } list = list->next; } @@ -1834,13 +1980,44 @@ c_common_type_for_size (unsigned int bits, int unsignedp) return 0; } +/* Return a fixed-point type that has at least IBIT ibits and FBIT fbits + that is unsigned if UNSIGNEDP is nonzero, otherwise signed; + and saturating if SATP is nonzero, otherwise not saturating. */ + +tree +c_common_fixed_point_type_for_size (unsigned int ibit, unsigned int fbit, + int unsignedp, int satp) +{ + enum machine_mode mode; + if (ibit == 0) + mode = unsignedp ? UQQmode : QQmode; + else + mode = unsignedp ? UHAmode : HAmode; + + for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode)) + if (GET_MODE_IBIT (mode) >= ibit && GET_MODE_FBIT (mode) >= fbit) + break; + + if (mode == VOIDmode || !targetm.scalar_mode_supported_p (mode)) + { + sorry ("GCC cannot support operators with integer types and " + "fixed-point types that have too many integral and " + "fractional bits together"); + return 0; + } + + return c_common_type_for_mode (mode, satp); +} + /* Used for communication between c_common_type_for_mode and c_register_builtin_type. */ static GTY(()) tree registered_builtin_types; /* Return a data type that has machine mode MODE. If the mode is an integer, - then UNSIGNEDP selects between signed and unsigned types. */ + then UNSIGNEDP selects between signed and unsigned types. + If the mode is a fixed-point mode, + then UNSIGNEDP selects between saturating and nonsaturating types. */ tree c_common_type_for_mode (enum machine_mode mode, int unsignedp) @@ -1940,6 +2117,95 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp) if (mode == TYPE_MODE (dfloat128_type_node)) return dfloat128_type_node; + if (ALL_SCALAR_FIXED_POINT_MODE_P (mode)) + { + if (mode == TYPE_MODE (short_fract_type_node)) + return unsignedp ? sat_short_fract_type_node : short_fract_type_node; + if (mode == TYPE_MODE (fract_type_node)) + return unsignedp ? sat_fract_type_node : fract_type_node; + if (mode == TYPE_MODE (long_fract_type_node)) + return unsignedp ? sat_long_fract_type_node : long_fract_type_node; + if (mode == TYPE_MODE (long_long_fract_type_node)) + return unsignedp ? sat_long_long_fract_type_node + : long_long_fract_type_node; + + if (mode == TYPE_MODE (unsigned_short_fract_type_node)) + return unsignedp ? sat_unsigned_short_fract_type_node + : unsigned_short_fract_type_node; + if (mode == TYPE_MODE (unsigned_fract_type_node)) + return unsignedp ? sat_unsigned_fract_type_node + : unsigned_fract_type_node; + if (mode == TYPE_MODE (unsigned_long_fract_type_node)) + return unsignedp ? sat_unsigned_long_fract_type_node + : unsigned_long_fract_type_node; + if (mode == TYPE_MODE (unsigned_long_long_fract_type_node)) + return unsignedp ? sat_unsigned_long_long_fract_type_node + : unsigned_long_long_fract_type_node; + + if (mode == TYPE_MODE (short_accum_type_node)) + return unsignedp ? sat_short_accum_type_node : short_accum_type_node; + if (mode == TYPE_MODE (accum_type_node)) + return unsignedp ? sat_accum_type_node : accum_type_node; + if (mode == TYPE_MODE (long_accum_type_node)) + return unsignedp ? sat_long_accum_type_node : long_accum_type_node; + if (mode == TYPE_MODE (long_long_accum_type_node)) + return unsignedp ? sat_long_long_accum_type_node + : long_long_accum_type_node; + + if (mode == TYPE_MODE (unsigned_short_accum_type_node)) + return unsignedp ? sat_unsigned_short_accum_type_node + : unsigned_short_accum_type_node; + if (mode == TYPE_MODE (unsigned_accum_type_node)) + return unsignedp ? sat_unsigned_accum_type_node + : unsigned_accum_type_node; + if (mode == TYPE_MODE (unsigned_long_accum_type_node)) + return unsignedp ? sat_unsigned_long_accum_type_node + : unsigned_long_accum_type_node; + if (mode == TYPE_MODE (unsigned_long_long_accum_type_node)) + return unsignedp ? sat_unsigned_long_long_accum_type_node + : unsigned_long_long_accum_type_node; + + if (mode == QQmode) + return unsignedp ? sat_qq_type_node : qq_type_node; + if (mode == HQmode) + return unsignedp ? sat_hq_type_node : hq_type_node; + if (mode == SQmode) + return unsignedp ? sat_sq_type_node : sq_type_node; + if (mode == DQmode) + return unsignedp ? sat_dq_type_node : dq_type_node; + if (mode == TQmode) + return unsignedp ? sat_tq_type_node : tq_type_node; + + if (mode == UQQmode) + return unsignedp ? sat_uqq_type_node : uqq_type_node; + if (mode == UHQmode) + return unsignedp ? sat_uhq_type_node : uhq_type_node; + if (mode == USQmode) + return unsignedp ? sat_usq_type_node : usq_type_node; + if (mode == UDQmode) + return unsignedp ? sat_udq_type_node : udq_type_node; + if (mode == UTQmode) + return unsignedp ? sat_utq_type_node : utq_type_node; + + if (mode == HAmode) + return unsignedp ? sat_ha_type_node : ha_type_node; + if (mode == SAmode) + return unsignedp ? sat_sa_type_node : sa_type_node; + if (mode == DAmode) + return unsignedp ? sat_da_type_node : da_type_node; + if (mode == TAmode) + return unsignedp ? sat_ta_type_node : ta_type_node; + + if (mode == UHAmode) + return unsignedp ? sat_uha_type_node : uha_type_node; + if (mode == USAmode) + return unsignedp ? sat_usa_type_node : usa_type_node; + if (mode == UDAmode) + return unsignedp ? sat_uda_type_node : uda_type_node; + if (mode == UTAmode) + return unsignedp ? sat_uta_type_node : uta_type_node; + } + for (t = registered_builtin_types; t; t = TREE_CHAIN (t)) if (TYPE_MODE (TREE_VALUE (t)) == mode) return TREE_VALUE (t); @@ -1947,36 +2213,9 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp) return 0; } -/* Return an unsigned type the same as TYPE in other respects. */ tree c_common_unsigned_type (tree type) { - tree type1 = TYPE_MAIN_VARIANT (type); - if (type1 == signed_char_type_node || type1 == char_type_node) - return unsigned_char_type_node; - if (type1 == integer_type_node) - return unsigned_type_node; - if (type1 == short_integer_type_node) - return short_unsigned_type_node; - if (type1 == long_integer_type_node) - return long_unsigned_type_node; - if (type1 == long_long_integer_type_node) - return long_long_unsigned_type_node; - if (type1 == widest_integer_literal_type_node) - return widest_unsigned_literal_type_node; -#if HOST_BITS_PER_WIDE_INT >= 64 - if (type1 == intTI_type_node) - return unsigned_intTI_type_node; -#endif - if (type1 == intDI_type_node) - return unsigned_intDI_type_node; - if (type1 == intSI_type_node) - return unsigned_intSI_type_node; - if (type1 == intHI_type_node) - return unsigned_intHI_type_node; - if (type1 == intQI_type_node) - return unsigned_intQI_type_node; - return c_common_signed_or_unsigned_type (1, type); } @@ -1985,32 +2224,6 @@ c_common_unsigned_type (tree type) tree c_common_signed_type (tree type) { - tree type1 = TYPE_MAIN_VARIANT (type); - if (type1 == unsigned_char_type_node || type1 == char_type_node) - return signed_char_type_node; - if (type1 == unsigned_type_node) - return integer_type_node; - if (type1 == short_unsigned_type_node) - return short_integer_type_node; - if (type1 == long_unsigned_type_node) - return long_integer_type_node; - if (type1 == long_long_unsigned_type_node) - return long_long_integer_type_node; - if (type1 == widest_unsigned_literal_type_node) - return widest_integer_literal_type_node; -#if HOST_BITS_PER_WIDE_INT >= 64 - if (type1 == unsigned_intTI_type_node) - return intTI_type_node; -#endif - if (type1 == unsigned_intDI_type_node) - return intDI_type_node; - if (type1 == unsigned_intSI_type_node) - return intSI_type_node; - if (type1 == unsigned_intHI_type_node) - return intHI_type_node; - if (type1 == unsigned_intQI_type_node) - return intQI_type_node; - return c_common_signed_or_unsigned_type (0, type); } @@ -2020,9 +2233,87 @@ c_common_signed_type (tree type) tree c_common_signed_or_unsigned_type (int unsignedp, tree type) { - if (!INTEGRAL_TYPE_P (type) - || TYPE_UNSIGNED (type) == unsignedp) - return type; + tree type1; + + /* This block of code emulates the behavior of the old + c_common_unsigned_type. In particular, it returns + long_unsigned_type_node if passed a long, even when a int would + have the same size. This is necessary for warnings to work + correctly in archs where sizeof(int) == sizeof(long) */ + + type1 = TYPE_MAIN_VARIANT (type); + if (type1 == signed_char_type_node || type1 == char_type_node || type1 == unsigned_char_type_node) + return unsignedp ? unsigned_char_type_node : signed_char_type_node; + if (type1 == integer_type_node || type1 == unsigned_type_node) + return unsignedp ? unsigned_type_node : integer_type_node; + if (type1 == short_integer_type_node || type1 == short_unsigned_type_node) + return unsignedp ? short_unsigned_type_node : short_integer_type_node; + if (type1 == long_integer_type_node || type1 == long_unsigned_type_node) + return unsignedp ? long_unsigned_type_node : long_integer_type_node; + if (type1 == long_long_integer_type_node || type1 == long_long_unsigned_type_node) + return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node; + if (type1 == widest_integer_literal_type_node || type1 == widest_unsigned_literal_type_node) + return unsignedp ? widest_unsigned_literal_type_node : widest_integer_literal_type_node; +#if HOST_BITS_PER_WIDE_INT >= 64 + if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node) + return unsignedp ? unsigned_intTI_type_node : intTI_type_node; +#endif + if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node) + return unsignedp ? unsigned_intDI_type_node : intDI_type_node; + if (type1 == intSI_type_node || type1 == unsigned_intSI_type_node) + return unsignedp ? unsigned_intSI_type_node : intSI_type_node; + if (type1 == intHI_type_node || type1 == unsigned_intHI_type_node) + return unsignedp ? unsigned_intHI_type_node : intHI_type_node; + if (type1 == intQI_type_node || type1 == unsigned_intQI_type_node) + return unsignedp ? unsigned_intQI_type_node : intQI_type_node; + +#define C_COMMON_FIXED_TYPES(SAT,NAME) \ + if (type1 == SAT ## short_ ## NAME ## _type_node \ + || type1 == SAT ## unsigned_short_ ## NAME ## _type_node) \ + return unsignedp ? SAT ## unsigned_short_ ## NAME ## _type_node \ + : SAT ## short_ ## NAME ## _type_node; \ + if (type1 == SAT ## NAME ## _type_node \ + || type1 == SAT ## unsigned_ ## NAME ## _type_node) \ + return unsignedp ? SAT ## unsigned_ ## NAME ## _type_node \ + : SAT ## NAME ## _type_node; \ + if (type1 == SAT ## long_ ## NAME ## _type_node \ + || type1 == SAT ## unsigned_long_ ## NAME ## _type_node) \ + return unsignedp ? SAT ## unsigned_long_ ## NAME ## _type_node \ + : SAT ## long_ ## NAME ## _type_node; \ + if (type1 == SAT ## long_long_ ## NAME ## _type_node \ + || type1 == SAT ## unsigned_long_long_ ## NAME ## _type_node) \ + return unsignedp ? SAT ## unsigned_long_long_ ## NAME ## _type_node \ + : SAT ## long_long_ ## NAME ## _type_node; + +#define C_COMMON_FIXED_MODE_TYPES(SAT,NAME) \ + if (type1 == SAT ## NAME ## _type_node \ + || type1 == SAT ## u ## NAME ## _type_node) \ + return unsignedp ? SAT ## u ## NAME ## _type_node \ + : SAT ## NAME ## _type_node; + + C_COMMON_FIXED_TYPES (, fract); + C_COMMON_FIXED_TYPES (sat_, fract); + C_COMMON_FIXED_TYPES (, accum); + C_COMMON_FIXED_TYPES (sat_, accum); + + C_COMMON_FIXED_MODE_TYPES (, qq); + C_COMMON_FIXED_MODE_TYPES (, hq); + C_COMMON_FIXED_MODE_TYPES (, sq); + C_COMMON_FIXED_MODE_TYPES (, dq); + C_COMMON_FIXED_MODE_TYPES (, tq); + C_COMMON_FIXED_MODE_TYPES (sat_, qq); + C_COMMON_FIXED_MODE_TYPES (sat_, hq); + C_COMMON_FIXED_MODE_TYPES (sat_, sq); + C_COMMON_FIXED_MODE_TYPES (sat_, dq); + C_COMMON_FIXED_MODE_TYPES (sat_, tq); + C_COMMON_FIXED_MODE_TYPES (, ha); + C_COMMON_FIXED_MODE_TYPES (, sa); + C_COMMON_FIXED_MODE_TYPES (, da); + C_COMMON_FIXED_MODE_TYPES (, ta); + C_COMMON_FIXED_MODE_TYPES (sat_, ha); + C_COMMON_FIXED_MODE_TYPES (sat_, sa); + C_COMMON_FIXED_MODE_TYPES (sat_, da); + C_COMMON_FIXED_MODE_TYPES (sat_, ta); /* For ENUMERAL_TYPEs in C++, must check the mode of the types, not the precision; they have precision set to match their range, but @@ -2033,6 +2324,10 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type) types, and producing a signed or unsigned variant of an ENUMERAL_TYPE may cause other problems as well. */ + if (!INTEGRAL_TYPE_P (type) + || TYPE_UNSIGNED (type) == unsignedp) + return type; + #define TYPE_OK(node) \ (TYPE_MODE (type) == TYPE_MODE (node) \ && (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node))) @@ -2141,10 +2436,10 @@ min_precision (tree value, int unsignedp) } /* Print an error message for invalid operands to arith operation - CODE. */ + CODE with TYPE0 for operand 0, and TYPE1 for operand 1. */ void -binary_op_error (enum tree_code code) +binary_op_error (enum tree_code code, tree type0, tree type1) { const char *opname; @@ -2195,7 +2490,8 @@ binary_op_error (enum tree_code code) default: gcc_unreachable (); } - error ("invalid operands to binary %s", opname); + error ("invalid operands to binary %s (have %qT and %qT)", opname, + type0, type1); } /* Subroutine of build_binary_op, used for comparison operations. @@ -2247,7 +2543,8 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, the second arg is 0. */ if (TREE_CONSTANT (primop0) - && !integer_zerop (primop1) && !real_zerop (primop1)) + && !integer_zerop (primop1) && !real_zerop (primop1) + && !fixed_zerop (primop1)) { tree tem = primop0; int temi = unsignedp0; @@ -2302,6 +2599,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, and see if that preserves the constant's value. */ if (!real1 && !real2 + && TREE_CODE (TREE_TYPE (primop0)) != FIXED_POINT_TYPE && TREE_CODE (primop1) == INTEGER_CST && TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr)) { @@ -2428,9 +2726,9 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, if (TREE_CODE (primop0) != INTEGER_CST) { if (val == truthvalue_false_node) - warning (0, "comparison is always false due to limited range of data type"); + warning (OPT_Wtype_limits, "comparison is always false due to limited range of data type"); if (val == truthvalue_true_node) - warning (0, "comparison is always true due to limited range of data type"); + warning (OPT_Wtype_limits, "comparison is always true due to limited range of data type"); } if (val != 0) @@ -2500,24 +2798,26 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr, switch (code) { case GE_EXPR: - /* All unsigned values are >= 0, so we warn if extra warnings - are requested. However, if OP0 is a constant that is - >= 0, the signedness of the comparison isn't an issue, - so suppress the warning. */ - if (extra_warnings && !in_system_header + /* All unsigned values are >= 0, so we warn. However, + if OP0 is a constant that is >= 0, the signedness of + the comparison isn't an issue, so suppress the + warning. */ + if (warn_type_limits && !in_system_header && !(TREE_CODE (primop0) == INTEGER_CST && !TREE_OVERFLOW (convert (c_common_signed_type (type), primop0)))) - warning (0, "comparison of unsigned expression >= 0 is always true"); + warning (OPT_Wtype_limits, + "comparison of unsigned expression >= 0 is always true"); value = truthvalue_true_node; break; case LT_EXPR: - if (extra_warnings && !in_system_header + if (warn_type_limits && !in_system_header && !(TREE_CODE (primop0) == INTEGER_CST && !TREE_OVERFLOW (convert (c_common_signed_type (type), primop0)))) - warning (0, "comparison of unsigned expression < 0 is always false"); + warning (OPT_Wtype_limits, + "comparison of unsigned expression < 0 is always false"); value = truthvalue_false_node; break; @@ -2553,7 +2853,6 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop) tree size_exp, ret; /* The result is a pointer of the same type that is being added. */ - tree result_type = TREE_TYPE (ptrop); if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE) @@ -2587,7 +2886,6 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop) contains a constant term, apply distributive law and multiply that constant term separately. This helps produce common subexpressions. */ - if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR) && !TREE_CONSTANT (intop) && TREE_CONSTANT (TREE_OPERAND (intop, 1)) @@ -2616,7 +2914,6 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop) /* Convert the integer argument to a type the same size as sizetype so the multiply won't overflow spuriously. */ - if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype) || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype)) intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype), @@ -2624,14 +2921,16 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop) /* Replace the integer argument with a suitable product by the object size. Do this multiplication as signed, then convert to the appropriate - pointer type (actually unsigned integral). */ - - intop = convert (result_type, + type for the pointer operation. */ + intop = convert (sizetype, build_binary_op (MULT_EXPR, intop, convert (TREE_TYPE (intop), size_exp), 1)); /* Create the sum or difference. */ - ret = fold_build2 (resultcode, result_type, ptrop, intop); + if (resultcode == MINUS_EXPR) + intop = fold_build1 (NEGATE_EXPR, sizetype, intop); + + ret = fold_build2 (POINTER_PLUS_EXPR, result_type, ptrop, intop); fold_undefer_and_ignore_overflow_warnings (); @@ -2642,7 +2941,7 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop) NULL. */ bool -decl_with_nonnull_addr_p (tree expr) +decl_with_nonnull_addr_p (const_tree expr) { return (DECL_P (expr) && (TREE_CODE (expr) == PARM_DECL @@ -2706,6 +3005,12 @@ c_common_truthvalue_conversion (tree expr) ? truthvalue_true_node : truthvalue_false_node; + case FIXED_CST: + return fixed_compare (NE_EXPR, &TREE_FIXED_CST (expr), + &FCONST0 (TYPE_MODE (TREE_TYPE (expr)))) + ? truthvalue_true_node + : truthvalue_false_node; + case FUNCTION_DECL: expr = build_unary_op (ADDR_EXPR, expr, 0); /* Fall through. */ @@ -2716,7 +3021,7 @@ c_common_truthvalue_conversion (tree expr) if (decl_with_nonnull_addr_p (inner)) { /* Common Ada/Pascal programmer's mistake. */ - warning (OPT_Walways_true, + warning (OPT_Waddress, "the address of %qD will always evaluate as %", inner); return truthvalue_true_node; @@ -2806,6 +3111,14 @@ c_common_truthvalue_conversion (tree expr) 0)); } + if (TREE_CODE (TREE_TYPE (expr)) == FIXED_POINT_TYPE) + { + tree fixed_zero_node = build_fixed (TREE_TYPE (expr), + FCONST0 (TYPE_MODE + (TREE_TYPE (expr)))); + return build_binary_op (NE_EXPR, expr, fixed_zero_node, 1); + } + return build_binary_op (NE_EXPR, expr, integer_zero_node, 1); } @@ -2816,52 +3129,6 @@ static void def_builtin_1 (enum built_in_function fncode, bool both_p, bool fallback_p, bool nonansi_p, tree fnattrs, bool implicit_p); -/* Make a variant type in the proper way for C/C++, propagating qualifiers - down to the element type of an array. */ - -tree -c_build_qualified_type (tree type, int type_quals) -{ - if (type == error_mark_node) - return type; - - if (TREE_CODE (type) == ARRAY_TYPE) - { - tree t; - tree element_type = c_build_qualified_type (TREE_TYPE (type), - type_quals); - - /* See if we already have an identically qualified type. */ - for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t)) - { - if (TYPE_QUALS (strip_array_types (t)) == type_quals - && TYPE_NAME (t) == TYPE_NAME (type) - && TYPE_CONTEXT (t) == TYPE_CONTEXT (type) - && attribute_list_equal (TYPE_ATTRIBUTES (t), - TYPE_ATTRIBUTES (type))) - break; - } - if (!t) - { - t = build_variant_type_copy (type); - TREE_TYPE (t) = element_type; - } - return t; - } - - /* A restrict-qualified pointer type must be a pointer to object or - incomplete type. Note that the use of POINTER_TYPE_P also allows - REFERENCE_TYPEs, which is appropriate for C++. */ - if ((type_quals & TYPE_QUAL_RESTRICT) - && (!POINTER_TYPE_P (type) - || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))) - { - error ("invalid use of %"); - type_quals &= ~TYPE_QUAL_RESTRICT; - } - - return build_qualified_type (type, type_quals); -} /* Apply the TYPE_QUALS to the new DECL. */ @@ -2915,7 +3182,7 @@ c_type_hash (const void *p) { int i = 0; int shift, size; - tree t = (tree) p; + const_tree const t = (const_tree) p; tree t2; switch (TREE_CODE (t)) { @@ -2944,7 +3211,11 @@ c_type_hash (const void *p) } for (; t2; t2 = TREE_CHAIN (t2)) i++; - size = TREE_INT_CST_LOW (TYPE_SIZE (t)); + /* We might have a VLA here. */ + if (TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST) + size = 0; + else + size = TREE_INT_CST_LOW (TYPE_SIZE (t)); return ((size << 24) | (i << shift)); } @@ -2953,7 +3224,7 @@ static GTY((param_is (union tree_node))) htab_t type_hash_table; /* Return the typed-based alias set for T, which may be an expression or a type. Return -1 if we don't do anything special. */ -HOST_WIDE_INT +alias_set_type c_common_get_alias_set (tree t) { tree u; @@ -3051,16 +3322,16 @@ c_common_get_alias_set (tree t) tree t2; /* Find bottom type under any nested POINTERs. */ for (t2 = TREE_TYPE (t); - TREE_CODE (t2) == POINTER_TYPE; - t2 = TREE_TYPE (t2)) - ; + TREE_CODE (t2) == POINTER_TYPE; + t2 = TREE_TYPE (t2)) + ; if (TREE_CODE (t2) != RECORD_TYPE - && TREE_CODE (t2) != ENUMERAL_TYPE - && TREE_CODE (t2) != QUAL_UNION_TYPE - && TREE_CODE (t2) != UNION_TYPE) - return -1; + && TREE_CODE (t2) != ENUMERAL_TYPE + && TREE_CODE (t2) != QUAL_UNION_TYPE + && TREE_CODE (t2) != UNION_TYPE) + return -1; if (TYPE_SIZE (t2) == 0) - return -1; + return -1; } /* These are the only cases that need special handling. */ if (TREE_CODE (t) != RECORD_TYPE @@ -3113,6 +3384,8 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain) { if (complain && (pedantic || warn_pointer_arith)) pedwarn ("invalid application of % to a function type"); + else if (!complain) + return error_mark_node; value = size_one_node; } else @@ -3123,6 +3396,8 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain) if (type_code == VOID_TYPE && complain && (pedantic || warn_pointer_arith)) pedwarn ("invalid application of %qs to a void type", op_name); + else if (!complain) + return error_mark_node; value = size_one_node; } else if (!COMPLETE_TYPE_P (type)) @@ -3154,16 +3429,16 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain) } /* Implement the __alignof keyword: Return the minimum required - alignment of EXPR, measured in bytes. For VAR_DECL's and - FIELD_DECL's return DECL_ALIGN (which can be set from an - "aligned" __attribute__ specification). */ + alignment of EXPR, measured in bytes. For VAR_DECLs, + FUNCTION_DECLs and FIELD_DECLs return DECL_ALIGN (which can be set + from an "aligned" __attribute__ specification). */ tree c_alignof_expr (tree expr) { tree t; - if (TREE_CODE (expr) == VAR_DECL) + if (VAR_OR_FUNCTION_DECL_P (expr)) t = size_int (DECL_ALIGN_UNIT (expr)); else if (TREE_CODE (expr) == COMPONENT_REF @@ -3377,9 +3652,10 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node) #include "builtins.def" #undef DEF_BUILTIN + targetm.init_builtins (); + build_common_builtin_nodes (); - targetm.init_builtins (); if (flag_mudflap) mudflap_init (); } @@ -3390,6 +3666,8 @@ c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node) void c_common_nodes_and_builtins (void) { + int char16_type_size; + int char32_type_size; int wchar_type_size; tree array_domain_type; tree va_list_ref_type_node; @@ -3498,6 +3776,67 @@ c_common_nodes_and_builtins (void) record_builtin_type (RID_DFLOAT128, NULL, dfloat128_type_node); } + if (targetm.fixed_point_supported_p ()) + { + record_builtin_type (RID_MAX, "short _Fract", short_fract_type_node); + record_builtin_type (RID_FRACT, NULL, fract_type_node); + record_builtin_type (RID_MAX, "long _Fract", long_fract_type_node); + record_builtin_type (RID_MAX, "long long _Fract", + long_long_fract_type_node); + record_builtin_type (RID_MAX, "unsigned short _Fract", + unsigned_short_fract_type_node); + record_builtin_type (RID_MAX, "unsigned _Fract", + unsigned_fract_type_node); + record_builtin_type (RID_MAX, "unsigned long _Fract", + unsigned_long_fract_type_node); + record_builtin_type (RID_MAX, "unsigned long long _Fract", + unsigned_long_long_fract_type_node); + record_builtin_type (RID_MAX, "_Sat short _Fract", + sat_short_fract_type_node); + record_builtin_type (RID_MAX, "_Sat _Fract", sat_fract_type_node); + record_builtin_type (RID_MAX, "_Sat long _Fract", + sat_long_fract_type_node); + record_builtin_type (RID_MAX, "_Sat long long _Fract", + sat_long_long_fract_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned short _Fract", + sat_unsigned_short_fract_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned _Fract", + sat_unsigned_fract_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned long _Fract", + sat_unsigned_long_fract_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned long long _Fract", + sat_unsigned_long_long_fract_type_node); + record_builtin_type (RID_MAX, "short _Accum", short_accum_type_node); + record_builtin_type (RID_ACCUM, NULL, accum_type_node); + record_builtin_type (RID_MAX, "long _Accum", long_accum_type_node); + record_builtin_type (RID_MAX, "long long _Accum", + long_long_accum_type_node); + record_builtin_type (RID_MAX, "unsigned short _Accum", + unsigned_short_accum_type_node); + record_builtin_type (RID_MAX, "unsigned _Accum", + unsigned_accum_type_node); + record_builtin_type (RID_MAX, "unsigned long _Accum", + unsigned_long_accum_type_node); + record_builtin_type (RID_MAX, "unsigned long long _Accum", + unsigned_long_long_accum_type_node); + record_builtin_type (RID_MAX, "_Sat short _Accum", + sat_short_accum_type_node); + record_builtin_type (RID_MAX, "_Sat _Accum", sat_accum_type_node); + record_builtin_type (RID_MAX, "_Sat long _Accum", + sat_long_accum_type_node); + record_builtin_type (RID_MAX, "_Sat long long _Accum", + sat_long_long_accum_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned short _Accum", + sat_unsigned_short_accum_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned _Accum", + sat_unsigned_accum_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned long _Accum", + sat_unsigned_long_accum_type_node); + record_builtin_type (RID_MAX, "_Sat unsigned long long _Accum", + sat_unsigned_long_long_accum_type_node); + + } + lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, get_identifier ("complex int"), complex_integer_type_node)); @@ -3578,6 +3917,38 @@ c_common_nodes_and_builtins (void) wchar_array_type_node = build_array_type (wchar_type_node, array_domain_type); + /* Define 'char16_t'. */ + char16_type_node = get_identifier (CHAR16_TYPE); + char16_type_node = TREE_TYPE (identifier_global_value (char16_type_node)); + char16_type_size = TYPE_PRECISION (char16_type_node); + if (c_dialect_cxx ()) + { + char16_type_node = make_unsigned_type (char16_type_size); + + if (cxx_dialect == cxx0x) + record_builtin_type (RID_CHAR16, "char16_t", char16_type_node); + } + + /* This is for UTF-16 string constants. */ + char16_array_type_node + = build_array_type (char16_type_node, array_domain_type); + + /* Define 'char32_t'. */ + char32_type_node = get_identifier (CHAR32_TYPE); + char32_type_node = TREE_TYPE (identifier_global_value (char32_type_node)); + char32_type_size = TYPE_PRECISION (char32_type_node); + if (c_dialect_cxx ()) + { + char32_type_node = make_unsigned_type (char32_type_size); + + if (cxx_dialect == cxx0x) + record_builtin_type (RID_CHAR32, "char32_t", char32_type_node); + } + + /* This is for UTF-32 string constants. */ + char32_array_type_node + = build_array_type (char32_type_node, array_domain_type); + wint_type_node = TREE_TYPE (identifier_global_value (get_identifier (WINT_TYPE))); @@ -3749,7 +4120,7 @@ def_builtin_1 (enum built_in_function fncode, integral promotions defined in ISO C99 6.3.1.1/2. */ bool -c_promoting_integer_type_p (tree t) +c_promoting_integer_type_p (const_tree t) { switch (TREE_CODE (t)) { @@ -3779,9 +4150,9 @@ c_promoting_integer_type_p (tree t) and none of their types is affected by default promotions. */ int -self_promoting_args_p (tree parms) +self_promoting_args_p (const_tree parms) { - tree t; + const_tree t; for (t = parms; t; t = TREE_CHAIN (t)) { tree type = TREE_VALUE (t); @@ -3825,6 +4196,15 @@ strip_pointer_operator (tree t) return t; } +/* Recursively remove pointer or array type from TYPE. */ +tree +strip_pointer_or_array_types (tree t) +{ + while (TREE_CODE (t) == ARRAY_TYPE || POINTER_TYPE_P (t)) + t = TREE_TYPE (t); + return t; +} + /* Used to compare case labels. K1 and K2 are actually tree nodes representing case labels, or NULL_TREE for a `default' label. Returns -1 if K1 is ordered before K2, -1 if K1 is ordered after @@ -4023,13 +4403,16 @@ match_case_to_enum_1 (tree key, tree type, tree label) -TREE_INT_CST_LOW (key)); else snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_DOUBLE_HEX, - TREE_INT_CST_HIGH (key), TREE_INT_CST_LOW (key)); + (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (key), + (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (key)); if (TYPE_NAME (type) == 0) - warning (0, "%Jcase value %qs not in enumerated type", + warning (warn_switch ? OPT_Wswitch : OPT_Wswitch_enum, + "%Jcase value %qs not in enumerated type", CASE_LABEL (label), buf); else - warning (0, "%Jcase value %qs not in enumerated type %qT", + warning (warn_switch ? OPT_Wswitch : OPT_Wswitch_enum, + "%Jcase value %qs not in enumerated type %qT", CASE_LABEL (label), buf, type); } @@ -4081,6 +4464,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, splay_tree_node default_node; splay_tree_node node; tree chain; + int saved_warn_switch; if (!warn_switch && !warn_switch_enum && !warn_switch_default) return; @@ -4150,7 +4534,13 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, if (cond && tree_int_cst_compare (cond, value)) continue; - warning (0, "%Henumeration value %qE not handled in switch", + /* If there is a default_node, the only relevant option is + Wswitch-enum. Otherwise, if both are enabled then we prefer + to warn using -Wswitch because -Wswitch is enabled by -Wall + while -Wswitch-enum is explicit. */ + warning ((default_node || !warn_switch) + ? OPT_Wswitch_enum : OPT_Wswitch, + "%Henumeration value %qE not handled in switch", &switch_location, TREE_PURPOSE (chain)); } @@ -4162,7 +4552,17 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location, we should have marked both the lower bound and upper bound of every disjoint case label, with CASE_LOW_SEEN and CASE_HIGH_SEEN above. This scan also resets those fields. */ + + /* If there is a default_node, the only relevant option is + Wswitch-enum. Otherwise, if both are enabled then we prefer + to warn using -Wswitch because -Wswitch is enabled by -Wall + while -Wswitch-enum is explicit. */ + saved_warn_switch = warn_switch; + if (default_node) + warn_switch = 0; splay_tree_foreach (cases, match_case_to_enum, type); + warn_switch = saved_warn_switch; + } /* Finish an expression taking the address of LABEL (an @@ -4238,7 +4638,7 @@ tree boolean_increment (enum tree_code code, tree arg) { tree val; - tree true_res = boolean_true_node; + tree true_res = build_int_cst (TREE_TYPE (arg), 1); arg = stabilize_reference (arg); switch (code) @@ -4406,6 +4806,59 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args), return NULL_TREE; } +/* Handle a "hot" and attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + { + if (lookup_attribute ("cold", DECL_ATTRIBUTES (*node)) != NULL) + { + warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s", + name, "cold"); + *no_add_attrs = true; + } + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} +/* Handle a "cold" and attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args), + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL) + { + if (lookup_attribute ("hot", DECL_ATTRIBUTES (*node)) != NULL) + { + warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s", + name, "hot"); + *no_add_attrs = true; + } + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Handle a "noinline" attribute; arguments as in struct attribute_spec.handler. */ @@ -4436,8 +4889,9 @@ handle_always_inline_attribute (tree *node, tree name, { if (TREE_CODE (*node) == FUNCTION_DECL) { - /* Do nothing else, just set the attribute. We'll get at - it later with lookup_attribute. */ + /* Set the attribute and mark it for disregarding inline + limits. */ + DECL_DISREGARD_INLINE_LIMITS (*node) = 1; } else { @@ -4471,6 +4925,29 @@ handle_gnu_inline_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle an "artificial" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_artificial_attribute (tree *node, tree name, + tree ARG_UNUSED (args), + int ARG_UNUSED (flags), + bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node)) + { + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ + } + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} + /* Handle a "flatten" attribute; arguments as in struct attribute_spec.handler. */ @@ -4492,6 +4969,26 @@ handle_flatten_attribute (tree *node, tree name, return NULL_TREE; } +/* Handle a "warning" or "error" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_error_attribute (tree *node, tree name, tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + if (TREE_CODE (*node) == FUNCTION_DECL + || TREE_CODE (TREE_VALUE (args)) == STRING_CST) + /* Do nothing else, just set the attribute. We'll get at + it later with lookup_attribute. */ + ; + else + { + warning (OPT_Wattributes, "%qE attribute ignored", name); + *no_add_attrs = true; + } + + return NULL_TREE; +} /* Handle a "used" attribute; arguments as in struct attribute_spec.handler. */ @@ -4615,21 +5112,13 @@ handle_transparent_union_attribute (tree *node, tree name, tree ARG_UNUSED (args), int flags, bool *no_add_attrs) { - tree type = NULL; + tree type; *no_add_attrs = true; - if (DECL_P (*node)) - { - if (TREE_CODE (*node) != TYPE_DECL) - goto ignored; - node = &TREE_TYPE (*node); - type = *node; - } - else if (TYPE_P (*node)) - type = *node; - else - goto ignored; + if (TREE_CODE (*node) == TYPE_DECL) + node = &TREE_TYPE (*node); + type = *node; if (TREE_CODE (type) == UNION_TYPE) { @@ -4655,12 +5144,68 @@ handle_transparent_union_attribute (tree *node, tree name, return NULL_TREE; } +/* Subroutine of handle_{con,de}structor_attribute. Evaluate ARGS to + get the requested priority for a constructor or destructor, + possibly issuing diagnostics for invalid or reserved + priorities. */ + +static priority_type +get_priority (tree args, bool is_destructor) +{ + HOST_WIDE_INT pri; + tree arg; + + if (!args) + return DEFAULT_INIT_PRIORITY; + + if (!SUPPORTS_INIT_PRIORITY) + { + if (is_destructor) + error ("destructor priorities are not supported"); + else + error ("constructor priorities are not supported"); + return DEFAULT_INIT_PRIORITY; + } + + arg = TREE_VALUE (args); + if (!host_integerp (arg, /*pos=*/0) + || !INTEGRAL_TYPE_P (TREE_TYPE (arg))) + goto invalid; + + pri = tree_low_cst (TREE_VALUE (args), /*pos=*/0); + if (pri < 0 || pri > MAX_INIT_PRIORITY) + goto invalid; + + if (pri <= MAX_RESERVED_INIT_PRIORITY) + { + if (is_destructor) + warning (0, + "destructor priorities from 0 to %d are reserved " + "for the implementation", + MAX_RESERVED_INIT_PRIORITY); + else + warning (0, + "constructor priorities from 0 to %d are reserved " + "for the implementation", + MAX_RESERVED_INIT_PRIORITY); + } + return pri; + + invalid: + if (is_destructor) + error ("destructor priorities must be integers from 0 to %d inclusive", + MAX_INIT_PRIORITY); + else + error ("constructor priorities must be integers from 0 to %d inclusive", + MAX_INIT_PRIORITY); + return DEFAULT_INIT_PRIORITY; +} + /* Handle a "constructor" attribute; arguments as in struct attribute_spec.handler. */ static tree -handle_constructor_attribute (tree *node, tree name, - tree ARG_UNUSED (args), +handle_constructor_attribute (tree *node, tree name, tree args, int ARG_UNUSED (flags), bool *no_add_attrs) { @@ -4671,7 +5216,10 @@ handle_constructor_attribute (tree *node, tree name, && TREE_CODE (type) == FUNCTION_TYPE && decl_function_context (decl) == 0) { + priority_type priority; DECL_STATIC_CONSTRUCTOR (decl) = 1; + priority = get_priority (args, /*is_destructor=*/false); + SET_DECL_INIT_PRIORITY (decl, priority); TREE_USED (decl) = 1; } else @@ -4687,8 +5235,7 @@ handle_constructor_attribute (tree *node, tree name, struct attribute_spec.handler. */ static tree -handle_destructor_attribute (tree *node, tree name, - tree ARG_UNUSED (args), +handle_destructor_attribute (tree *node, tree name, tree args, int ARG_UNUSED (flags), bool *no_add_attrs) { @@ -4699,7 +5246,10 @@ handle_destructor_attribute (tree *node, tree name, && TREE_CODE (type) == FUNCTION_TYPE && decl_function_context (decl) == 0) { + priority_type priority; DECL_STATIC_DESTRUCTOR (decl) = 1; + priority = get_priority (args, /*is_destructor=*/true); + SET_DECL_FINI_PRIORITY (decl, priority); TREE_USED (decl) = 1; } else @@ -4751,6 +5301,10 @@ handle_mode_attribute (tree *node, tree name, tree args, mode = word_mode; else if (!strcmp (p, "pointer")) mode = ptr_mode; + else if (!strcmp (p, "libgcc_cmp_return")) + mode = targetm.libgcc_cmp_return_mode (); + else if (!strcmp (p, "libgcc_shift_count")) + mode = targetm.libgcc_shift_count_mode (); else for (j = 0; j < NUM_MACHINE_MODES; j++) if (!strcmp (p, GET_MODE_NAME (j))) @@ -4772,6 +5326,10 @@ handle_mode_attribute (tree *node, tree name, tree args, case MODE_PARTIAL_INT: case MODE_FLOAT: case MODE_DECIMAL_FLOAT: + case MODE_FRACT: + case MODE_UFRACT: + case MODE_ACCUM: + case MODE_UACCUM: valid_mode = targetm.scalar_mode_supported_p (mode); break; @@ -4782,6 +5340,10 @@ handle_mode_attribute (tree *node, tree name, tree args, case MODE_VECTOR_INT: case MODE_VECTOR_FLOAT: + case MODE_VECTOR_FRACT: + case MODE_VECTOR_UFRACT: + case MODE_VECTOR_ACCUM: + case MODE_VECTOR_UACCUM: warning (OPT_Wattributes, "specifying vector types with " "__attribute__ ((mode)) is deprecated"); warning (OPT_Wattributes, @@ -4815,7 +5377,20 @@ handle_mode_attribute (tree *node, tree name, tree args, typefm = fn (TREE_TYPE (type), mode, false); } else - typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type)); + { + /* For fixed-point modes, we need to test if the signness of type + and the machine mode are consistent. */ + if (ALL_FIXED_POINT_MODE_P (mode) + && TYPE_UNSIGNED (type) != UNSIGNED_FIXED_POINT_MODE_P (mode)) + { + error ("signness of type and machine mode %qs don't match", p); + return NULL_TREE; + } + /* For fixed-point modes, we need to pass saturating info. */ + typefm = lang_hooks.types.type_for_mode (mode, + ALL_FIXED_POINT_MODE_P (mode) ? TYPE_SATURATING (type) + : TYPE_UNSIGNED (type)); + } if (typefm == NULL_TREE) { @@ -4978,12 +5553,24 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args, TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT; TYPE_USER_ALIGN (*type) = 1; } - else if (TREE_CODE (decl) != VAR_DECL + else if (! VAR_OR_FUNCTION_DECL_P (decl) && TREE_CODE (decl) != FIELD_DECL) { error ("alignment may not be specified for %q+D", decl); *no_add_attrs = true; } + else if (TREE_CODE (decl) == FUNCTION_DECL + && DECL_ALIGN (decl) > (1 << i) * BITS_PER_UNIT) + { + if (DECL_USER_ALIGN (decl)) + error ("alignment for %q+D was previously specified as %d " + "and may not be decreased", decl, + DECL_ALIGN (decl) / BITS_PER_UNIT); + else + error ("alignment for %q+D must be at least %d", decl, + DECL_ALIGN (decl) / BITS_PER_UNIT); + *no_add_attrs = true; + } else { DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT; @@ -5003,11 +5590,16 @@ handle_weak_attribute (tree *node, tree name, bool * ARG_UNUSED (no_add_attrs)) { if (TREE_CODE (*node) == FUNCTION_DECL - || TREE_CODE (*node) == VAR_DECL) + && DECL_DECLARED_INLINE_P (*node)) + { + error ("inline function %q+D cannot be declared weak", *node); + *no_add_attrs = true; + } + else if (TREE_CODE (*node) == FUNCTION_DECL + || TREE_CODE (*node) == VAR_DECL) declare_weak (*node); else warning (OPT_Wattributes, "%qE attribute ignored", name); - return NULL_TREE; } @@ -5190,11 +5782,22 @@ handle_visibility_attribute (tree *node, tree name, tree args, } if (DECL_VISIBILITY_SPECIFIED (decl) - && vis != DECL_VISIBILITY (decl) - && lookup_attribute ("visibility", (TYPE_P (*node) - ? TYPE_ATTRIBUTES (*node) - : DECL_ATTRIBUTES (decl)))) - error ("%qD redeclared with different visibility", decl); + && vis != DECL_VISIBILITY (decl)) + { + tree attributes = (TYPE_P (*node) + ? TYPE_ATTRIBUTES (*node) + : DECL_ATTRIBUTES (decl)); + if (lookup_attribute ("visibility", attributes)) + error ("%qD redeclared with different visibility", decl); + else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES + && lookup_attribute ("dllimport", attributes)) + error ("%qD was declared %qs which implies default visibility", + decl, "dllimport"); + else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES + && lookup_attribute ("dllexport", attributes)) + error ("%qD was declared %qs which implies default visibility", + decl, "dllexport"); + } DECL_VISIBILITY (decl) = vis; DECL_VISIBILITY_SPECIFIED (decl) = 1; @@ -5227,18 +5830,12 @@ c_determine_visibility (tree decl) to distinguish the use of an attribute from the use of a "#pragma GCC visibility push(...)"; in the latter case we still want other considerations to be able to overrule the #pragma. */ - if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))) + if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl)) + || (TARGET_DLLIMPORT_DECL_ATTRIBUTES + && (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl)) + || lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))))) return true; - /* Anything that is exported must have default visibility. */ - if (TARGET_DLLIMPORT_DECL_ATTRIBUTES - && lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl))) - { - DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT; - DECL_VISIBILITY_SPECIFIED (decl) = 1; - return true; - } - /* Set default visibility to whatever the user supplied with visibility_specified depending on #pragma GCC visibility. */ if (!DECL_VISIBILITY_SPECIFIED (decl)) @@ -5337,6 +5934,37 @@ handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args), return NULL_TREE; } +/* Handle a "alloc_size" attribute; arguments as in + struct attribute_spec.handler. */ + +static tree +handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args, + int ARG_UNUSED (flags), bool *no_add_attrs) +{ + tree params = TYPE_ARG_TYPES (*node); + unsigned arg_count = 0; + + for (; TREE_CHAIN (params); params = TREE_CHAIN (params)) + arg_count ++; + + for (; args; args = TREE_CHAIN (args)) + { + tree position = TREE_VALUE (args); + + if (TREE_CODE (position) != INTEGER_CST + || TREE_INT_CST_HIGH (position) + || TREE_INT_CST_LOW (position) < 1 + || TREE_INT_CST_LOW (position) > arg_count ) + { + warning (OPT_Wattributes, + "alloc_size parameter outside range"); + *no_add_attrs = true; + return NULL_TREE; + } + } + return NULL_TREE; +} + /* Handle a "returns_twice" attribute; arguments as in struct attribute_spec.handler. */ @@ -5506,17 +6134,19 @@ handle_vector_size_attribute (tree *node, tree name, tree args, while (POINTER_TYPE_P (type) || TREE_CODE (type) == FUNCTION_TYPE || TREE_CODE (type) == METHOD_TYPE - || TREE_CODE (type) == ARRAY_TYPE) + || TREE_CODE (type) == ARRAY_TYPE + || TREE_CODE (type) == OFFSET_TYPE) type = TREE_TYPE (type); /* Get the mode of the type being modified. */ orig_mode = TYPE_MODE (type); - if (TREE_CODE (type) == RECORD_TYPE - || TREE_CODE (type) == UNION_TYPE - || TREE_CODE (type) == VECTOR_TYPE + if ((!INTEGRAL_TYPE_P (type) + && !SCALAR_FLOAT_TYPE_P (type) + && !FIXED_POINT_TYPE_P (type)) || (!SCALAR_FLOAT_MODE_P (orig_mode) - && GET_MODE_CLASS (orig_mode) != MODE_INT) + && GET_MODE_CLASS (orig_mode) != MODE_INT + && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode)) || !host_integerp (TYPE_SIZE_UNIT (type), 1)) { error ("invalid vector type for attribute %qE", name); @@ -5621,13 +6251,15 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name), } /* Check the argument list of a function call for null in argument slots - that are marked as requiring a non-null pointer argument. */ + that are marked as requiring a non-null pointer argument. The NARGS + arguments are passed in the array ARGARRAY. +*/ static void -check_function_nonnull (tree attrs, tree params) +check_function_nonnull (tree attrs, int nargs, tree *argarray) { - tree a, args, param; - int param_num; + tree a, args; + int i; for (a = attrs; a; a = TREE_CHAIN (a)) { @@ -5639,85 +6271,65 @@ check_function_nonnull (tree attrs, tree params) should check for non-null, do it. If the attribute has no args, then every pointer argument is checked (in which case the check for pointer type is done in check_nonnull_arg). */ - for (param = params, param_num = 1; ; - param_num++, param = TREE_CHAIN (param)) + for (i = 0; i < nargs; i++) { - if (!param) - break; - if (!args || nonnull_check_p (args, param_num)) + if (!args || nonnull_check_p (args, i + 1)) check_function_arguments_recurse (check_nonnull_arg, NULL, - TREE_VALUE (param), - param_num); + argarray[i], + i + 1); } } } } /* Check that the Nth argument of a function call (counting backwards - from the end) is a (pointer)0. */ + from the end) is a (pointer)0. The NARGS arguments are passed in the + array ARGARRAY. */ static void -check_function_sentinel (tree attrs, tree params, tree typelist) +check_function_sentinel (tree attrs, int nargs, tree *argarray, tree typelist) { tree attr = lookup_attribute ("sentinel", attrs); if (attr) { - /* Skip over the named arguments. */ - while (typelist && params) - { - typelist = TREE_CHAIN (typelist); - params = TREE_CHAIN (params); - } + int len = 0; + int pos = 0; + tree sentinel; - if (typelist || !params) - warning (OPT_Wformat, - "not enough variable arguments to fit a sentinel"); - else + /* Skip over the named arguments. */ + while (typelist && len < nargs) { - tree sentinel, end; - unsigned pos = 0; - - if (TREE_VALUE (attr)) - { - tree p = TREE_VALUE (TREE_VALUE (attr)); - pos = TREE_INT_CST_LOW (p); - } - - sentinel = end = params; - - /* Advance `end' ahead of `sentinel' by `pos' positions. */ - while (pos > 0 && TREE_CHAIN (end)) - { - pos--; - end = TREE_CHAIN (end); - } - if (pos > 0) - { - warning (OPT_Wformat, - "not enough variable arguments to fit a sentinel"); - return; - } + typelist = TREE_CHAIN (typelist); + len++; + } - /* Now advance both until we find the last parameter. */ - while (TREE_CHAIN (end)) - { - end = TREE_CHAIN (end); - sentinel = TREE_CHAIN (sentinel); - } + if (TREE_VALUE (attr)) + { + tree p = TREE_VALUE (TREE_VALUE (attr)); + pos = TREE_INT_CST_LOW (p); + } - /* Validate the sentinel. */ - if ((!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel))) - || !integer_zerop (TREE_VALUE (sentinel))) - /* Although __null (in C++) is only an integer we allow it - nevertheless, as we are guaranteed that it's exactly - as wide as a pointer, and we don't want to force - users to cast the NULL they have written there. - We warn with -Wstrict-null-sentinel, though. */ - && (warn_strict_null_sentinel - || null_node != TREE_VALUE (sentinel))) - warning (OPT_Wformat, "missing sentinel in function call"); + /* The sentinel must be one of the varargs, i.e. + in position >= the number of fixed arguments. */ + if ((nargs - 1 - pos) < len) + { + warning (OPT_Wformat, + "not enough variable arguments to fit a sentinel"); + return; } + + /* Validate the sentinel. */ + sentinel = argarray[nargs - 1 - pos]; + if ((!POINTER_TYPE_P (TREE_TYPE (sentinel)) + || !integer_zerop (sentinel)) + /* Although __null (in C++) is only an integer we allow it + nevertheless, as we are guaranteed that it's exactly + as wide as a pointer, and we don't want to force + users to cast the NULL they have written there. + We warn with -Wstrict-null-sentinel, though. */ + && (warn_strict_null_sentinel || null_node != sentinel)) + warning (OPT_Wformat, "missing sentinel in function call"); } } @@ -5891,14 +6503,16 @@ handle_sentinel_attribute (tree *node, tree name, tree args, if (TREE_CODE (position) != INTEGER_CST) { - warning (0, "requested position is not an integer constant"); + warning (OPT_Wattributes, + "requested position is not an integer constant"); *no_add_attrs = true; } else { if (tree_int_cst_lt (position, integer_zero_node)) { - warning (0, "requested position is less than zero"); + warning (OPT_Wattributes, + "requested position is less than zero"); *no_add_attrs = true; } } @@ -5906,24 +6520,40 @@ handle_sentinel_attribute (tree *node, tree name, tree args, return NULL_TREE; } + +/* Handle a "type_generic" attribute. */ + +static tree +handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name), + tree ARG_UNUSED (args), int ARG_UNUSED (flags), + bool * ARG_UNUSED (no_add_attrs)) +{ + /* Ensure we have a function type, with no arguments. */ + gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE && ! TYPE_ARG_TYPES (*node)); + + return NULL_TREE; +} -/* Check for valid arguments being passed to a function. */ +/* Check for valid arguments being passed to a function. + ATTRS is a list of attributes. There are NARGS arguments in the array + ARGARRAY. TYPELIST is the list of argument types for the function. + */ void -check_function_arguments (tree attrs, tree params, tree typelist) +check_function_arguments (tree attrs, int nargs, tree *argarray, tree typelist) { /* Check for null being passed in a pointer argument that must be non-null. We also need to do this if format checking is enabled. */ if (warn_nonnull) - check_function_nonnull (attrs, params); + check_function_nonnull (attrs, nargs, argarray); /* Check for errors in format strings. */ if (warn_format || warn_missing_format_attribute) - check_function_format (attrs, params); + check_function_format (attrs, nargs, argarray); if (warn_format) - check_function_sentinel (attrs, params, typelist); + check_function_sentinel (attrs, nargs, argarray, typelist); } /* Generic argument checking recursion routine. PARAM is the argument to @@ -6103,20 +6733,39 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value) if (token == CPP_EOF) message = catenate_messages (gmsgid, " at end of input"); - else if (token == CPP_CHAR || token == CPP_WCHAR) + else if (token == CPP_CHAR || token == CPP_WCHAR || token == CPP_CHAR16 + || token == CPP_CHAR32) { unsigned int val = TREE_INT_CST_LOW (value); - const char *const ell = (token == CPP_CHAR) ? "" : "L"; + const char *prefix; + + switch (token) + { + default: + prefix = ""; + break; + case CPP_WCHAR: + prefix = "L"; + break; + case CPP_CHAR16: + prefix = "u"; + break; + case CPP_CHAR32: + prefix = "U"; + break; + } + if (val <= UCHAR_MAX && ISGRAPH (val)) message = catenate_messages (gmsgid, " before %s'%c'"); else message = catenate_messages (gmsgid, " before %s'\\x%x'"); - error (message, ell, val); + error (message, prefix, val); free (message); message = NULL; } - else if (token == CPP_STRING || token == CPP_WSTRING) + else if (token == CPP_STRING || token == CPP_WSTRING || token == CPP_STRING16 + || token == CPP_STRING32) message = catenate_messages (gmsgid, " before string constant"); else if (token == CPP_NUMBER) message = catenate_messages (gmsgid, " before numeric constant"); @@ -6312,6 +6961,12 @@ fold_offsetof_1 (tree expr, tree stop_ref) off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t); break; + case COMPOUND_EXPR: + /* Handle static members of volatile structs. */ + t = TREE_OPERAND (expr, 1); + gcc_assert (TREE_CODE (t) == VAR_DECL); + return fold_offsetof_1 (t, stop_ref); + default: gcc_unreachable (); } @@ -6447,11 +7102,34 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default) hashcode); main_type = type_hash_canon (hashcode, main_type); + /* Fix the canonical type. */ + if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type)) + || TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type))) + SET_TYPE_STRUCTURAL_EQUALITY (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) + = build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)), + TYPE_CANONICAL (TYPE_DOMAIN (main_type))); + else + TYPE_CANONICAL (main_type) = main_type; + if (quals == 0) type = main_type; else type = c_build_qualified_type (main_type, quals); + if (COMPLETE_TYPE_P (type) + && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST + && TREE_OVERFLOW (TYPE_SIZE_UNIT (type))) + { + error ("size of array is too large"); + /* If we proceed with the array type as it is, we'll eventually + crash in tree_low_cst(). */ + type = error_mark_node; + } + *ptype = type; return failure; } @@ -6643,13 +7321,14 @@ same_scalar_type_ignoring_signedness (tree t1, tree t2) { enum tree_code c1 = TREE_CODE (t1), c2 = TREE_CODE (t2); - gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE) - && (c2 == INTEGER_TYPE || c2 == REAL_TYPE)); + gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE || c1 == FIXED_POINT_TYPE) + && (c2 == INTEGER_TYPE || c2 == REAL_TYPE + || c2 == FIXED_POINT_TYPE)); /* Equality works here because c_common_signed_type uses TYPE_MAIN_VARIANT. */ - return lang_hooks.types.signed_type (t1) - == lang_hooks.types.signed_type (t2); + return c_common_signed_type (t1) + == c_common_signed_type (t2); } /* Check for missing format attributes on function pointers. LTYPE is @@ -6800,4 +7479,22 @@ warn_for_unused_label (tree label) } } +#ifndef TARGET_HAS_TARGETCM +struct gcc_targetcm targetcm = TARGETCM_INITIALIZER; +#endif + +/* Warn for division by zero according to the value of DIVISOR. */ + +void +warn_for_div_by_zero (tree divisor) +{ + /* If DIVISOR is zero, and has integral or fixed-point type, issue a warning + about division by zero. Do not issue a warning if DIVISOR has a + floating-point type, since we consider 0.0/0.0 a valid way of + generating a NaN. */ + if (skip_evaluation == 0 + && (integer_zerop (divisor) || fixed_zerop (divisor))) + warning (OPT_Wdiv_by_zero, "division by zero"); +} + #include "gt-c-common.h"