OSDN Git Service

2005-08-09 Richard Guenther <rguenther@suse.de>
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index c05779c..0b208fd 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 Free Software Foundation, Inc.
+   2001, 2002, 2003, 2004, 2005 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"
@@ -46,6 +46,8 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "hashtab.h"
 #include "tree-mudflap.h"
 #include "opts.h"
+#include "real.h"
+#include "cgraph.h"
 
 cpp_reader *parse_in;          /* Declared in c-pragma.h.  */
 
@@ -190,11 +192,6 @@ cpp_reader *parse_in;              /* Declared in c-pragma.h.  */
 */
 
 tree c_global_trees[CTI_MAX];
-
-/* TRUE if a code represents a statement.  The front end init
-   langhook should take care of initialization of this array.  */
-
-bool statement_code_p[MAX_TREE_CODES];
 \f
 /* Switches common to the C front ends.  */
 
@@ -268,7 +265,6 @@ int flag_const_strings;
 /* Nonzero means to treat bitfields as signed unless they say `unsigned'.  */
 
 int flag_signed_bitfields = 1;
-int explicit_flag_signed_bitfields;
 
 /* Nonzero means warn about deprecated conversion from string constant to
    `char *'.  */
@@ -284,18 +280,17 @@ int warn_unknown_pragmas; /* Tri state variable.  */
 
 int warn_format;
 
+/* Warn about using __null (as NULL in C++) as sentinel.  For code compiled
+   with GCC this doesn't matter as __null is guaranteed to have the right
+   size.  */
+
+int warn_strict_null_sentinel;
+
 /* Zero means that faster, ...NonNil variants of objc_msgSend...
    calls will be used in ObjC; passing nil receivers to such calls
    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.  */
@@ -339,14 +334,6 @@ 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.  */
@@ -482,14 +469,6 @@ tree *ridpointers;
 
 tree (*make_fname_decl) (tree, int);
 
-/* If non-NULL, the address of a language-specific function that
-   returns 1 for language-specific statement codes.  */
-int (*lang_statement_code_p) (enum tree_code);
-
-/* If non-NULL, the address of a language-specific function that takes
-   any action required right before expand_function_end is called.  */
-void (*lang_expand_function_end) (void);
-
 /* Nonzero means the expression being parsed will never be evaluated.
    This is a count, since unevaluated expressions can nest.  */
 int skip_evaluation;
@@ -526,8 +505,11 @@ 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_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 *);
@@ -545,9 +527,11 @@ static tree handle_tls_model_attribute (tree *, tree, tree, int,
 static tree handle_no_instrument_function_attribute (tree *, tree,
                                                     tree, int, bool *);
 static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
+static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
 static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
                                             bool *);
 static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
+static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
 static tree handle_deprecated_attribute (tree *, tree, tree, int,
                                         bool *);
 static tree handle_vector_size_attribute (tree *, tree, tree, int,
@@ -588,10 +572,14 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_noinline_attribute },
   { "always_inline",          0, 0, true,  false, false,
                              handle_always_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 },
@@ -615,10 +603,16 @@ const struct attribute_spec c_common_attribute_table[] =
                              handle_no_instrument_function_attribute },
   { "malloc",                 0, 0, true,  false, false,
                              handle_malloc_attribute },
+  { "returns_twice",          0, 0, true,  false, false,
+                             handle_returns_twice_attribute },
   { "no_stack_limit",         0, 0, true,  false, false,
                              handle_no_limit_stack_attribute },
   { "pure",                   0, 0, true,  false, false,
                              handle_pure_attribute },
+  /* For internal use (marking of builtins) only.  The name contains space
+     to prevent its usage in source code.  */
+  { "no vops",                0, 0, true,  false, false,
+                             handle_novops_attribute },
   { "deprecated",             0, 0, false, false, false,
                              handle_deprecated_attribute },
   { "vector_size",           1, 1, false, true, false,
@@ -755,7 +749,10 @@ fname_as_string (int pretty_p)
       strname.len = len - 1;
 
       if (cpp_interpret_string (parse_in, &strname, 1, &cstr, false))
-       return (char *) cstr.text;
+       {
+         XDELETEVEC (namep);
+         return (char *) cstr.text;
+       }
     }
   else
     namep = xstrdup (name);
@@ -828,7 +825,7 @@ fname_decl (unsigned int rid, tree id)
       input_location = saved_location;
     }
   if (!ix && !current_function_decl)
-    pedwarn ("%J%qD is not defined outside of function scope", decl, decl);
+    pedwarn ("%qD is not defined outside of function scope", decl);
 
   return decl;
 }
@@ -867,12 +864,7 @@ fix_string_type (tree value)
   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)
-    {
-      /* bleah, c_build_qualified_type should set TYPE_MAIN_VARIANT.  */
-      tree qa_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST);
-      TYPE_MAIN_VARIANT (qa_type) = a_type;
-      a_type = qa_type;
-    }
+    a_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST);
 
   TREE_TYPE (value) = a_type;
   TREE_CONSTANT (value) = 1;
@@ -915,7 +907,7 @@ overflow_warning (tree value)
     {
       TREE_OVERFLOW (value) = 0;
       if (skip_evaluation == 0)
-       warning ("integer overflow in expression");
+       warning (0, "integer overflow in expression");
     }
   else if ((TREE_CODE (value) == REAL_CST
            || (TREE_CODE (value) == COMPLEX_CST
@@ -924,13 +916,13 @@ overflow_warning (tree value)
     {
       TREE_OVERFLOW (value) = 0;
       if (skip_evaluation == 0)
-       warning ("floating point overflow in expression");
+       warning (0, "floating point overflow in expression");
     }
   else if (TREE_CODE (value) == VECTOR_CST && TREE_OVERFLOW (value))
     {
       TREE_OVERFLOW (value) = 0;
       if (skip_evaluation == 0)
-       warning ("vector overflow in expression");
+       warning (0, "vector overflow in expression");
     }
 }
 
@@ -952,9 +944,10 @@ unsigned_conversion_warning (tree result, tree operand)
     {
       if (!int_fits_type_p (operand, c_common_signed_type (type)))
        /* This detects cases like converting -129 or 256 to unsigned char.  */
-       warning ("large integer implicitly truncated to unsigned type");
-      else if (warn_conversion)
-       warning ("negative integer implicitly converted to unsigned type");
+       warning (0, "large integer implicitly truncated to unsigned type");
+      else
+       warning (OPT_Wconversion,
+                "negative integer implicitly converted to unsigned type");
     }
 }
 
@@ -1012,7 +1005,7 @@ convert_and_check (tree type, tree expr)
                 || !constant_fits_type_p (expr,
                                           c_common_unsigned_type (type)))
                && skip_evaluation == 0)
-             warning ("overflow in implicit constant conversion");
+             warning (0, "overflow in implicit constant conversion");
        }
       else
        unsigned_conversion_warning (t, expr);
@@ -1148,8 +1141,7 @@ warn_for_collisions_1 (tree written, tree writer, struct tlist *list,
          && DECL_NAME (list->expr))
        {
          warned_ids = new_tlist (warned_ids, written, NULL_TREE);
-         warning ("operation on %qs may be undefined",
-                  IDENTIFIER_POINTER (DECL_NAME (list->expr)));
+         warning (0, "operation on %qE may be undefined", list->expr);
        }
       list = list->next;
     }
