OSDN Git Service

007-01-29 Manuel Lopez-Ibanez <manu@gcc.gnu.org>
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index ecbe402..1bd59ff 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 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -16,8 +16,8 @@ for more details.
 
 You should have received a copy of the GNU General Public License
 along with GCC; see the file COPYING.  If not, write to the Free
-Software Foundation, 59 Temple Place - Suite 330, Boston, MA
-02111-1307, USA.  */
+Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
+02110-1301, USA.  */
 
 #include "config.h"
 #include "system.h"
@@ -47,6 +47,7 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "tree-mudflap.h"
 #include "opts.h"
 #include "real.h"
+#include "cgraph.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
@@ -130,6 +131,10 @@ cpp_reader *parse_in;              /* Declared in c-pragma.h.  */
        tree complex_double_type_node;
        tree complex_long_double_type_node;
 
+       tree dfloat32_type_node;
+       tree dfloat64_type_node;
+       tree_dfloat128_type_node;
+
        tree intQI_type_node;
        tree intHI_type_node;
        tree intSI_type_node;
@@ -249,6 +254,10 @@ int flag_short_double;
 
 int flag_short_wchar;
 
+/* Nonzero means allow implicit conversions between vectors with
+   differing numbers of subparts and/or differing element types.  */
+int flag_lax_vector_conversions;
+
 /* Nonzero means allow Microsoft extensions without warnings or errors.  */
 int flag_ms_extensions;
 
@@ -256,20 +265,10 @@ int flag_ms_extensions;
 
 int flag_no_asm;
 
-/* Nonzero means give string constants the type `const char *', as mandated
-   by the standard.  */
-
-int flag_const_strings;
-
 /* Nonzero means to treat bitfields as signed unless they say `unsigned'.  */
 
 int flag_signed_bitfields = 1;
 
-/* Nonzero means warn about deprecated conversion from string constant to
-   `char *'.  */
-
-int warn_write_strings;
-
 /* Warn about #pragma directives that are not recognized.  */
 
 int warn_unknown_pragmas; /* Tri state variable.  */
@@ -290,13 +289,6 @@ int warn_strict_null_sentinel;
    will most likely result in crashes.  */
 int flag_nil_receivers = 1;
 
-/* Nonzero means that we will allow new ObjC exception syntax (@throw,
-   @try, etc.) in source code.  */
-int flag_objc_exceptions = 0;
-
-/* Nonzero means that we generate NeXT setjmp based exceptions.  */
-int flag_objc_sjlj_exceptions = -1;
-
 /* Nonzero means that code generation will be altered to support
    "zero-link" execution.  This currently affects ObjC only, but may
    affect other languages in the future.  */
@@ -340,21 +332,13 @@ int warn_main;
 
 int flag_gen_declaration;
 
-/* Generate code for GNU or NeXT runtime environment.  */
-
-#ifdef NEXT_OBJC_RUNTIME
-int flag_next_runtime = 1;
-#else
-int flag_next_runtime = 0;
-#endif
-
 /* Tells the compiler that this is a special run.  Do not perform any
    compiling, instead we are to test some platform dependent features
    and output a C header file with appropriate definitions.  */
 
 int print_struct_values;
 
-/* ???.  Undocumented.  */
+/* Tells the compiler what is the constant string class for Objc.  */
 
 const char *constant_string_class_name;
 
@@ -421,6 +405,11 @@ int flag_access_control = 1;
 
 int flag_check_new;
 
+/* Nonzero if we want to allow the use of experimental features that
+   are likely to become part of C++0x. */
+
+int flag_cpp0x = 0;
+
 /* Nonzero if we want the new ISO rules for pushing a new scope for `for'
    initialization variables.
    0: Old rules, set by -fno-for-scope.
@@ -444,10 +433,16 @@ int flag_weak = 1;
 int flag_working_directory = -1;
 
 /* Nonzero to use __cxa_atexit, rather than atexit, to register
-   destructors for local statics and global objects.  */
+   destructors for local statics and global objects.  '2' means it has been
+   set nonzero as a default, not by a command-line flag.  */
 
 int flag_use_cxa_atexit = DEFAULT_USE_CXA_ATEXIT;
 
+/* Nonzero to use __cxa_get_exception_ptr in C++ exception-handling
+   code.  '2' means it has not been set explicitly on the command line.  */
+
+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.  */
 
@@ -508,7 +503,6 @@ const struct fname_var_t fname_vars[] =
   {NULL, 0, 0},
 };
 
-static int constant_fits_type_p (tree, tree);
 static tree check_case_value (tree);
 static bool check_case_bounds (tree, tree, tree *, tree *);
 
@@ -519,8 +513,13 @@ static tree handle_noreturn_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_flatten_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,
+                                                bool *);
 static tree handle_const_attribute (tree *, tree, tree, int, bool *);
 static tree handle_transparent_union_attribute (tree *, tree, tree,
                                                int, bool *);
@@ -531,6 +530,7 @@ static tree handle_section_attribute (tree *, tree, tree, int, bool *);
 static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
 static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
 static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
+static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ;
 static tree handle_visibility_attribute (tree *, tree, tree, int,
                                         bool *);
 static tree handle_tls_model_attribute (tree *, tree, tree, int,
@@ -583,10 +583,16 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_noinline_attribute },
   { "always_inline",          0, 0, true,  false, false,
                              handle_always_inline_attribute },
+  { "gnu_inline",             0, 0, true,  false, false,
+                             handle_gnu_inline_attribute },
+  { "flatten",                0, 0, true,  false, false,
+                             handle_flatten_attribute },
   { "used",                   0, 0, true,  false, false,
                              handle_used_attribute },
   { "unused",                 0, 0, false, false, false,
                              handle_unused_attribute },
+  { "externally_visible",     0, 0, true,  false, false,
+                             handle_externally_visible_attribute },
   /* The same comments as for noreturn attributes apply to const ones.  */
   { "const",                  0, 0, true,  false, false,
                              handle_const_attribute },
@@ -606,6 +612,8 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_weak_attribute },
   { "alias",                  1, 1, true,  false, false,
                              handle_alias_attribute },
+  { "weakref",                0, 1, true,  false, false,
+                             handle_weakref_attribute },
   { "no_instrument_function", 0, 0, true,  false, false,
                              handle_no_instrument_function_attribute },
   { "malloc",                 0, 0, true,  false, false,
@@ -702,7 +710,7 @@ finish_fname_decls (void)
       if (TREE_CODE (*bodyp) == BIND_EXPR)
        bodyp = &BIND_EXPR_BODY (*bodyp);
 
-      append_to_statement_list (*bodyp, &stmts);
+      append_to_statement_list_force (*bodyp, &stmts);
       *bodyp = stmts;
     }
 
@@ -777,10 +785,10 @@ c_expand_decl (tree decl)
     {
       /* Let the back-end know about this variable.  */
       if (!anon_aggr_type_p (TREE_TYPE (decl)))
-        emit_local_var (decl);
+       emit_local_var (decl);
       else
-        expand_anon_union_decl (decl, NULL_TREE,
-                                DECL_ANON_UNION_ELEMS (decl));
+       expand_anon_union_decl (decl, NULL_TREE,
+                               DECL_ANON_UNION_ELEMS (decl));
     }
   else
     return 0;
@@ -844,7 +852,6 @@ 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;
-  const int nchars_max = flag_isoc99 ? 4095 : 509;
   int length = TREE_STRING_LENGTH (value);
   int nchars;
   tree e_type, i_type, a_type;
@@ -852,15 +859,32 @@ fix_string_type (tree value)
   /* Compute the number of elements, for the array type.  */
   nchars = wide_flag ? length / wchar_bytes : length;
 
-  if (pedantic && nchars - 1 > nchars_max && !c_dialect_cxx ())
-    pedwarn ("string length %qd is greater than the length %qd ISO C%d compilers are required to support",
-            nchars - 1, nchars_max, flag_isoc99 ? 99 : 89);
-
-  e_type = wide_flag ? wchar_type_node : char_type_node;
-  /* Create the array type for the string constant.  flag_const_strings
-     says make the string constant an array of const char so that
-     copying it to a non-const pointer will get a warning.  For C++,
-     this is the standard behavior.
+  /* 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,
+     so we do not diagnose it (warn_overlength_strings is forced off
+     in c_common_post_options).  */
+  if (warn_overlength_strings)
+    {
+      const int nchars_max = flag_isoc99 ? 4095 : 509;
+      const int relevant_std = flag_isoc99 ? 99 : 90;
+      if (nchars - 1 > nchars_max)
+       /* Translators: The %d after 'ISO C' will be 90 or 99.  Do not
+          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 "
+                "ISO C%d compilers are required to support",
+                nchars - 1, nchars_max, relevant_std);
+    }
+
+  /* Create the array type for the string constant.  The ISO C++
+     standard says that a string literal has type `const char[N]' or
+     `const wchar_t[N]'.  We use the same logic when invoked as a C
+     front-end with -Wwrite-strings.
+     ??? We should change the type of an expression depending on the
+     state of a warning flag.  We should just be warning -- see how
+     this is handled in the C++ front-end for the deprecated implicit
+     conversion from string literals to `char*' or `wchar_t*'.
 
      The C++ front end relies on TYPE_MAIN_VARIANT of a cv-qualified
      array type being the unqualified version of that type.
@@ -868,9 +892,10 @@ 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 (flag_const_strings)
+  if (c_dialect_cxx() || warn_write_strings)
     a_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST);
 
   TREE_TYPE (value) = a_type;
@@ -893,93 +918,317 @@ constant_expression_warning (tree value)
   if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
        || TREE_CODE (value) == VECTOR_CST
        || TREE_CODE (value) == COMPLEX_CST)
-      && TREE_CONSTANT_OVERFLOW (value) && pedantic)
+      && TREE_OVERFLOW (value)
+      && warn_overflow
+      && pedantic)
     pedwarn ("overflow in constant expression");
 }
 
-/* Print a warning if an expression had overflow in folding.
+/* Print a warning if an expression had overflow in folding and its
+   operands hadn't.
+
    Invoke this function on every expression that
    (1) appears in the source code, and
-   (2) might be a constant expression that overflowed, and
+   (2) is a constant expression that overflowed, and
    (3) is not already checked by convert_and_check;
-   however, do not invoke this function on operands of explicit casts.  */
+   however, do not invoke this function on operands of explicit casts
+   or when the expression is the result of an operator and any operand
+   already overflowed.  */
 
 void
 overflow_warning (tree value)
 {
-  if ((TREE_CODE (value) == INTEGER_CST
-       || (TREE_CODE (value) == COMPLEX_CST
-          && TREE_CODE (TREE_REALPART (value)) == INTEGER_CST))
-      && TREE_OVERFLOW (value))
+  if (skip_evaluation) return;
+
+  switch (TREE_CODE (value))
     {
-      TREE_OVERFLOW (value) = 0;
-      if (skip_evaluation == 0)
-       warning (0, "integer overflow in expression");
+    case INTEGER_CST:
+      warning (OPT_Woverflow, "integer overflow in expression");
+      break;
+      
+    case REAL_CST:
+      warning (OPT_Woverflow, "floating point overflow in expression");
+      break;
+      
+    case VECTOR_CST:
+      warning (OPT_Woverflow, "vector overflow in expression");
+      break;
+      
+    case COMPLEX_CST:
+      if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)
+       warning (OPT_Woverflow, "complex integer overflow in expression");
+      else if (TREE_CODE (TREE_REALPART (value)) == REAL_CST)
+       warning (OPT_Woverflow, "complex floating point overflow in expression");
+      break;
+
+    default:
+      break;
     }
-  else if ((TREE_CODE (value) == REAL_CST
-           || (TREE_CODE (value) == COMPLEX_CST
-               && TREE_CODE (TREE_REALPART (value)) == REAL_CST))
-          && TREE_OVERFLOW (value))
-    {
-      TREE_OVERFLOW (value) = 0;
-      if (skip_evaluation == 0)
-       warning (0, "floating point overflow in expression");
+}
+
+/* Print a warning about casts that might indicate violation
+   of strict aliasing rules if -Wstrict-aliasing is used and
+   strict aliasing mode is in effect. OTYPE is the original
+   TREE_TYPE of EXPR, and TYPE the type we're casting to. */
+
+void
+strict_aliasing_warning (tree otype, tree type, tree expr)
+{
+  if (flag_strict_aliasing && warn_strict_aliasing
+      && POINTER_TYPE_P (type) && POINTER_TYPE_P (otype)
+      && TREE_CODE (expr) == ADDR_EXPR
+      && (DECL_P (TREE_OPERAND (expr, 0))
+          || handled_component_p (TREE_OPERAND (expr, 0)))
+      && !VOID_TYPE_P (TREE_TYPE (type)))
+    {
+      /* Casting the address of an object to non void pointer. Warn
+         if the cast breaks type based aliasing.  */
+      if (!COMPLETE_TYPE_P (TREE_TYPE (type)))
+        warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
+                 "might break strict-aliasing rules");
+      else
+        {
+          HOST_WIDE_INT set1 = get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
+          HOST_WIDE_INT set2 = get_alias_set (TREE_TYPE (type));
+
+          if (!alias_sets_conflict_p (set1, set2))
+            warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+                     "pointer will break strict-aliasing rules");
+          else if (warn_strict_aliasing > 1
+                  && !alias_sets_might_conflict_p (set1, set2))
+            warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
+                     "pointer might break strict-aliasing rules");
+        }
     }
