OSDN Git Service

Daily bump.
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 8d20efd..b94ac1b 100644 (file)
@@ -1,6 +1,6 @@
 /* Subroutines shared by all languages that are variants of C.
    Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
-   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -48,6 +48,8 @@ along with GCC; see the file COPYING3.  If not see
 #include "real.h"
 #include "cgraph.h"
 #include "target-def.h"
+#include "gimple.h"
+#include "fixed-value.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
@@ -65,6 +67,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 +132,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 +186,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;
@@ -199,7 +222,7 @@ tree c_global_trees[CTI_MAX];
 \f
 /* Switches common to the C front ends.  */
 
-/* Nonzero if prepreprocessing only.  */
+/* Nonzero if preprocessing only.  */
 
 int flag_preprocess_only;
 
@@ -319,10 +342,6 @@ int flag_isoc99;
 
 int flag_hosted = 1;
 
-/* Warn if main is suspicious.  */
-
-int warn_main;
-
 
 /* ObjC language option variables.  */
 
@@ -338,7 +357,7 @@ int flag_gen_declaration;
 
 int print_struct_values;
 
-/* Tells the compiler what is the constant string class for Objc.  */
+/* Tells the compiler what is the constant string class for ObjC.  */
 
 const char *constant_string_class_name;
 
@@ -442,11 +461,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
@@ -514,9 +528,10 @@ 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,
@@ -556,6 +571,8 @@ static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
 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 tree handle_target_attribute (tree *, tree, tree, int, bool *);
+static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
 
 static void check_function_nonnull (tree, int, tree *);
 static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
@@ -563,6 +580,179 @@ static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
 static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
 static int resort_field_decl_cmp (const void *, const void *);
 
+/* Reserved words.  The third field is a mask: keywords are disabled
+   if they match the mask.
+
+   Masks for languages:
+   C --std=c89: D_C99 | D_CXXONLY | D_OBJC | D_CXX_OBJC
+   C --std=c99: D_CXXONLY | D_OBJC
+   ObjC is like C except that D_OBJC and D_CXX_OBJC are not set
+   C++ --std=c98: D_CONLY | D_CXXOX | D_OBJC
+   C++ --std=c0x: D_CONLY | D_OBJC
+   ObjC++ is like C++ except that D_OBJC is not set
+
+   If -fno-asm is used, D_ASM is added to the mask.  If
+   -fno-gnu-keywords is used, D_EXT is added.  If -fno-asm and C in
+   C89 mode, D_EXT89 is added for both -fno-asm and -fno-gnu-keywords.
+   In C with -Wc++-compat, we warn if D_CXXWARN is set.  */
+
+const struct c_common_resword c_common_reswords[] =
+{
+  { "_Bool",           RID_BOOL,      D_CONLY },
+  { "_Complex",                RID_COMPLEX,    0 },
+  { "_Decimal32",       RID_DFLOAT32,  D_CONLY | D_EXT },
+  { "_Decimal64",       RID_DFLOAT64,  D_CONLY | D_EXT },
+  { "_Decimal128",      RID_DFLOAT128, D_CONLY | D_EXT },
+  { "_Fract",           RID_FRACT,     D_CONLY | D_EXT },
+  { "_Accum",           RID_ACCUM,     D_CONLY | D_EXT },
+  { "_Sat",             RID_SAT,       D_CONLY | D_EXT },
+  { "__FUNCTION__",    RID_FUNCTION_NAME, 0 },
+  { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
+  { "__alignof",       RID_ALIGNOF,    0 },
+  { "__alignof__",     RID_ALIGNOF,    0 },
+  { "__asm",           RID_ASM,        0 },
+  { "__asm__",         RID_ASM,        0 },
+  { "__attribute",     RID_ATTRIBUTE,  0 },
+  { "__attribute__",   RID_ATTRIBUTE,  0 },
+  { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
+  { "__builtin_offsetof", RID_OFFSETOF, 0 },
+  { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY },
+  { "__builtin_va_arg",        RID_VA_ARG,     0 },
+  { "__complex",       RID_COMPLEX,    0 },
+  { "__complex__",     RID_COMPLEX,    0 },
+  { "__const",         RID_CONST,      0 },
+  { "__const__",       RID_CONST,      0 },
+  { "__decltype",       RID_DECLTYPE,   D_CXXONLY },
+  { "__extension__",   RID_EXTENSION,  0 },
+  { "__func__",                RID_C99_FUNCTION_NAME, 0 },
+  { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
+  { "__has_nothrow_constructor", RID_HAS_NOTHROW_CONSTRUCTOR, D_CXXONLY },
+  { "__has_nothrow_copy", RID_HAS_NOTHROW_COPY, D_CXXONLY },
+  { "__has_trivial_assign", RID_HAS_TRIVIAL_ASSIGN, D_CXXONLY },
+  { "__has_trivial_constructor", RID_HAS_TRIVIAL_CONSTRUCTOR, D_CXXONLY },
+  { "__has_trivial_copy", RID_HAS_TRIVIAL_COPY, D_CXXONLY },
+  { "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, D_CXXONLY },
+  { "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, D_CXXONLY },
+  { "__is_abstract",   RID_IS_ABSTRACT, D_CXXONLY },
+  { "__is_base_of",    RID_IS_BASE_OF, D_CXXONLY },
+  { "__is_class",      RID_IS_CLASS,   D_CXXONLY },
+  { "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY },
+  { "__is_empty",      RID_IS_EMPTY,   D_CXXONLY },
+  { "__is_enum",       RID_IS_ENUM,    D_CXXONLY },
+  { "__is_pod",                RID_IS_POD,     D_CXXONLY },
+  { "__is_polymorphic",        RID_IS_POLYMORPHIC, D_CXXONLY },
+  { "__is_union",      RID_IS_UNION,   D_CXXONLY },
+  { "__imag",          RID_IMAGPART,   0 },
+  { "__imag__",                RID_IMAGPART,   0 },
+  { "__inline",                RID_INLINE,     0 },
+  { "__inline__",      RID_INLINE,     0 },
+  { "__label__",       RID_LABEL,      0 },
+  { "__null",          RID_NULL,       0 },
+  { "__real",          RID_REALPART,   0 },
+  { "__real__",                RID_REALPART,   0 },
+  { "__restrict",      RID_RESTRICT,   0 },
+  { "__restrict__",    RID_RESTRICT,   0 },
+  { "__signed",                RID_SIGNED,     0 },
+  { "__signed__",      RID_SIGNED,     0 },
+  { "__thread",                RID_THREAD,     0 },
+  { "__typeof",                RID_TYPEOF,     0 },
+  { "__typeof__",      RID_TYPEOF,     0 },
+  { "__volatile",      RID_VOLATILE,   0 },
+  { "__volatile__",    RID_VOLATILE,   0 },
+  { "asm",             RID_ASM,        D_ASM },
+  { "auto",            RID_AUTO,       0 },
+  { "bool",            RID_BOOL,       D_CXXONLY | D_CXXWARN },
+  { "break",           RID_BREAK,      0 },
+  { "case",            RID_CASE,       0 },
+  { "catch",           RID_CATCH,      D_CXX_OBJC | D_CXXWARN },
+  { "char",            RID_CHAR,       0 },
+  { "char16_t",                RID_CHAR16,     D_CXXONLY | D_CXX0X | D_CXXWARN },
+  { "char32_t",                RID_CHAR32,     D_CXXONLY | D_CXX0X | D_CXXWARN },
+  { "class",           RID_CLASS,      D_CXX_OBJC | D_CXXWARN },
+  { "const",           RID_CONST,      0 },
+  { "const_cast",      RID_CONSTCAST,  D_CXXONLY | D_CXXWARN },
+  { "continue",                RID_CONTINUE,   0 },
+  { "decltype",         RID_DECLTYPE,   D_CXXONLY | D_CXX0X | D_CXXWARN },
+  { "default",         RID_DEFAULT,    0 },
+  { "delete",          RID_DELETE,     D_CXXONLY | D_CXXWARN },
+  { "do",              RID_DO,         0 },
+  { "double",          RID_DOUBLE,     0 },
+  { "dynamic_cast",    RID_DYNCAST,    D_CXXONLY | D_CXXWARN },
+  { "else",            RID_ELSE,       0 },
+  { "enum",            RID_ENUM,       0 },
+  { "explicit",                RID_EXPLICIT,   D_CXXONLY | D_CXXWARN },
+  { "export",          RID_EXPORT,     D_CXXONLY | D_CXXWARN },
+  { "extern",          RID_EXTERN,     0 },
+  { "false",           RID_FALSE,      D_CXXONLY | D_CXXWARN },
+  { "float",           RID_FLOAT,      0 },
+  { "for",             RID_FOR,        0 },
+  { "friend",          RID_FRIEND,     D_CXXONLY | D_CXXWARN },
+  { "goto",            RID_GOTO,       0 },
+  { "if",              RID_IF,         0 },
+  { "inline",          RID_INLINE,     D_EXT89 },
+  { "int",             RID_INT,        0 },
+  { "long",            RID_LONG,       0 },
+  { "mutable",         RID_MUTABLE,    D_CXXONLY | D_CXXWARN },
+  { "namespace",       RID_NAMESPACE,  D_CXXONLY | D_CXXWARN },
+  { "new",             RID_NEW,        D_CXXONLY | D_CXXWARN },
+  { "operator",                RID_OPERATOR,   D_CXXONLY | D_CXXWARN },
+  { "private",         RID_PRIVATE,    D_CXX_OBJC | D_CXXWARN },
+  { "protected",       RID_PROTECTED,  D_CXX_OBJC | D_CXXWARN },
+  { "public",          RID_PUBLIC,     D_CXX_OBJC | D_CXXWARN },
+  { "register",                RID_REGISTER,   0 },
+  { "reinterpret_cast",        RID_REINTCAST,  D_CXXONLY | D_CXXWARN },
+  { "restrict",                RID_RESTRICT,   D_CONLY | D_C99 },
+  { "return",          RID_RETURN,     0 },
+  { "short",           RID_SHORT,      0 },
+  { "signed",          RID_SIGNED,     0 },
+  { "sizeof",          RID_SIZEOF,     0 },
+  { "static",          RID_STATIC,     0 },
+  { "static_assert",    RID_STATIC_ASSERT, D_CXXONLY | D_CXX0X | D_CXXWARN },
+  { "static_cast",     RID_STATCAST,   D_CXXONLY | D_CXXWARN },
+  { "struct",          RID_STRUCT,     0 },
+  { "switch",          RID_SWITCH,     0 },
+  { "template",                RID_TEMPLATE,   D_CXXONLY | D_CXXWARN },
+  { "this",            RID_THIS,       D_CXXONLY | D_CXXWARN },
+  { "throw",           RID_THROW,      D_CXX_OBJC | D_CXXWARN },
+  { "true",            RID_TRUE,       D_CXXONLY | D_CXXWARN },
+  { "try",             RID_TRY,        D_CXX_OBJC | D_CXXWARN },
+  { "typedef",         RID_TYPEDEF,    0 },
+  { "typename",                RID_TYPENAME,   D_CXXONLY | D_CXXWARN },
+  { "typeid",          RID_TYPEID,     D_CXXONLY | D_CXXWARN },
+  { "typeof",          RID_TYPEOF,     D_ASM | D_EXT },
+  { "union",           RID_UNION,      0 },
+  { "unsigned",                RID_UNSIGNED,   0 },
+  { "using",           RID_USING,      D_CXXONLY | D_CXXWARN },
+  { "virtual",         RID_VIRTUAL,    D_CXXONLY | D_CXXWARN },
+  { "void",            RID_VOID,       0 },
+  { "volatile",                RID_VOLATILE,   0 },
+  { "wchar_t",         RID_WCHAR,      D_CXXONLY },
+  { "while",           RID_WHILE,      0 },
+  /* These Objective-C keywords are recognized only immediately after
+     an '@'.  */
+  { "compatibility_alias", RID_AT_ALIAS,       D_OBJC },
+  { "defs",            RID_AT_DEFS,            D_OBJC },
+  { "encode",          RID_AT_ENCODE,          D_OBJC },
+  { "end",             RID_AT_END,             D_OBJC },
+  { "implementation",  RID_AT_IMPLEMENTATION,  D_OBJC },
+  { "interface",       RID_AT_INTERFACE,       D_OBJC },
+  { "protocol",                RID_AT_PROTOCOL,        D_OBJC },
+  { "selector",                RID_AT_SELECTOR,        D_OBJC },
+  { "finally",         RID_AT_FINALLY,         D_OBJC },
+  { "synchronized",    RID_AT_SYNCHRONIZED,    D_OBJC },
+  /* These are recognized only in protocol-qualifier context
+     (see above) */
+  { "bycopy",          RID_BYCOPY,             D_OBJC },
+  { "byref",           RID_BYREF,              D_OBJC },
+  { "in",              RID_IN,                 D_OBJC },
+  { "inout",           RID_INOUT,              D_OBJC },
+  { "oneway",          RID_ONEWAY,             D_OBJC },
+  { "out",             RID_OUT,                D_OBJC },
+};
+
+const unsigned int num_c_common_reswords =
+  sizeof c_common_reswords / sizeof (struct c_common_resword);
+
 /* Table of machine-independent attributes common to all C-like languages.  */
 const struct attribute_spec c_common_attribute_table[] =
 {
@@ -588,6 +778,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,
@@ -660,6 +852,14 @@ const struct attribute_spec c_common_attribute_table[] =
                              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 },
+  { "target",                 1, -1, true, false, false,
+                             handle_target_attribute },
+  { "optimize",               1, -1, true, false, false,
+                             handle_optimize_attribute },
   { NULL,                     0, 0, false, false, false, NULL }
 };
 
@@ -755,7 +955,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)
     {
@@ -766,59 +967,32 @@ 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;
-
-      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 (const char *) cstr.text;
-       }
-    }
-  else
-    namep = xstrdup (name);
-
-  return namep;
-}
+  len = strlen (name) + 3; /* Two for '"'s.  One for NULL.  */
 
-/* Expand DECL if it declares an entity not handled by the
-   common code.  */
+  namep = XNEWVEC (char, len);
+  snprintf (namep, len, "\"%s\"", name);
+  strname.text = (unsigned char *) namep;
+  strname.len = len - 1;
 
-int
-c_expand_decl (tree decl)
-{
-  if (TREE_CODE (decl) == VAR_DECL && !TREE_STATIC (decl))
+  if (cpp_interpret_string (parse_in, &strname, 1, &cstr, CPP_STRING))
     {
-      /* Let the back-end know about this variable.  */
-      if (!anon_aggr_type_p (TREE_TYPE (decl)))
-       emit_local_var (decl);
-      else
-       expand_anon_union_decl (decl, NULL_TREE,
-                               DECL_ANON_UNION_ELEMS (decl));
+      XDELETEVEC (namep);
+      return (const char *) cstr.text;
     }
-  else
-    return 0;
 
-  return 1;
+  return namep;
 }
 
-
 /* Return the VAR_DECL for a const char array naming the current
    function. If the VAR_DECL has not yet been created, create it
    now. RID indicates how it should be formatted and IDENTIFIER_NODE
    ID is its name (unfortunately C and C++ hold the RID values of
    keywords in different places, so we can't derive RID from ID in
-   this language independent code.  */
+   this language independent code. LOC is the location of the
+   function.  */
 
 tree
-fname_decl (unsigned int rid, tree id)
+fname_decl (location_t loc, unsigned int rid, tree id)
 {
   unsigned ix;
   tree decl = NULL_TREE;
@@ -837,11 +1011,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);
@@ -853,7 +1023,7 @@ fname_decl (unsigned int rid, tree id)
       input_location = saved_location;
     }
   if (!ix && !current_function_decl)
-    pedwarn ("%qD is not defined outside of function scope", decl);
+    pedwarn (loc, 0, "%qD is not defined outside of function scope", decl);
 
   return decl;
 }