@@ -1365,8 +1357,6 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
         Other non-expressions need not be processed.  */
       if (cl == tcc_unary)
        {
-         if (first_rtl_op (code) == 0)
-           return;
          x = TREE_OPERAND (x, 0);
          writer = 0;
          goto restart;
@@ -1374,7 +1364,7 @@ verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
       else if (IS_EXPR_CODE_CLASS (cl))
        {
          int lp;
-         int max = first_rtl_op (TREE_CODE (x));
+         int max = TREE_CODE_LENGTH (TREE_CODE (x));
          for (lp = 0; lp < max; lp++)
            {
              tmp_before = tmp_nosp = 0;
@@ -1416,7 +1406,8 @@ check_case_value (tree value)
   if (value == NULL_TREE)
     return value;
 
-  /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
+  /* ??? Can we ever get nops here for a valid case value?  We
+     shouldn't for C.  */
   STRIP_TYPE_NOPS (value);
   /* In C++, the following is allowed:
 
@@ -1431,15 +1422,14 @@ check_case_value (tree value)
       value = fold (value);
     }
 
-  if (TREE_CODE (value) != INTEGER_CST
-      && value != error_mark_node)
+  if (TREE_CODE (value) == INTEGER_CST)
+    /* Promote char or short to int.  */
+    value = perform_integral_promotions (value);
+  else if (value != error_mark_node)
     {
       error ("case label does not reduce to an integer constant");
       value = error_mark_node;
     }
-  else
-    /* Promote char or short to int.  */
-    value = default_conversion (value);
 
   constant_expression_warning (value);
 
@@ -1455,7 +1445,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
@@ -1477,7 +1467,7 @@ check_case_bounds (tree type, tree orig_type,
   if (tree_int_cst_compare (case_low, min_value) < 0
       && tree_int_cst_compare (case_high, min_value) < 0)
     {
-      warning ("case label value is less than minimum value for type");
+      warning (0, "case label value is less than minimum value for type");
       return false;
     }
 
@@ -1485,7 +1475,7 @@ check_case_bounds (tree type, tree orig_type,
   if (tree_int_cst_compare (case_low, max_value) > 0
       && tree_int_cst_compare (case_high, max_value) > 0)
     {
-      warning ("case label value exceeds maximum value for type");
+      warning (0, "case label value exceeds maximum value for type");
       return false;
     }
 
@@ -1493,7 +1483,7 @@ check_case_bounds (tree type, tree orig_type,
   if (tree_int_cst_compare (case_high, min_value) >= 0
       && tree_int_cst_compare (case_low, min_value) < 0)
     {
-      warning ("lower value in case label range"
+      warning (0, "lower value in case label range"
               " less than minimum value for type");
       case_low = min_value;
     }
@@ -1502,7 +1492,7 @@ check_case_bounds (tree type, tree orig_type,
   if (tree_int_cst_compare (case_low, max_value) <= 0
       && tree_int_cst_compare (case_high, max_value) > 0)
     {
-      warning ("upper value in case label range"
+      warning (0, "upper value in case label range"
               " exceeds maximum value for type");
       case_high = max_value;
     }
@@ -1618,12 +1608,36 @@ c_common_type_for_mode (enum machine_mode mode, int unsignedp)
     return void_type_node;
 
   if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
-    return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
+    return (unsignedp
+           ? make_unsigned_type (GET_MODE_PRECISION (mode))
+           : make_signed_type (GET_MODE_PRECISION (mode)));
 
   if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
-    return unsignedp ? make_unsigned_type (mode) : make_signed_type (mode);
+    return (unsignedp
+           ? make_unsigned_type (GET_MODE_PRECISION (mode))
+           : make_signed_type (GET_MODE_PRECISION (mode)));
+
+  if (COMPLEX_MODE_P (mode))
+    {
+      enum machine_mode inner_mode;
+      tree inner_type;
+
+      if (mode == TYPE_MODE (complex_float_type_node))
+       return complex_float_type_node;
+      if (mode == TYPE_MODE (complex_double_type_node))
+       return complex_double_type_node;
+      if (mode == TYPE_MODE (complex_long_double_type_node))
+       return complex_long_double_type_node;
 
-  if (VECTOR_MODE_P (mode))
+      if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
+       return complex_integer_type_node;
+
+      inner_mode = GET_MODE_INNER (mode);
+      inner_type = c_common_type_for_mode (inner_mode, unsignedp);
+      if (inner_type != NULL_TREE)
+       return build_complex_type (inner_type);
+    }
+  else if (VECTOR_MODE_P (mode))
     {
       enum machine_mode inner_mode = GET_MODE_INNER (mode);
       tree inner_type = c_common_type_for_mode (inner_mode, unsignedp);
@@ -1793,7 +1807,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.  */
@@ -1863,11 +1877,8 @@ binary_op_error (enum tree_code code)
       opname = "||"; break;
     case BIT_XOR_EXPR:
       opname = "^"; break;
-    case LROTATE_EXPR:
-    case RROTATE_EXPR:
-      opname = "rotate"; break;
     default:
-      opname = "unknown"; break;
+      gcc_unreachable ();
     }
   error ("invalid operands to binary %s", opname);
 }
@@ -1988,14 +1999,6 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
       type = c_common_signed_or_unsigned_type (unsignedp0,
                                               TREE_TYPE (primop0));
 
-      /* In C, if TYPE is an enumeration, then we need to get its
-        min/max values from its underlying integral type, not the
-        enumerated type itself.  In C++, TYPE_MAX_VALUE and
-        TYPE_MIN_VALUE have already been set correctly on the
-        enumeration type.  */
-      if (!c_dialect_cxx () && TREE_CODE (type) == ENUMERAL_TYPE)
-       type = c_common_type_for_size (TYPE_PRECISION (type), unsignedp0);
-
       maxval = TYPE_MAX_VALUE (type);
       minval = TYPE_MIN_VALUE (type);
 
@@ -2112,9 +2115,9 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
       if (TREE_CODE (primop0) != INTEGER_CST)
        {
          if (val == truthvalue_false_node)
-           warning ("comparison is always false due to limited range of data type");
+           warning (0, "comparison is always false due to limited range of data type");
          if (val == truthvalue_true_node)
-           warning ("comparison is always true due to limited range of data type");
+           warning (0, "comparison is always true due to limited range of data type");
        }
 
       if (val != 0)
@@ -2184,7 +2187,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
                  && !(TREE_CODE (primop0) == INTEGER_CST
                       && !TREE_OVERFLOW (convert (c_common_signed_type (type),
                                                   primop0))))
-               warning ("comparison of unsigned expression >= 0 is always true");
+               warning (0, "comparison of unsigned expression >= 0 is always true");
              value = truthvalue_true_node;
              break;
 
@@ -2193,7 +2196,7 @@ shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
                  && !(TREE_CODE (primop0) == INTEGER_CST
                       && !TREE_OVERFLOW (convert (c_common_signed_type (type),
                                                   primop0))))
-               warning ("comparison of unsigned expression < 0 is always false");
+               warning (0, "comparison of unsigned expression < 0 is always false");
              value = truthvalue_false_node;
              break;
 
@@ -2301,11 +2304,13 @@ 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
 /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
-   or validate its data type for an `if' or `while' statement or ?..: exp.
+   or for an `if' or `while' statement or ?..: exp.  It should already
+   have been validated to be of suitable type; otherwise, a bad
+   diagnostic may result.
 
    This preparation consists of taking the ordinary
    representation of an expression expr and producing a valid tree
@@ -2318,35 +2323,51 @@ pointer_int_sum (enum tree_code resultcode, tree ptrop, tree intop)
 tree
 c_common_truthvalue_conversion (tree expr)
 {
-  if (TREE_CODE (expr) == ERROR_MARK)
-    return expr;
-
-  if (TREE_CODE (expr) == FUNCTION_DECL)
-    expr = build_unary_op (ADDR_EXPR, expr, 0);
-
   switch (TREE_CODE (expr))
     {
     case EQ_EXPR:   case NE_EXPR:   case UNEQ_EXPR: case LTGT_EXPR:
     case LE_EXPR:   case GE_EXPR:   case LT_EXPR:   case GT_EXPR:
     case UNLE_EXPR: case UNGE_EXPR: case UNLT_EXPR: case UNGT_EXPR:
     case ORDERED_EXPR: case UNORDERED_EXPR:
+      if (TREE_TYPE (expr) == truthvalue_type_node)
+       return expr;
+      return build2 (TREE_CODE (expr), truthvalue_type_node,
+                    TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
+
     case TRUTH_ANDIF_EXPR:
     case TRUTH_ORIF_EXPR:
     case TRUTH_AND_EXPR:
     case TRUTH_OR_EXPR:
     case TRUTH_XOR_EXPR:
+      if (TREE_TYPE (expr) == truthvalue_type_node)
+       return expr;
+      return build2 (TREE_CODE (expr), truthvalue_type_node,
+                c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
+                c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)));
+
     case TRUTH_NOT_EXPR:
-      TREE_TYPE (expr) = truthvalue_type_node;
-      return expr;
+      if (TREE_TYPE (expr) == truthvalue_type_node)
+       return expr;
+      return build1 (TREE_CODE (expr), truthvalue_type_node,
+                c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
 
     case ERROR_MARK:
       return expr;
 
     case INTEGER_CST:
-      return integer_zerop (expr) ? truthvalue_false_node : truthvalue_true_node;
+      /* 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;
 
     case REAL_CST:
-      return real_zerop (expr) ? truthvalue_false_node : truthvalue_true_node;
+      return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst0)
+            ? truthvalue_true_node
+            : truthvalue_false_node;
+
+    case FUNCTION_DECL:
+      expr = build_unary_op (ADDR_EXPR, expr, 0);
+      /* Fall through.  */
 
     case ADDR_EXPR:
       {
@@ -2355,7 +2376,7 @@ c_common_truthvalue_conversion (tree expr)
          {
            /* Common Ada/Pascal programmer's mistake.  We always warn
               about this since it is so bad.  */
-           warning ("the address of %qD, will always evaluate as %<true%>",
+           warning (0, "the address of %qD, will always evaluate as %<true%>",
                     TREE_OPERAND (expr, 0));
            return truthvalue_true_node;
          }
@@ -2376,15 +2397,15 @@ c_common_truthvalue_conversion (tree expr)
     case COMPLEX_EXPR:
       return build_binary_op ((TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
                               ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-               lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 0)),
-               lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 1)),
+               c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)),
+               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
                              0);
 
     case NEGATE_EXPR:
     case ABS_EXPR:
     case FLOAT_EXPR:
       /* These don't change whether an object is nonzero or zero.  */
-      return lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 0));
+      return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
 
     case LROTATE_EXPR:
     case RROTATE_EXPR:
@@ -2393,16 +2414,16 @@ c_common_truthvalue_conversion (tree expr)
       if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
        return build2 (COMPOUND_EXPR, truthvalue_type_node,
                       TREE_OPERAND (expr, 1),
-                      lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 0)));
+                      c_common_truthvalue_conversion (TREE_OPERAND (expr, 0)));
       else