-  else if (TREE_CODE (value) == VECTOR_CST && TREE_OVERFLOW (value))
+}
+
+/* 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_body_warning (tree inner_then, tree inner_else)
+{
+  if (warn_empty_body)
     {
-      TREE_OVERFLOW (value) = 0;
-      if (skip_evaluation == 0)
-       warning (0, "vector overflow in expression");
-    }
+      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, "%Hempty body in an if-statement",
+                EXPR_LOCUS (inner_then));
+
+      if (inner_else && IS_EMPTY_STMT (inner_else))
+       warning (OPT_Wempty_body, "%Hempty body in an else-statement",
+                EXPR_LOCUS (inner_else));
+   }
 }
 
-/* Print a warning if a large constant is truncated to unsigned,
-   or if -Wconversion is used and a constant < 0 is converted to unsigned.
-   Invoke this function on every expression that might be implicitly
-   converted to an unsigned type.  */
+/* Warn for unlikely, improbable, or stupid DECL declarations
+   of `main'.  */
 
 void
-unsigned_conversion_warning (tree result, tree operand)
+check_main_parameter_types (tree decl)
+{
+  tree args;
+  int argct = 0;
+
+  for (args = TYPE_ARG_TYPES (TREE_TYPE (decl)); args;
+      args = TREE_CHAIN (args))
+   {
+     tree type = args ? TREE_VALUE (args) : 0;
+
+     if (type == void_type_node || type == error_mark_node )
+       break;
+
+     ++argct;
+     switch (argct)
+       {
+       case 1:
+         if (TYPE_MAIN_VARIANT (type) != integer_type_node)
+           pedwarn ("first argument of %q+D should be %<int%>", decl);
+         break;
+
+       case 2:
+         if (TREE_CODE (type) != POINTER_TYPE
+             || 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);
+         break;
+
+       case 3:
+         if (TREE_CODE (type) != POINTER_TYPE
+             || 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);
+         break;
+       }
+   }
+
+  /* It is intentional that this message does not mention the third
+    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);
+}
+
+/* True if vector types T1 and T2 can be converted to each other
+   without an explicit cast.  If EMIT_LAX_NOTE is true, and T1 and T2
+   can only be converted with -flax-vector-conversions yet that is not
+   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)
 {
-  tree type = TREE_TYPE (result);
+  static bool emitted_lax_note = false;
+  bool convertible_lax;
+
+  if ((targetm.vector_opaque_p (t1) || targetm.vector_opaque_p (t2))
+      && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
+    return true;
+
+  convertible_lax =
+    (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
+     && (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE ||
+        TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
+     && (INTEGRAL_TYPE_P (TREE_TYPE (t1))
+        == INTEGRAL_TYPE_P (TREE_TYPE (t2))));
+
+  if (!convertible_lax || flag_lax_vector_conversions)
+    return convertible_lax;
 
-  if (TREE_CODE (operand) == INTEGER_CST
-      && TREE_CODE (type) == INTEGER_TYPE
-      && TYPE_UNSIGNED (type)
-      && skip_evaluation == 0
-      && !int_fits_type_p (operand, type))
+  if (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
+      && comptypes (TREE_TYPE (t1), TREE_TYPE (t2)))
+    return true;
+
+  if (emit_lax_note && !emitted_lax_note)
     {
-      if (!int_fits_type_p (operand, c_common_signed_type (type)))
-       /* This detects cases like converting -129 or 256 to unsigned char.  */
-       warning (0, "large integer implicitly truncated to unsigned type");
-      else if (warn_conversion)
-       warning (0, "negative integer implicitly converted to unsigned type");
+      emitted_lax_note = true;
+      inform ("use -flax-vector-conversions to permit "
+              "conversions between vectors with differing "
+              "element types or numbers of subparts");
     }
+
+  return false;
 }
 
-/* Nonzero if constant C has a value that is permissible
-   for type TYPE (an INTEGER_TYPE).  */
+/* Warns if the conversion of EXPR to TYPE may alter a value.
+   This function is called from convert_and_check.  */
 
-static int
-constant_fits_type_p (tree c, tree type)
+static void
+conversion_warning (tree type, tree expr)
 {
-  if (TREE_CODE (c) == INTEGER_CST)
-    return int_fits_type_p (c, type);
+  bool give_warning = false;
 
-  c = convert (type, c);
-  return !TREE_OVERFLOW (c);
-}
+  unsigned int formal_prec = TYPE_PRECISION (type);
 
-/* Nonzero if vector types T1 and T2 can be converted to each other
-   without an explicit cast.  */
-int
-vector_types_convertible_p (tree t1, tree t2)
-{
-  return targetm.vector_opaque_p (t1)
-        || targetm.vector_opaque_p (t2)
-         || (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
-            && INTEGRAL_TYPE_P (TREE_TYPE (t1))
-               == INTEGRAL_TYPE_P (TREE_TYPE (t2)));
+  if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
+    {
+      /* Warn for real constant that is not an exact integer converted
+         to integer type.  */
+      if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+          && TREE_CODE (type) == INTEGER_TYPE)
+        {
+          if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (TREE_TYPE (expr))))
+            give_warning = true;
+        }
+      /* Warn for an integer constant that does not fit into integer type.  */
+      else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+               && TREE_CODE (type) == INTEGER_TYPE
+               && !int_fits_type_p (expr, type))
+        {
+          if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr)))
+            warning (OPT_Wconversion,
+                     "negative integer implicitly converted to unsigned type");
+          else
+            give_warning = true;
+        }
+      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)
+            {
+              REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
+              if (!exact_real_truncate (TYPE_MODE (type), &a))
+                give_warning = true;
+            }
+          /* 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)))
+            {
+              REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
+              if (!exact_real_truncate (TYPE_MODE (type), &a))
+                give_warning = true;
+            }
+        }
+
+      if (give_warning)
+        warning (OPT_Wconversion,
+                 "conversion to %qT alters %qT constant value",
+                 type, TREE_TYPE (expr));
+    }
+  else /* 'expr' is not a constant.  */
+    {
+      /* Warn for real types converted to integer types.  */
+      if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+          && TREE_CODE (type) == INTEGER_TYPE)
+        give_warning = true;
+
+      else if (TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
+               && TREE_CODE (type) == INTEGER_TYPE)
+        {
+          /* Warn for integer types converted to smaller integer types.  */
+          if (formal_prec < TYPE_PRECISION (TREE_TYPE (expr))
+              /* When they are the same width but different signedness,
+                 then the value may change.  */
+              || (formal_prec == TYPE_PRECISION (TREE_TYPE (expr))
+                  && TYPE_UNSIGNED (TREE_TYPE (expr)) != TYPE_UNSIGNED (type))
+              /* Even when converted to a bigger type, if the type is
+                 unsigned but expr is signed, then negative values
+                 will be changed.  */
+              || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (TREE_TYPE (expr))))
+            give_warning = true;
+        }
+
+      /* 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
+               && 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);
+
+          if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
+              || !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
+            give_warning = true;
+        }
+
+      /* Warn for real types converted to smaller real types.  */
+      else if (TREE_CODE (TREE_TYPE (expr)) == REAL_TYPE
+               && TREE_CODE (type) == REAL_TYPE
+               && formal_prec < TYPE_PRECISION (TREE_TYPE (expr)))
+        give_warning = true;
+
+
+      if (give_warning)
+        warning (OPT_Wconversion,
+                 "conversion to %qT from %qT may alter its value",
+                 type, TREE_TYPE (expr));
+    }
 }
 
 /* Convert EXPR to TYPE, warning about conversion problems with constants.
@@ -989,34 +1238,60 @@ vector_types_convertible_p (tree t1, tree t2)
 tree
 convert_and_check (tree type, tree expr)
 {
-  tree t = convert (type, expr);
-  if (TREE_CODE (t) == INTEGER_CST)
+  tree result;
+
+  if (TREE_TYPE (expr) == type)
+    return expr;
+  
+  result = convert (type, expr);
+
+  if (skip_evaluation)
+    return result;
+
+
+  if (TREE_CODE (expr) == INTEGER_CST
+      && (TREE_CODE (type) == INTEGER_TYPE
+          || TREE_CODE (type) == ENUMERAL_TYPE)
+      && !int_fits_type_p (expr, type))
     {
-      if (TREE_OVERFLOW (t))
-       {
-         TREE_OVERFLOW (t) = 0;
-
-         /* Do not diagnose overflow in a constant expression merely
-            because a conversion overflowed.  */
-         TREE_CONSTANT_OVERFLOW (t) = TREE_CONSTANT_OVERFLOW (expr);
-
-         /* No warning for converting 0x80000000 to int.  */
-         if (!(TYPE_UNSIGNED (type) < TYPE_UNSIGNED (TREE_TYPE (expr))
-               && TREE_CODE (TREE_TYPE (expr)) == INTEGER_TYPE
-               && TYPE_PRECISION (type) == TYPE_PRECISION (TREE_TYPE (expr))))
-           /* If EXPR fits in the unsigned version of TYPE,
-              don't warn unless pedantic.  */
-           if ((pedantic
-                || TYPE_UNSIGNED (type)
-                || !constant_fits_type_p (expr,
-                                          c_common_unsigned_type (type)))
-               && skip_evaluation == 0)
-             warning (0, "overflow in implicit constant conversion");
-       }
+      /* Do not diagnose overflow in a constant expression merely
+         because a conversion overflowed.  */
+      if (TREE_OVERFLOW (result))
+        TREE_OVERFLOW (result) = TREE_OVERFLOW (expr);
+
+      if (TYPE_UNSIGNED (type))
+        {
+          /* This detects cases like converting -129 or 256 to
+             unsigned char.  */
+          if (!int_fits_type_p (expr, c_common_signed_type (type)))
+            warning (OPT_Woverflow,
+                     "large integer implicitly truncated to unsigned type");
+          else if (warn_conversion)
+            conversion_warning (type, expr);
+        }
       else
-       unsigned_conversion_warning (t, expr);
-    }
-  return t;
+        {
+          if (!int_fits_type_p (expr, c_common_unsigned_type (type)))
+            warning (OPT_Woverflow,
+                     "overflow in implicit constant conversion");
+          /* No warning for converting 0x80000000 to int.  */
+          else if (pedantic
+                   && (TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE
+                       || TYPE_PRECISION (TREE_TYPE (expr))
+                       != TYPE_PRECISION (type)))
+            warning (OPT_Woverflow,
+                     "overflow in implicit constant conversion");
+          else if (warn_conversion)
+            conversion_warning (type, expr);
+        }
+    }
+  else if (TREE_CODE (result) == INTEGER_CST && TREE_OVERFLOW (result)) 
+    warning (OPT_Woverflow,
+             "overflow in implicit constant conversion");
+  else if (warn_conversion)
+    conversion_warning (type, expr);
+  
+  return result;
 }
 \f
 /* A node in a list that describes references to variables (EXPR), which are
@@ -1359,7 +1634,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
 
     default:
       /* For other expressions, simply recurse on their operands.
-         Manual tail recursion for unary expressions.
+        Manual tail recursion for unary expressions.
         Other non-expressions need not be processed.  */
       if (cl == tcc_unary)
        {
@@ -1451,7 +1726,7 @@ check_case_value (tree value)
    if the case is not a case range.
    The caller has to make sure that we are not called with NULL for
    CASE_LOW_P (i.e. the default case).
-   Returns true if the case label is in range of ORIG_TYPE (satured or
+   Returns true if the case label is in range of ORIG_TYPE (saturated or
    untouched) or false if the label is out of range.  */
 
 static bool
@@ -1651,6 +1926,13 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
        return build_vector_type_for_mode (inner_type, mode);
     }
 
+  if (mode == TYPE_MODE (dfloat32_type_node))
+    return dfloat32_type_node;
+  if (mode == TYPE_MODE (dfloat64_type_node))
+    return dfloat64_type_node;
+  if (mode == TYPE_MODE (dfloat128_type_node))
+    return dfloat128_type_node;
+
   for (t = registered_builtin_types; t; t = TREE_CHAIN (t))
     if (TYPE_MODE (TREE_VALUE (t)) == mode)
       return TREE_VALUE (t);
@@ -1782,6 +2064,31 @@ c_common_signed_or_unsigned_type (int unsignedp, tree type)
     return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
 }
 