@@ -863,14 +1033,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,
@@ -885,7 +1072,8 @@ fix_string_type (tree value)
           separate the %d from the 'C'.  'ISO' should not be
           translated, but it may be moved after 'C%d' in languages
           where modifiers follow nouns.  */
-       pedwarn ("string length %qd is greater than the length %qd "
+       pedwarn (input_location, OPT_Woverlength_strings,
+                "string length %qd is greater than the length %qd "
                 "ISO C%d compilers are required to support",
                 nchars - 1, nchars_max, relevant_std);
     }
@@ -905,7 +1093,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)
@@ -913,7 +1100,6 @@ fix_string_type (tree value)
 
   TREE_TYPE (value) = a_type;
   TREE_CONSTANT (value) = 1;
-  TREE_INVARIANT (value) = 1;
   TREE_READONLY (value) = 1;
   TREE_STATIC (value) = 1;
   return value;
@@ -928,13 +1114,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 (input_location, OPT_Woverflow, "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
@@ -963,6 +1161,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;
@@ -1023,8 +1225,13 @@ warn_logical_operator (enum tree_code code, tree arg1, tree
 bool
 strict_aliasing_warning (tree otype, tree type, tree expr)
 {
-  if (!(flag_strict_aliasing && POINTER_TYPE_P (type) 
-        && POINTER_TYPE_P (otype) && !VOID_TYPE_P (TREE_TYPE (type))))
+  if (!(flag_strict_aliasing
+       && POINTER_TYPE_P (type)
+       && POINTER_TYPE_P (otype)
+       && !VOID_TYPE_P (TREE_TYPE (type)))
+      /* If the type we are casting to is a ref-all pointer
+         dereferencing it is always valid.  */
+      || TYPE_REF_CAN_ALIAS_ALL (type))
     return false;
 
   if ((warn_strict_aliasing > 1) && TREE_CODE (expr) == ADDR_EXPR
@@ -1043,11 +1250,12 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
         {
           /* warn_strict_aliasing >= 3.   This includes the default (3).  
              Only warn if the cast is dereferenced immediately.  */
-          HOST_WIDE_INT set1 =
+          alias_set_type set1 =
            get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
-          HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
+          alias_set_type set2 = get_alias_set (TREE_TYPE (type));
 
-          if (!alias_sets_conflict_p (set1, set2))
+          if (set1 != set2 && set2 != 0
+             && (set1 == 0 || !alias_sets_conflict_p (set1, set2)))
            {
              warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
                       "pointer will break strict-aliasing rules");
@@ -1069,9 +1277,9 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
            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.  */
-        HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (otype));
-        HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
-        if (!COMPLETE_TYPE_P(type)
+        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 "
@@ -1083,31 +1291,6 @@ strict_aliasing_warning (tree otype, tree type, tree expr)
   return false;
 }
 
-/* Print a warning about if (); or if () .. else; constructs
-   via the special empty statement node that we create.  INNER_THEN
-   and INNER_ELSE are the statement lists of the if and the else
-   block.  */
-
-void
-empty_if_body_warning (tree inner_then, tree inner_else)
-{
-  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 (IS_EMPTY_STMT (inner_then) && !inner_else)
-    warning (OPT_Wempty_body, "%Hsuggest braces around empty body "
-             "in an %<if%> statement", EXPR_LOCUS (inner_then));
-
-  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
    of `main'.  */
 
@@ -1130,7 +1313,8 @@ check_main_parameter_types (tree decl)
        {
        case 1:
          if (TYPE_MAIN_VARIANT (type) != integer_type_node)
-           pedwarn ("first argument of %q+D should be %<int%>", decl);
+           pedwarn (input_location, OPT_Wmain, "first argument of %q+D should be %<int%>", 
+                   decl);
          break;
 
        case 2:
@@ -1138,8 +1322,8 @@ check_main_parameter_types (tree decl)
              || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
              || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
                  != char_type_node))
-           pedwarn ("second argument of %q+D should be %<char **%>",
-                    decl);
+           pedwarn (input_location, OPT_Wmain, "second argument of %q+D should be %<char **%>",
+                   decl);
          break;
 
        case 3:
@@ -1147,8 +1331,8 @@ check_main_parameter_types (tree decl)
              || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
              || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
                  != char_type_node))
-           pedwarn ("third argument of %q+D should probably be "
-                    "%<char **%>", decl);
+          pedwarn (input_location, OPT_Wmain, "third argument of %q+D should probably be "
+                   "%<char **%>", decl);
          break;
        }
    }
@@ -1157,7 +1341,21 @@ check_main_parameter_types (tree decl)
     argument because it's only mentioned in an appendix of the
     standard.  */
   if (argct > 0 && (argct < 2 || argct > 3))
-   pedwarn ("%q+D takes only zero or two arguments", decl);
+    pedwarn (input_location, OPT_Wmain, "%q+D takes only zero or two arguments", decl);
+}
+
+/* True if pointers to distinct types T1 and T2 can be converted to
+   each other without an explicit cast.  Only returns true for opaque
+   vector types.  */
+bool
+vector_targets_convertible_p (const_tree t1, const_tree t2)
+{
+  if (TREE_CODE (t1) == VECTOR_TYPE && TREE_CODE (t2) == VECTOR_TYPE
+      && (targetm.vector_opaque_p (t1) || targetm.vector_opaque_p (t2))
+      && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
+    return true;
+
+  return false;
 }
 
 /* True if vector types T1 and T2 can be converted to each other
@@ -1166,7 +1364,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;
@@ -1186,13 +1384,13 @@ 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)
     {
       emitted_lax_note = true;
-      inform ("use -flax-vector-conversions to permit "
+      inform (input_location, "use -flax-vector-conversions to permit "
               "conversions between vectors with differing "
               "element types or numbers of subparts");
     }
@@ -1200,6 +1398,110 @@ vector_types_convertible_p (tree t1, tree t2, bool emit_lax_note)
   return false;
 }
 
+/* This is a helper function of build_binary_op.
+
+   For certain operations if both args were extended from the same
+   smaller type, do the arithmetic in that type and then extend.
+
+   BITWISE indicates a bitwise operation.
+   For them, this optimization is safe only if
+   both args are zero-extended or both are sign-extended.
+   Otherwise, we might change the result.
+   Eg, (short)-1 | (unsigned short)-1 is (int)-1
+   but calculated in (unsigned short) it would be (unsigned short)-1.  
+*/
+tree shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
+{
+  int unsigned0, unsigned1;
+  tree arg0, arg1;
+  int uns;
+  tree type;
+
+  /* Cast OP0 and OP1 to RESULT_TYPE.  Doing so prevents
+     excessive narrowing when we call get_narrower below.  For
+     example, suppose that OP0 is of unsigned int extended
+     from signed char and that RESULT_TYPE is long long int.
+     If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
+     like
+     
+     (long long int) (unsigned int) signed_char
+
+     which get_narrower would narrow down to
+     
+     (unsigned int) signed char
+     
+     If we do not cast OP0 first, get_narrower would return
+     signed_char, which is inconsistent with the case of the
+     explicit cast.  */
+  op0 = convert (result_type, op0);
+  op1 = convert (result_type, op1);
+
+  arg0 = get_narrower (op0, &unsigned0);
+  arg1 = get_narrower (op1, &unsigned1);
+
+  /* UNS is 1 if the operation to be done is an unsigned one.  */
+  uns = TYPE_UNSIGNED (result_type);
+
+  /* Handle the case that OP0 (or OP1) does not *contain* a conversion
+     but it *requires* conversion to FINAL_TYPE.  */
+  
+  if ((TYPE_PRECISION (TREE_TYPE (op0))
+       == TYPE_PRECISION (TREE_TYPE (arg0)))
+      && TREE_TYPE (op0) != result_type)
+    unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
+  if ((TYPE_PRECISION (TREE_TYPE (op1))
+       == TYPE_PRECISION (TREE_TYPE (arg1)))
+      && TREE_TYPE (op1) != result_type)
+    unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
+  
+  /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE.  */
+  
+  /* For bitwise operations, signedness of nominal type
+     does not matter.  Consider only how operands were extended.  */
+  if (bitwise)
+    uns = unsigned0;
+  
+  /* Note that in all three cases below we refrain from optimizing
+     an unsigned operation on sign-extended args.
+     That would not be valid.  */
+  
+  /* Both args variable: if both extended in same way
+     from same width, do it in that width.
+     Do it unsigned if args were zero-extended.  */
+  if ((TYPE_PRECISION (TREE_TYPE (arg0))
+       < TYPE_PRECISION (result_type))
+      && (TYPE_PRECISION (TREE_TYPE (arg1))
+         == TYPE_PRECISION (TREE_TYPE (arg0)))
+      && unsigned0 == unsigned1
+      && (unsigned0 || !uns))
+    return c_common_signed_or_unsigned_type
+      (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
+
+  else if (TREE_CODE (arg0) == INTEGER_CST
+          && (unsigned1 || !uns)
+          && (TYPE_PRECISION (TREE_TYPE (arg1))
+              < TYPE_PRECISION (result_type))
+          && (type
+              = c_common_signed_or_unsigned_type (unsigned1,
+                                                  TREE_TYPE (arg1)))
+          && !POINTER_TYPE_P (type)
+          && int_fits_type_p (arg0, type))
+    return type;
+
+  else if (TREE_CODE (arg1) == INTEGER_CST
+          && (unsigned0 || !uns)
+          && (TYPE_PRECISION (TREE_TYPE (arg0))
+              < TYPE_PRECISION (result_type))
+          && (type
+              = c_common_signed_or_unsigned_type (unsigned0,
+                                                  TREE_TYPE (arg0)))
+          && !POINTER_TYPE_P (type)
+          && int_fits_type_p (arg1, type))
+    return type;
+
+  return result_type;
+}
+
 /* Warns if the conversion of EXPR to TYPE may alter a value.
    This is a helper function for warnings_for_convert_and_check.  */
 
@@ -1208,39 +1510,74 @@ conversion_warning (tree type, tree expr)
 {
   bool give_warning = false;
 
-  unsigned int formal_prec = TYPE_PRECISION (type);
+  int i;
+  const int expr_num_operands = TREE_OPERAND_LENGTH (expr);
+  tree expr_type = TREE_TYPE (expr);
 
   if (!warn_conversion && !warn_sign_conversion)
     return;
 
-  if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
+  /* If any operand is artificial, then this expression was generated
+     by the compiler and we do not warn.  */
+  for (i = 0; i < expr_num_operands; i++)
+    {
+      tree op = TREE_OPERAND (expr, i);
+      if (op && DECL_P (op) && DECL_ARTIFICIAL (op))
+       return;
+    }
+
+  switch (TREE_CODE (expr))
     {
+    case EQ_EXPR:
+    case NE_EXPR:
+    case LE_EXPR:
+    case GE_EXPR:
+    case LT_EXPR:
+    case GT_EXPR:
+    case TRUTH_ANDIF_EXPR:
+    case TRUTH_ORIF_EXPR:
+    case TRUTH_AND_EXPR:
+    case TRUTH_OR_EXPR:
+    case TRUTH_XOR_EXPR:
+    case TRUTH_NOT_EXPR:
+      /* Conversion from boolean to a signed:1 bit-field (which only
+        can hold the values 0 and -1) doesn't lose information - but
+        it does change the value.  */
+      if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type)) 
+       warning (OPT_Wconversion,
+                 "conversion to %qT from boolean expression", type);
+      return;
+
+    case REAL_CST:
+    case INTEGER_CST:
+
       /* Warn for real constant that is not an exact integer converted
          to integer type.  */
-      if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+      if (TREE_CODE (expr_type) == REAL_TYPE
           && TREE_CODE (type) == INTEGER_TYPE)
         {
-          if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (TREE_TYPE (expr))))
+          if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type)))
             give_warning = true;
         }
       /* Warn for an integer constant that does not fit into integer type.  */
-      else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+      else if (TREE_CODE (expr_type) == INTEGER_TYPE
                && TREE_CODE (type) == INTEGER_TYPE
                && !int_fits_type_p (expr, type))
         {
-          if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr)))
+          if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type) 
+             && tree_int_cst_sgn (expr) < 0)
            warning (OPT_Wsign_conversion,
                     "negative integer implicitly converted to unsigned type");
-          else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (TREE_TYPE (expr)))
-           warning (OPT_Wsign_conversion,
-                    "conversion of unsigned constant value to negative integer");
+          else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (expr_type))
+           warning (OPT_Wsign_conversion,  "conversion of unsigned constant "
+                    "value to negative integer");
          else
            give_warning = true;
         }
       else if (TREE_CODE (type) == REAL_TYPE)
         {
           /* Warn for an integer constant that does not fit into real type.  */
-          if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE)
+          if (TREE_CODE (expr_type) == INTEGER_TYPE)
             {
               REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
               if (!exact_real_truncate (TYPE_MODE (type), &a))
@@ -1248,8 +1585,8 @@ conversion_warning (tree type, tree expr)
             }
           /* Warn for a real constant that does not fit into a smaller
              real type.  */
-          else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
-                   && formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+          else if (TREE_CODE (expr_type) == REAL_TYPE
+                   && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
             {
               REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
               if (!exact_real_truncate (TYPE_MODE (type), &a))
@@ -1260,45 +1597,114 @@ conversion_warning (tree type, tree expr)
       if (give_warning)
         warning (OPT_Wconversion,
                  "conversion to %qT alters %qT constant value",
-                 type, TREE_TYPE (expr));
-    }
-  else /* 'expr' is not a constant.  */
-    {
+                 type, expr_type);
+
+      return;
+
+    case COND_EXPR:
+      {
+       /* In case of COND_EXPR, if both operands are constants or
+          COND_EXPR, then we do not care about the type of COND_EXPR,
+          only about the conversion of each operand.  */
+       tree op1 = TREE_OPERAND (expr, 1);
+       tree op2 = TREE_OPERAND (expr, 2);
+
+       if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST 
+            || TREE_CODE (op1) == COND_EXPR)
+           && (TREE_CODE (op2) == REAL_CST || TREE_CODE (op2) == INTEGER_CST
+               || TREE_CODE (op2) == COND_EXPR))
+         {
+           conversion_warning (type, op1);
+           conversion_warning (type, op2);
+           return;
+         }
+       /* Fall through.  */
+      }
+
+    default: /* 'expr' is not a constant.  */
+
       /* Warn for real types converted to integer types.  */
-      if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+      if (TREE_CODE (expr_type) == REAL_TYPE
           && TREE_CODE (type) == INTEGER_TYPE)
         give_warning = true;
 
-      else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+      else if (TREE_CODE (expr_type) == INTEGER_TYPE
                && TREE_CODE (type) == INTEGER_TYPE)
         {
+         /* Don't warn about unsigned char y = 0xff, x = (int) y;  */
+         expr = get_unwidened (expr, 0);
+         expr_type = TREE_TYPE (expr);
+
+         /* Don't warn for short y; short x = ((int)y & 0xff);  */
+         if (TREE_CODE (expr) == BIT_AND_EXPR 
+               || TREE_CODE (expr) == BIT_IOR_EXPR 
+             || TREE_CODE (expr) == BIT_XOR_EXPR)
+           {
+             /* If both args were extended from a shortest type,
+                use that type if that is safe.  */
+             expr_type = shorten_binary_op (expr_type, 
+                                            TREE_OPERAND (expr, 0), 
+                                            TREE_OPERAND (expr, 1), 
+                                            /* bitwise */1);
+
+             if (TREE_CODE (expr) == BIT_AND_EXPR)
+               {
+                 tree op0 = TREE_OPERAND (expr, 0);
+                 tree op1 = TREE_OPERAND (expr, 1);
+                 bool unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
+                 bool unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
+
+                 /* If one of the operands is a non-negative constant
+                    that fits in the target type, then the type of the
+                    other operand does not matter. */
+                 if ((TREE_CODE (op0) == INTEGER_CST
+                      && int_fits_type_p (op0, c_common_signed_type (type))
+                      && int_fits_type_p (op0, c_common_unsigned_type (type)))
+                     || (TREE_CODE (op1) == INTEGER_CST
+                         && int_fits_type_p (op1, c_common_signed_type (type))
+                         && int_fits_type_p (op1, 
+                                             c_common_unsigned_type (type))))
+                   return;
+                 /* If constant is unsigned and fits in the target
+                    type, then the result will also fit.  */
+                 else if ((TREE_CODE (op0) == INTEGER_CST
+                           && unsigned0 
+                           && int_fits_type_p (op0, type))
+                          || (TREE_CODE (op1) == INTEGER_CST
+                              && unsigned1
+                              && int_fits_type_p (op1, type)))
+                   return;
+               }
+           }
           /* Warn for integer types converted to smaller integer types.  */
-          if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr))) 
+         if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type)) 
            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))
+         else if ((TYPE_PRECISION (type) == TYPE_PRECISION (expr_type)
+                   && TYPE_UNSIGNED (expr_type) != 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));
+                  || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)))
+           warning (OPT_Wsign_conversion, "conversion to %qT from %qT "
+                    "may change the sign of the result",
+                    type, expr_type);
         }
 
       /* Warn for integer types converted to real types if and only if
          all the range of values of the integer type cannot be
          represented by the real type.  */
-      else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+      else if (TREE_CODE (expr_type) == INTEGER_TYPE
                && TREE_CODE (type) == REAL_TYPE)
         {
-          tree type_low_bound = TYPE_MIN_VALUE (TREE_TYPE (expr));
-          tree type_high_bound = TYPE_MAX_VALUE (TREE_TYPE (expr));
-          REAL_VALUE_TYPE real_low_bound = real_value_from_int_cst (0, type_low_bound);
-          REAL_VALUE_TYPE real_high_bound = real_value_from_int_cst (0, type_high_bound);
+          tree type_low_bound = TYPE_MIN_VALUE (expr_type);
+          tree type_high_bound = TYPE_MAX_VALUE (expr_type);
+          REAL_VALUE_TYPE real_low_bound 
+           = real_value_from_int_cst (0, type_low_bound);
+          REAL_VALUE_TYPE real_high_bound 
+           = real_value_from_int_cst (0, type_high_bound);
 
           if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
               || !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
@@ -1306,16 +1712,16 @@ conversion_warning (tree type, tree expr)
         }
 
       /* Warn for real types converted to smaller real types.  */
-      else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+      else if (TREE_CODE (expr_type) == REAL_TYPE
                && TREE_CODE (type) == REAL_TYPE
-               && formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+               && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
         give_warning = true;
 
 
       if (give_warning)
         warning (OPT_Wconversion,
                  "conversion to %qT from %qT may alter its value",
-                 type, TREE_TYPE (expr));
+                 type, expr_type);
     }
 }
 
@@ -1360,7 +1766,8 @@ warnings_for_convert_and_check (tree type, tree expr, tree result)
       else
        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
@@ -1516,7 +1923,10 @@ 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_at (EXPR_HAS_LOCATION (writer)
+                     ? EXPR_LOCATION (writer) : input_location,
+                     OPT_Wsequence_point, "operation on %qE may be undefined",
+                     list->expr);
        }
       list = list->next;
     }
@@ -1733,6 +2143,13 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
        return;
       }
 
+    case ADDR_EXPR:
+      x = TREE_OPERAND (x, 0);
+      if (DECL_P (x))
+       return;
+      writer = 0;
+      goto restart;
+
     default:
       /* For other expressions, simply recurse on their operands.
         Manual tail recursion for unary expressions.
@@ -1928,13 +2345,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)
@@ -2034,6 +2482,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);
@@ -2095,6 +2632,78 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
   if (type1 == intQI_type_node || type1 == unsigned_intQI_type_node)
     return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
 
+#define C_COMMON_FIXED_TYPES(NAME)         \
+  if (type1 == short_ ## NAME ## _type_node \
+      || type1 == unsigned_short_ ## NAME ## _type_node) \
+    return unsignedp ? unsigned_short_ ## NAME ## _type_node \
+                    : short_ ## NAME ## _type_node; \
+  if (type1 == NAME ## _type_node \
+      || type1 == unsigned_ ## NAME ## _type_node) \
+    return unsignedp ? unsigned_ ## NAME ## _type_node \
+                    : NAME ## _type_node; \
+  if (type1 == long_ ## NAME ## _type_node \
+      || type1 == unsigned_long_ ## NAME ## _type_node) \
+    return unsignedp ? unsigned_long_ ## NAME ## _type_node \
+                    : long_ ## NAME ## _type_node; \
+  if (type1 == long_long_ ## NAME ## _type_node \
+      || type1 == unsigned_long_long_ ## NAME ## _type_node) \
+    return unsignedp ? unsigned_long_long_ ## NAME ## _type_node \
+                    : long_long_ ## NAME ## _type_node;
+
+#define C_COMMON_FIXED_MODE_TYPES(NAME) \
+  if (type1 == NAME ## _type_node \
+      || type1 == u ## NAME ## _type_node) \
+    return unsignedp ? u ## NAME ## _type_node \
+                    : NAME ## _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
      may use a wider mode to match an ABI.  If we change modes, we may
@@ -2110,7 +2719,7 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
 
 #define TYPE_OK(node)                                                      \
   (TYPE_MODE (type) == TYPE_MODE (node)                                            \
-   && (c_dialect_cxx () || TYPE_PRECISION (type) == TYPE_PRECISION (node)))
+   && TYPE_PRECISION (type) == TYPE_PRECISION (node))
   if (TYPE_OK (signed_char_type_node))
     return unsignedp ? unsigned_char_type_node : signed_char_type_node;
   if (TYPE_OK (integer_type_node))
@@ -2140,10 +2749,7 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
     return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
 #undef TYPE_OK
 
-  if (c_dialect_cxx ())
-    return type;
-  else
-    return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
+  return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
 }
 
 /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
@@ -2186,40 +2792,14 @@ c_register_builtin_type (tree type, const char* name)
 
   registered_builtin_types = tree_cons (0, type, registered_builtin_types);
 }
-
-\f
-/* Return the minimum number of bits needed to represent VALUE in a
-   signed or unsigned type, UNSIGNEDP says which.  */
-
-unsigned int
-min_precision (tree value, int unsignedp)
-{
-  int log;
-
-  /* If the value is negative, compute its negative minus 1.  The latter
-     adjustment is because the absolute value of the largest negative value
-     is one larger than the largest positive value.  This is equivalent to
-     a bit-wise negation, so use that operation instead.  */
-
-  if (tree_int_cst_sgn (value) < 0)
-    value = fold_build1 (BIT_NOT_EXPR, TREE_TYPE (value), value);
-
-  /* Return the number of bits needed, taking into account the fact
-     that we need one more bit for a signed than unsigned type.  */
-
-  if (integer_zerop (value))
-    log = 0;
-  else
-    log = tree_floor_log2 (value);
-
-  return log + 1 + !unsignedp;
-}
 \f
 /* Print an error message for invalid operands to arith operation
-   CODE with TYPE0 for operand 0, and TYPE1 for operand 1.  */
+   CODE with TYPE0 for operand 0, and TYPE1 for operand 1.
+   LOCATION is the location of the message.  */
 
 void
-binary_op_error (enum tree_code code, tree type0, tree type1)
+binary_op_error (location_t location, enum tree_code code,
+                tree type0, tree type1)
 {
   const char *opname;
 
@@ -2270,8 +2850,9 @@ binary_op_error (enum tree_code code, tree type0, tree type1)
     default:
       gcc_unreachable ();
     }
-  error ("invalid operands to binary %s (have %qT and %qT)", opname,
-        type0, type1);
+  error_at (location,
+           "invalid operands to binary %s (have %qT and %qT)", opname,
+           type0, type1);
 }
 \f
 /* Subroutine of build_binary_op, used for comparison operations.
@@ -2323,7 +2904,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;
@@ -2378,6 +2960,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))
     {
@@ -2635,20 +3218,20 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
 
   if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
     {
-      if (pedantic || warn_pointer_arith)
-       pedwarn ("pointer of type %<void *%> used in arithmetic");
+      pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+              "pointer of type %<void *%> used in arithmetic");
       size_exp = integer_one_node;
     }
   else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
     {
-      if (pedantic || warn_pointer_arith)
-       pedwarn ("pointer to a function used in arithmetic");
+      pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+              "pointer to a function used in arithmetic");
       size_exp = integer_one_node;
     }
   else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
     {
-      if (pedantic || warn_pointer_arith)
-       pedwarn ("pointer to member function used in arithmetic");
+      pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+              "pointer to member function used in arithmetic");
       size_exp = integer_one_node;
     }
   else
@@ -2685,7 +3268,8 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
       /* Convert both subexpression types to the type of intop,
         because weird cases involving pointer arithmetic
         can result in a sum or difference with different type args.  */
-      ptrop = build_binary_op (subcode, ptrop,
+      ptrop = build_binary_op (EXPR_LOCATION (TREE_OPERAND (intop, 1)),
+                              subcode, ptrop,
                               convert (int_type, TREE_OPERAND (intop, 1)), 1);
       intop = convert (int_type, TREE_OPERAND (intop, 0));
     }
@@ -2701,7 +3285,8 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
      Do this multiplication as signed, then convert to the appropriate
      type for the pointer operation.  */
   intop = convert (sizetype,
-                  build_binary_op (MULT_EXPR, intop,
+                  build_binary_op (EXPR_LOCATION (intop),
+                                   MULT_EXPR, intop,
                                    convert (TREE_TYPE (intop), size_exp), 1));
 
   /* Create the sum or difference.  */
@@ -2719,7 +3304,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
@@ -2732,6 +3317,8 @@ decl_with_nonnull_addr_p (tree expr)
    have been validated to be of suitable type; otherwise, a bad
    diagnostic may result.
 
+   The EXPR is located at LOCATION.
+
    This preparation consists of taking the ordinary
    representation of an expression expr and producing a valid tree
    boolean expression describing whether expr is nonzero.  We could
@@ -2741,7 +3328,7 @@ decl_with_nonnull_addr_p (tree expr)
    The resulting type should always be `truthvalue_type_node'.  */
 
 tree
-c_common_truthvalue_conversion (tree expr)
+c_common_truthvalue_conversion (location_t location, tree expr)
 {
   switch (TREE_CODE (expr))
     {
@@ -2762,14 +3349,17 @@ c_common_truthvalue_conversion (tree expr)
       if (TREE_TYPE (expr) == truthvalue_type_node)
        return expr;
       return build2 (TREE_CODE (expr), truthvalue_type_node,
-                c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
-                c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)));
+                c_common_truthvalue_conversion (location, 
+                                                TREE_OPERAND (expr, 0)),
+                c_common_truthvalue_conversion (location,
+                                                TREE_OPERAND (expr, 1)));
 
     case TRUTH_NOT_EXPR:
       if (TREE_TYPE (expr) == truthvalue_type_node)
        return expr;
       return build1 (TREE_CODE (expr), truthvalue_type_node,
-                c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+                c_common_truthvalue_conversion (location,
+                                                TREE_OPERAND (expr, 0)));
 
     case ERROR_MARK:
       return expr;
@@ -2783,8 +3373,14 @@ 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);
+      expr = build_unary_op (location, ADDR_EXPR, expr, 0);
       /* Fall through.  */
 
     case ADDR_EXPR:
@@ -2793,9 +3389,10 @@ c_common_truthvalue_conversion (tree expr)
        if (decl_with_nonnull_addr_p (inner))
          {
            /* Common Ada/Pascal programmer's mistake.  */
-           warning (OPT_Waddress,
-                    "the address of %qD will always evaluate as %<true%>",
-                    inner);
+           warning_at (location,
+                       OPT_Waddress,
+                       "the address of %qD will always evaluate as %<true%>",
+                       inner);
            return truthvalue_true_node;
          }
 
@@ -2815,17 +3412,20 @@ c_common_truthvalue_conversion (tree expr)
       }
 
     case COMPLEX_EXPR:
-      return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
+      return build_binary_op (EXPR_LOCATION (expr),
+                             (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
                               ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
+               c_common_truthvalue_conversion (location,
+                                               TREE_OPERAND (expr, 0)),
+               c_common_truthvalue_conversion (location,
+                                               TREE_OPERAND (expr, 1)),
                              0);
 
     case NEGATE_EXPR:
     case ABS_EXPR:
     case FLOAT_EXPR:
       /* These don't change whether an object is nonzero or zero.  */
-      return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+      return c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 0));
 
     case LROTATE_EXPR:
     case RROTATE_EXPR:
@@ -2834,19 +3434,22 @@ c_common_truthvalue_conversion (tree expr)
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
        return build2 (COMPOUND_EXPR, truthvalue_type_node,
                       TREE_OPERAND (expr, 1),
-                      c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
+                      c_common_truthvalue_conversion 
+                       (location, TREE_OPERAND (expr, 0)));
       else
-       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return c_common_truthvalue_conversion (location,
+                                              TREE_OPERAND (expr, 0));
 
     case COND_EXPR:
       /* Distribute the conversion into the arms of a COND_EXPR.  */
       return fold_build3 (COND_EXPR, truthvalue_type_node,
                TREE_OPERAND (expr, 0),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
-               c_common_truthvalue_conversion (TREE_OPERAND (expr, 2)));
+               c_common_truthvalue_conversion (location,
+                                               TREE_OPERAND (expr, 1)),
+               c_common_truthvalue_conversion (location,
+                                               TREE_OPERAND (expr, 2)));
 