-       return lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
 
     case COND_EXPR:
       /* Distribute the conversion into the arms of a COND_EXPR.  */
-      return fold (build3 (COND_EXPR, truthvalue_type_node,
+      return fold_build3 (COND_EXPR, truthvalue_type_node,
                TREE_OPERAND (expr, 0),
-               lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 1)),
-               lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 2))));
+               c_common_truthvalue_conversion (TREE_OPERAND (expr, 1)),
+               c_common_truthvalue_conversion (TREE_OPERAND (expr, 2)));
 
     case CONVERT_EXPR:
       /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
@@ -2415,7 +2436,7 @@ c_common_truthvalue_conversion (tree expr)
       /* If this is widening the argument, we can ignore it.  */
       if (TYPE_PRECISION (TREE_TYPE (expr))
          >= TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (expr, 0))))
-       return lang_hooks.truthvalue_conversion (TREE_OPERAND (expr, 0));
+       return c_common_truthvalue_conversion (TREE_OPERAND (expr, 0));
       break;
 
     case MINUS_EXPR:
@@ -2435,12 +2456,12 @@ c_common_truthvalue_conversion (tree expr)
         two objects.  */
       if (TREE_TYPE (TREE_OPERAND (expr, 0))
          == TREE_TYPE (TREE_OPERAND (expr, 1)))
-       return build_binary_op (NE_EXPR, TREE_OPERAND (expr, 0),
-                               TREE_OPERAND (expr, 1), 1);
-      return build_binary_op (NE_EXPR, TREE_OPERAND (expr, 0),
-                             fold (build1 (NOP_EXPR,
-                                           TREE_TYPE (TREE_OPERAND (expr, 0)),
-                                           TREE_OPERAND (expr, 1))), 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))
@@ -2450,8 +2471,9 @@ c_common_truthvalue_conversion (tree expr)
       break;
 
     case MODIFY_EXPR:
-      if (warn_parentheses && !TREE_NO_WARNING (expr))
-       warning ("suggest parentheses around assignment used as truth value");
+      if (!TREE_NO_WARNING (expr))
+       warning (OPT_Wparentheses,
+                "suggest parentheses around assignment used as truth value");
       break;
 
     default:
@@ -2464,20 +2486,20 @@ c_common_truthvalue_conversion (tree expr)
       return (build_binary_op
              ((TREE_SIDE_EFFECTS (expr)
                ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
-       lang_hooks.truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
-       lang_hooks.truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
+       c_common_truthvalue_conversion (build_unary_op (REALPART_EXPR, t, 0)),
+       c_common_truthvalue_conversion (build_unary_op (IMAGPART_EXPR, t, 0)),
               0));
     }
 
   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.  */
@@ -2489,9 +2511,28 @@ c_build_qualified_type (tree type, int type_quals)
     return type;
 
   if (TREE_CODE (type) == ARRAY_TYPE)
-    return build_array_type (c_build_qualified_type (TREE_TYPE (type),
-                                                    type_quals),
-                            TYPE_DOMAIN (type));
+    {
+      tree t;
+      tree element_type = c_build_qualified_type (TREE_TYPE (type),
+                                                 type_quals);
+
+      /* See if we already have an identically qualified type.  */
+      for (t = TYPE_MAIN_VARIANT (type); t; t = TYPE_NEXT_VARIANT (t))
+       {
+         if (TYPE_QUALS (strip_array_types (t)) == type_quals
+             && TYPE_NAME (t) == TYPE_NAME (type)
+             && TYPE_CONTEXT (t) == TYPE_CONTEXT (type)
+             && attribute_list_equal (TYPE_ATTRIBUTES (t),
+                                      TYPE_ATTRIBUTES (type)))
+           break;
+       }
+      if (!t)
+       {
+         t = build_variant_type_copy (type);
+         TREE_TYPE (t) = element_type;
+       }
+      return t;
+    }
 
   /* A restrict-qualified pointer type must be a pointer to object or
      incomplete type.  Note that the use of POINTER_TYPE_P also allows
@@ -2741,19 +2782,19 @@ c_common_get_alias_set (tree t)
    second parameter indicates which OPERATOR is being applied.  The COMPLAIN
    flag controls whether we should diagnose possibly ill-formed
    constructs or not.  */
+
 tree
-c_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
+c_sizeof_or_alignof_type (tree type, bool is_sizeof, int complain)
 {
   const char *op_name;
   tree value = NULL;
   enum tree_code type_code = TREE_CODE (type);
 
-  gcc_assert (op == SIZEOF_EXPR || op == ALIGNOF_EXPR);
-  op_name = op == SIZEOF_EXPR ? "sizeof" : "__alignof__";
+  op_name = is_sizeof ? "sizeof" : "__alignof__";
 
   if (type_code == FUNCTION_TYPE)
     {
-      if (op == SIZEOF_EXPR)
+      if (is_sizeof)
        {
          if (complain && (pedantic || warn_pointer_arith))
            pedwarn ("invalid application of %<sizeof%> to a function type");
@@ -2778,7 +2819,7 @@ c_sizeof_or_alignof_type (tree type, enum tree_code op, int complain)
     }
   else
     {
-      if (op == (enum tree_code) SIZEOF_EXPR)
+      if (is_sizeof)
        /* Convert in case a char is more than one unit.  */
        value = size_binop (CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
                            size_int (TYPE_PRECISION (char_type_node)
@@ -2791,7 +2832,7 @@ c_sizeof_or_alignof_type (tree type, enum tree_code op, 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_build1 (NOP_EXPR, size_type_node, value);
   gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
 
   return value;
@@ -2841,7 +2882,7 @@ c_alignof_expr (tree expr)
   else
     return c_alignof (TREE_TYPE (expr));
 
-  return fold (build1 (NOP_EXPR, size_type_node, t));
+  return fold_build1 (NOP_EXPR, size_type_node, t);
 }
 \f
 /* Handle C and C++ default attributes.  */
@@ -2878,10 +2919,16 @@ c_common_nodes_and_builtins (void)
 #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_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
@@ -2890,10 +2937,14 @@ 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_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
   };
@@ -2950,9 +3001,10 @@ c_common_nodes_and_builtins (void)
   lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
                                         intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
-                                        get_identifier ("__int128_t"),
-                                        intTI_type_node));
+  if (targetm.scalar_mode_supported_p (TImode))
+    lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                          get_identifier ("__int128_t"),
+                                          intTI_type_node));
 #endif
   lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
                                         unsigned_intQI_type_node));
@@ -2963,9 +3015,10 @@ c_common_nodes_and_builtins (void)
   lang_hooks.decls.pushdecl (build_decl (TYPE_DECL, NULL_TREE,
                                         unsigned_intDI_type_node));
 #if HOST_BITS_PER_WIDE_INT >= 64