+/* Build a bit-field integer type for the given WIDTH and UNSIGNEDP.  */
+
+tree
+c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
+{
+  /* Extended integer types of the same width as a standard type have
+     lesser rank, so those of the same width as int promote to int or
+     unsigned int and are valid for printf formats expecting int or
+     unsigned int.  To avoid such special cases, avoid creating
+     extended integer types for bit-fields if a standard integer type
+     is available.  */
+  if (width == TYPE_PRECISION (integer_type_node))
+    return unsignedp ? unsigned_type_node : integer_type_node;
+  if (width == TYPE_PRECISION (signed_char_type_node))
+    return unsignedp ? unsigned_char_type_node : signed_char_type_node;
+  if (width == TYPE_PRECISION (short_integer_type_node))
+    return unsignedp ? short_unsigned_type_node : short_integer_type_node;
+  if (width == TYPE_PRECISION (long_integer_type_node))
+    return unsignedp ? long_unsigned_type_node : long_integer_type_node;
+  if (width == TYPE_PRECISION (long_long_integer_type_node))
+    return (unsignedp ? long_long_unsigned_type_node
+           : long_long_integer_type_node);
+  return build_nonstandard_integer_type (width, unsignedp);
+}
+
 /* The C version of the register_builtin_type langhook.  */
 
 void
@@ -1813,7 +2120,7 @@ min_precision (tree value, int unsignedp)
      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));
+    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.  */
@@ -1827,8 +2134,7 @@ min_precision (tree value, int unsignedp)
 }
 \f
 /* Print an error message for invalid operands to arith operation
-   CODE.  NOP_EXPR is used as a special case (see
-   c_common_truthvalue_conversion).  */
+   CODE.  */
 
 void
 binary_op_error (enum tree_code code)
@@ -1837,10 +2143,6 @@ binary_op_error (enum tree_code code)
 
   switch (code)
     {
-    case NOP_EXPR:
-      error ("invalid truth-value expression");
-      return;
-
     case PLUS_EXPR:
       opname = "+"; break;
     case MINUS_EXPR:
@@ -2015,12 +2317,10 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
        {
          /* Convert primop1 to target type, but do not introduce
             additional overflow.  We know primop1 is an int_cst.  */
-         tree tmp = build_int_cst_wide (*restype_ptr,
-                                        TREE_INT_CST_LOW (primop1),
-                                        TREE_INT_CST_HIGH (primop1));
-
-         primop1 = force_fit_type (tmp, 0, TREE_OVERFLOW (primop1),
-                                   TREE_CONSTANT_OVERFLOW (primop1));
+         primop1 = force_fit_type_double (*restype_ptr,
+                                          TREE_INT_CST_LOW (primop1),
+                                          TREE_INT_CST_HIGH (primop1), 0,
+                                          TREE_OVERFLOW (primop1));
        }
       if (type != *restype_ptr)
        {
@@ -2138,6 +2438,14 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
         in the type of the operand that is not constant.
         TYPE is already properly set.  */
     }
+
+  /* If either arg is decimal float and the other is float, find the
+     proper common type to use for comparison.  */
+  else if (real1 && real2
+          && (DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop0)))
+              || DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop1)))))
+    type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
+
   else if (real1 && real2
           && (TYPE_PRECISION (TREE_TYPE (primop0))
               == TYPE_PRECISION (TREE_TYPE (primop1))))
@@ -2310,9 +2618,21 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
                                    convert (TREE_TYPE (intop), size_exp), 1));
 
   /* Create the sum or difference.  */
-  return fold (build2 (resultcode, result_type, ptrop, intop));
+  return fold_build2 (resultcode, result_type, ptrop, intop);
 }
 \f
+/* Return whether EXPR is a declaration whose address can never be
+   NULL.  */
+
+bool
+decl_with_nonnull_addr_p (tree expr)
+{
+  return (DECL_P (expr)
+         && (TREE_CODE (expr) == PARM_DECL
+             || TREE_CODE (expr) == LABEL_DECL
+             || !DECL_WEAK (expr)));
+}
+
 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
    or for an `if' or `while' statement or ?..: exp.  It should already
    have been validated to be of suitable type; otherwise, a bad
@@ -2361,10 +2681,8 @@ c_common_truthvalue_conversion (tree expr)
       return expr;
 
     case INTEGER_CST:
-      /* Avoid integer_zerop to ignore TREE_CONSTANT_OVERFLOW.  */
-      return (TREE_INT_CST_LOW (expr) != 0 || TREE_INT_CST_HIGH (expr) != 0)
-            ? truthvalue_true_node
-            : truthvalue_false_node;
+      return integer_zerop (expr) ? truthvalue_false_node
+                                 : truthvalue_true_node;
 
     case REAL_CST:
       return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst0)
@@ -2377,25 +2695,27 @@ c_common_truthvalue_conversion (tree expr)
 
     case ADDR_EXPR:
       {
-       if (TREE_CODE (TREE_OPERAND (expr, 0)) == FUNCTION_DECL
-           && !DECL_WEAK (TREE_OPERAND (expr, 0)))
+       tree inner = TREE_OPERAND (expr, 0);
+       if (decl_with_nonnull_addr_p (inner))
          {
-           /* Common Ada/Pascal programmer's mistake.  We always warn
-              about this since it is so bad.  */
-           warning (0, "the address of %qD, will always evaluate as %<true%>",
-                    TREE_OPERAND (expr, 0));
+           /* Common Ada/Pascal programmer's mistake.  */
+           warning (OPT_Walways_true,
+                    "the address of %qD will always evaluate as %<true%>",
+                    inner);
            return truthvalue_true_node;
          }
 
-       /* If we are taking the address of an external decl, it might be
-          zero if it is weak, so we cannot optimize.  */
-       if (DECL_P (TREE_OPERAND (expr, 0))
-           && DECL_EXTERNAL (TREE_OPERAND (expr, 0)))
-         break;
+       /* If we still have a decl, it is possible for its address to
+          be NULL, so we cannot optimize.  */
+       if (DECL_P (inner))
+         {
+           gcc_assert (DECL_WEAK (inner));
+           break;
+         }
 
-       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 0)))
+       if (TREE_SIDE_EFFECTS (inner))
          return build2 (COMPOUND_EXPR, truthvalue_type_node,
-                        TREE_OPERAND (expr, 0), truthvalue_true_node);
+                        inner, truthvalue_true_node);
        else
          return truthvalue_true_node;
       }
@@ -2426,59 +2746,32 @@ c_common_truthvalue_conversion (tree expr)
 
     case COND_EXPR:
       /* Distribute the conversion into the arms of a COND_EXPR.  */
-      return fold (build3 (COND_EXPR, truthvalue_type_node,
+      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 (TREE_OPERAND (expr, 2)));
 
     case CONVERT_EXPR:
+    case NOP_EXPR:
       /* 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
          || TREE_CODE (TREE_TYPE (TREE_OPERAND (expr, 0))) == REFERENCE_TYPE)
        break;
-      /* Fall through....  */
-    case NOP_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));
       break;
 
-    case MINUS_EXPR:
-      /* Perhaps reduce (x - y) != 0 to (x != y).  The expressions
-        aren't guaranteed to the be same for modes that can represent
-        infinity, since if x and y are both +infinity, or both
-        -infinity, then x - y is not a number.
-
-        Note that this transformation is safe when x or y is NaN.
-        (x - y) is then NaN, and both (x - y) != 0 and x != y will
-        be false.  */
-      if (HONOR_INFINITIES (TYPE_MODE (TREE_TYPE (TREE_OPERAND (expr, 0)))))
-       break;
-      /* Fall through....  */
-    case BIT_XOR_EXPR:
-      /* This and MINUS_EXPR can be changed into a comparison of the
-        two objects.  */
-      if (TREE_TYPE (TREE_OPERAND (expr, 0))
-         == TREE_TYPE (TREE_OPERAND (expr, 1)))
-       return fold_build2 (NE_EXPR, truthvalue_type_node,
-                           TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
-      return fold_build2 (NE_EXPR, truthvalue_type_node,
-                         TREE_OPERAND (expr, 0),
-                         fold_convert (TREE_TYPE (TREE_OPERAND (expr, 0)),
-                                       TREE_OPERAND (expr, 1)));
-
-    case BIT_AND_EXPR:
-      if (integer_onep (TREE_OPERAND (expr, 1))
-         && TREE_TYPE (expr) != truthvalue_type_node)
-       /* Using convert here would cause infinite recursion.  */
-       return build1 (NOP_EXPR, truthvalue_type_node, expr);
-      break;
-
     case MODIFY_EXPR:
-      if (warn_parentheses && !TREE_NO_WARNING (expr))
-       warning (0, "suggest parentheses around assignment used as truth value");
+      if (!TREE_NO_WARNING (expr)
+         && warn_parentheses)
+       {
+         warning (OPT_Wparentheses,
+                  "suggest parentheses around assignment used as truth value");
+         TREE_NO_WARNING (expr) = 1;
+       }
       break;
 
     default:
@@ -2499,12 +2792,12 @@ c_common_truthvalue_conversion (tree expr)
   return build_binary_op (NE_EXPR, expr, integer_zero_node, 1);
 }
 \f
