OSDN Git Service

2008-03-25 Douglas Gregor <doug.gregor@gmail.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 51fd226..1b62974 100644 (file)
@@ -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
+<http://www.gnu.org/licenses/>.  */
 
 #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.  */
 
@@ -405,10 +406,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 +443,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 +505,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 +551,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 +585,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 +600,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 +649,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 +758,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 +770,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, false))
+    {
+      XDELETEVEC (namep);
+      return (const char *) cstr.text;
     }
-  else
-    namep = xstrdup (name);
 
   return namep;
 }
@@ -824,11 +835,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);
@@ -915,13 +922,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 +969,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 +989,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 +1099,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 %<if%> 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 %<else%> statement", EXPR_LOCUS (inner_else));
 }
 
 /* Warn for unlikely, improbable, or stupid DECL declarations
@@ -1088,7 +1176,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 +1196,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 +1211,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 +1220,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 +1239,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 +1282,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 +1332,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 +1356,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;
 }
 \f
@@ -1422,7 +1530,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 +1943,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 +2080,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 +2176,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 +2187,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 +2196,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 +2287,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 +2399,10 @@ min_precision (tree value, int unsignedp)
 }
 \f
 /* 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 +2453,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);
 }
 \f
 /* Subroutine of build_binary_op, used for comparison operations.
@@ -2247,7 +2506,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 +2562,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 +2689,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 +2761,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 +2816,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 +2849,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 +2877,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 +2884,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 +2904,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 +2968,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.  */
@@ -2806,6 +3074,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);
 }
 \f
@@ -2816,52 +3092,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 %<restrict%>");
-      type_quals &= ~TYPE_QUAL_RESTRICT;
-    }
-
-  return build_qualified_type (type, type_quals);
-}
 
 /* Apply the TYPE_QUALS to the new DECL.  */
 
@@ -2915,7 +3145,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 +3174,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 +3187,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 +3285,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 +3347,8 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
        {
          if (complain && (pedantic || warn_pointer_arith))
            pedwarn ("invalid application of %<sizeof%> to a function type");
+          else if (!complain)
+            return error_mark_node;
          value = size_one_node;
        }
       else
@@ -3123,6 +3359,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 +3392,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 +3615,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 ();
 }
@@ -3498,6 +3737,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));
@@ -3749,7 +4049,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 +4079,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 +4125,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
@@ -4026,10 +4335,12 @@ match_case_to_enum_1 (tree key, tree type, tree label)
              TREE_INT_CST_HIGH (key), 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 +4392,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 +4462,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 +4480,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 +4566,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 +4734,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 +4817,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 +4853,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 +4897,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 +5040,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 +5072,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 +5144,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 +5163,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 +5174,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 +5229,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 +5254,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 +5268,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 +5305,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 +5481,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;
@@ -5190,11 +5705,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 +5753,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 +5857,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 +6057,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 +6174,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 +6194,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 +6426,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 +6443,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;
+}
 \f
-/* 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
@@ -6312,6 +6865,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 +7006,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 +7225,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 +7383,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"