-  lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
-                                        get_identifier ("__uint128_t"),
-                                        unsigned_intTI_type_node));
+  if (targetm.scalar_mode_supported_p (TImode))
+    lang_hooks.decls.pushdecl (build_decl (TYPE_DECL,
+                                          get_identifier ("__uint128_t"),
+                                          unsigned_intTI_type_node));
 #endif
 
   /* Create the widest literal types.  */
@@ -3140,6 +3193,42 @@ c_common_nodes_and_builtins (void)
                              tree_cons (NULL_TREE,                     \
                                         builtin_types[(int) ARG4],     \
                                         void_list_node)))));
+#define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5)        \
+  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],     \
+                                        tree_cons (NULL_TREE,          \
+                                             builtin_types[(int) ARG5],\
+                                             void_list_node))))));
+#define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
+                           ARG6)                                       \
+  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],               \
+                              tree_cons (NULL_TREE,                    \
+                                        builtin_types[(int) ARG5],     \
+                                        tree_cons (NULL_TREE,          \
+                                             builtin_types[(int) ARG6],\
+                                             void_list_node)))))));
 #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN)                          \
   builtin_types[(int) ENUM]                                            \
     = build_function_type (builtin_types[(int) RETURN], NULL_TREE);
@@ -3172,6 +3261,38 @@ c_common_nodes_and_builtins (void)
                                        builtin_types[(int) ARG3],      \
                                        NULL_TREE))));
 
+#define DEF_FUNCTION_TYPE_VAR_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],\
+                                             NULL_TREE)))));
+
+#define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4,  \
+                               ARG5)                                   \
+   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],      \
+                                       tree_cons (NULL_TREE,           \
+                                             builtin_types[(int) ARG5],\
+                                             NULL_TREE))))));
+
 #define DEF_POINTER_TYPE(ENUM, TYPE)                   \
   builtin_types[(int) ENUM]                            \
     = build_pointer_type (builtin_types[(int) TYPE]);
@@ -3181,54 +3302,61 @@ 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_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
 
   c_init_attributes ();
 
-#define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE,                  \
-                   BOTH_P, FALLBACK_P, NONANSI_P, ATTRS, IMPLICIT)     \
-  if (NAME)                                                            \
-    {                                                                  \
-      tree decl;                                                       \
-                                                                       \
-      gcc_assert (!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;                     \
-    }
+#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 ();
 
   main_identifier_node = get_identifier ("main");
+
+  /* Create the built-in __null node.  It is important that this is
+     not shared.  */
+  null_node = make_node (INTEGER_CST);
+  TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
+}
+
+/* Look up the function in built_in_decls that corresponds to DECL
+   and set ASMSPEC as its user assembler name.  DECL must be a
+   function decl that declares a builtin.  */
+
+void
+set_builtin_user_assembler_name (tree decl, const char *asmspec)
+{
+  tree builtin;
+  gcc_assert (TREE_CODE (decl) == FUNCTION_DECL
+             && DECL_BUILT_IN_CLASS (decl) == BUILT_IN_NORMAL
+             && asmspec != 0);
+
+  builtin = built_in_decls [DECL_FUNCTION_CODE (decl)];
+  set_user_assembler_name (builtin, asmspec);
+  if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMCPY)
+    init_block_move_fn (asmspec);
+  else if (DECL_FUNCTION_CODE (decl) == BUILT_IN_MEMSET)
+    init_block_clear_fn (asmspec);
 }
 
 tree
@@ -3283,42 +3411,39 @@ 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;
-
-  if (builtin_name != 0)
-    bdecl = lang_hooks.builtin_function (builtin_name, builtin_type,
-                                        function_code, cl,
-                                        library_name_p ? name : NULL, attrs);
-
-  if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name)
+  tree decl;
+  const char *libname;
+
+  gcc_assert ((!both_p && !fallback_p)
+             || !strncmp (name, "__builtin_",
+                          strlen ("__builtin_")));
+
+  libname = name + strlen ("__builtin_");
+  decl = lang_hooks.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);
+    lang_hooks.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
@@ -3398,76 +3523,6 @@ strip_pointer_operator (tree t)
   return t;
 }
 
-/* Walk the statement tree, rooted at *tp.  Apply FUNC to all the
-   sub-trees of *TP in a pre-order traversal.  FUNC is called with the
-   DATA and the address of each sub-tree.  If FUNC returns a non-NULL
-   value, the traversal is aborted, and the value returned by FUNC is
-   returned.  If FUNC sets WALK_SUBTREES to zero, then the subtrees of
-   the node being visited are not walked.
-
-   We don't need a without_duplicates variant of this one because the
-   statement tree is a tree, not a graph.  */
-
-tree
-walk_stmt_tree (tree *tp, walk_tree_fn func, void *data)
-{
-  enum tree_code code;
-  int walk_subtrees;
-  tree result;
-  int i, len;
-
-#define WALK_SUBTREE(NODE)                             \
-  do                                                   \
-    {                                                  \
-      result = walk_stmt_tree (&(NODE), func, data);   \
-      if (result)                                      \
-       return result;                                  \
-    }                                                  \
-  while (0)
-
-  /* Skip empty subtrees.  */
-  if (!*tp)
-    return NULL_TREE;
-
-  /* Skip subtrees below non-statement nodes.  */
-  if (!STATEMENT_CODE_P (TREE_CODE (*tp)))
-    return NULL_TREE;
-
-  /* Call the function.  */
-  walk_subtrees = 1;
-  result = (*func) (tp, &walk_subtrees, data);
-
-  /* If we found something, return it.  */
-  if (result)
-    return result;
-
-  /* FUNC may have modified the tree, recheck that we're looking at a
-     statement node.  */
-  code = TREE_CODE (*tp);
-  if (!STATEMENT_CODE_P (code))
-    return NULL_TREE;
-
-  /* Visit the subtrees unless FUNC decided that there was nothing
-     interesting below this point in the tree.  */
-  if (walk_subtrees)
-    {
-      /* Walk over all the sub-trees of this operand.  Statement nodes
-        never contain RTL, and we needn't worry about TARGET_EXPRs.  */
-      len = TREE_CODE_LENGTH (code);
-
-      /* Go through the subtrees.  We need to do this in forward order so
-        that the scope of a FOR_EXPR is handled properly.  */
-      for (i = 0; i < len; ++i)
-       WALK_SUBTREE (TREE_OPERAND (*tp, i));
-    }
-
-  /* Finally visit the chain.  This can be tail-recursion optimized if
-     we write it this way.  */
-  return walk_stmt_tree (&TREE_CHAIN (*tp), func, data);
-
-#undef WALK_SUBTREE
-}
-
 /* Used to compare case labels.  K1 and K2 are actually tree nodes
    representing case labels, or NULL_TREE for a `default' label.
    Returns -1 if K1 is ordered before K2, -1 if K1 is ordered after
@@ -3516,7 +3571,10 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
        && POINTER_TYPE_P (TREE_TYPE (low_value)))
       || (high_value && TREE_TYPE (high_value)
          && POINTER_TYPE_P (TREE_TYPE (high_value))))
-    error ("pointers are not permitted as case values");
+    {
+      error ("pointers are not permitted as case values");
+      goto error_out;
+    }
 
   /* Case ranges are a GNU extension.  */
   if (high_value && pedantic)
@@ -3545,7 +3603,7 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
     high_value = NULL_TREE;
   if (low_value && high_value
       && !tree_int_cst_lt (low_value, high_value))