-static tree builtin_function_2 (const char *builtin_name, const char *name,
-                               tree builtin_type, tree type,
-                               enum built_in_function function_code,
-                               enum built_in_class cl, int library_name_p,
-                               bool nonansi_p,
-                               tree attrs);
+static void def_builtin_1  (enum built_in_function fncode,
+                           const char *name,
+                           enum built_in_class fnclass,
+                           tree fntype, tree libtype,
+                           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.  */
@@ -2707,9 +3000,9 @@ c_common_get_alias_set (tree t)
         But, the standard is wrong.  In particular, this code is
         legal C++:
 
-            int *ip;
-            int **ipp = &ip;
-            const int* const* cipp = ipp;
+           int *ip;
+           int **ipp = &ip;
+           const int* const* cipp = ipp;
 
         And, it doesn't make sense for that to be legal unless you
         can dereference IPP and CIPP.  So, we ignore cv-qualifiers on
@@ -2837,7 +3130,7 @@ c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
      TYPE_IS_SIZETYPE means that certain things (like overflow) will
      never happen.  However, this node should really have type
      `size_t', which is just a typedef for an ordinary integer type.  */
-  value = fold (build1 (NOP_EXPR, size_type_node, value));
+  value = fold_convert (size_type_node, value);
   gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
 
   return value;
@@ -2872,7 +3165,7 @@ c_alignof_expr (tree expr)
       tree best = t;
       int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
 
-      while (TREE_CODE (t) == NOP_EXPR
+      while ((TREE_CODE (t) == NOP_EXPR || TREE_CODE (t) == CONVERT_EXPR)
             && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
        {
          int thisalign;
@@ -2887,7 +3180,7 @@ c_alignof_expr (tree expr)
   else
     return c_alignof (TREE_TYPE (expr));
 
-  return fold (build1 (NOP_EXPR, size_type_node, t));
+  return fold_convert (size_type_node, t);
 }
 \f
 /* Handle C and C++ default attributes.  */
@@ -2910,24 +3203,24 @@ static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
 
 static void c_init_attributes (void);
 
-/* Build tree nodes and builtin functions common to both C and C++ language
-   frontends.  */
-
-void
-c_common_nodes_and_builtins (void)
+enum c_builtin_type
 {
-  enum builtin_type
-  {
 #define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME,
 #define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME,
 #define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME,
 #define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME,
 #define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
 #define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
+#define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME,
+#define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME,
 #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
 #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
 #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
 #define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
+#define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
+#define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG6) \
+  NAME,
 #define DEF_POINTER_TYPE(NAME, TYPE) NAME,
 #include "builtin-types.def"
 #undef DEF_PRIMITIVE_TYPE
@@ -2936,17 +3229,150 @@ c_common_nodes_and_builtins (void)
 #undef DEF_FUNCTION_TYPE_2
 #undef DEF_FUNCTION_TYPE_3
 #undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
+#undef DEF_FUNCTION_TYPE_7
+#undef DEF_FUNCTION_TYPE_VAR_0
+#undef DEF_FUNCTION_TYPE_VAR_1
+#undef DEF_FUNCTION_TYPE_VAR_2
+#undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
+#undef DEF_POINTER_TYPE
+  BT_LAST
+};
+
+typedef enum c_builtin_type builtin_type;
+
+/* A temporary array for c_common_nodes_and_builtins.  Used in
+   communication with def_fn_type.  */
+static tree builtin_types[(int) BT_LAST + 1];
+
+/* A helper function for c_common_nodes_and_builtins.  Build function type
+   for DEF with return type RET and N arguments.  If VAR is true, then the
+   function should be variadic after those N arguments.
+
+   Takes special care not to ICE if any of the types involved are
+   error_mark_node, which indicates that said type is not in fact available
+   (see builtin_type_for_size).  In which case the function type as a whole
+   should be error_mark_node.  */
+
+static void
+def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
+{
+  tree args = NULL, t;
+  va_list list;
+  int i;
+
+  va_start (list, n);
+  for (i = 0; i < n; ++i)
+    {
+      builtin_type a = va_arg (list, builtin_type);
+      t = builtin_types[a];
+      if (t == error_mark_node)
+       goto egress;
+      args = tree_cons (NULL_TREE, t, args);
+    }
+  va_end (list);
+
+  args = nreverse (args);
+  if (!var)
+    args = chainon (args, void_list_node);
+
+  t = builtin_types[ret];
+  if (t == error_mark_node)
+    goto egress;
+  t = build_function_type (t, args);
+
+ egress:
+  builtin_types[def] = t;
+}
+
+/* Build builtin functions common to both C and C++ language
+   frontends.  */
+
+static void
+c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
+{
+#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
+  builtin_types[ENUM] = VALUE;
+#define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
+  def_fn_type (ENUM, RETURN, 0, 0);
+#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
+  def_fn_type (ENUM, RETURN, 0, 1, ARG1);
+#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
+  def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
+#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+  def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
+#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
+  def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
+#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)        \
+  def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
+#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+                           ARG6)                                       \
+  def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
+#define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+                           ARG6, ARG7)                                 \
+  def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
+#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
+  def_fn_type (ENUM, RETURN, 1, 0);
+#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
+  def_fn_type (ENUM, RETURN, 1, 1, ARG1);
+#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
+  def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
+#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
+  def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
+#define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
+  def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
+#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
+  def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
+#define DEF_POINTER_TYPE(ENUM, TYPE) \
+  builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
+
+#include "builtin-types.def"
+
+#undef DEF_PRIMITIVE_TYPE
+#undef DEF_FUNCTION_TYPE_1
+#undef DEF_FUNCTION_TYPE_2
+#undef DEF_FUNCTION_TYPE_3
+#undef DEF_FUNCTION_TYPE_4
+#undef DEF_FUNCTION_TYPE_5
+#undef DEF_FUNCTION_TYPE_6
 #undef DEF_FUNCTION_TYPE_VAR_0
 #undef DEF_FUNCTION_TYPE_VAR_1
 #undef DEF_FUNCTION_TYPE_VAR_2
 #undef DEF_FUNCTION_TYPE_VAR_3
+#undef DEF_FUNCTION_TYPE_VAR_4
+#undef DEF_FUNCTION_TYPE_VAR_5
 #undef DEF_POINTER_TYPE
-    BT_LAST
-  };
+  builtin_types[(int) BT_LAST] = NULL_TREE;
+
+  c_init_attributes ();
+
+#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
+                   NONANSI_P, ATTRS, IMPLICIT, COND)                   \
+  if (NAME && COND)                                                    \
+    def_builtin_1 (ENUM, NAME, CLASS,                                   \
+                  builtin_types[(int) TYPE],                           \
+                  builtin_types[(int) LIBTYPE],                        \
+                  BOTH_P, FALLBACK_P, NONANSI_P,                       \
+                  built_in_attributes[(int) ATTRS], IMPLICIT);
+#include "builtins.def"
+#undef DEF_BUILTIN
+
+  build_common_builtin_nodes ();
+
+  targetm.init_builtins ();
+  if (flag_mudflap)
+    mudflap_init ();
+}
 
-  typedef enum builtin_type builtin_type;
+/* Build tree nodes and builtin functions common to both C and C++ language
+   frontends.  */
 
-  tree builtin_types[(int) BT_LAST];
+void
+c_common_nodes_and_builtins (void)
+{
   int wchar_type_size;
   tree array_domain_type;
   tree va_list_ref_type_node;
@@ -3044,6 +3470,17 @@ c_common_nodes_and_builtins (void)
   record_builtin_type (RID_DOUBLE, NULL, double_type_node);
   record_builtin_type (RID_MAX, "long double", long_double_type_node);
 
+  /* Only supported decimal floating point extension if the target
+     actually supports underlying modes. */
+  if (targetm.scalar_mode_supported_p (SDmode) 
+      && targetm.scalar_mode_supported_p (DDmode)
+      && targetm.scalar_mode_supported_p (TDmode))
+    {
+      record_builtin_type (RID_DFLOAT32, NULL, dfloat32_type_node);
+      record_builtin_type (RID_DFLOAT64, NULL, dfloat64_type_node);
+      record_builtin_type (RID_DFLOAT128, NULL, dfloat128_type_node);
+    }
+
   lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
                                         get_identifier ("complex int"),
                                         complex_integer_type_node));
@@ -3064,6 +3501,16 @@ c_common_nodes_and_builtins (void)
 
   record_builtin_type (RID_VOID, NULL, void_type_node);
 
+  /* Set the TYPE_NAME for any variants that were built before
+     record_builtin_type gave names to the built-in types. */
+  {
+    tree void_name = TYPE_NAME (void_type_node);
+    TYPE_NAME (void_type_node) = NULL_TREE;
+    TYPE_NAME (build_qualified_type (void_type_node, TYPE_QUAL_CONST))
+      = void_name;
+    TYPE_NAME (void_type_node) = void_name;
+  }
+
   /* This node must not be shared.  */
   void_zero_node = make_node (INTEGER_CST);
   TREE_TYPE (void_zero_node) = void_type_node;
@@ -3142,142 +3589,8 @@ c_common_nodes_and_builtins (void)
       va_list_ref_type_node = build_reference_type (va_list_type_node);
     }
 
-#define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
-  builtin_types[(int) ENUM] = VALUE;
-#define DEF_FUNCTION_TYPE_0(ENUM, RETURN)              \
-  builtin_types[(int) ENUM]                            \
-    = build_function_type (builtin_types[(int) RETURN],        \
-                          void_list_node);
-#define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1)                                \
-  builtin_types[(int) ENUM]                                            \
-    = build_function_type (builtin_types[(int) RETURN],                        \
-                          tree_cons (NULL_TREE,                        \
-                                     builtin_types[(int) ARG1],        \
-                                     void_list_node));
-#define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2)  \
-  builtin_types[(int) ENUM]                            \
-    = build_function_type                              \
-      (builtin_types[(int) RETURN],                    \
-       tree_cons (NULL_TREE,                           \
-                 builtin_types[(int) ARG1],            \
-                 tree_cons (NULL_TREE,                 \
-                            builtin_types[(int) ARG2], \
-                            void_list_node)));
-#define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3)             \
-  builtin_types[(int) ENUM]                                             \
-    = build_function_type                                               \
-      (builtin_types[(int) RETURN],                                     \
-       tree_cons (NULL_TREE,                                            \
-                 builtin_types[(int) ARG1],                             \
-                 tree_cons (NULL_TREE,                                  \
-                            builtin_types[(int) ARG2],                  \
-                            tree_cons (NULL_TREE,                       \
-                                       builtin_types[(int) ARG3],       \
-                                       void_list_node))));
-#define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4)      \
-  builtin_types[(int) ENUM]                                            \
-    = build_function_type                                              \
-      (builtin_types[(int) RETURN],                                    \
-       tree_cons (NULL_TREE,                                           \
-                 builtin_types[(int) ARG1],                            \
-                 tree_cons (NULL_TREE,                                 \
-                            builtin_types[(int) ARG2],                 \
-                            tree_cons                                  \
-                            (NULL_TREE,                                \
-                             builtin_types[(int) ARG3],                \
-                             tree_cons (NULL_TREE,                     \
-                                        builtin_types[(int) ARG4],     \
-                                        void_list_node)))));
-#define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN)                          \
-  builtin_types[(int) ENUM]                                            \
-    = build_function_type (builtin_types[(int) RETURN], NULL_TREE);
-#define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1)                     \
-   builtin_types[(int) ENUM]                                            \
-    = build_function_type (builtin_types[(int) RETURN],                 \
-                          tree_cons (NULL_TREE,                         \
-                                     builtin_types[(int) ARG1],         \
-                                     NULL_TREE));
-
-#define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2)      \
-   builtin_types[(int) ENUM]                                   \
-    = build_function_type                                      \
-      (builtin_types[(int) RETURN],                            \
-       tree_cons (NULL_TREE,                                   \
-                 builtin_types[(int) ARG1],                    \
-                 tree_cons (NULL_TREE,                         \
-                            builtin_types[(int) ARG2],         \
-                            NULL_TREE)));
-
-#define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3)                \
-   builtin_types[(int) ENUM]                                           \
-    = build_function_type                                              \
-      (builtin_types[(int) RETURN],                                    \
-       tree_cons (NULL_TREE,                                           \
-                 builtin_types[(int) ARG1],                            \
-                 tree_cons (NULL_TREE,                                 \
-                            builtin_types[(int) ARG2],                 \
-                            tree_cons (NULL_TREE,                      \
-                                       builtin_types[(int) ARG3],      \
-                                       NULL_TREE))));
-
-#define DEF_POINTER_TYPE(ENUM, TYPE)                   \
-  builtin_types[(int) ENUM]                            \
-    = build_pointer_type (builtin_types[(int) TYPE]);
-#include "builtin-types.def"
-#undef DEF_PRIMITIVE_TYPE
-#undef DEF_FUNCTION_TYPE_1
-#undef DEF_FUNCTION_TYPE_2
-#undef DEF_FUNCTION_TYPE_3
-#undef DEF_FUNCTION_TYPE_4
-#undef DEF_FUNCTION_TYPE_VAR_0
-#undef DEF_FUNCTION_TYPE_VAR_1
-#undef DEF_FUNCTION_TYPE_VAR_2
-#undef DEF_FUNCTION_TYPE_VAR_3
-#undef DEF_POINTER_TYPE
-
-  c_init_attributes ();
-
-#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
-                   NONANSI_P, ATTRS, IMPLICIT, COND)                   \
-  if (NAME && COND)                                                    \
-    {                                                                  \
-      tree decl;                                                       \
-                                                                       \
-      gcc_assert ((!BOTH_P && !FALLBACK_P)                             \
-                 || !strncmp (NAME, "__builtin_",                      \
-                              strlen ("__builtin_")));                 \
-                                                                       \
-      if (!BOTH_P)                                                     \
-       decl = lang_hooks.builtin_function (NAME, builtin_types[TYPE],  \
-                                ENUM,                                  \
-                                CLASS,                                 \
-                                (FALLBACK_P                            \
-                                 ? (NAME + strlen ("__builtin_"))      \
-                                 : NULL),                              \
-                                built_in_attributes[(int) ATTRS]);     \
-      else                                                             \
-       decl = builtin_function_2 (NAME,                                \
-                                  NAME + strlen ("__builtin_"),        \
-                                  builtin_types[TYPE],                 \
-                                  builtin_types[LIBTYPE],              \
-                                  ENUM,                                \
-                                  CLASS,                               \
-                                  FALLBACK_P,                          \
-                                  NONANSI_P,                           \
-                                  built_in_attributes[(int) ATTRS]);   \
-                                                                       \
-      built_in_decls[(int) ENUM] = decl;                               \
-      if (IMPLICIT)                                                    \
-       implicit_built_in_decls[(int) ENUM] = decl;                     \
-    }
-#include "builtins.def"
-#undef DEF_BUILTIN
-
-  build_common_builtin_nodes ();
-
-  targetm.init_builtins ();
-  if (flag_mudflap)
-    mudflap_init ();
+  if (!flag_preprocess_only)
+    c_define_builtins (va_list_ref_type_node, va_list_arg_type_node);
 
   main_identifier_node = get_identifier ("main");
 
@@ -3285,6 +3598,9 @@ c_common_nodes_and_builtins (void)
      not shared.  */
   null_node = make_node (INTEGER_CST);
   TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
+
+  /* Since builtin_types isn't gc'ed, don't export these nodes.  */
+  memset (builtin_types, 0, sizeof (builtin_types));
 }
 
 /* Look up the function in built_in_decls that corresponds to DECL
@@ -3307,6 +3623,21 @@ set_builtin_user_assembler_name (tree decl, const char *asmspec)
     init_block_clear_fn (asmspec);
 }
 
+/* The number of named compound-literals generated thus far.  */
+static GTY(()) int compound_literal_number;
+
+/* Set DECL_NAME for DECL, a VAR_DECL for a compound-literal.  */
+
+void
+set_compound_literal_name (tree decl)
+{
+  char *name;
+  ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
+                          compound_literal_number);
+  compound_literal_number++;
+  DECL_NAME (decl) = get_identifier (name);
+}
+
 tree
 build_va_arg (tree expr, tree type)
 {
@@ -3359,42 +3690,42 @@ builtin_function_disabled_p (const char *name)
 }
 
 
-/* Possibly define a builtin function with one or two names.  BUILTIN_NAME
-   is an __builtin_-prefixed name; NAME is the ordinary name; one or both
-   of these may be NULL (though both being NULL is useless).
-   BUILTIN_TYPE is the type of the __builtin_-prefixed function;
-   TYPE is the type of the function with the ordinary name.  These
-   may differ if the ordinary name is declared with a looser type to avoid
-   conflicts with headers.  FUNCTION_CODE and CL are as for
-   builtin_function.  If LIBRARY_NAME_P is nonzero, NAME is passed as
-   the LIBRARY_NAME parameter to builtin_function when declaring BUILTIN_NAME.
-   If NONANSI_P is true, the name NAME is treated as a non-ANSI name;
-   ATTRS is the tree list representing the builtin's function attributes.
-   Returns the declaration of BUILTIN_NAME, if any, otherwise
-   the declaration of NAME.  Does not declare NAME if flag_no_builtin,
-   or if NONANSI_P and flag_no_nonansi_builtin.  */
+/* Worker for DEF_BUILTIN.
+   Possibly define a builtin function with one or two names.
+   Does not declare a non-__builtin_ function if flag_no_builtin, or if
+   nonansi_p and flag_no_nonansi_builtin.  */
 
-static tree
-builtin_function_2 (const char *builtin_name, const char *name,
-                   tree builtin_type, tree type,
-                   enum built_in_function function_code,
-                   enum built_in_class cl, int library_name_p,
-                   bool nonansi_p, tree attrs)
+static void
+def_builtin_1 (enum built_in_function fncode,
+              const char *name,
+              enum built_in_class fnclass,
+              tree fntype, tree libtype,
+              bool both_p, bool fallback_p, bool nonansi_p,
+              tree fnattrs, bool implicit_p)
 {
-  tree bdecl = NULL_TREE;
-  tree decl = NULL_TREE;
+  tree decl;
+  const char *libname;
+
+  if (fntype == error_mark_node)
+    return;
 
-  if (builtin_name != 0)
-    bdecl = lang_hooks.builtin_function (builtin_name, builtin_type,
-                                        function_code, cl,
-                                        library_name_p ? name : NULL, attrs);
+  gcc_assert ((!both_p && !fallback_p)
+             || !strncmp (name, "__builtin_",
+                          strlen ("__builtin_")));
 
-  if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name)
+  libname = name + strlen ("__builtin_");
+  decl = add_builtin_function (name, fntype, fncode, fnclass,
+                              (fallback_p ? libname : NULL),
+                              fnattrs);
+  if (both_p
+      && !flag_no_builtin && !builtin_function_disabled_p (libname)
       && !(nonansi_p && flag_no_nonansi_builtin))
-    decl = lang_hooks.builtin_function (name, type, function_code, cl,
-                                       NULL, attrs);
+    add_builtin_function (libname, libtype, fncode, fnclass,
+                         NULL, fnattrs);
 
-  return (bdecl != 0 ? bdecl : decl);
+  built_in_decls[(int) fncode] = decl;
+  if (implicit_p)
+    implicit_built_in_decls[(int) fncode] = decl;
 }
 \f
 /* Nonzero if the type T promotes to int.  This is (nearly) the
@@ -3438,6 +3769,9 @@ self_promoting_args_p (tree parms)
     {
       tree type = TREE_VALUE (t);
 
+      if (type == error_mark_node)
+       continue;
+
       if (TREE_CHAIN (t) == 0 && type != void_type_node)
        return 0;
 
@@ -3536,25 +3870,27 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
     {
       low_value = check_case_value (low_value);
       low_value = convert_and_check (type, low_value);
+      if (low_value == error_mark_node)
+       goto error_out;
     }
   if (high_value)
     {
       high_value = check_case_value (high_value);
       high_value = convert_and_check (type, high_value);
+      if (high_value == error_mark_node)
+       goto error_out;
     }
 
-  /* If an error has occurred, bail out now.  */
-  if (low_value == error_mark_node || high_value == error_mark_node)
-    goto error_out;
-
-  /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
-     really a case range, even though it was written that way.  Remove
-     the HIGH_VALUE to simplify later processing.  */
-  if (tree_int_cst_equal (low_value, high_value))
-    high_value = NULL_TREE;
-  if (low_value && high_value
-      && !tree_int_cst_lt (low_value, high_value))
-    warning (0, "empty range specified");
+  if (low_value && high_value)
+    {
+      /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
+        really a case range, even though it was written that way.
+        Remove the HIGH_VALUE to simplify later processing.  */
+      if (tree_int_cst_equal (low_value, high_value))
+       high_value = NULL_TREE;
+      else if (!tree_int_cst_lt (low_value, high_value))
+       warning (0, "empty range specified");
+    }
 
   /* See if the case is in range of the type of the original testing
      expression.  If both low_value and high_value are out of range,
@@ -3680,6 +4016,9 @@ match_case_to_enum_1 (tree key, tree type, tree label)
             CASE_LABEL (label), buf, type);
 }
 
+/* Subroutine of c_do_switch_warnings, called via splay_tree_foreach.
+   Used to verify that case values match up with enumerator values.  */
+
 static int
 match_case_to_enum (splay_tree_node node, void *data)
 {
@@ -3690,26 +4029,22 @@ match_case_to_enum (splay_tree_node node, void *data)
   if (!CASE_LOW (label))
     return 0;
 
-  /* If TREE_ADDRESSABLE is not set, that means CASE_LOW did not appear
+  /* If CASE_LOW_SEEN is not set, that means CASE_LOW did not appear
      when we did our enum->case scan.  Reset our scratch bit after.  */
-  if (!TREE_ADDRESSABLE (label))
+  if (!CASE_LOW_SEEN (label))
     match_case_to_enum_1 (CASE_LOW (label), type, label);
   else
-    TREE_ADDRESSABLE (label) = 0;
+    CASE_LOW_SEEN (label) = 0;
 
-  /* If CASE_HIGH is non-null, we have a range.  Here we must search.
-     Note that the old code in stmt.c did not check for the values in
-     the range either, just the endpoints.  */
+  /* If CASE_HIGH is non-null, we have a range.  If CASE_HIGH_SEEN is
+     not set, that means that CASE_HIGH did not appear when we did our
+     enum->case scan.  Reset our scratch bit after.  */
   if (CASE_HIGH (label))
     {
-      tree chain, key = CASE_HIGH (label);
-
-      for (chain = TYPE_VALUES (type);
-          chain && !tree_int_cst_equal (key, TREE_VALUE (chain));
-          chain = TREE_CHAIN (chain))
-       continue;
-      if (!chain)
-       match_case_to_enum_1 (key, type, label);
+      if (!CASE_HIGH_SEEN (label))
+       match_case_to_enum_1 (CASE_HIGH (label), type, label);
+      else
+       CASE_HIGH_SEEN (label) = 0;
     }
 
   return 0;
@@ -3727,62 +4062,90 @@ c_do_switch_warnings (splay_tree cases, location_t switch_location,
                      tree type, tree cond)
 {
   splay_tree_node default_node;
+  splay_tree_node node;
+  tree chain;
 
   if (!warn_switch && !warn_switch_enum && !warn_switch_default)
     return;
 
   default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
-  if (warn_switch_default && !default_node)
-    warning (0, "%Hswitch missing default case", &switch_location);
+  if (!default_node)
+    warning (OPT_Wswitch_default, "%Hswitch missing default case",
+            &switch_location);
+
+  /* From here on, we only care about about enumerated types.  */
+  if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
+    return;
 
   /* If the switch expression was an enumerated type, check that
      exactly all enumeration literals are covered by the cases.
      The check is made when -Wswitch was specified and there is no
      default case, or when -Wswitch-enum was specified.  */
-  if (((warn_switch && !default_node) || warn_switch_enum)
-      && type && TREE_CODE (type) == ENUMERAL_TYPE
-      && TREE_CODE (cond) != INTEGER_CST)
-    {
-      tree chain;
 
-      /* The time complexity here is O(N*lg(N)) worst case, but for the
-        common case of monotonically increasing enumerators, it is
-        O(N), since the nature of the splay tree will keep the next
-        element adjacent to the root at all times.  */
+  if (!warn_switch_enum
+      && !(warn_switch && !default_node))
+    return;
+
+  /* Clearing COND if it is not an integer constant simplifies
+     the tests inside the loop below.  */
+  if (TREE_CODE (cond) != INTEGER_CST)
+    cond = NULL_TREE;
+
+  /* The time complexity here is O(N*lg(N)) worst case, but for the
+      common case of monotonically increasing enumerators, it is
+      O(N), since the nature of the splay tree will keep the next
+      element adjacent to the root at all times.  */
 
-      for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
+  for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
+    {
+      tree value = TREE_VALUE (chain);
+      node = splay_tree_lookup (cases, (splay_tree_key) value);
+      if (node)
        {
-         splay_tree_node node
-           = splay_tree_lookup (cases, (splay_tree_key) TREE_VALUE (chain));
+         /* Mark the CASE_LOW part of the case entry as seen.  */
+         tree label = (tree) node->value;
+         CASE_LOW_SEEN (label) = 1;
+         continue;
+       }
 
-         if (node)
-           {
-             /* Mark the CASE_LOW part of the case entry as seen, so
-                that we save time later.  Choose TREE_ADDRESSABLE
-                randomly as a bit that won't have been set to-date.  */
-             tree label = (tree) node->value;
-             TREE_ADDRESSABLE (label) = 1;
-           }
-         else
+      /* Even though there wasn't an exact match, there might be a
+        case range which includes the enumator's value.  */
+      node = splay_tree_predecessor (cases, (splay_tree_key) value);
+      if (node && CASE_HIGH ((tree) node->value))
+       {
+         tree label = (tree) node->value;
+         int cmp = tree_int_cst_compare (CASE_HIGH (label), value);
+         if (cmp >= 0)
            {
-             /* Warn if there are enumerators that don't correspond to
-                case expressions.  */
-             warning (0, "%Henumeration value %qE not handled in switch",
-                      &switch_location, TREE_PURPOSE (chain));
+             /* If we match the upper bound exactly, mark the CASE_HIGH
+                part of the case entry as seen.  */
+             if (cmp == 0)
+               CASE_HIGH_SEEN (label) = 1;
+             continue;
            }
        }
 
-      /* Warn if there are case expressions that don't correspond to
-        enumerators.  This can occur since C and C++ don't enforce
-        type-checking of assignments to enumeration variables.
+      /* We've now determined that this enumerated literal isn't
+        handled by the case labels of the switch statement.  */
 
-        The time complexity here is O(N**2) worst case, since we've
-        not sorted the enumeration values.  However, in the absence
-        of case ranges this is O(N), since all single cases that
-        corresponded to enumerations have been marked above.  */
+      /* If the switch expression is a constant, we only really care
+        about whether that constant is handled by the switch.  */
+      if (cond && tree_int_cst_compare (cond, value))
+       continue;
 
-      splay_tree_foreach (cases, match_case_to_enum, type);
+      warning (0, "%Henumeration value %qE not handled in switch",
+              &switch_location, TREE_PURPOSE (chain));
     }
+
+  /* Warn if there are case expressions that don't correspond to
+     enumerators.  This can occur since C and C++ don't enforce
+     type-checking of assignments to enumeration variables.
+
+     The time complexity here is now always O(N) worst case, since
+     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.  */
+  splay_tree_foreach (cases, match_case_to_enum, type);
 }
 
 /* Finish an expression taking the address of LABEL (an
@@ -3939,31 +4302,23 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
        *node = build_variant_type_copy (*node);
       TYPE_PACKED (*node) = 1;
-      if (TYPE_MAIN_VARIANT (*node) == *node)
-       {
-         /* If it is the main variant, then pack the other variants
-            too. This happens in,
-
-            struct Foo {
-              struct Foo const *ptr; // creates a variant w/o packed flag
-              } __ attribute__((packed)); // packs it now.
-         */
-         tree probe;
-
-         for (probe = *node; probe; probe = TYPE_NEXT_VARIANT (probe))
-           TYPE_PACKED (probe) = 1;
-       }
-
     }
   else if (TREE_CODE (*node) == FIELD_DECL)
-    DECL_PACKED (*node) = 1;
+    {
+      if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT)
+       warning (OPT_Wattributes,
+                "%qE attribute ignored for field of type %qT",
+                name, TREE_TYPE (*node));
+      else
+       DECL_PACKED (*node) = 1;
+    }
   /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
      used for DECL_REGISTER.  It wouldn't mean anything anyway.
      We can't set DECL_PACKED on the type of a TYPE_DECL, because
      that changes what the typedef is typing.  */
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -3982,7 +4337,7 @@ handle_nocommon_attribute (tree *node, tree name,
     DECL_COMMON (*node) = 0;
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4000,7 +4355,7 @@ handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     DECL_COMMON (*node) = 1;
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4027,7 +4382,7 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                             TYPE_READONLY (TREE_TYPE (type)), 1));
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4046,7 +4401,7 @@ handle_noinline_attribute (tree *node, tree name,
     DECL_UNINLINABLE (*node) = 1;
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4069,13 +4424,58 @@ handle_always_inline_attribute (tree *node, tree name,
     }
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
   return NULL_TREE;
 }
 
+/* Handle a "gnu_inline" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_gnu_inline_attribute (tree *node, tree name,
+                            tree ARG_UNUSED (args),
+                            int ARG_UNUSED (flags),
+                            bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
+    {
+      /* Do nothing else, just set the attribute.  We'll get at
+        it later with lookup_attribute.  */
+    }
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "flatten" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+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 "used" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -4093,7 +4493,7 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
     }
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4119,7 +4519,7 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
        TREE_USED (decl) = 1;
       else
        {
-         warning (0, "%qE attribute ignored", name);
+         warning (OPT_Wattributes, "%qE attribute ignored", name);
          *no_add_attrs = true;
        }
     }
@@ -4133,6 +4533,36 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   return NULL_TREE;
 }
 
+/* Handle a "externally_visible" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_externally_visible_attribute (tree *pnode, tree name,
+                                    tree ARG_UNUSED (args),
+                                    int ARG_UNUSED (flags),
+                                    bool *no_add_attrs)
+{
+  tree node = *pnode;
+
+  if (TREE_CODE (node) == FUNCTION_DECL || TREE_CODE (node) == VAR_DECL)
+    {
+      if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL
+          && !DECL_EXTERNAL (node)) || !TREE_PUBLIC (node))
+       {
+         warning (OPT_Wattributes,
+                  "%qE attribute have effect only on public objects", name);
+         *no_add_attrs = true;
+       }
+    }
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle a "const" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -4153,7 +4583,7 @@ handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                             TREE_THIS_VOLATILE (TREE_TYPE (type))));
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4168,39 +4598,43 @@ handle_transparent_union_attribute (tree *node, tree name,
                                    tree ARG_UNUSED (args), int flags,
                                    bool *no_add_attrs)
 {
-  tree decl = NULL_TREE;
-  tree *type = NULL;
-  int is_type = 0;
+  tree type = NULL;
+
+  *no_add_attrs = true;
 
   if (DECL_P (*node))
     {
-      decl = *node;
-      type = &TREE_TYPE (decl);
-      is_type = TREE_CODE (*node) == TYPE_DECL;
+      if (TREE_CODE (*node) != TYPE_DECL)
+       goto ignored;
+      node = &TREE_TYPE (*node);
+      type = *node;
     }
   else if (TYPE_P (*node))
-    type = node, is_type = 1;
+    type = *node;
+  else
+    goto ignored;
 
-  if (is_type
-      && TREE_CODE (*type) == UNION_TYPE
-      && (decl == 0
-         || (TYPE_FIELDS (*type) != 0
-             && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
+  if (TREE_CODE (type) == UNION_TYPE)
     {
+      /* When IN_PLACE is set, leave the check for FIELDS and MODE to
+        the code in finish_struct.  */
       if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-       *type = build_variant_type_copy (*type);
-      TYPE_TRANSPARENT_UNION (*type) = 1;
-    }
-  else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
-          && TREE_CODE (*type) == UNION_TYPE
-          && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
-    DECL_TRANSPARENT_UNION (decl) = 1;
-  else
-    {
-      warning (0, "%qE attribute ignored", name);
-      *no_add_attrs = true;
+       {
+         if (TYPE_FIELDS (type) == NULL_TREE
+             || TYPE_MODE (type) != DECL_MODE (TYPE_FIELDS (type)))
+           goto ignored;
+
+         /* A type variant isn't good enough, since we don't a cast
+            to such a type removed as a no-op.  */
+         *node = type = build_duplicate_type (type);
+       }
+
+      TYPE_TRANSPARENT_UNION (type) = 1;
+      return NULL_TREE;
     }
 
+ ignored:
+  warning (OPT_Wattributes, "%qE attribute ignored", name);
   return NULL_TREE;
 }
 
@@ -4225,7 +4659,7 @@ handle_constructor_attribute (tree *node, tree name,
     }
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4253,7 +4687,7 @@ handle_destructor_attribute (tree *node, tree name,
     }
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4272,7 +4706,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
   *no_add_attrs = true;
 
   if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
-    warning (0, "%qE attribute ignored", name);
+    warning (OPT_Wattributes, "%qE attribute ignored", name);
   else
     {
       int j;
@@ -4320,6 +4754,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
        case MODE_INT:
        case MODE_PARTIAL_INT:
        case MODE_FLOAT:
+       case MODE_DECIMAL_FLOAT:
          valid_mode = targetm.scalar_mode_supported_p (mode);
          break;
 
@@ -4330,9 +4765,10 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
        case MODE_VECTOR_INT:
        case MODE_VECTOR_FLOAT:
-         warning (0, "specifying vector types with __attribute__ ((mode)) "
-                  "is deprecated");
-         warning (0, "use __attribute__ ((vector_size)) instead");
+         warning (OPT_Wattributes, "specifying vector types with "
+                  "__attribute__ ((mode)) is deprecated");
+         warning (OPT_Wattributes,
+                  "use __attribute__ ((vector_size)) instead");
          valid_mode = vector_mode_valid_p (mode);
          break;
 
@@ -4355,14 +4791,14 @@ handle_mode_attribute (tree *node, tree name, tree args,
              return NULL_TREE;
            }
 
-          if (TREE_CODE (type) == POINTER_TYPE)
+         if (TREE_CODE (type) == POINTER_TYPE)
            fn = build_pointer_type_for_mode;
          else
            fn = build_reference_type_for_mode;
          typefm = fn (TREE_TYPE (type), mode, false);
        }
       else
-        typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
+       typefm = lang_hooks.types.type_for_mode (mode, TYPE_UNSIGNED (type));
 
       if (typefm == NULL_TREE)
        {
@@ -4380,21 +4816,24 @@ handle_mode_attribute (tree *node, tree name, tree args,
              return NULL_TREE;
            }
 
-         if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-           type = build_variant_type_copy (type);
-
-         /* We cannot use layout_type here, because that will attempt
-            to re-layout all variants, corrupting our original.  */
-         TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
-         TYPE_MIN_VALUE (type) = TYPE_MIN_VALUE (typefm);
-         TYPE_MAX_VALUE (type) = TYPE_MAX_VALUE (typefm);
-         TYPE_SIZE (type) = TYPE_SIZE (typefm);
-         TYPE_SIZE_UNIT (type) = TYPE_SIZE_UNIT (typefm);
-         TYPE_MODE (type) = TYPE_MODE (typefm);
-         if (!TYPE_USER_ALIGN (type))
-           TYPE_ALIGN (type) = TYPE_ALIGN (typefm);
-
-         typefm = type;
+         if (flags & ATTR_FLAG_TYPE_IN_PLACE)
+           {
+             TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
+             typefm = type;
+           }
+         else
+           {
+             /* We cannot build a type variant, as there's code that assumes
+                that TYPE_MAIN_VARIANT has the same mode.  This includes the
+                debug generators.  Instead, create a subrange type.  This
+                results in all of the enumeral values being emitted only once
+                in the original, and the subtype gets them by reference.  */
+             if (TYPE_UNSIGNED (type))
+               typefm = make_unsigned_type (TYPE_PRECISION (typefm));
+             else
+               typefm = make_signed_type (TYPE_PRECISION (typefm));
+             TREE_TYPE (typefm) = type;
+           }
        }
       else if (VECTOR_MODE_P (mode)
               ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
@@ -4442,8 +4881,8 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
                   && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
                              TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
            {
-             error ("%Jsection of %qD conflicts with previous declaration",
-                    *node, *node);
+             error ("section of %q+D conflicts with previous declaration",
+                    *node);
              *no_add_attrs = true;
            }
          else
@@ -4451,7 +4890,7 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
        }
       else
        {
-         error ("%Jsection attribute not allowed for %qD", *node, *node);
+         error ("section attribute not allowed for %q+D", *node);
          *no_add_attrs = true;
        }
     }
@@ -4525,7 +4964,7 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   else if (TREE_CODE (decl) != VAR_DECL
           && TREE_CODE (decl) != FIELD_DECL)
     {
-      error ("%Jalignment may not be specified for %qD", decl, decl);
+      error ("alignment may not be specified for %q+D", decl);
       *no_add_attrs = true;
     }
   else
@@ -4541,12 +4980,17 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
    struct attribute_spec.handler.  */
 
 static tree
-handle_weak_attribute (tree *node, tree ARG_UNUSED (name),
+handle_weak_attribute (tree *node, tree name,
                       tree ARG_UNUSED (args),
                       int ARG_UNUSED (flags),
                       bool * ARG_UNUSED (no_add_attrs))
 {
-  declare_weak (*node);
+  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;
 }
@@ -4561,9 +5005,14 @@ handle_alias_attribute (tree *node, tree name, tree args,
   tree decl = *node;
 
   if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
-      || (TREE_CODE (decl) != FUNCTION_DECL && !DECL_EXTERNAL (decl)))
-    {
-      error ("%J%qD defined both normally and as an alias", decl, decl);
+      || (TREE_CODE (decl) != FUNCTION_DECL 
+         && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
+      /* A static variable declaration is always a tentative definition,
+        but the alias is a non-tentative definition which overrides.  */
+      || (TREE_CODE (decl) != FUNCTION_DECL 
+         && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
+    {
+      error ("%q+D defined both normally and as an alias", decl);
       *no_add_attrs = true;
     }
 
@@ -4591,43 +5040,101 @@ handle_alias_attribute (tree *node, tree name, tree args,
        DECL_INITIAL (decl) = error_mark_node;
       else
        {
-         DECL_EXTERNAL (decl) = 0;
+         if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
+           DECL_EXTERNAL (decl) = 1;
+         else
+           DECL_EXTERNAL (decl) = 0;
          TREE_STATIC (decl) = 1;
        }
     }
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
   return NULL_TREE;
 }
 
+/* Handle a "weakref" attribute; arguments as in struct
+   attribute_spec.handler.  */
+
+static tree
+handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
+                         int flags, bool *no_add_attrs)
+{
+  tree attr = NULL_TREE;
+
+  /* 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)
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+      return NULL_TREE;
+    }
+
+  /* The idea here is that `weakref("name")' mutates into `weakref,
+     alias("name")', and weakref without arguments, in turn,
+     implicitly adds weak. */
+
+  if (args)
+    {
+      attr = tree_cons (get_identifier ("alias"), args, attr);
+      attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr);
+
+      *no_add_attrs = true;
+
+      decl_attributes (node, attr, flags);
+    }
+  else
+    {
+      if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node)))
+       error ("%Jweakref attribute must appear before alias attribute",
+              *node);
+
+      /* Can't call declare_weak because it wants this to be TREE_PUBLIC,
+        and that isn't supported; and because it wants to add it to
+        the list of weak decls, which isn't helpful.  */
+      DECL_WEAK (*node) = 1;
+    }
+
+  return NULL_TREE;
+}
+
 /* Handle an "visibility" attribute; arguments as in
    struct attribute_spec.handler.  */
 
 static tree
 handle_visibility_attribute (tree *node, tree name, tree args,
                             int ARG_UNUSED (flags),
-                            bool *no_add_attrs)
+                            bool *ARG_UNUSED (no_add_attrs))
 {
   tree decl = *node;
   tree id = TREE_VALUE (args);
-
-  *no_add_attrs = true;
+  enum symbol_visibility vis;
 
   if (TYPE_P (*node))
     {
-      if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
-       {
-         warning (0, "%qE attribute ignored on non-class types", name);
-         return NULL_TREE;
-       }
+      if (TREE_CODE (*node) == ENUMERAL_TYPE)
+       /* OK */;
+      else if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
+       {
+         warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
+                  name);
+         return NULL_TREE;
+       }
+      else if (TYPE_FIELDS (*node))
+       {
+         error ("%qE attribute ignored because %qT is already defined",
+                name, *node);
+         return NULL_TREE;
+       }
     }
   else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       return NULL_TREE;
     }
 