-    case CONVERT_EXPR:
-    case NOP_EXPR:
+    CASE_CONVERT:
       /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
         since that affects how `default_conversion' will behave.  */
       if (TREE_CODE (TREE_TYPE (expr)) == REFERENCE_TYPE
@@ -2855,7 +3458,8 @@ c_common_truthvalue_conversion (tree expr)
       /* If this is widening the argument, we can ignore it.  */
       if (TYPE_PRECISION (TREE_TYPE (expr))
          >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
-       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return c_common_truthvalue_conversion (location,
+                                              TREE_OPERAND (expr, 0));
       break;
 
     case MODIFY_EXPR:
@@ -2876,14 +3480,29 @@ c_common_truthvalue_conversion (tree expr)
     {
       tree t = save_expr (expr);
       return (build_binary_op
-             ((TREE_SIDE_EFFECTS (expr)
+             (EXPR_LOCATION (expr),
+              (TREE_SIDE_EFFECTS (expr)
                ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-       c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
-       c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
+       c_common_truthvalue_conversion
+              (location,
+               build_unary_op (location, REALPART_EXPR, t, 0)),
+       c_common_truthvalue_conversion
+              (location,
+               build_unary_op (location, IMAGPART_EXPR, t, 0)),
               0));
     }
 
-  return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
+  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 (EXPR_LOCATION (expr),
+                             NE_EXPR, expr, fixed_zero_node, 1);
+    }
+
+  return build_binary_op (EXPR_LOCATION (expr),
+                         NE_EXPR, expr, integer_zero_node, 1);
 }
 \f
 static void def_builtin_1  (enum built_in_function fncode,
@@ -2893,70 +3512,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)
-       {
-          tree domain = TYPE_DOMAIN (type);
-
-         t = build_variant_type_copy (type);
-         TREE_TYPE (t) = element_type;
-
-          if (TYPE_STRUCTURAL_EQUALITY_P (element_type)
-              || (domain && TYPE_STRUCTURAL_EQUALITY_P (domain)))
-            SET_TYPE_STRUCTURAL_EQUALITY (t);
-          else if (TYPE_CANONICAL (element_type) != element_type
-                   || (domain && TYPE_CANONICAL (domain) != domain))
-            {
-              tree unqualified_canon 
-                = build_array_type (TYPE_CANONICAL (element_type),
-                                    domain? TYPE_CANONICAL (domain) 
-                                          : NULL_TREE);
-              TYPE_CANONICAL (t) 
-                = c_build_qualified_type (unqualified_canon, type_quals);
-            }
-          else
-            TYPE_CANONICAL (t) = t;
-       }
-      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.  */
 
@@ -3039,7 +3594,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));
 }
 
@@ -3048,7 +3607,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;
@@ -3078,10 +3637,6 @@ c_common_get_alias_set (tree t)
       || t == unsigned_char_type_node)
     return 0;
 
-  /* If it has the may_alias attribute, it can alias anything.  */
-  if (lookup_attribute ("may_alias", TYPE_ATTRIBUTES (t)))
-    return 0;
-
   /* The C standard specifically allows aliasing between signed and
      unsigned variants of the same type.  We treat the signed
      variant as canonical.  */
@@ -3207,7 +3762,10 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
       if (is_sizeof)
        {
          if (complain && (pedantic || warn_pointer_arith))
-           pedwarn ("invalid application of %<sizeof%> to a function type");
+           pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+                    "invalid application of %<sizeof%> to a function type");
+          else if (!complain)
+            return error_mark_node;
          value = size_one_node;
        }
       else
@@ -3217,7 +3775,10 @@ 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);
+       pedwarn (input_location, pedantic ? OPT_pedantic : OPT_Wpointer_arith, 
+                "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))
@@ -3277,7 +3838,7 @@ c_alignof_expr (tree expr)
       tree best = t;
       int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
 
-      while ((TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR)
+      while (CONVERT_EXPR_P (t)
             && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
        {
          int thisalign;
@@ -3379,7 +3940,7 @@ def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
   va_start (list, n);
   for (i = 0; i < n; ++i)
     {
-      builtin_type a = va_arg (list, builtin_type);
+      builtin_type a = (builtin_type) va_arg (list, int);
       t = builtin_types[a];
       if (t == error_mark_node)
        goto egress;
@@ -3486,6 +4047,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;
@@ -3594,6 +4157,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));
@@ -3674,6 +4298,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)));
 
@@ -3690,6 +4346,20 @@ c_common_nodes_and_builtins (void)
   lang_hooks.decls.pushdecl
     (build_decl (TYPE_DECL, get_identifier ("__builtin_va_list"),
                 va_list_type_node));
+#ifdef TARGET_ENUM_VA_LIST
+  {
+    int l;
+    const char *pname;
+    tree ptype;
+    for (l = 0; TARGET_ENUM_VA_LIST (l, &pname, &ptype); ++l)
+      {
+       lang_hooks.decls.pushdecl
+         (build_decl (TYPE_DECL, get_identifier (pname),
+                      ptype));
+
+      }
+  }
+#endif
 
   if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
     {
@@ -3845,7 +4515,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))
     {
@@ -3875,9 +4545,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);
@@ -3900,18 +4570,6 @@ self_promoting_args_p (tree parms)
   return 1;
 }
 
-/* Recursively examines the array elements of TYPE, until a non-array
-   element type is found.  */
-
-tree
-strip_array_types (tree type)
-{
-  while (TREE_CODE (type) == ARRAY_TYPE)
-    type = TREE_TYPE (type);
-
-  return type;
-}
-
 /* Recursively remove any '*' or '&' operator from TYPE.  */
 tree
 strip_pointer_operator (tree t)
@@ -3984,8 +4642,9 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
     }
 
   /* Case ranges are a GNU extension.  */
-  if (high_value && pedantic)
-    pedwarn ("range expressions in switch statements are non-standard");
+  if (high_value)
+    pedwarn (input_location, OPT_pedantic, 
+            "range expressions in switch statements are non-standard");
 
   type = TREE_TYPE (cond);
   if (low_value)
@@ -4128,13 +4787,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);
 }
 
@@ -4186,6 +4848,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;
@@ -4221,6 +4884,8 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
   for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
     {
       tree value = TREE_VALUE (chain);
+      if (TREE_CODE (value) == CONST_DECL)
+        value = DECL_INITIAL (value);
       node = splay_tree_lookup (cases, (splay_tree_key) value);
       if (node)
        {
@@ -4231,7 +4896,7 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
        }
 
       /* Even though there wasn't an exact match, there might be a
-        case range which includes the enumator's value.  */
+        case range which includes the enumerator's value.  */
       node = splay_tree_predecessor (cases, (splay_tree_key) value);
       if (node && CASE_HIGH ((tree) node->value))
        {
@@ -4255,7 +4920,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));
     }
 
@@ -4267,19 +4938,30 @@ 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
-   IDENTIFIER_NODE).  Returns an expression for the address.  */
+   IDENTIFIER_NODE).  Returns an expression for the address.
+
+   LOC is the location for the expression returned.  */
 
 tree
-finish_label_address_expr (tree label)
+finish_label_address_expr (tree label, location_t loc)
 {
   tree result;
 
-  if (pedantic)
-    pedwarn ("taking the address of a label is non-standard");
+  pedwarn (input_location, OPT_pedantic, "taking the address of a label is non-standard");
 
   if (label == error_mark_node)
     return error_mark_node;
@@ -4294,6 +4976,7 @@ finish_label_address_expr (tree label)
       /* The current function in not necessarily uninlinable.
         Computed gotos are incompatible with inlining, but the value
         here could be used only in a diagnostic, for example.  */
+      protected_set_expr_location (result, loc);
     }
 
   return result;
@@ -4306,9 +4989,10 @@ finish_label_address_expr (tree label)
 
 rtx
 c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
-              int modifier /* Actually enum_modifier.  */,
+              int modifiera /* Actually enum expand_modifier.  */,
               rtx *alt_rtl)
 {
+  enum expand_modifier modifier = (enum expand_modifier) modifiera;
   switch (TREE_CODE (exp))
     {
     case COMPOUND_LITERAL_EXPR:
@@ -4325,15 +5009,6 @@ c_expand_expr (tree exp, rtx target, enum machine_mode tmode,
     }
 }
 
-
-/* Generate the RTL for the body of FNDECL.  */
-
-void
-c_expand_body (tree fndecl)
-{
-  tree_rest_of_compilation (fndecl);
-}
-
 /* Hook used by staticp to handle language-specific tree codes.  */
 
 tree
@@ -4395,6 +5070,8 @@ c_stddef_cpp_builtins(void)
   builtin_define_with_value ("__WINT_TYPE__", WINT_TYPE, 0);
   builtin_define_with_value ("__INTMAX_TYPE__", INTMAX_TYPE, 0);
   builtin_define_with_value ("__UINTMAX_TYPE__", UINTMAX_TYPE, 0);
+  builtin_define_with_value ("__CHAR16_TYPE__", CHAR16_TYPE, 0);
+  builtin_define_with_value ("__CHAR32_TYPE__", CHAR32_TYPE, 0);
 }
 
 static void
@@ -4525,7 +5202,7 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
 
 static tree
 handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
-                         int ARG_UNUSED (flags), bool *no_add_attrs)
+                     int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
     {
@@ -4535,8 +5212,8 @@ handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                   name, "cold");
          *no_add_attrs = true;
        }
-      /* Do nothing else, just set the attribute.  We'll get at
-        it later with lookup_attribute.  */
+      /* Most of the rest of the hot processing is done later with
+        lookup_attribute.  */
     }
   else
     {
@@ -4561,8 +5238,8 @@ handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                   name, "hot");
          *no_add_attrs = true;
        }
-      /* Do nothing else, just set the attribute.  We'll get at
-        it later with lookup_attribute.  */
+      /* Most of the rest of the cold processing is done later with
+        lookup_attribute.  */
     }
   else
     {
@@ -4603,8 +5280,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
     {
@@ -4638,27 +5316,70 @@ handle_gnu_inline_attribute (tree *node, tree name,
   return NULL_TREE;
 }
 
-/* Handle a "flatten" attribute; arguments as in
+/* Handle an "artificial" attribute; arguments as in
    struct attribute_spec.handler.  */
 
 static tree
-handle_flatten_attribute (tree *node, tree name,
-                         tree args ATTRIBUTE_UNUSED,
-                         int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+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)
-    /* Do nothing else, just set the attribute.  We'll get at
-       it later with lookup_attribute.  */
-    ;
-  else
+  if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
     {
-      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      /* 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.  */
+
+static tree
+handle_flatten_attribute (tree *node, tree name,
+                         tree args ATTRIBUTE_UNUSED,
+                         int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    /* 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 "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.  */
@@ -4782,21 +5503,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)
     {
@@ -4983,6 +5696,8 @@ handle_mode_attribute (tree *node, tree name, tree args,
        mode = targetm.libgcc_cmp_return_mode ();
       else if (!strcmp (p, "libgcc_shift_count"))
        mode = targetm.libgcc_shift_count_mode ();
+      else if (!strcmp (p, "unwind_word"))
+       mode = targetm.unwind_word_mode ();
       else
        for (j = 0; j < NUM_MACHINE_MODES; j++)
          if (!strcmp (p, GET_MODE_NAME (j)))
@@ -5004,6 +5719,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;
 
@@ -5014,6 +5733,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,
@@ -5047,7 +5770,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)
        {
@@ -5134,6 +5870,13 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
                     *node);
              *no_add_attrs = true;
            }
+         else if (TREE_CODE (decl) == VAR_DECL
+                  && !targetm.have_tls && targetm.emutls.tmpl_section
+                  && DECL_THREAD_LOCAL_P (decl))
+           {
+             error ("section of %q+D cannot be overridden", *node);
+             *no_add_attrs = true;
+           }
          else
            DECL_SECTION_NAME (decl) = TREE_VALUE (args);
        }
@@ -5247,11 +5990,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;
 }
@@ -5329,7 +6077,9 @@ handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   /* We must ignore the attribute when it is associated with
      local-scoped decls, since attribute alias is ignored and many
      such symbols do not even have a DECL_WEAK field.  */
-  if (decl_function_context (*node) || current_function_decl)
+  if (decl_function_context (*node)
+      || current_function_decl
+      || (TREE_CODE (*node) != VAR_DECL && TREE_CODE (*node) != FUNCTION_DECL))
     {
       warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
@@ -5593,12 +6343,7 @@ 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 ++;
-
+  unsigned arg_count = type_num_arguments (*node);
   for (; args; args = TREE_CHAIN (args))
     {
       tree position = TREE_VALUE (args);
@@ -5670,7 +6415,7 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                       int ARG_UNUSED (flags), bool *no_add_attrs)
 {
   if (TREE_CODE (*node) == FUNCTION_DECL)
-    DECL_IS_PURE (*node) = 1;
+    DECL_PURE_P (*node) = 1;
   /* ??? TODO: Support types.  */
   else
     {
@@ -5786,18 +6531,21 @@ 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)
-      || !host_integerp (TYPE_SIZE_UNIT (type), 1))
+         && GET_MODE_CLASS (orig_mode) != MODE_INT
+         && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
+      || !host_integerp (TYPE_SIZE_UNIT (type), 1)
+      || TREE_CODE (type) == BOOLEAN_TYPE)
     {
       error ("invalid vector type for attribute %qE", name);
       return NULL_TREE;
@@ -5826,7 +6574,7 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
   new_type = build_vector_type (type, nunits);
 
   /* Build back pointers if needed.  */
-  *node = reconstruct_complex_type (*node, new_type);
+  *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
 
   return NULL_TREE;
 }
@@ -6178,8 +6926,194 @@ 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));
+  tree params;
+  
+  /* Ensure we have a function type.  */
+  gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
+  
+  params = TYPE_ARG_TYPES (*node);
+  while (params && ! VOID_TYPE_P (TREE_VALUE (params)))
+    params = TREE_CHAIN (params);
+
+  /* Ensure we have a variadic function.  */
+  gcc_assert (!params);
+
+  return NULL_TREE;
+}
+
+/* Handle a "target" attribute.  */
+
+static tree
+handle_target_attribute (tree *node, tree name, tree args, int flags,
+                        bool *no_add_attrs)
+{
+  /* Ensure we have a function type.  */
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+  else if (! targetm.target_option.valid_attribute_p (*node, name, args,
+                                                     flags))
+    *no_add_attrs = true;
+
+  return NULL_TREE;
+}
+
+/* Arguments being collected for optimization.  */
+typedef const char *const_char_p;              /* For DEF_VEC_P.  */
+DEF_VEC_P(const_char_p);
+DEF_VEC_ALLOC_P(const_char_p, gc);
+static GTY(()) VEC(const_char_p, gc) *optimize_args;
+
+
+/* Inner function to convert a TREE_LIST to argv string to parse the optimize
+   options in ARGS.  ATTR_P is true if this is for attribute(optimize), and
+   false for #pragma GCC optimize.  */
+
+bool
+parse_optimize_options (tree args, bool attr_p)
+{
+  bool ret = true;
+  unsigned opt_argc;
+  unsigned i;
+  int saved_flag_strict_aliasing;
+  const char **opt_argv;
+  tree ap;
+
+  /* Build up argv vector.  Just in case the string is stored away, use garbage
+     collected strings.  */
+  VEC_truncate (const_char_p, optimize_args, 0);
+  VEC_safe_push (const_char_p, gc, optimize_args, NULL);
+
+  for (ap = args; ap != NULL_TREE; ap = TREE_CHAIN (ap))
+    {
+      tree value = TREE_VALUE (ap);
+
+      if (TREE_CODE (value) == INTEGER_CST)
+       {
+         char buffer[20];
+         sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value));
+         VEC_safe_push (const_char_p, gc, optimize_args, ggc_strdup (buffer));
+       }
+
+      else if (TREE_CODE (value) == STRING_CST)
+       {
+         /* Split string into multiple substrings.  */
+         size_t len = TREE_STRING_LENGTH (value);
+         char *p = ASTRDUP (TREE_STRING_POINTER (value));
+         char *end = p + len;
+         char *comma;
+         char *next_p = p;
+
+         while (next_p != NULL)
+           {
+             size_t len2;
+             char *q, *r;
+
+             p = next_p;
+             comma = strchr (p, ',');
+             if (comma)
+               {
+                 len2 = comma - p;
+                 *comma = '\0';
+                 next_p = comma+1;
+               }
+             else
+               {
+                 len2 = end - p;
+                 next_p = NULL;
+               }
+
+             r = q = (char *) ggc_alloc (len2 + 3);
+
+             /* If the user supplied -Oxxx or -fxxx, only allow -Oxxx or -fxxx
+                options.  */
+             if (*p == '-' && p[1] != 'O' && p[1] != 'f')
+               {
+                 ret = false;
+                 if (attr_p)
+                   warning (OPT_Wattributes,
+                            "Bad option %s to optimize attribute.", p);
+                 else
+                   warning (OPT_Wpragmas,
+                            "Bad option %s to pragma attribute", p);
+                 continue;
+               }
+
+             if (*p != '-')
+               {
+                 *r++ = '-';
+
+                 /* Assume that Ox is -Ox, a numeric value is -Ox, a s by
+                    itself is -Os, and any other switch begins with a -f.  */
+                 if ((*p >= '0' && *p <= '9')
+                     || (p[0] == 's' && p[1] == '\0'))
+                   *r++ = 'O';
+                 else if (*p != 'O')
+                   *r++ = 'f';
+               }
+
+             memcpy (r, p, len2);
+             r[len2] = '\0';
+             VEC_safe_push (const_char_p, gc, optimize_args, q);
+           }
+
+       }
+    }
+
+  opt_argc = VEC_length (const_char_p, optimize_args);
+  opt_argv = (const char **) alloca (sizeof (char *) * (opt_argc + 1));
+
+  for (i = 1; i < opt_argc; i++)
+    opt_argv[i] = VEC_index (const_char_p, optimize_args, i);
+
+  saved_flag_strict_aliasing = flag_strict_aliasing;
+
+  /* Now parse the options.  */
+  decode_options (opt_argc, opt_argv);
+
+  /* Don't allow changing -fstrict-aliasing.  */
+  flag_strict_aliasing = saved_flag_strict_aliasing;
+
+  VEC_truncate (const_char_p, optimize_args, 0);
+  return ret;
+}
+
+/* For handling "optimize" attribute. arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_optimize_attribute (tree *node, tree name, tree args,
+                          int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  /* Ensure we have a function type.  */
+  if (TREE_CODE (*node) != FUNCTION_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+  else
+    {
+      struct cl_optimization cur_opts;
+      tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
+
+      /* Save current options.  */
+      cl_optimization_save (&cur_opts);
+
+      /* If we previously had some optimization options, use them as the
+        default.  */
+      if (old_opts)
+       cl_optimization_restore (TREE_OPTIMIZATION (old_opts));
+
+      /* Parse options, and update the vector.  */
+      parse_optimize_options (args, true);
+      DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
+       = build_optimization_node ();
+
+      /* Restore current options.  */
+      cl_optimization_restore (&cur_opts);
+    }
 
   return NULL_TREE;
 }
@@ -6215,7 +7149,7 @@ check_function_arguments_recurse (void (*callback)
                                  void *ctx, tree param,
                                  unsigned HOST_WIDE_INT param_num)
 {
-  if ((TREE_CODE (param) == NOP_EXPR || TREE_CODE (param) == CONVERT_EXPR)
+  if (CONVERT_EXPR_P (param)
       && (TYPE_PRECISION (TREE_TYPE (param))
          == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (param, 0)))))
     {
@@ -6287,6 +7221,109 @@ check_function_arguments_recurse (void (*callback)
   (*callback) (ctx, param, param_num);
 }
 
+/* Checks the number of arguments NARGS against the required number
+   REQUIRED and issues an error if there is a mismatch.  Returns true
+   if the number of arguments is correct, otherwise false.  */
+
+static bool
+validate_nargs (tree fndecl, int nargs, int required)
+{
+  if (nargs < required)
+    {
+      error ("not enough arguments to function %qE", fndecl);
+      return false;
+    }
+  else if (nargs > required)
+    {
+      error ("too many arguments to function %qE", fndecl);
+      return false;
+    }
+  return true;
+}
+
+/* Verifies the NARGS arguments ARGS to the builtin function FNDECL.
+   Returns false if there was an error, otherwise true.  */
+
+bool
+check_builtin_function_arguments (tree fndecl, int nargs, tree *args)
+{
+  if (!DECL_BUILT_IN (fndecl)
+      || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
+    return true;
+
+  switch (DECL_FUNCTION_CODE (fndecl))
+    {
+    case BUILT_IN_CONSTANT_P:
+      return validate_nargs (fndecl, nargs, 1);
+
+    case BUILT_IN_ISFINITE:
+    case BUILT_IN_ISINF:
+    case BUILT_IN_ISINF_SIGN:
+    case BUILT_IN_ISNAN:
+    case BUILT_IN_ISNORMAL:
+      if (validate_nargs (fndecl, nargs, 1))
+       {
+         if (TREE_CODE (TREE_TYPE (args[0])) != REAL_TYPE)
+           {
+             error ("non-floating-point argument in call to "
+                    "function %qE", fndecl);
+             return false;
+           }
+         return true;
+       }
+      return false;
+
+    case BUILT_IN_ISGREATER:
+    case BUILT_IN_ISGREATEREQUAL:
+    case BUILT_IN_ISLESS:
+    case BUILT_IN_ISLESSEQUAL:
+    case BUILT_IN_ISLESSGREATER:
+    case BUILT_IN_ISUNORDERED:
+      if (validate_nargs (fndecl, nargs, 2))
+       {
+         enum tree_code code0, code1;
+         code0 = TREE_CODE (TREE_TYPE (args[0]));
+         code1 = TREE_CODE (TREE_TYPE (args[1]));
+         if (!((code0 == REAL_TYPE && code1 == REAL_TYPE)
+               || (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
+               || (code0 == INTEGER_TYPE && code1 == REAL_TYPE)))
+           {
+             error ("non-floating-point arguments in call to "
+                    "function %qE", fndecl);
+             return false;
+           }
+         return true;
+       }
+      return false;
+
+    case BUILT_IN_FPCLASSIFY:
+      if (validate_nargs (fndecl, nargs, 6))
+       {
+         unsigned i;
+         
+         for (i=0; i<5; i++)
+           if (TREE_CODE (args[i]) != INTEGER_CST)
+             {
+               error ("non-const integer argument %u in call to function %qE",
+                      i+1, fndecl);
+               return false;
+             }
+
+         if (TREE_CODE (TREE_TYPE (args[5])) != REAL_TYPE)
+           {
+             error ("non-floating-point argument in call to function %qE",
+                    fndecl);
+             return false;
+           }
+         return true;
+       }
+      return false;
+
+    default:
+      return true;
+    }
+}
+
 /* Function to help qsort sort FIELD_DECLs by name order.  */
 
 int
@@ -6383,20 +7420,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");
@@ -6434,71 +7490,60 @@ c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
    inlining, so we don't have to worry about that.  */
 
 void
-c_warn_unused_result (tree *top_p)
+c_warn_unused_result (gimple_seq seq)
 {
-  tree t = *top_p;
-  tree_stmt_iterator i;
   tree fdecl, ftype;
+  gimple_stmt_iterator i;
 
-  switch (TREE_CODE (t))
+  for (i = gsi_start (seq); !gsi_end_p (i); gsi_next (&i))
     {
-    case STATEMENT_LIST:
-      for (i = tsi_start (*top_p); !tsi_end_p (i); tsi_next (&i))
-       c_warn_unused_result (tsi_stmt_ptr (i));
-      break;
+      gimple g = gsi_stmt (i);
 
-    case COND_EXPR:
-      c_warn_unused_result (&COND_EXPR_THEN (t));
-      c_warn_unused_result (&COND_EXPR_ELSE (t));
-      break;
-    case BIND_EXPR:
-      c_warn_unused_result (&BIND_EXPR_BODY (t));
-      break;
-    case TRY_FINALLY_EXPR:
-    case TRY_CATCH_EXPR:
-      c_warn_unused_result (&TREE_OPERAND (t, 0));
-      c_warn_unused_result (&TREE_OPERAND (t, 1));
-      break;
-    case CATCH_EXPR:
-      c_warn_unused_result (&CATCH_BODY (t));
-      break;
-    case EH_FILTER_EXPR:
-      c_warn_unused_result (&EH_FILTER_FAILURE (t));
-      break;
+      switch (gimple_code (g))
+       {
+       case GIMPLE_BIND:
+         c_warn_unused_result (gimple_bind_body (g));
+         break;
+       case GIMPLE_TRY:
+         c_warn_unused_result (gimple_try_eval (g));
+         c_warn_unused_result (gimple_try_cleanup (g));
+         break;
+       case GIMPLE_CATCH:
+         c_warn_unused_result (gimple_catch_handler (g));
+         break;
+       case GIMPLE_EH_FILTER:
+         c_warn_unused_result (gimple_eh_filter_failure (g));
+         break;
 
-    case CALL_EXPR:
-      if (TREE_USED (t))
-       break;
+       case GIMPLE_CALL:
+         if (gimple_call_lhs (g))
+           break;
 
-      /* This is a naked call, as opposed to a CALL_EXPR nested inside
-        a MODIFY_EXPR.  All calls whose value is ignored should be
-        represented like this.  Look for the attribute.  */
-      fdecl = get_callee_fndecl (t);
-      if (fdecl)
-       ftype = TREE_TYPE (fdecl);
-      else
-       {
-         ftype = TREE_TYPE (CALL_EXPR_FN (t));
-         /* Look past pointer-to-function to the function type itself.  */
-         ftype = TREE_TYPE (ftype);
-       }
+         /* This is a naked call, as opposed to a GIMPLE_CALL with an
+            LHS.  All calls whose value is ignored should be
+            represented like this.  Look for the attribute.  */
+         fdecl = gimple_call_fndecl (g);
+         ftype = TREE_TYPE (TREE_TYPE (gimple_call_fn (g)));
 
-      if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
-       {
-         if (fdecl)
-           warning (0, "%Hignoring return value of %qD, "
-                    "declared with attribute warn_unused_result",
-                    EXPR_LOCUS (t), fdecl);
-         else
-           warning (0, "%Hignoring return value of function "
-                    "declared with attribute warn_unused_result",
-                    EXPR_LOCUS (t));
-       }
-      break;
+         if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
+           {
+             location_t loc = gimple_location (g);
 
-    default:
-      /* Not a container, not a call, or a call whose value is used.  */
-      break;
+             if (fdecl)
+               warning (0, "%Hignoring return value of %qD, "
+                        "declared with attribute warn_unused_result",
+                        &loc, fdecl);
+             else
+               warning (0, "%Hignoring return value of function "
+                        "declared with attribute warn_unused_result",
+                        &loc);
+           }
+         break;
+
+       default:
+         /* Not a container, not a call, or a call whose value is used.  */
+         break;
+       }
     }
 }
 
@@ -6547,6 +7592,7 @@ fold_offsetof_1 (tree expr, tree stop_ref)
       return error_mark_node;
 
     case CALL_EXPR:
+    case TARGET_EXPR:
       error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
       return error_mark_node;
 
@@ -6733,11 +7779,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;
 }
@@ -6929,8 +7998,9 @@ 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.  */
@@ -6982,94 +8052,134 @@ warn_array_subscript_with_type_char (tree index)
 /* Implement -Wparentheses for the unexpected C precedence rules, to
    cover cases like x + y << z which readers are likely to
    misinterpret.  We have seen an expression in which CODE is a binary
-   operator used to combine expressions headed by CODE_LEFT and
-   CODE_RIGHT.  CODE_LEFT and CODE_RIGHT may be ERROR_MARK, which
-   means that that side of the expression was not formed using a
-   binary operator, or it was enclosed in parentheses.  */
+   operator used to combine expressions ARG_LEFT and ARG_RIGHT, which
+   before folding had CODE_LEFT and CODE_RIGHT.  CODE_LEFT and
+   CODE_RIGHT may be ERROR_MARK, which means that that side of the
+   expression was not formed using a binary or unary operator, or it
+   was enclosed in parentheses.  */
 
 void
-warn_about_parentheses (enum tree_code code, enum tree_code code_left,
-                       enum tree_code code_right)
+warn_about_parentheses (enum tree_code code,
+                       enum tree_code code_left, tree arg_left,
+                       enum tree_code code_right, tree arg_right)
 {
   if (!warn_parentheses)
     return;
 
-  if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
+  /* This macro tests that the expression ARG with original tree code
+     CODE appears to be a boolean expression. or the result of folding a
+     boolean expression.  */
+#define APPEARS_TO_BE_BOOLEAN_EXPR_P(CODE, ARG)                             \
+       (truth_value_p (TREE_CODE (ARG))                                    \
+        || TREE_CODE (TREE_TYPE (ARG)) == BOOLEAN_TYPE                     \
+        /* Folding may create 0 or 1 integers from other expressions.  */  \
+        || ((CODE) != INTEGER_CST                                          \
+            && (integer_onep (ARG) || integer_zerop (ARG))))
+
+  switch (code) 
     {
-      if (code_left == PLUS_EXPR || code_left == MINUS_EXPR
-         || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+    case LSHIFT_EXPR:
+      if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
        warning (OPT_Wparentheses,
-                "suggest parentheses around + or - inside shift");
-    }
+                "suggest parentheses around %<+%> inside %<<<%>");
+      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around %<-%> inside %<<<%>");
+      return;
 
-  if (code == TRUTH_ORIF_EXPR)
-    {
-      if (code_left == TRUTH_ANDIF_EXPR
-         || code_right == TRUTH_ANDIF_EXPR)
+    case RSHIFT_EXPR:
+      if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
        warning (OPT_Wparentheses,
-                "suggest parentheses around && within ||");
-    }
+                "suggest parentheses around %<+%> inside %<>>%>");
+      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around %<-%> inside %<>>%>");
+      return;
 
-  if (code == BIT_IOR_EXPR)
-    {
+    case TRUTH_ORIF_EXPR:
+      if (code_left == TRUTH_ANDIF_EXPR || code_right == TRUTH_ANDIF_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around %<&&%> within %<||%>");
+      return;
+
+    case BIT_IOR_EXPR:
       if (code_left == BIT_AND_EXPR || code_left == BIT_XOR_EXPR
          || code_left == PLUS_EXPR || code_left == MINUS_EXPR
          || code_right == BIT_AND_EXPR || code_right == BIT_XOR_EXPR
          || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
        warning (OPT_Wparentheses,
-                "suggest parentheses around arithmetic in operand of |");
+                "suggest parentheses around arithmetic in operand of %<|%>");
       /* Check cases like x|y==z */
-      if (TREE_CODE_CLASS (code_left) == tcc_comparison
-         || TREE_CODE_CLASS (code_right) == tcc_comparison)
+      else if (TREE_CODE_CLASS (code_left) == tcc_comparison
+              || TREE_CODE_CLASS (code_right) == tcc_comparison)
        warning (OPT_Wparentheses,
-                "suggest parentheses around comparison in operand of |");
-    }
+                "suggest parentheses around comparison in operand of %<|%>");
+      /* Check cases like !x | y */
+      else if (code_left == TRUTH_NOT_EXPR
+              && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
+       warning (OPT_Wparentheses, "suggest parentheses around operand of "
+                "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>");
+      return;
 
-  if (code == BIT_XOR_EXPR)
-    {
+    case BIT_XOR_EXPR:
       if (code_left == BIT_AND_EXPR
          || code_left == PLUS_EXPR || code_left == MINUS_EXPR
          || code_right == BIT_AND_EXPR
          || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
        warning (OPT_Wparentheses,
-                "suggest parentheses around arithmetic in operand of ^");
+                "suggest parentheses around arithmetic in operand of %<^%>");
       /* Check cases like x^y==z */
-      if (TREE_CODE_CLASS (code_left) == tcc_comparison
-         || TREE_CODE_CLASS (code_right) == tcc_comparison)
+      else if (TREE_CODE_CLASS (code_left) == tcc_comparison
+              || TREE_CODE_CLASS (code_right) == tcc_comparison)
        warning (OPT_Wparentheses,
-                "suggest parentheses around comparison in operand of ^");
-    }
+                "suggest parentheses around comparison in operand of %<^%>");
+      return;
 
-  if (code == BIT_AND_EXPR)
-    {
-      if (code_left == PLUS_EXPR || code_left == MINUS_EXPR
-         || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+    case BIT_AND_EXPR:
+      if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around %<+%> in operand of %<&%>");
+      else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
        warning (OPT_Wparentheses,
-                "suggest parentheses around + or - in operand of &");
+                "suggest parentheses around %<-%> in operand of %<&%>");
       /* Check cases like x&y==z */
-      if (TREE_CODE_CLASS (code_left) == tcc_comparison
-         || TREE_CODE_CLASS (code_right) == tcc_comparison)
+      else if (TREE_CODE_CLASS (code_left) == tcc_comparison
+              || TREE_CODE_CLASS (code_right) == tcc_comparison)
        warning (OPT_Wparentheses,
-                "suggest parentheses around comparison in operand of &");
-    }
+                "suggest parentheses around comparison in operand of %<&%>");
+      /* Check cases like !x & y */
+      else if (code_left == TRUTH_NOT_EXPR
+              && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
+       warning (OPT_Wparentheses, "suggest parentheses around operand of "
+                "%<!%> or change %<&%> to %<&&%> or %<!%> to %<~%>");
+      return;
 
-  if (code == EQ_EXPR || code == NE_EXPR)
-    {
+    case EQ_EXPR:
       if (TREE_CODE_CLASS (code_left) == tcc_comparison
           || TREE_CODE_CLASS (code_right) == tcc_comparison)
        warning (OPT_Wparentheses,
-                "suggest parentheses around comparison in operand of %s",
-                 code == EQ_EXPR ? "==" : "!=");
-    }
-  else if (TREE_CODE_CLASS (code) == tcc_comparison)
-    {
-      if ((TREE_CODE_CLASS (code_left) == tcc_comparison
-          && code_left != NE_EXPR && code_left != EQ_EXPR)
-         || (TREE_CODE_CLASS (code_right) == tcc_comparison
-             && code_right != NE_EXPR && code_right != EQ_EXPR))
-       warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not "
+                "suggest parentheses around comparison in operand of %<==%>");
+      return;
+    case NE_EXPR:
+      if (TREE_CODE_CLASS (code_left) == tcc_comparison
+          || TREE_CODE_CLASS (code_right) == tcc_comparison)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around comparison in operand of %<!=%>");
+      return;
+
+    default:
+      if (TREE_CODE_CLASS (code) == tcc_comparison
+          && ((TREE_CODE_CLASS (code_left) == tcc_comparison
+               && code_left != NE_EXPR && code_left != EQ_EXPR
+               && INTEGRAL_TYPE_P (TREE_TYPE (arg_left)))
+              || (TREE_CODE_CLASS (code_right) == tcc_comparison
+                  && code_right != NE_EXPR && code_right != EQ_EXPR
+                  && INTEGRAL_TYPE_P (TREE_TYPE (arg_right)))))
+       warning (OPT_Wparentheses, "comparisons like %<X<=Y<=Z%> do not "
                 "have their mathematical meaning");
+      return;
     }
+#undef NOT_A_BOOLEAN_EXPR_P
 }
 
 /* If LABEL (a LABEL_DECL) has not been used, issue a warning.  */
@@ -7090,17 +8200,167 @@ warn_for_unused_label (tree label)
 struct gcc_targetcm targetcm = TARGETCM_INITIALIZER;
 #endif
 
-/* Warn for division by zero according to the value of DIVISOR.  */
+/* Warn for division by zero according to the value of DIVISOR.  LOC
+   is the location of the division operator.  */
 
 void
-warn_for_div_by_zero (tree divisor)
+warn_for_div_by_zero (location_t loc, tree divisor)
 {
-  /* If DIVISOR is zero, and has integral type, issue a warning about
-     division by zero.  Do not issue a warning if DIVISOR has a
+  /* 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))
-    warning (OPT_Wdiv_by_zero, "division by zero");
+  if (skip_evaluation == 0
+      && (integer_zerop (divisor) || fixed_zerop (divisor)))
+    warning_at (loc, OPT_Wdiv_by_zero, "division by zero");
+}
+
+/* Subroutine of build_binary_op. Give warnings for comparisons
+   between signed and unsigned quantities that may fail. Do the
+   checking based on the original operand trees ORIG_OP0 and ORIG_OP1,
+   so that casts will be considered, but default promotions won't
+   be.
+
+   LOCATION is the location of the comparison operator.
+
+   The arguments of this function map directly to local variables
+   of build_binary_op.  */
+
+void 
+warn_for_sign_compare (location_t location,
+                      tree orig_op0, tree orig_op1, 
+                      tree op0, tree op1, 
+                      tree result_type, enum tree_code resultcode)
+{
+  int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
+  int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
+  int unsignedp0, unsignedp1;
+  
+  /* In C++, check for comparison of different enum types.  */
+  if (c_dialect_cxx()
+      && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
+      && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
+      && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
+        != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
+    {
+      warning_at (location,
+                 OPT_Wsign_compare, "comparison between types %qT and %qT",
+                 TREE_TYPE (orig_op0), TREE_TYPE (orig_op1));
+    }
+
+  /* Do not warn if the comparison is being done in a signed type,
+     since the signed type will only be chosen if it can represent
+     all the values of the unsigned type.  */
+  if (!TYPE_UNSIGNED (result_type))
+    /* OK */;
+  /* Do not warn if both operands are unsigned.  */
+  else if (op0_signed == op1_signed)
+    /* OK */;
+  else
+    {
+      tree sop, uop, base_type;
+      bool ovf;
+
+      if (op0_signed)
+        sop = orig_op0, uop = orig_op1;
+      else 
+        sop = orig_op1, uop = orig_op0;
+
+      STRIP_TYPE_NOPS (sop); 
+      STRIP_TYPE_NOPS (uop);
+      base_type = (TREE_CODE (result_type) == COMPLEX_TYPE
+                  ? TREE_TYPE (result_type) : result_type);
+
+      /* Do not warn if the signed quantity is an unsuffixed integer
+         literal (or some static constant expression involving such
+         literals or a conditional expression involving such literals)
+         and it is non-negative.  */
+      if (tree_expr_nonnegative_warnv_p (sop, &ovf))
+        /* OK */;
+      /* Do not warn if the comparison is an equality operation, the
+         unsigned quantity is an integral constant, and it would fit
+         in the result if the result were signed.  */
+      else if (TREE_CODE (uop) == INTEGER_CST
+               && (resultcode == EQ_EXPR || resultcode == NE_EXPR)
+              && int_fits_type_p (uop, c_common_signed_type (base_type)))
+        /* OK */;
+      /* In C, do not warn if the unsigned quantity is an enumeration
+         constant and its maximum value would fit in the result if the
+         result were signed.  */
+      else if (!c_dialect_cxx() && TREE_CODE (uop) == INTEGER_CST
+               && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
+               && int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE (uop)),
+                                  c_common_signed_type (base_type)))
+        /* OK */;
+      else 
+        warning_at (location,
+                   OPT_Wsign_compare, 
+                   "comparison between signed and unsigned integer expressions");
+    }
+  
+  /* Warn if two unsigned values are being compared in a size larger
+     than their original size, and one (and only one) is the result of
+     a `~' operator.  This comparison will always fail.
+     
+     Also warn if one operand is a constant, and the constant does not
+     have all bits set that are set in the ~ operand when it is
+     extended.  */
+
+  op0 = get_narrower (op0, &unsignedp0);
+  op1 = get_narrower (op1, &unsignedp1);
+  
+  if ((TREE_CODE (op0) == BIT_NOT_EXPR)
+      ^ (TREE_CODE (op1) == BIT_NOT_EXPR))
+    {
+      if (TREE_CODE (op0) == BIT_NOT_EXPR)
+       op0 = get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
+      if (TREE_CODE (op1) == BIT_NOT_EXPR)
+       op1 = get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
+
+      if (host_integerp (op0, 0) || host_integerp (op1, 0))
+        {
+          tree primop;
+          HOST_WIDE_INT constant, mask;
+          int unsignedp;
+          unsigned int bits;
+          
+          if (host_integerp (op0, 0))
+            {
+              primop = op1;
+              unsignedp = unsignedp1;
+              constant = tree_low_cst (op0, 0);
+            }
+          else
+            {
+              primop = op0;
+              unsignedp = unsignedp0;
+              constant = tree_low_cst (op1, 0);
+            }
+          
+          bits = TYPE_PRECISION (TREE_TYPE (primop));
+          if (bits < TYPE_PRECISION (result_type)
+              && bits < HOST_BITS_PER_LONG && unsignedp)
+            {
+              mask = (~ (HOST_WIDE_INT) 0) << bits;
+              if ((mask & constant) != mask)
+               {
+                 if (constant == 0)
+                   warning (OPT_Wsign_compare, 
+                            "promoted ~unsigned is always non-zero");
+                 else
+                   warning_at (location, OPT_Wsign_compare, 
+                               "comparison of promoted ~unsigned with constant");
+               }
+            }
+        }
+      else if (unsignedp0 && unsignedp1
+               && (TYPE_PRECISION (TREE_TYPE (op0))
+                   < TYPE_PRECISION (result_type))
+               && (TYPE_PRECISION (TREE_TYPE (op1))
+                   < TYPE_PRECISION (result_type)))
+        warning_at (location, OPT_Wsign_compare,
+                 "comparison of promoted ~unsigned with unsigned");
+    }
 }
 
 #include "gt-c-common.h"