-    warning ("empty range specified");
+    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,
@@ -3632,7 +3690,7 @@ c_add_case_label (splay_tree cases, tree cond, tree orig_type,
  error_out:
   /* Add a label so that the back-end doesn't think that the beginning of
      the switch is unreachable.  Note that we do not add a case label, as
-     that just leads to duplicates and thence to aborts later on.  */
+     that just leads to duplicates and thence to failure later on.  */
   if (!cases->root)
     {
       tree t = create_artificial_label ();
@@ -3664,10 +3722,10 @@ match_case_to_enum_1 (tree key, tree type, tree label)
              TREE_INT_CST_HIGH (key), TREE_INT_CST_LOW (key));
 
   if (TYPE_NAME (type) == 0)
-    warning ("%Jcase value %qs not in enumerated type",
+    warning (0, "%Jcase value %qs not in enumerated type",
             CASE_LABEL (label), buf);
   else
-    warning ("%Jcase value %qs not in enumerated type %qT",
+    warning (0, "%Jcase value %qs not in enumerated type %qT",
             CASE_LABEL (label), buf, type);
 }
 
@@ -3706,35 +3764,26 @@ match_case_to_enum (splay_tree_node node, void *data)
   return 0;
 }
 
-/* Handle -Wswitch*.  Called from the front end after parsing the switch
-   construct.  */
-/* ??? Should probably be somewhere generic, since other languages besides
-   C and C++ would want this.  We'd want to agree on the datastructure,
-   however, which is a problem.  Alternately, we operate on gimplified
-   switch_exprs, which I don't especially like.  At the moment, however,
-   C/C++ are the only tree-ssa languages that support enumerations at all,
+/* Handle -Wswitch*.  Called from the front end after parsing the
+   switch construct.  */
+/* ??? Should probably be somewhere generic, since other languages
+   besides C and C++ would want this.  At the moment, however, C/C++
+   are the only tree-ssa languages that support enumerations at all,
    so the point is moot.  */
 
 void
-c_do_switch_warnings (splay_tree cases, tree switch_stmt)
+c_do_switch_warnings (splay_tree cases, location_t switch_location,
+                     tree type, tree cond)
 {
   splay_tree_node default_node;
-  location_t switch_location;
-  tree type;
 
   if (!warn_switch && !warn_switch_enum && !warn_switch_default)
     return;
 
-  if (EXPR_HAS_LOCATION (switch_stmt))
-    switch_location = EXPR_LOCATION (switch_stmt);
-  else
-    switch_location = input_location;
-
-  type = SWITCH_TYPE (switch_stmt);
-
   default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
-  if (warn_switch_default && !default_node)
-    warning ("%Hswitch missing default case", &switch_location);
+  if (!default_node)
+    warning (OPT_Wswitch_default, "%Hswitch missing default case",
+            &switch_location);
 
   /* If the switch expression was an enumerated type, check that
      exactly all enumeration literals are covered by the cases.
@@ -3742,7 +3791,7 @@ c_do_switch_warnings (splay_tree cases, tree switch_stmt)
      default case, or when -Wswitch-enum was specified.  */
   if (((warn_switch && !default_node) || warn_switch_enum)
       && type && TREE_CODE (type) == ENUMERAL_TYPE
-      && TREE_CODE (SWITCH_COND (switch_stmt)) != INTEGER_CST)
+      && TREE_CODE (cond) != INTEGER_CST)
     {
       tree chain;
 
@@ -3768,7 +3817,7 @@ c_do_switch_warnings (splay_tree cases, tree switch_stmt)
            {
              /* Warn if there are enumerators that don't correspond to
                 case expressions.  */
-             warning ("%Henumeration value %qE not handled in switch",
+             warning (0, "%Henumeration value %qE not handled in switch",
                       &switch_location, TREE_PURPOSE (chain));
            }
        }
@@ -3964,7 +4013,7 @@ handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
      that changes what the typedef is typing.  */
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -3983,7 +4032,7 @@ handle_nocommon_attribute (tree *node, tree name,
     DECL_COMMON (*node) = 0;
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4001,7 +4050,7 @@ handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
     DECL_COMMON (*node) = 1;
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4028,7 +4077,7 @@ handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                             TYPE_READONLY (TREE_TYPE (type)), 1));
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4047,7 +4096,7 @@ handle_noinline_attribute (tree *node, tree name,
     DECL_UNINLINABLE (*node) = 1;
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4070,13 +4119,35 @@ handle_always_inline_attribute (tree *node, tree name,
     }
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      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.  */
 
@@ -4094,7 +4165,7 @@ handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
     }
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4120,7 +4191,7 @@ handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
        TREE_USED (decl) = 1;
       else
        {
-         warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+         warning (OPT_Wattributes, "%qE attribute ignored", name);
          *no_add_attrs = true;
        }
     }
@@ -4134,6 +4205,47 @@ 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_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL)
+      || !TREE_PUBLIC (node))
+    {
+      warning (OPT_Wattributes,
+              "%qE attribute have effect only on public objects", name);
+      *no_add_attrs = true;
+    }
+  else if (TREE_CODE (node) == FUNCTION_DECL)
+    {
+      struct cgraph_node *n = cgraph_node (node);
+      n->local.externally_visible = true;
+      if (n->local.finalized)
+       cgraph_mark_needed_node (n);
+    }
+  else if (TREE_CODE (node) == VAR_DECL)
+    {
+      struct cgraph_varpool_node *n = cgraph_varpool_node (node);
+      n->externally_visible = true;
+      if (n->finalized)
+       cgraph_varpool_mark_needed_node (n);
+    }
+  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.  */
 
@@ -4154,7 +4266,7 @@ handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                             TREE_THIS_VOLATILE (TREE_TYPE (type))));
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4198,7 +4310,7 @@ handle_transparent_union_attribute (tree *node, tree name,
     DECL_TRANSPARENT_UNION (decl) = 1;
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4226,7 +4338,7 @@ handle_constructor_attribute (tree *node, tree name,
     }
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4254,7 +4366,7 @@ handle_destructor_attribute (tree *node, tree name,
     }
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4273,7 +4385,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
   *no_add_attrs = true;
 
   if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
-    warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+    warning (OPT_Wattributes, "%qE attribute ignored", name);
   else
     {
       int j;
@@ -4311,7 +4423,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
       if (mode == VOIDmode)
        {
-         error ("unknown machine mode %<%s%>", p);
+         error ("unknown machine mode %qs", p);
          return NULL_TREE;
        }
 
@@ -4331,9 +4443,10 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
        case MODE_VECTOR_INT:
        case MODE_VECTOR_FLOAT:
-         warning ("specifying vector types with __attribute__ ((mode)) "
-                  "is deprecated");
-         warning ("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;
 
@@ -4342,7 +4455,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
        }
       if (!valid_mode)
        {
-         error ("unable to emulate %<%s%>", p);
+         error ("unable to emulate %qs", p);
          return NULL_TREE;
        }
 
@@ -4352,7 +4465,7 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
          if (!targetm.valid_pointer_mode (mode))
            {
-             error ("invalid pointer mode %<%s%>", p);
+             error ("invalid pointer mode %qs", p);
              return NULL_TREE;
            }
 
@@ -4383,18 +4496,29 @@ handle_mode_attribute (tree *node, tree name, tree args,
 
          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;
        }
-      else if (TREE_CODE (type) != TREE_CODE (typefm))
+      else if (VECTOR_MODE_P (mode)
+              ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
+              : TREE_CODE (type) != TREE_CODE (typefm))
        {
          error ("mode %qs applied to inappropriate type", p);
          return NULL_TREE;
        }
 
       *node = typefm;
-
-      /* No need to layout the type here.  The caller should do this.  */
     }
 
   return NULL_TREE;
@@ -4432,8 +4556,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
@@ -4441,7 +4565,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;
        }
     }
@@ -4477,12 +4601,6 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   else if (TYPE_P (*node))
     type = node, is_type = 1;
 
-  /* Strip any NOPs of any kind.  */
-  while (TREE_CODE (align_expr) == NOP_EXPR
-        || TREE_CODE (align_expr) == CONVERT_EXPR
-        || TREE_CODE (align_expr) == NON_LVALUE_EXPR)
-    align_expr = TREE_OPERAND (align_expr, 0);
-
   if (TREE_CODE (align_expr) != INTEGER_CST)
     {
       error ("requested alignment is not a constant");
@@ -4521,7 +4639,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
@@ -4559,7 +4677,7 @@ handle_alias_attribute (tree *node, tree name, tree args,
   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);
+      error ("%q+D defined both normally and as an alias", decl);
       *no_add_attrs = true;
     }
 
@@ -4575,7 +4693,7 @@ handle_alias_attribute (tree *node, tree name, tree args,
       id = TREE_VALUE (args);
       if (TREE_CODE (id) != STRING_CST)
        {
-         error ("alias arg not a string");
+         error ("alias argument not a string");
          *no_add_attrs = true;
          return NULL_TREE;
        }
@@ -4593,7 +4711,7 @@ handle_alias_attribute (tree *node, tree name, tree args,
     }
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4617,20 +4735,20 @@ handle_visibility_attribute (tree *node, tree name, tree args,
     {
       if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
        {
-         warning ("%qs attribute ignored on non-class types",
-                  IDENTIFIER_POINTER (name));
+         warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
+                 name);
          return NULL_TREE;
        }
     }
   else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       return NULL_TREE;
     }
 
   if (TREE_CODE (id) != STRING_CST)
     {
-      error ("visibility arg not a string");
+      error ("visibility argument not a string");
       return NULL_TREE;
     }
 