@@ -4642,33 +5149,43 @@ handle_visibility_attribute (tree *node, tree name, tree args,
     {
       decl = TYPE_NAME (decl);
       if (!decl)
-        return NULL_TREE;
+       return NULL_TREE;
       if (TREE_CODE (decl) == IDENTIFIER_NODE)
        {
-          warning (0, "%qE attribute ignored on types",
+          warning (OPT_Wattributes, "%qE attribute ignored on types",
                    name);
           return NULL_TREE;
        }
     }
 
   if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
-    DECL_VISIBILITY (decl) = VISIBILITY_DEFAULT;
+    vis = VISIBILITY_DEFAULT;
   else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
-    DECL_VISIBILITY (decl) = VISIBILITY_INTERNAL;
+    vis = VISIBILITY_INTERNAL;
   else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
-    DECL_VISIBILITY (decl) = VISIBILITY_HIDDEN;
+    vis = VISIBILITY_HIDDEN;
   else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
-    DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED;
+    vis = VISIBILITY_PROTECTED;
   else
-    error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+    {
+      error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+      vis = VISIBILITY_DEFAULT;
+    }
+
+  if (DECL_VISIBILITY_SPECIFIED (decl)
+      && vis != DECL_VISIBILITY (decl)
+      && lookup_attribute ("visibility", (TYPE_P (*node)
+                                         ? TYPE_ATTRIBUTES (*node)
+                                         : DECL_ATTRIBUTES (decl))))
+    error ("%qD redeclared with different visibility", decl);
+
+  DECL_VISIBILITY (decl) = vis;
   DECL_VISIBILITY_SPECIFIED (decl) = 1;
 
-  /* For decls only, go ahead and attach the attribute to the node as well.
-     This is needed so we can determine whether we have VISIBILITY_DEFAULT
-     because the visibility was not specified, or because it was explicitly
-     overridden from the class visibility.  */
-  if (DECL_P (*node))
-    *no_add_attrs = false;
+  /* Go ahead and attach the attribute to the node as well.  This is needed
+     so we can determine whether we have VISIBILITY_DEFAULT because the
+     visibility was not specified, or because it was explicitly overridden
+     from the containing scope.  */
 
   return NULL_TREE;
 }
@@ -4705,6 +5222,13 @@ c_determine_visibility (tree decl)
       return true;
     }
 
