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"