@@ -4640,6 +4758,12 @@ handle_visibility_attribute (tree *node, tree name, tree args,
       decl = TYPE_NAME (decl);
       if (!decl)
         return NULL_TREE;
+      if (TREE_CODE (decl) == IDENTIFIER_NODE)
+       {
+          warning (OPT_Wattributes, "%qE attribute ignored on types",
+                   name);
+          return NULL_TREE;
+       }
     }
 
   if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
@@ -4651,7 +4775,7 @@ handle_visibility_attribute (tree *node, tree name, tree args,
   else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
     DECL_VISIBILITY (decl) = VISIBILITY_PROTECTED;
   else
-    error ("visibility arg must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
+    error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
   DECL_VISIBILITY_SPECIFIED (decl) = 1;
 
   /* For decls only, go ahead and attach the attribute to the node as well.
@@ -4706,35 +4830,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;
+
+  *no_add_attrs = true;
 
-  if (!DECL_THREAD_LOCAL (decl))
+  if (!DECL_THREAD_LOCAL_P (decl))
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (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 arg 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 arg 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;
 }
 
@@ -4772,12 +4899,30 @@ static tree
 handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
                         int ARG_UNUSED (flags), bool *no_add_attrs)
 {
-  if (TREE_CODE (*node) == FUNCTION_DECL)
+  if (TREE_CODE (*node) == FUNCTION_DECL
+      && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
     DECL_IS_MALLOC (*node) = 1;
-  /* ??? TODO: Support types.  */
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
+/* Handle a "returns_twice" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
+                        int ARG_UNUSED (flags), bool *no_add_attrs)
+{
+  if (TREE_CODE (*node) == FUNCTION_DECL)
+    DECL_IS_RETURNS_TWICE (*node) = 1;
+  else
+    {
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -4823,13 +4968,26 @@ handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   /* ??? TODO: Support types.  */
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
   return NULL_TREE;
 }
 
+/* Handle a "no vops" attribute; arguments as in
+   struct attribute_spec.handler.  */
+
+static tree
+handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
+                        tree ARG_UNUSED (args), int ARG_UNUSED (flags),
+                        bool *ARG_UNUSED (no_add_attrs))
+{
+  gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
+  DECL_IS_NOVOPS (*node) = 1;
+  return NULL_TREE;
+}
+
 /* Handle a "deprecated" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -4840,7 +4998,7 @@ handle_deprecated_attribute (tree *node, tree name,
 {
   tree type = NULL_TREE;
   int warn = 0;
-  const char *what = NULL;
+  tree what = NULL_TREE;
 
   if (DECL_P (*node))
     {
@@ -4872,17 +5030,15 @@ handle_deprecated_attribute (tree *node, tree name,
       if (type && TYPE_NAME (type))
        {
          if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
-           what = IDENTIFIER_POINTER (TYPE_NAME (*node));
+           what = TYPE_NAME (*node);
          else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
                   && DECL_NAME (TYPE_NAME (type)))
-           what = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (type)));
+           what = DECL_NAME (TYPE_NAME (type));
        }
       if (what)
-       warning ("%qs attribute ignored for %qs",
-                 IDENTIFIER_POINTER (name), what);
+       warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
       else
-       warning ("%qs attribute ignored",
-                     IDENTIFIER_POINTER (name));
+       warning (OPT_Wattributes, "%qE attribute ignored", name);
     }
 
   return NULL_TREE;
@@ -4902,15 +5058,11 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
 
   *no_add_attrs = true;
 
-  /* Stripping NON_LVALUE_EXPR allows declarations such as
-     typedef short v4si __attribute__((vector_size (4 * sizeof(short)))).  */
   size = TREE_VALUE (args);
-  if (TREE_CODE (size) == NON_LVALUE_EXPR)
-    size = TREE_OPERAND (size, 0);
 
   if (!host_integerp (size, 1))
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       return NULL_TREE;
     }
 
@@ -4939,8 +5091,7 @@ handle_vector_size_attribute (tree *node, tree name, tree args,
          && GET_MODE_CLASS (orig_mode) != MODE_INT)
       || !host_integerp (TYPE_SIZE_UNIT (type), 1))
     {
-      error ("invalid vector type for attribute %qs",
-            IDENTIFIER_POINTER (name));
+      error ("invalid vector type for attribute %qE", name);
       return NULL_TREE;
     }
 