+  /* Set default visibility to whatever the user supplied with
+     visibility_specified depending on #pragma GCC visibility.  */
+  if (!DECL_VISIBILITY_SPECIFIED (decl))
+    {
+      DECL_VISIBILITY (decl) = default_visibility;
+      DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
+    }
   return false;
 }
 
@@ -4715,35 +5239,38 @@ static tree
 handle_tls_model_attribute (tree *node, tree name, tree args,
                            int ARG_UNUSED (flags), bool *no_add_attrs)
 {
+  tree id;
   tree decl = *node;
+  enum tls_model kind;
 
-  if (!DECL_THREAD_LOCAL (decl))
+  *no_add_attrs = true;
+
+  if (!DECL_THREAD_LOCAL_P (decl))
     {
-      warning (0, "%qE attribute ignored", name);
-      *no_add_attrs = true;
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      return NULL_TREE;
     }
-  else
-    {
-      tree id;
 
-      id = TREE_VALUE (args);
-      if (TREE_CODE (id) != STRING_CST)
-       {
-         error ("tls_model argument not a string");
-         *no_add_attrs = true;
-         return NULL_TREE;
-       }
-      if (strcmp (TREE_STRING_POINTER (id), "local-exec")
-         && strcmp (TREE_STRING_POINTER (id), "initial-exec")
-         && strcmp (TREE_STRING_POINTER (id), "local-dynamic")
-         && strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
-       {
-         error ("tls_model argument must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
-         *no_add_attrs = true;
-         return NULL_TREE;
-       }
+  kind = DECL_TLS_MODEL (decl);
+  id = TREE_VALUE (args);
+  if (TREE_CODE (id) != STRING_CST)
+    {
+      error ("tls_model argument not a string");
+      return NULL_TREE;
     }
 
+  if (!strcmp (TREE_STRING_POINTER (id), "local-exec"))
+    kind = TLS_MODEL_LOCAL_EXEC;
+  else if (!strcmp (TREE_STRING_POINTER (id), "initial-exec"))
+    kind = TLS_MODEL_INITIAL_EXEC;
+  else if (!strcmp (TREE_STRING_POINTER (id), "local-dynamic"))
+    kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC;
+  else if (!strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
+    kind = TLS_MODEL_GLOBAL_DYNAMIC;
+  else
+    error ("tls_model argument must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
+
+  DECL_TLS_MODEL (decl) = kind;
   return NULL_TREE;
 }
 
@@ -4786,7 +5313,7 @@ handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     DECL_IS_MALLOC (*node) = 1;
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4804,7 +5331,7 @@ handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     DECL_IS_RETURNS_TWICE (*node) = 1;
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4850,7 +5377,7 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   /* ??? TODO: Support types.  */
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4918,9 +5445,9 @@ handle_deprecated_attribute (tree *node, tree name,
            what = DECL_NAME (TYPE_NAME (type));
        }
       if (what)
-       warning (0, "%qE attribute ignored for %qE", name, what);
+       warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
       else
-       warning (0, "%qE attribute ignored", name);
+       warning (OPT_Wattributes, "%qE attribute ignored", name);
     }
 
   return NULL_TREE;
@@ -4944,7 +5471,7 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
 
   if (!host_integerp (size, 1))
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       return NULL_TREE;
     }
 
@@ -4969,7 +5496,9 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
   orig_mode = TYPE_MODE (type);
 
   if (TREE_CODE (type) == RECORD_TYPE
-      || (GET_MODE_CLASS (orig_mode) != MODE_FLOAT
+      || TREE_CODE (type) == UNION_TYPE
+      || TREE_CODE (type) == VECTOR_TYPE
+      || (!SCALAR_FLOAT_MODE_P (orig_mode)
          && GET_MODE_CLASS (orig_mode) != MODE_INT)
       || !host_integerp (TYPE_SIZE_UNIT (type), 1))
     {
@@ -4977,6 +5506,18 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
       return NULL_TREE;
     }
 
+  if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1))
+    {
+      error ("vector size not an integral multiple of component size");
+      return NULL;
+    }
+
+  if (vecsize == 0)
+    {
+      error ("zero vector size");
+      return NULL;
+    }
+
   /* Calculate how many units fit in the vector.  */
   nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
   if (nunits & (nunits - 1))
@@ -5085,11 +5626,11 @@ check_function_nonnull (tree attrs, tree params)
               param_num++, param = TREE_CHAIN (param))
            {
              if (!param)
-       break;
+               break;
              if (!args || nonnull_check_p (args, param_num))
-       check_function_arguments_recurse (check_nonnull_arg, NULL,
-                                         TREE_VALUE (param),
-                                         param_num);
+               check_function_arguments_recurse (check_nonnull_arg, NULL,
+                                                 TREE_VALUE (param),
+                                                 param_num);
            }
        }
     }