@@ -4991,7 +5142,7 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
 
       if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
        {
-         error ("nonnull argument has invalid operand number (arg %lu)",
+         error ("nonnull argument has invalid operand number (argument %lu)",
                 (unsigned long) attr_arg_num);
          *no_add_attrs = true;
          return NULL_TREE;
@@ -5010,7 +5161,7 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
          if (!argument
              || TREE_CODE (TREE_VALUE (argument)) == VOID_TYPE)
            {
-             error ("nonnull argument with out-of-range operand number (arg %lu, operand %lu)",
+             error ("nonnull argument with out-of-range operand number (argument %lu, operand %lu)",
                     (unsigned long) attr_arg_num, (unsigned long) arg_num);
              *no_add_attrs = true;
              return NULL_TREE;
@@ -5018,7 +5169,7 @@ handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
 
          if (TREE_CODE (TREE_VALUE (argument)) != POINTER_TYPE)
            {
-             error ("nonnull argument references non-pointer operand (arg %lu, operand %lu)",
+             error ("nonnull argument references non-pointer operand (argument %lu, operand %lu)",
                   (unsigned long) attr_arg_num, (unsigned long) arg_num);
              *no_add_attrs = true;
              return NULL_TREE;
@@ -5066,14 +5217,22 @@ 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 ("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;
@@ -5082,7 +5241,6 @@ check_function_sentinel (tree attrs, tree params)
          if (TREE_VALUE (attr))
            {
              tree p = TREE_VALUE (TREE_VALUE (attr));
-             STRIP_NOPS (p);
              pos = TREE_INT_CST_LOW (p);
            }
 
@@ -5096,7 +5254,8 @@ check_function_sentinel (tree attrs, tree params)
            }
          if (pos > 0)
            {
-             warning ("not enough arguments to fit a sentinel");
+             warning (OPT_Wformat,
+                      "not enough variable arguments to fit a sentinel");
              return;
            }
 
@@ -5108,9 +5267,16 @@ check_function_sentinel (tree attrs, tree params)
            }
 
          /* Validate the sentinel.  */
-         if (!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
-             || !integer_zerop (TREE_VALUE (sentinel)))
-           warning ("missing sentinel in function call");
+         if ((!POINTER_TYPE_P (TREE_TYPE (TREE_VALUE (sentinel)))
+              || !integer_zerop (TREE_VALUE (sentinel)))
+             /* Although __null (in C++) is only an integer we allow it
+                nevertheless, as we are guaranteed that it's exactly
+                as wide as a pointer, and we don't want to force
+                users to cast the NULL they have written there.
+                We warn with -Wstrict-null-sentinel, though.  */
+              && (warn_strict_null_sentinel
+                 || null_node != TREE_VALUE (sentinel)))
+           warning (OPT_Wformat, "missing sentinel in function call");
        }
     }
 }
@@ -5152,8 +5318,8 @@ check_nonnull_arg (void * ARG_UNUSED (ctx), tree param,
     return;
 
   if (integer_zerop (param))
-    warning ("null argument where non-null required (arg %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
@@ -5162,13 +5328,7 @@ check_nonnull_arg (void * ARG_UNUSED (ctx), tree param,
 static bool
 get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
 {
-  /* Strip any conversions from the arg number and verify they
-     are constants.  */
-  while (TREE_CODE (arg_num_expr) == NOP_EXPR
-        || TREE_CODE (arg_num_expr) == CONVERT_EXPR
-        || TREE_CODE (arg_num_expr) == NON_LVALUE_EXPR)
-    arg_num_expr = TREE_OPERAND (arg_num_expr, 0);
-
+  /* Verify the arg number is a constant.  */
   if (TREE_CODE (arg_num_expr) != INTEGER_CST
       || TREE_INT_CST_HIGH (arg_num_expr) != 0)
     return false;
@@ -5189,7 +5349,7 @@ handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   /* ??? TODO: Support types.  */
   else
     {
-      warning ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -5212,7 +5372,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 ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -5223,14 +5383,14 @@ handle_cleanup_attribute (tree *node, tree name, tree args,
   cleanup_id = TREE_VALUE (args);
   if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE)
     {
-      error ("cleanup arg not an identifier");
+      error ("cleanup argument not an identifier");
       *no_add_attrs = true;
       return NULL_TREE;
     }
   cleanup_decl = lookup_name (cleanup_id);
   if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL)
     {
-      error ("cleanup arg not a function");
+      error ("cleanup argument not a function");
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -5251,7 +5411,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 ("%qs attribute ignored", IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes, "%qE attribute ignored", name);
       *no_add_attrs = true;
     }
 
@@ -5268,8 +5428,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
 
   if (!params)
     {
-      warning ("%qs attribute requires prototypes with named arguments",
-               IDENTIFIER_POINTER (name));
+      warning (OPT_Wattributes,
+              "%qE attribute requires prototypes with named arguments", name);
       *no_add_attrs = true;
     }
   else
@@ -5279,8 +5439,8 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
 
       if (VOID_TYPE_P (TREE_VALUE (params)))
         {
-         warning ("%qs attribute only applies to variadic functions",
-                  IDENTIFIER_POINTER (name));
+         warning (OPT_Wattributes,
+                  "%qE attribute only applies to variadic functions", name);
          *no_add_attrs = true;
        }
     }
@@ -5289,17 +5449,16 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
     {
       tree position = TREE_VALUE (args);
 
-      STRIP_NOPS (position);
       if (TREE_CODE (position) != INTEGER_CST)
         {
-         warning ("requested position is not an integer constant");
+         warning (0, "requested position is not an integer constant");
          *no_add_attrs = true;
        }
       else
         {
          if (tree_int_cst_lt (position, integer_zero_node))
            {
-             warning ("requested position is less than zero");
+             warning (0, "requested position is less than zero");
              *no_add_attrs = true;
            }
        }
@@ -5310,7 +5469,7 @@ handle_sentinel_attribute (tree *node, tree name, tree args,
 \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.  */
@@ -5320,11 +5479,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
@@ -5367,10 +5526,6 @@ check_function_arguments_recurse (void (*callback)
            /* Extract the argument number, which was previously checked
               to be valid.  */
            format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
-           while (TREE_CODE (format_num_expr) == NOP_EXPR
-                  || TREE_CODE (format_num_expr) == CONVERT_EXPR
-                  || TREE_CODE (format_num_expr) == NON_LVALUE_EXPR)
-             format_num_expr = TREE_OPERAND (format_num_expr, 0);
 
            gcc_assert (TREE_CODE (format_num_expr) == INTEGER_CST
                        && !TREE_INT_CST_HIGH (format_num_expr));
@@ -5477,36 +5632,75 @@ resort_sorted_fields (void *obj,
         resort_field_decl_cmp);
 }
 
-/* Issue the error given by MSGID, indicating that it occurred before
+/* Subroutine of c_parse_error.
+   Return the result of concatenating LHS and RHS. RHS is really
+   a string literal, its first character is indicated by RHS_START and
+   RHS_SIZE is its length (including the terminating NUL character).
+
+   The caller is responsible for deleting the returned pointer.  */
+
+static char *
+catenate_strings (const char *lhs, const char *rhs_start, int rhs_size)
+{
+  const int lhs_size = strlen (lhs);
+  char *result = XNEWVEC (char, lhs_size + rhs_size);
+  strncpy (result, lhs, lhs_size);
+  strncpy (result + lhs_size, rhs_start, rhs_size);
+  return result;
+}
+
+/* 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)
 {
-  const char *string = _(msgid);
+#define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
+
+  char *message = NULL;
 
   if (token == CPP_EOF)
-    error ("%s at end of input", string);
+    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))
-       error ("%s before %s'%c'", string, ell, val);
+        message = catenate_messages (gmsgid, " before %s'%c'");
       else
-       error ("%s before %s'\\x%x'", string, ell, val);
+        message = catenate_messages (gmsgid, " before %s'\\x%x'");
+
+      error (message, ell, val);
+      free (message);
+      message = NULL;
     }
-  else if (token == CPP_STRING
-          || token == CPP_WSTRING)
-    error ("%s before string constant", string);
+  else if (token == CPP_STRING || token == CPP_WSTRING)
+    message = catenate_messages (gmsgid, " before string constant");
   else if (token == CPP_NUMBER)
-    error ("%s before numeric constant", string);
+    message = catenate_messages (gmsgid, " before numeric constant");
   else if (token == CPP_NAME)
-    error ("%s before \"%s\"", string, IDENTIFIER_POINTER (value));
+    {
+      message = catenate_messages (gmsgid, " before %qE");
+      error (message, value);
+      free (message);
+      message = NULL;
+    }
   else if (token < N_TTYPES)
-    error ("%s before %qs token", string, cpp_type2name (token));
+    {
+      message = catenate_messages (gmsgid, " before %qs token");
+      error (message, cpp_type2name (token));
+      free (message);
+      message = NULL;
+    }
   else
-    error ("%s", string);
+    error (gmsgid);
+
+  if (message)
+    {
+      error (message);
+      free (message);
+    }
+#undef catenate_messages  
 }
 
 /* Walk a gimplified function and warn for functions whose return value is
@@ -5566,11 +5760,11 @@ c_warn_unused_result (tree *top_p)
       if (lookup_attribute ("warn_unused_result", TYPE_ATTRIBUTES (ftype)))
        {
          if (fdecl)
-           warning ("%Hignoring return value of %qD, "
+           warning (0, "%Hignoring return value of %qD, "
                     "declared with attribute warn_unused_result",
                     EXPR_LOCUS (t), fdecl);
          else
-           warning ("%Hignoring return value of function "
+           warning (0, "%Hignoring return value of function "
                     "declared with attribute warn_unused_result",
                     EXPR_LOCUS (t));
        }
@@ -5582,6 +5776,27 @@ c_warn_unused_result (tree *top_p)
     }
 }
 
+/* Convert a character from the host to the target execution character
+   set.  cpplib handles this, mostly.  */
+
+HOST_WIDE_INT
+c_common_to_target_charset (HOST_WIDE_INT c)
+{
+  /* Character constants in GCC proper are sign-extended under -fsigned-char,
+     zero-extended under -fno-signed-char.  cpplib insists that characters
+     and character constants are always unsigned.  Hence we must convert
+     back and forth.  */
+  cppchar_t uc = ((cppchar_t)c) & ((((cppchar_t)1) << CHAR_BIT)-1);
+
+  uc = cpp_host_to_exec_charset (parse_in, uc);
+
+  if (flag_signed_char)
+    return ((HOST_WIDE_INT)uc) << (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE)
+                              >> (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE);
+  else
+    return uc;
+}
+
 /* 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
@@ -5610,7 +5825,7 @@ fold_offsetof_1 (tree expr)
       if (DECL_C_BIT_FIELD (t))
        {
          error ("attempt to take address of bit-field structure "
-                "member %qs", IDENTIFIER_POINTER (DECL_NAME (t)));
+                "member %qD", t);
          return error_mark_node;
        }
       off = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (t),
@@ -5627,7 +5842,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);
@@ -5647,4 +5862,348 @@ fold_offsetof (tree expr)
   return convert (size_type_node, fold_offsetof_1 (expr));
 }
 
+/* Print an error message for an invalid lvalue.  USE says
+   how the lvalue is being used and so selects the error message.  */
+
+void
+lvalue_error (enum lvalue_use use)
+{
+  switch (use)
+    {
+    case lv_assign:
+      error ("invalid lvalue in assignment");
+      break;
+    case lv_increment:
+      error ("invalid lvalue in increment");
+      break;
+    case lv_decrement:
+      error ("invalid lvalue in decrement");
+      break;
+    case lv_addressof:
+      error ("invalid lvalue in unary %<&%>");
+      break;
+    case lv_asm:
+      error ("invalid lvalue in asm statement");
+      break;
+    default:
+      gcc_unreachable ();
+    }
+}
+\f
+/* *PTYPE is an incomplete array.  Complete it with a domain based on
+   INITIAL_VALUE.  If INITIAL_VALUE is not present, use 1 if DO_DEFAULT
+   is true.  Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
+   2 if INITIAL_VALUE was NULL, and 3 if INITIAL_VALUE was empty.  */
+
+int
+complete_array_type (tree *ptype, tree initial_value, bool do_default)
+{
+  tree maxindex, type, main_type, elt, unqual_elt;
+  int failure = 0, quals;
+
+  maxindex = size_zero_node;
+  if (initial_value)
+    {
+      if (TREE_CODE (initial_value) == STRING_CST)
+       {
+         int eltsize
+           = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
+         maxindex = size_int (TREE_STRING_LENGTH (initial_value)/eltsize - 1);
+       }
+      else if (TREE_CODE (initial_value) == CONSTRUCTOR)
+       {
+         VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value);
+
+         if (VEC_empty (constructor_elt, v))
+           {
+             if (pedantic)
+               failure = 3;
+             maxindex = integer_minus_one_node;
+           }
+         else
+           {
+             tree curindex;
+             unsigned HOST_WIDE_INT cnt;
+             constructor_elt *ce;
+
+             if (VEC_index (constructor_elt, v, 0)->index)
+               maxindex = fold_convert (sizetype,
+                                        VEC_index (constructor_elt,
+                                                   v, 0)->index);
+             curindex = maxindex;
+
+             for (cnt = 1;
+                  VEC_iterate (constructor_elt, v, cnt, ce);
+                  cnt++)
+               {
+                 if (ce->index)
+                   curindex = fold_convert (sizetype, ce->index);
+                 else
+                   curindex = size_binop (PLUS_EXPR, curindex, size_one_node);
+
+                 if (tree_int_cst_lt (maxindex, curindex))
+                   maxindex = curindex;
+               }
+           }
+       }
+      else
+       {
+         /* Make an error message unless that happened already.  */
+         if (initial_value != error_mark_node)
+           failure = 1;
+       }
+    }
+  else
+    {
+      failure = 2;
+      if (!do_default)
+       return failure;
+    }
+
+  type = *ptype;
+  elt = TREE_TYPE (type);
+  quals = TYPE_QUALS (strip_array_types (elt));
+  if (quals == 0)
+    unqual_elt = elt;
+  else
+    unqual_elt = c_build_qualified_type (elt, TYPE_UNQUALIFIED);
+
+  /* Using build_distinct_type_copy and modifying things afterward instead
+     of using build_array_type to create a new type preserves all of the
+     TYPE_LANG_FLAG_? bits that the front end may have set.  */
+  main_type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
+  TREE_TYPE (main_type) = unqual_elt;
+  TYPE_DOMAIN (main_type) = build_index_type (maxindex);
+  layout_type (main_type);
+
+  if (quals == 0)
+    type = main_type;
+  else
+    type = c_build_qualified_type (main_type, quals);
+
+  *ptype = type;
+  return failure;
+}
+
+\f
+/* Used to help initialize the builtin-types.def table.  When a type of
+   the correct size doesn't exist, use error_mark_node instead of NULL.
+   The later results in segfaults even when a decl using the type doesn't
+   get invoked.  */
+
+tree
+builtin_type_for_size (int size, bool unsignedp)
+{
+  tree type = lang_hooks.types.type_for_size (size, unsignedp);
+  return type ? type : error_mark_node;
+}
+
+/* A helper function for resolve_overloaded_builtin in resolving the
+   overloaded __sync_ builtins.  Returns a positive power of 2 if the
+   first operand of PARAMS is a pointer to a supported data type.
+   Returns 0 if an error is encountered.  */
+
+static int
+sync_resolve_size (tree function, tree params)
+{
+  tree type;
+  int size;
+
+  if (params == NULL)
+    {
+      error ("too few arguments to function %qE", function);
+      return 0;
+    }
+
+  type = TREE_TYPE (TREE_VALUE (params));
+  if (TREE_CODE (type) != POINTER_TYPE)
+    goto incompatible;
+
+  type = TREE_TYPE (type);
+  if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
+    goto incompatible;
+
+  size = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
+  if (size == 1 || size == 2 || size == 4 || size == 8)
+    return size;
+
+ incompatible:
+  error ("incompatible type for argument %d of %qE", 1, function);
+  return 0;
+}
+
+/* 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.  */
+
+static bool
+sync_resolve_params (tree orig_function, tree function, tree params)
+{
+  tree arg_types = TYPE_ARG_TYPES (TREE_TYPE (function));
+  tree ptype;
+  int number;
+
+  /* We've declared the implementation functions to use "volatile void *"
+     as the pointer parameter, so we shouldn't get any complaints from the
+     call to check_function_arguments what ever type the user used.  */
+  arg_types = TREE_CHAIN (arg_types);
+  ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+  number = 2;
+
+  /* For the rest of the values, we need to cast these to FTYPE, so that we
+     don't get warnings for passing pointer types, etc.  */
+  while (arg_types != void_list_node)
+    {
+      tree val;
+
+      params = TREE_CHAIN (params);
+      if (params == NULL)
+       {
+         error ("too few arguments to function %qE", orig_function);
+         return false;
+       }
+
+      /* ??? Ideally for the first conversion we'd use convert_for_assignment
+        so that we get warnings for anything that doesn't match the pointer
+        type.  This isn't portable across the C and C++ front ends atm.  */
+      val = TREE_VALUE (params);
+      val = convert (ptype, val);
+      val = convert (TREE_VALUE (arg_types), val);
+      TREE_VALUE (params) = val;
+
+      arg_types = TREE_CHAIN (arg_types);
+      number++;
+    }
+
+  /* The definition of these primitives is variadic, with the remaining
+     being "an optional list of variables protected by the memory barrier".
+     No clue what that's supposed to mean, precisely, but we consider all
+     call-clobbered variables to be protected so we're safe.  */
+  TREE_CHAIN (params) = NULL;
+
+  return true;
+}
+
+/* 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.  */
+
+static tree
+sync_resolve_return (tree params, tree result)
+{
+  tree ptype = TREE_TYPE (TREE_TYPE (TREE_VALUE (params)));
+  return convert (ptype, result);
+}
+
+/* Some builtin functions are placeholders for other expressions.  This
+   function should be called immediately after parsing the call expression
+   before surrounding code has committed to the type of the expression.
+
+   FUNCTION is the DECL that has been invoked; it is known to be a builtin.
+   PARAMS is the argument list for the call.  The return value is non-null
+   when expansion is complete, and null if normal processing should
+   continue.  */
+
+tree
+resolve_overloaded_builtin (tree function, tree params)
+{
+  enum built_in_function orig_code = DECL_FUNCTION_CODE (function);
+  switch (DECL_BUILT_IN_CLASS (function))
+    {
+    case BUILT_IN_NORMAL:
+      break;
+    case BUILT_IN_MD:
+      if (targetm.resolve_overloaded_builtin)
+        return targetm.resolve_overloaded_builtin (function, params);
+      else
+        return NULL_TREE;
+    default:
+      return NULL_TREE;
+    }
+    
+  /* Handle BUILT_IN_NORMAL here.  */
+  switch (orig_code)
+    {
+    case BUILT_IN_FETCH_AND_ADD_N:
+    case BUILT_IN_FETCH_AND_SUB_N:
+    case BUILT_IN_FETCH_AND_OR_N:
+    case BUILT_IN_FETCH_AND_AND_N:
+    case BUILT_IN_FETCH_AND_XOR_N:
+    case BUILT_IN_FETCH_AND_NAND_N:
+    case BUILT_IN_ADD_AND_FETCH_N:
+    case BUILT_IN_SUB_AND_FETCH_N:
+    case BUILT_IN_OR_AND_FETCH_N:
+    case BUILT_IN_AND_AND_FETCH_N:
+    case BUILT_IN_XOR_AND_FETCH_N:
+    case BUILT_IN_NAND_AND_FETCH_N:
+    case BUILT_IN_BOOL_COMPARE_AND_SWAP_N:
+    case BUILT_IN_VAL_COMPARE_AND_SWAP_N:
+    case BUILT_IN_LOCK_TEST_AND_SET_N:
+    case BUILT_IN_LOCK_RELEASE_N:
+      {
+       int n = sync_resolve_size (function, params);
+       tree new_function, result;
+
+       if (n == 0)
+         return error_mark_node;
+
+       new_function = built_in_decls[orig_code + exact_log2 (n) + 1];
+       if (!sync_resolve_params (function, new_function, params))
+         return error_mark_node;
+
+       result = build_function_call (new_function, params);
+       if (orig_code != BUILT_IN_BOOL_COMPARE_AND_SWAP_N
+           && orig_code != BUILT_IN_LOCK_RELEASE_N)
+         result = sync_resolve_return (params, result);
+
+       return result;
+      }
+
+    default:
+      return NULL_TREE;
+    }
+}
+
+/* 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;
+}
+
 #include "gt-c-common.h"