@@ -5099,19 +5640,27 @@ check_function_nonnull (tree attrs, tree params)
    from the end) is a (pointer)0.  */
 
 static void
-check_function_sentinel (tree attrs, tree params)
+check_function_sentinel (tree attrs, tree params, tree typelist)
 {
   tree attr = lookup_attribute ("sentinel", attrs);
 
   if (attr)
     {
-      if (!params)
-       warning (0, "missing sentinel in function call");
+      /* Skip over the named arguments.  */
+      while (typelist && params)
+      {
+       typelist = TREE_CHAIN (typelist);
+       params = TREE_CHAIN (params);
+      }
+
+      if (typelist || !params)
+       warning (OPT_Wformat,
+                "not enough variable arguments to fit a sentinel");
       else
-        {
+       {
          tree sentinel, end;
          unsigned pos = 0;
-         
+
          if (TREE_VALUE (attr))
            {
              tree p = TREE_VALUE (TREE_VALUE (attr));
@@ -5128,7 +5677,8 @@ check_function_sentinel (tree attrs, tree params)
            }
          if (pos > 0)
            {
-             warning (0, "not enough arguments to fit a sentinel");
+             warning (OPT_Wformat,
+                      "not enough variable arguments to fit a sentinel");
              return;
            }
 
@@ -5147,9 +5697,9 @@ check_function_sentinel (tree attrs, tree params)
                 as wide as a pointer, and we don't want to force
                 users to cast the NULL they have written there.
                 We warn with -Wstrict-null-sentinel, though.  */
-              && (warn_strict_null_sentinel
+             && (warn_strict_null_sentinel
                  || null_node != TREE_VALUE (sentinel)))
-           warning (0, "missing sentinel in function call");
+           warning (OPT_Wformat, "missing sentinel in function call");
        }
     }
 }
@@ -5191,8 +5741,8 @@ check_nonnull_arg (void * ARG_UNUSED (ctx), tree param,
     return;
 
   if (integer_zerop (param))
-    warning (0, "null argument where non-null required (argument %lu)",
-            (unsigned long) param_num);
+    warning (OPT_Wnonnull, "null argument where non-null required "
+            "(argument %lu)", (unsigned long) param_num);
 }
 
 /* Helper for nonnull attribute handling; fetch the operand number
@@ -5222,7 +5772,7 @@ handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   /* ??? TODO: Support types.  */
   else
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -5245,7 +5795,7 @@ handle_cleanup_attribute (tree *node, tree name, tree args,
      we'd be missing too much, since we do have attribute constructor.  */
   if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -5284,7 +5834,7 @@ handle_warn_unused_result_attribute (tree *node, tree name,
   /* Ignore the attribute for functions not returning any value.  */
   if (VOID_TYPE_P (TREE_TYPE (*node)))
     {
-      warning (0, "%qE attribute ignored", name);
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -5301,7 +5851,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
 
   if (!params)
     {
-      warning (0, "%qE attribute requires prototypes with named arguments", name);
+      warning (OPT_Wattributes,
+              "%qE attribute requires prototypes with named arguments", name);
       *no_add_attrs = true;
     }
   else
@@ -5310,23 +5861,24 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
        params = TREE_CHAIN (params);
 
       if (VOID_TYPE_P (TREE_VALUE (params)))
-        {
-         warning (0, "%qE attribute only applies to variadic functions", name);
+       {
+         warning (OPT_Wattributes,
+                  "%qE attribute only applies to variadic functions", name);
          *no_add_attrs = true;
        }
     }
-  
+
   if (args)
     {
       tree position = TREE_VALUE (args);
 
       if (TREE_CODE (position) != INTEGER_CST)
-        {
+       {
          warning (0, "requested position is not an integer constant");
          *no_add_attrs = true;
        }
       else
-        {
+       {
          if (tree_int_cst_lt (position, integer_zero_node))
            {
              warning (0, "requested position is less than zero");
@@ -5334,13 +5886,13 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
            }
        }
     }
-  
+
   return NULL_TREE;
 }
 \f
 /* Check for valid arguments being passed to a function.  */
 void
-check_function_arguments (tree attrs, tree params)
+check_function_arguments (tree attrs, tree params, tree typelist)
 {
   /* Check for null being passed in a pointer argument that must be
      non-null.  We also need to do this if format checking is enabled.  */
@@ -5350,11 +5902,11 @@ check_function_arguments (tree attrs, tree params)
 
   /* Check for errors in format strings.  */
 
-  if (warn_format)
-    {
+  if (warn_format || warn_missing_format_attribute)
       check_function_format (attrs, params);
-      check_function_sentinel (attrs, params);
-    }
+
+  if (warn_format)
+    check_function_sentinel (attrs, params, typelist);
 }
 
 /* Generic argument checking recursion routine.  PARAM is the argument to
@@ -5366,7 +5918,9 @@ check_function_arguments_recurse (void (*callback)
                                  void *ctx, tree param,
                                  unsigned HOST_WIDE_INT param_num)
 {
-  if (TREE_CODE (param) == NOP_EXPR)
+  if ((TREE_CODE (param) == NOP_EXPR || TREE_CODE (param) == CONVERT_EXPR)
+      && (TYPE_PRECISION (TREE_TYPE (param))
+         == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (param, 0)))))
     {
       /* Strip coercion.  */
       check_function_arguments_recurse (callback, ctx,
@@ -5520,58 +6074,62 @@ catenate_strings (const char *lhs, const char *rhs_start, int rhs_size)
   return result;
 }
 
-/* Issue the error given by MSGID, indicating that it occurred before
+/* Issue the error given by GMSGID, indicating that it occurred before
    TOKEN, which had the associated VALUE.  */
 
 void
-c_parse_error (const char *msgid, enum cpp_ttype token, tree value)
+c_parse_error (const char *gmsgid, enum cpp_ttype token, tree value)
 {
 #define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
 
   char *message = NULL;
 
   if (token == CPP_EOF)
-    message = catenate_messages (msgid, " at end of input");
+    message = catenate_messages (gmsgid, " at end of input");
   else if (token == CPP_CHAR || token == CPP_WCHAR)
     {
       unsigned int val = TREE_INT_CST_LOW (value);
       const char *const ell = (token == CPP_CHAR) ? "" : "L";
       if (val <= UCHAR_MAX && ISGRAPH (val))
-        message = catenate_messages (msgid, " before %s'%c'");
+       message = catenate_messages (gmsgid, " before %s'%c'");
       else
-        message = catenate_messages (msgid, " before %s'\\x%x'");
+       message = catenate_messages (gmsgid, " before %s'\\x%x'");
 
       error (message, ell, val);
       free (message);
       message = NULL;
     }
   else if (token == CPP_STRING || token == CPP_WSTRING)
-    message = catenate_messages (msgid, " before string constant");
+    message = catenate_messages (gmsgid, " before string constant");
   else if (token == CPP_NUMBER)
-    message = catenate_messages (msgid, " before numeric constant");
+    message = catenate_messages (gmsgid, " before numeric constant");
   else if (token == CPP_NAME)
     {
-      message = catenate_messages (msgid, " before %qE");
+      message = catenate_messages (gmsgid, " before %qE");
       error (message, value);
       free (message);
       message = NULL;
     }
+  else if (token == CPP_PRAGMA)
+    message = catenate_messages (gmsgid, " before %<#pragma%>");
+  else if (token == CPP_PRAGMA_EOL)
+    message = catenate_messages (gmsgid, " before end of line");
   else if (token < N_TTYPES)
     {
-      message = catenate_messages (msgid, " before %qs token");
+      message = catenate_messages (gmsgid, " before %qs token");
       error (message, cpp_type2name (token));
       free (message);
       message = NULL;
     }
   else
-    error (msgid);
+    error (gmsgid);
 
   if (message)
     {
       error (message);
       free (message);
     }
-#undef catenate_messages  
+#undef catenate_messages
 }
 
 /* Walk a gimplified function and warn for functions whose return value is
@@ -5669,26 +6227,44 @@ c_common_to_target_charset (HOST_WIDE_INT c)
 }
 
 /* Build the result of __builtin_offsetof.  EXPR is a nested sequence of
-   component references, with an INDIRECT_REF at the bottom; much like
-   the traditional rendering of offsetof as a macro.  Returns the folded
-   and properly cast result.  */
+   component references, with STOP_REF, or alternatively an INDIRECT_REF of
+   NULL, at the bottom; much like the traditional rendering of offsetof as a
+   macro.  Returns the folded and properly cast result.  */
 
 static tree
-fold_offsetof_1 (tree expr)
+fold_offsetof_1 (tree expr, tree stop_ref)
 {
   enum tree_code code = PLUS_EXPR;
   tree base, off, t;
 
+  if (expr == stop_ref && TREE_CODE (expr) != ERROR_MARK)
+    return size_zero_node;
+
   switch (TREE_CODE (expr))
     {
     case ERROR_MARK:
       return expr;
 
-    case INDIRECT_REF:
+    case VAR_DECL:
+      error ("cannot apply %<offsetof%> to static data member %qD", expr);
+      return error_mark_node;
+
+    case CALL_EXPR:
+      error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
+      return error_mark_node;
+
+    case INTEGER_CST:
+      gcc_assert (integer_zerop (expr));
       return size_zero_node;
 
+    case NOP_EXPR:
+    case INDIRECT_REF:
+      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
+      gcc_assert (base == error_mark_node || base == size_zero_node);
+      return base;
+
     case COMPONENT_REF:
-      base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
+      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
       if (base == error_mark_node)
        return base;
 
@@ -5705,7 +6281,7 @@ fold_offsetof_1 (tree expr)
       break;
 
     case ARRAY_REF:
-      base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
+      base = fold_offsetof_1 (TREE_OPERAND (expr, 0), stop_ref);
       if (base == error_mark_node)
        return base;
 
@@ -5713,7 +6289,7 @@ fold_offsetof_1 (tree expr)
       if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) < 0)
        {
          code = MINUS_EXPR;
-         t = fold (build1 (NEGATE_EXPR, TREE_TYPE (t), t));
+         t = fold_build1 (NEGATE_EXPR, TREE_TYPE (t), t);
        }
       t = convert (sizetype, t);
       off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
@@ -5727,10 +6303,10 @@ fold_offsetof_1 (tree expr)
 }
 
 tree
-fold_offsetof (tree expr)
+fold_offsetof (tree expr, tree stop_ref)
 {
   /* Convert back from the internal sizetype to size_t.  */
-  return convert (size_type_node, fold_offsetof_1 (expr));
+  return convert (size_type_node, fold_offsetof_1 (expr, stop_ref));
 }
 
 /* Print an error message for an invalid lvalue.  USE says
@@ -5742,19 +6318,19 @@ lvalue_error (enum lvalue_use use)
   switch (use)
     {
     case lv_assign:
-      error ("invalid lvalue in assignment");
+      error ("lvalue required as left operand of assignment");
       break;
     case lv_increment:
-      error ("invalid lvalue in increment");
+      error ("lvalue required as increment operand");
       break;
     case lv_decrement:
-      error ("invalid lvalue in decrement");
+      error ("lvalue required as decrement operand");
       break;
     case lv_addressof:
-      error ("invalid lvalue in unary %<&%>");
+      error ("lvalue required as unary %<&%> operand");
       break;
     case lv_asm:
-      error ("invalid lvalue in asm statement");
+      error ("lvalue required in asm statement");
       break;
     default:
       gcc_unreachable ();
@@ -5771,6 +6347,7 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
 {
   tree maxindex, type, main_type, elt, unqual_elt;
   int failure = 0, quals;
+  hashval_t hashcode = 0;
 
   maxindex = size_zero_node;
   if (initial_value)
@@ -5783,9 +6360,9 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
        }
       else if (TREE_CODE (initial_value) == CONSTRUCTOR)
        {
-         tree elts = CONSTRUCTOR_ELTS (initial_value);
+         VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value);
 
-         if (elts == NULL)
+         if (VEC_empty (constructor_elt, v))
            {
              if (pedantic)
                failure = 3;
@@ -5794,15 +6371,21 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
          else
            {
              tree curindex;
+             unsigned HOST_WIDE_INT cnt;
+             constructor_elt *ce;
 
-             if (TREE_PURPOSE (elts))
-               maxindex = fold_convert (sizetype, TREE_PURPOSE (elts));
+             if (VEC_index (constructor_elt, v, 0)->index)
+               maxindex = fold_convert (sizetype,
+                                        VEC_index (constructor_elt,
+                                                   v, 0)->index);
              curindex = maxindex;
 
-             for (elts = TREE_CHAIN (elts); elts; elts = TREE_CHAIN (elts))
+             for (cnt = 1;
+                  VEC_iterate (constructor_elt, v, cnt, ce);
+                  cnt++)
                {
-                 if (TREE_PURPOSE (elts))
-                   curindex = fold_convert (sizetype, TREE_PURPOSE (elts));
+                 if (ce->index)
+                   curindex = fold_convert (sizetype, ce->index);
                  else
                    curindex = size_binop (PLUS_EXPR, curindex, size_one_node);
 
@@ -5841,6 +6424,12 @@ complete_array_type (tree *ptype, tree initial_value, bool do_default)
   TYPE_DOMAIN (main_type) = build_index_type (maxindex);
   layout_type (main_type);
 
+  /* Make sure we have the canonical MAIN_TYPE. */
+  hashcode = iterative_hash_object (TYPE_HASH (unqual_elt), hashcode);
+  hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (main_type)), 
+                                   hashcode);
+  main_type = type_hash_canon (hashcode, main_type);
+
   if (quals == 0)
     type = main_type;
   else
@@ -5889,7 +6478,7 @@ sync_resolve_size (tree function, tree params)
     goto incompatible;
 
   size = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
-  if (size == 1 || size == 2 || size == 4 || size == 8)
+  if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
     return size;
 
  incompatible:
@@ -5897,7 +6486,7 @@ sync_resolve_size (tree function, tree params)
   return 0;
 }
 
-/* A helper function for resolve_overloaded_builtin.  Adds casts to 
+/* A helper function for resolve_overloaded_builtin.  Adds casts to
    PARAMS to make arguments match up with those of FUNCTION.  Drops
    the variadic arguments at the end.  Returns false if some error
    was encountered; true on success.  */
@@ -5950,7 +6539,7 @@ sync_resolve_params (tree orig_function, tree function, tree params)
   return true;
 }
 
-/* A helper function for resolve_overloaded_builtin.  Adds a cast to 
+/* A helper function for resolve_overloaded_builtin.  Adds a cast to
    RESULT to make it match the type of the first pointer argument in
    PARAMS.  */
 
@@ -5958,6 +6547,7 @@ static tree
 sync_resolve_return (tree params, tree result)
 {
   tree ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+  ptype = TYPE_MAIN_VARIANT (ptype);
   return convert (ptype, result);
 }
 
@@ -5980,13 +6570,13 @@ resolve_overloaded_builtin (tree function, tree params)
       break;
     case BUILT_IN_MD:
       if (targetm.resolve_overloaded_builtin)
-        return targetm.resolve_overloaded_builtin (function, params);
+       return targetm.resolve_overloaded_builtin (function, params);
       else
-        return NULL_TREE;
+       return NULL_TREE;
     default:
       return NULL_TREE;
     }
-    
+
   /* Handle BUILT_IN_NORMAL here.  */
   switch (orig_code)
     {
@@ -6030,4 +6620,156 @@ resolve_overloaded_builtin (tree function, tree params)
     }
 }
 
+/* Ignoring their sign, return true if two scalar types are the same.  */
+bool
+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));
+
+  /* Equality works here because c_common_signed_type uses
+     TYPE_MAIN_VARIANT.  */
+  return lang_hooks.types.signed_type (t1)
+    == lang_hooks.types.signed_type (t2);
+}
+
+/* Check for missing format attributes on function pointers.  LTYPE is
+   the new type or left-hand side type.  RTYPE is the old type or
+   right-hand side type.  Returns TRUE if LTYPE is missing the desired
+   attribute.  */
+
+bool
+check_missing_format_attribute (tree ltype, tree rtype)
+{
+  tree const ttr = TREE_TYPE (rtype), ttl = TREE_TYPE (ltype);
+  tree ra;
+
+  for (ra = TYPE_ATTRIBUTES (ttr); ra; ra = TREE_CHAIN (ra))
+    if (is_attribute_p ("format", TREE_PURPOSE (ra)))
+      break;
+  if (ra)
+    {
+      tree la;
+      for (la = TYPE_ATTRIBUTES (ttl); la; la = TREE_CHAIN (la))
+       if (is_attribute_p ("format", TREE_PURPOSE (la)))
+         break;
+      return !la;
+    }
+  else
+    return false;
+}
+
+/* Subscripting with type char is likely to lose on a machine where
+   chars are signed.  So warn on any machine, but optionally.  Don't
+   warn for unsigned char since that type is safe.  Don't warn for
+   signed char because anyone who uses that must have done so
+   deliberately. Furthermore, we reduce the false positive load by
+   warning only for non-constant value of type char.  */
+
+void
+warn_array_subscript_with_type_char (tree index)
+{
+  if (TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node
+      && TREE_CODE (index) != INTEGER_CST)
+    warning (OPT_Wchar_subscripts, "array subscript has type %<char%>");
+}
+
+/* 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.  */
+
+void
+warn_about_parentheses (enum tree_code code, enum tree_code code_left,
+                       enum tree_code code_right)
+{
+  if (!warn_parentheses)
+    return;
+
+  if (code == LSHIFT_EXPR || code == RSHIFT_EXPR)
+    {
+      if (code_left == PLUS_EXPR || code_left == MINUS_EXPR
+         || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around + or - inside shift");
+    }
+
+  if (code == TRUTH_ORIF_EXPR)
+    {
+      if (code_left == TRUTH_ANDIF_EXPR
+         || code_right == TRUTH_ANDIF_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around && within ||");
+    }
+
+  if (code == 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 |");
+      /* Check cases like x|y==z */
+      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 |");
+    }
+
+  if (code == 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 ^");
+      /* Check cases like x^y==z */
+      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 ^");
+    }
+
+  if (code == BIT_AND_EXPR)
+    {
+      if (code_left == PLUS_EXPR || code_left == MINUS_EXPR
+         || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
+       warning (OPT_Wparentheses,
+                "suggest parentheses around + or - in operand of &");
+      /* Check cases like x&y==z */
+      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 &");
+    }
+
+  /* Similarly, check for cases like 1<=i<=10 that are probably errors.  */
+  if (TREE_CODE_CLASS (code) == tcc_comparison
+      && (TREE_CODE_CLASS (code_left) == tcc_comparison
+         || TREE_CODE_CLASS (code_right) == tcc_comparison))
+    warning (OPT_Wparentheses, "comparisons like X<=Y<=Z do not "
+            "have their mathematical meaning");
+}
+
+/* If LABEL (a LABEL_DECL) has not been used, issue a warning.  */
+
+void
+warn_for_unused_label (tree label)
+{
+  if (!TREE_USED (label))
+    {
+      if (DECL_INITIAL (label))
+       warning (OPT_Wunused_label, "label %q+D defined but not used", label);
+      else
+        warning (OPT_Wunused_label, "label %q+D declared but not defined", label);
+    }
+}
+
 #include "gt-c-common.h"