OSDN Git Service

Document the __OBJC__ macro.
[pf3gnuchains/gcc-fork.git] / gcc / c-common.c
index 3aa402f..b08ef5b 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
-   Free Software Foundation, Inc.
+   Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
+   2001, 2002 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -30,8 +30,11 @@ Software Foundation, 59 Temple Place - Suite 330, Boston, MA
 #include "ggc.h"
 #include "expr.h"
 #include "c-common.h"
+#include "tree-inline.h"
+#include "diagnostic.h"
 #include "tm_p.h"
 #include "obstack.h"
+#include "c-lex.h"
 #include "cpplib.h"
 #include "target.h"
 cpp_reader *parse_in;          /* Declared in c-lex.h.  */
@@ -77,6 +80,10 @@ cpp_reader *parse_in;                /* Declared in c-lex.h.  */
                        : "long long unsigned int"))
 #endif
 
+/* The variant of the C language being processed.  */
+
+enum c_language_kind c_language;
+
 /* The following symbols are subsumed in the c_global_trees array, and
    listed here individually for documentation purposes.
 
@@ -157,12 +164,12 @@ cpp_reader *parse_in;             /* Declared in c-lex.h.  */
 
        tree void_list_node;
 
-  The lazily created VAR_DECLS for __FUNCTION__, __PRETTY_FUNCTION__,
+  The lazily created VAR_DECLs for __FUNCTION__, __PRETTY_FUNCTION__,
   and __func__. (C doesn't generate __FUNCTION__ and__PRETTY_FUNCTION__
   VAR_DECLS, but C++ does.)
 
        tree function_name_decl_node;
-       tree pretty_function_name_declnode;
+       tree pretty_function_name_decl_node;
        tree c99_function_name_decl_node;
 
   Stack of nested function name VAR_DECLs.
@@ -194,6 +201,9 @@ int flag_short_wchar;
 
 int warn_sequence_point;
 
+/* Nonzero means to warn about compile-time division by zero.  */
+int warn_div_by_zero = 1;
+
 /* The elements of `ridpointers' are identifier nodes for the reserved
    type names and storage classes.  It is indexed by a RID_... value.  */
 tree *ridpointers;
@@ -208,26 +218,16 @@ int (*lang_statement_code_p)           PARAMS ((enum tree_code));
    any action required right before expand_function_end is called.  */
 void (*lang_expand_function_end)       PARAMS ((void));
 
-/* If this variable is defined to a non-NULL value, it will be called
-   after the file has been completely parsed.  */
-void (*back_end_hook) PARAMS ((tree));
-
 /* Nonzero means the expression being parsed will never be evaluated.
    This is a count, since unevaluated expressions can nest.  */
 int skip_evaluation;
 
-enum attrs {A_PACKED, A_NOCOMMON, A_COMMON, A_NORETURN, A_CONST, A_T_UNION,
-           A_NO_CHECK_MEMORY_USAGE, A_NO_INSTRUMENT_FUNCTION,
-           A_CONSTRUCTOR, A_DESTRUCTOR, A_MODE, A_SECTION, A_ALIGNED,
-           A_UNUSED, A_FORMAT, A_FORMAT_ARG, A_WEAK, A_ALIAS, A_MALLOC,
-           A_NO_LIMIT_STACK, A_PURE};
-
 /* Information about how a function name is generated.  */
 struct fname_var_t
 {
-  tree *decl;  /* pointer to the VAR_DECL.  */
-  unsigned rid;        /* RID number for the identifier.  */
-  int pretty;  /* How pretty is it? */
+  tree *const decl;    /* pointer to the VAR_DECL.  */
+  const unsigned rid;  /* RID number for the identifier.  */
+  const int pretty;    /* How pretty is it? */
 };
 
 /* The three ways of getting then name of the current function.  */
@@ -243,7 +243,6 @@ const struct fname_var_t fname_vars[] =
   {NULL, 0, 0},
 };
 
-static void init_attributes            PARAMS ((void));
 static int constant_fits_type_p                PARAMS ((tree, tree));
 
 /* Keep a stack of if statements.  We record the number of compound
@@ -269,28 +268,32 @@ static int if_stack_space = 0;
 static int if_stack_pointer = 0;
 
 /* Record the start of an if-then, and record the start of it
-   for ambiguous else detection.  */
+   for ambiguous else detection.
+
+   COND is the condition for the if-then statement.
+
+   IF_STMT is the statement node that has already been created for
+   this if-then statement.  It is created before parsing the
+   condition to keep line number information accurate.  */
 
 void
-c_expand_start_cond (cond, compstmt_count)
+c_expand_start_cond (cond, compstmt_count, if_stmt)
      tree cond;
      int compstmt_count;
+     tree if_stmt;
 {
-  tree if_stmt;
-
   /* Make sure there is enough space on the stack.  */
   if (if_stack_space == 0)
     {
       if_stack_space = 10;
-      if_stack = (if_elt *)xmalloc (10 * sizeof (if_elt));
+      if_stack = (if_elt *) xmalloc (10 * sizeof (if_elt));
     }
   else if (if_stack_space == if_stack_pointer)
     {
       if_stack_space += 10;
-      if_stack = (if_elt *)xrealloc (if_stack, if_stack_space * sizeof (if_elt));
+      if_stack = (if_elt *) xrealloc (if_stack, if_stack_space * sizeof (if_elt));
     }
 
-  if_stmt = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
   IF_COND (if_stmt) = cond;
   add_stmt (if_stmt);
 
@@ -356,6 +359,46 @@ c_finish_else ()
   RECHAIN_STMTS (if_stmt, ELSE_CLAUSE (if_stmt));
 }
 
+/* Begin an if-statement.  Returns a newly created IF_STMT if
+   appropriate.
+
+   Unlike the C++ front-end, we do not call add_stmt here; it is
+   probably safe to do so, but I am not very familiar with this
+   code so I am being extra careful not to change its behavior
+   beyond what is strictly necessary for correctness.  */
+
+tree
+c_begin_if_stmt ()
+{
+  tree r;
+  r = build_stmt (IF_STMT, NULL_TREE, NULL_TREE, NULL_TREE);
+  return r;
+}
+
+/* Begin a while statement.  Returns a newly created WHILE_STMT if
+   appropriate.
+
+   Unlike the C++ front-end, we do not call add_stmt here; it is
+   probably safe to do so, but I am not very familiar with this
+   code so I am being extra careful not to change its behavior
+   beyond what is strictly necessary for correctness.  */
+
+tree
+c_begin_while_stmt ()
+{
+  tree r;
+  r = build_stmt (WHILE_STMT, NULL_TREE, NULL_TREE);
+  return r;
+}
+
+void
+c_finish_while_stmt_cond (cond, while_stmt)
+     tree while_stmt;
+     tree cond;
+{
+  WHILE_COND (while_stmt) = cond;
+}
+
 /* Push current bindings for the function name VAR_DECLS.  */
 
 void
@@ -400,7 +443,7 @@ finish_fname_decls ()
   
   if (body)
     {
-      /* They were called into existance, so add to statement tree.  */
+      /* They were called into existence, so add to statement tree.  */
       body = chainon (body,
                      TREE_CHAIN (DECL_SAVED_TREE (current_function_decl)));
       body = build_stmt (COMPOUND_STMT, body);
@@ -469,7 +512,7 @@ fname_string (rid)
    now. RID indicates how it should be formatted and IDENTIFIER_NODE
    ID is its name (unfortunately C and C++ hold the RID values of
    keywords in different places, so we can't derive RID from ID in
-   this language independant code.  */
+   this language independent code.  */
 
 tree
 fname_decl (rid, id)
@@ -496,1291 +539,157 @@ fname_decl (rid, id)
             it after the function is complete.  */
          tree stmts = TREE_CHAIN (saved_last_tree);
 
-         TREE_CHAIN (saved_last_tree) = NULL_TREE;
-         last_tree = saved_last_tree;
-         saved_function_name_decls = tree_cons (decl, stmts,
-                                                saved_function_name_decls);
-       }
-      *fname_vars[ix].decl = decl;
-    }
-  if (!ix && !current_function_decl)
-    pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
-  
-  return decl;
-}
-
-/* Given a chain of STRING_CST nodes,
-   concatenate them into one STRING_CST
-   and give it a suitable array-of-chars data type.  */
-
-tree
-combine_strings (strings)
-     tree strings;
-{
-  register tree value, t;
-  register int length = 1;
-  int wide_length = 0;
-  int wide_flag = 0;
-  int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
-  int nchars;
-  const int nchars_max = flag_isoc99 ? 4095 : 509;
-
-  if (TREE_CHAIN (strings))
-    {
-      /* More than one in the chain, so concatenate.  */
-      register char *p, *q;
-
-      /* Don't include the \0 at the end of each substring,
-        except for the last one.
-        Count wide strings and ordinary strings separately.  */
-      for (t = strings; t; t = TREE_CHAIN (t))
-       {
-         if (TREE_TYPE (t) == wchar_array_type_node)
-           {
-             wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes);
-             wide_flag = 1;
-           }
-         else
-           length += (TREE_STRING_LENGTH (t) - 1);
-       }
-
-      /* If anything is wide, the non-wides will be converted,
-        which makes them take more space.  */
-      if (wide_flag)
-       length = length * wchar_bytes + wide_length;
-
-      p = alloca (length);
-
-      /* Copy the individual strings into the new combined string.
-        If the combined string is wide, convert the chars to ints
-        for any individual strings that are not wide.  */
-
-      q = p;
-      for (t = strings; t; t = TREE_CHAIN (t))
-       {
-         int len = (TREE_STRING_LENGTH (t)
-                    - ((TREE_TYPE (t) == wchar_array_type_node)
-                       ? wchar_bytes : 1));
-         if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
-           {
-             memcpy (q, TREE_STRING_POINTER (t), len);
-             q += len;
-           }
-         else
-           {
-             int i, j;
-             for (i = 0; i < len; i++)
-               {
-                 if (BYTES_BIG_ENDIAN)
-                   {
-                     for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
-                       *q++ = 0;
-                     *q++ = TREE_STRING_POINTER (t)[i];
-                   }
-                 else
-                   {
-                     *q++ = TREE_STRING_POINTER (t)[i];
-                     for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
-                       *q++ = 0;
-                   }
-               }
-           }
-       }
-      if (wide_flag)
-       {
-         int i;
-         for (i = 0; i < wchar_bytes; i++)
-           *q++ = 0;
-       }
-      else
-       *q = 0;
-
-      value = build_string (length, p);
-    }
-  else
-    {
-      value = strings;
-      length = TREE_STRING_LENGTH (value);
-      if (TREE_TYPE (value) == wchar_array_type_node)
-       wide_flag = 1;
-    }
-
-  /* Compute the number of elements, for the array type.  */
-  nchars = wide_flag ? length / wchar_bytes : length;
-
-  if (pedantic && nchars - 1 > nchars_max && c_language == clk_c)
-    pedwarn ("string length `%d' is greater than the length `%d' ISO C%d compilers are required to support",
-            nchars - 1, nchars_max, flag_isoc99 ? 99 : 89);
-
-  /* Create the array type for the string constant.
-     -Wwrite-strings says make the string constant an array of const char
-     so that copying it to a non-const pointer will get a warning.
-     For C++, this is the standard behavior.  */
-  if (flag_const_strings
-      && (! flag_traditional  && ! flag_writable_strings))
-    {
-      tree elements
-       = build_type_variant (wide_flag ? wchar_type_node : char_type_node,
-                             1, 0);
-      TREE_TYPE (value)
-       = build_array_type (elements,
-                           build_index_type (build_int_2 (nchars - 1, 0)));
-    }
-  else
-    TREE_TYPE (value)
-      = build_array_type (wide_flag ? wchar_type_node : char_type_node,
-                         build_index_type (build_int_2 (nchars - 1, 0)));
-
-  TREE_CONSTANT (value) = 1;
-  TREE_READONLY (value) = ! flag_writable_strings;
-  TREE_STATIC (value) = 1;
-  return value;
-}
-\f
-/* Table of the tables of attributes (common, language, machine) searched.  */
-static const struct attribute_spec *attribute_tables[3];
-
-static bool attributes_initialized = false;
-
-static tree handle_packed_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_nocommon_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_common_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_noreturn_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_unused_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_const_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_transparent_union_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_constructor_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_destructor_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_mode_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_section_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_aligned_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_weak_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_alias_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_no_instrument_function_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_no_check_memory_usage_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_malloc_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_no_limit_stack_attribute PARAMS ((tree *, tree, tree, int, bool *));
-static tree handle_pure_attribute PARAMS ((tree *, tree, tree, int, bool *));
-
-/* Table of machine-independent attributes common to all C-like languages.  */
-static const struct attribute_spec c_common_attribute_table[] =
-{
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
-  { "packed",                 0, 0, false, false, false,
-                             handle_packed_attribute },
-  { "nocommon",               0, 0, true,  false, false,
-                             handle_nocommon_attribute },
-  { "common",                 0, 0, true,  false, false,
-                             handle_common_attribute },
-  /* FIXME: logically, noreturn attributes should be listed as
-     "false, true, true" and apply to function types.  But implementing this
-     would require all the places in the compiler that use TREE_THIS_VOLATILE
-     on a decl to identify non-returning functions to be located and fixed
-     to check the function type instead.  */
-  { "noreturn",               0, 0, true,  false, false,
-                             handle_noreturn_attribute },
-  { "volatile",               0, 0, true,  false, false,
-                             handle_noreturn_attribute },
-  { "unused",                 0, 0, false, false, false,
-                             handle_unused_attribute },
-  /* The same comments as for noreturn attributes apply to const ones.  */
-  { "const",                  0, 0, true,  false, false,
-                             handle_const_attribute },
-  { "transparent_union",      0, 0, false, false, false,
-                             handle_transparent_union_attribute },
-  { "constructor",            0, 0, true,  false, false,
-                             handle_constructor_attribute },
-  { "destructor",             0, 0, true,  false, false,
-                             handle_destructor_attribute },
-  { "mode",                   1, 1, true,  false, false,
-                             handle_mode_attribute },
-  { "section",                1, 1, true,  false, false,
-                             handle_section_attribute },
-  { "aligned",                0, 1, false, false, false,
-                             handle_aligned_attribute },
-  { "format",                 3, 3, true,  false, false,
-                             handle_format_attribute },
-  { "format_arg",             1, 1, true,  false, false,
-                             handle_format_arg_attribute },
-  { "weak",                   0, 0, true,  false, false,
-                             handle_weak_attribute },
-  { "alias",                  1, 1, true,  false, false,
-                             handle_alias_attribute },
-  { "no_instrument_function", 0, 0, true,  false, false,
-                             handle_no_instrument_function_attribute },
-  { "no_check_memory_usage",  0, 0, true,  false, false,
-                             handle_no_check_memory_usage_attribute },
-  { "malloc",                 0, 0, true,  false, false,
-                             handle_malloc_attribute },
-  { "no_stack_limit",         0, 0, true,  false, false,
-                             handle_no_limit_stack_attribute },
-  { "pure",                   0, 0, true,  false, false,
-                             handle_pure_attribute },
-  { NULL,                     0, 0, false, false, false, NULL }
-};
-
-/* Default empty table of language attributes.  */
-static const struct attribute_spec default_lang_attribute_table[] =
-{
-  { NULL, 0, 0, false, false, false, NULL }
-};
-
-/* Table of machine-independent attributes for a particular language.  */
-const struct attribute_spec *lang_attribute_table
-  = default_lang_attribute_table;
-
-/* Initialize attribute tables, and make some sanity checks
-   if --enable-checking.  */
-
-static void
-init_attributes ()
-{
-#ifdef ENABLE_CHECKING
-  int i;
-#endif
-  attribute_tables[0] = c_common_attribute_table;
-  attribute_tables[1] = lang_attribute_table;
-  attribute_tables[2] = targetm.attribute_table;
-#ifdef ENABLE_CHECKING
-  /* Make some sanity checks on the attribute tables.  */
-  for (i = 0;
-       i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
-       i++)
-    {
-      int j;
-      for (j = 0; attribute_tables[i][j].name != NULL; j++)
-       {
-         /* The name must not begin and end with __.  */
-         const char *name = attribute_tables[i][j].name;
-         int len = strlen (name);
-         if (name[0] == '_' && name[1] == '_'
-             && name[len - 1] == '_' && name[len - 2] == '_')
-           abort ();
-         /* The minimum and maximum lengths must be consistent.  */
-         if (attribute_tables[i][j].min_length < 0)
-           abort ();
-         if (attribute_tables[i][j].max_length != -1
-             && attribute_tables[i][j].max_length < attribute_tables[i][j].min_length)
-           abort ();
-         /* An attribute cannot require both a DECL and a TYPE.  */
-         if (attribute_tables[i][j].decl_required
-             && attribute_tables[i][j].type_required)
-           abort ();
-         /* If an attribute requires a function type, in particular
-            it requires a type.  */
-         if (attribute_tables[i][j].function_type_required
-             && !attribute_tables[i][j].type_required)
-           abort ();
-       }
-    }
-  /* Check that each name occurs just once in each table.  */
-  for (i = 0;
-       i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
-       i++)
-    {
-      int j, k;
-      for (j = 0; attribute_tables[i][j].name != NULL; j++)
-       for (k = j + 1; attribute_tables[i][k].name != NULL; k++)
-         if (!strcmp (attribute_tables[i][j].name,
-                      attribute_tables[i][k].name))
-           abort ();
-    }
-  /* Check that no name occurs in more than one table.  */
-  for (i = 0;
-       i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
-       i++)
-    {
-      int j;
-      for (j = i + 1;
-          j < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
-          j++)
-       {
-         int k, l;
-         for (k = 0; attribute_tables[i][k].name != NULL; k++)
-           for (l = 0; attribute_tables[j][l].name != NULL; l++)
-             if (!strcmp (attribute_tables[i][k].name,
-                          attribute_tables[j][l].name))
-               abort ();
-       }
-    }
-#endif
-  attributes_initialized = true;
-}
-\f
-/* Process the attributes listed in ATTRIBUTES and install them in *NODE,
-   which is either a DECL (including a TYPE_DECL) or a TYPE.  If a DECL,
-   it should be modified in place; if a TYPE, a copy should be created
-   unless ATTR_FLAG_TYPE_IN_PLACE is set in FLAGS.  FLAGS gives further
-   information, in the form of a bitwise OR of flags in enum attribute_flags
-   from tree.h.  Depending on these flags, some attributes may be
-   returned to be applied at a later stage (for example, to apply
-   a decl attribute to the declaration rather than to its type).  */
-
-tree
-decl_attributes (node, attributes, flags)
-     tree *node, attributes;
-     int flags;
-{
-  tree a;
-  tree returned_attrs = NULL_TREE;
-
-  if (!attributes_initialized)
-    init_attributes ();
-
-  (*targetm.insert_attributes) (*node, &attributes);
-
-  for (a = attributes; a; a = TREE_CHAIN (a))
-    {
-      tree name = TREE_PURPOSE (a);
-      tree args = TREE_VALUE (a);
-      tree *anode = node;
-      const struct attribute_spec *spec = NULL;
-      bool no_add_attrs = 0;
-      int i;
-
-      for (i = 0;
-          i < (int) (sizeof (attribute_tables) / sizeof (attribute_tables[0]));
-          i++)
-       {
-         int j;
-         for (j = 0; attribute_tables[i][j].name != NULL; j++)
-           {
-             if (is_attribute_p (attribute_tables[i][j].name, name))
-               {
-                 spec = &attribute_tables[i][j];
-                 break;
-               }
-           }
-         if (spec != NULL)
-           break;
-       }
-
-      if (spec == NULL)
-       {
-         warning ("`%s' attribute directive ignored",
-                  IDENTIFIER_POINTER (name));
-         continue;
-       }
-      else if (list_length (args) < spec->min_length
-              || (spec->max_length >= 0
-                  && list_length (args) > spec->max_length))
-       {
-         error ("wrong number of arguments specified for `%s' attribute",
-                IDENTIFIER_POINTER (name));
-         continue;
-       }
-
-      if (spec->decl_required && !DECL_P (*anode))
-       {
-         if (flags & ((int) ATTR_FLAG_DECL_NEXT
-                      | (int) ATTR_FLAG_FUNCTION_NEXT
-                      | (int) ATTR_FLAG_ARRAY_NEXT))
-           {
-             /* Pass on this attribute to be tried again.  */
-             returned_attrs = tree_cons (name, args, returned_attrs);
-             continue;
-           }
-         else
-           {
-             warning ("`%s' attribute does not apply to types",
-                      IDENTIFIER_POINTER (name));
-             continue;
-           }
-       }
-
-      if (spec->type_required && DECL_P (*anode))
-       {
-         anode = &TREE_TYPE (*anode);
-       }
-
-      if (spec->function_type_required && TREE_CODE (*anode) != FUNCTION_TYPE
-         && TREE_CODE (*anode) != METHOD_TYPE)
-       {
-         if (TREE_CODE (*anode) == POINTER_TYPE
-             && (TREE_CODE (TREE_TYPE (*anode)) == FUNCTION_TYPE
-                 || TREE_CODE (TREE_TYPE (*anode)) == METHOD_TYPE))
-           {
-             if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-               *anode = build_type_copy (*anode);
-             anode = &TREE_TYPE (*anode);
-           }
-         else if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
-           {
-             /* Pass on this attribute to be tried again.  */
-             returned_attrs = tree_cons (name, args, returned_attrs);
-             continue;
-           }
-
-         if (TREE_CODE (*anode) != FUNCTION_TYPE
-             && TREE_CODE (*anode) != METHOD_TYPE)
-           {
-             warning ("`%s' attribute only applies to function types",
-                      IDENTIFIER_POINTER (name));
-             continue;
-           }
-       }
-
-      if (spec->handler != NULL)
-       returned_attrs = chainon ((*spec->handler) (anode, name, args,
-                                                   flags, &no_add_attrs),
-                                 returned_attrs);
-      if (!no_add_attrs)
-       {
-         tree old_attrs;
-         tree a;
-
-         if (DECL_P (*anode))
-           old_attrs = DECL_ATTRIBUTES (*anode);
-         else
-           old_attrs = TYPE_ATTRIBUTES (*anode);
-
-         for (a = lookup_attribute (spec->name, old_attrs);
-              a != NULL_TREE;
-              a = lookup_attribute (spec->name, TREE_CHAIN (a)))
-           {
-             if (simple_cst_equal (TREE_VALUE (a), args) == 1)
-               break;
-           }
-
-         if (a == NULL_TREE)
-           {
-             /* This attribute isn't already in the list.  */
-             if (DECL_P (*anode))
-               DECL_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
-             else if (flags & (int) ATTR_FLAG_TYPE_IN_PLACE)
-               TYPE_ATTRIBUTES (*anode) = tree_cons (name, args, old_attrs);
-             else
-               *anode = build_type_attribute_variant (*anode,
-                                                      tree_cons (name, args,
-                                                                 old_attrs));
-           }
-       }
-    }
-
-  return returned_attrs;
-}
-
-/* Handle a "packed" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_packed_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags;
-     bool *no_add_attrs;
-{
-  tree *type = NULL;
-  if (DECL_P (*node))
-    {
-      if (TREE_CODE (*node) == TYPE_DECL)
-       type = &TREE_TYPE (*node);
-    }
-  else
-    type = node;
-  if (type)
-    {
-      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-       *type = build_type_copy (*type);
-      TYPE_PACKED (*type) = 1;
-    }
-  else if (TREE_CODE (*node) == FIELD_DECL)
-    DECL_PACKED (*node) = 1;
-  /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
-     used for DECL_REGISTER.  It wouldn't mean anything anyway.  */
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "nocommon" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_nocommon_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  if (TREE_CODE (*node) == VAR_DECL)
-    DECL_COMMON (*node) = 0;
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "common" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_common_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  if (TREE_CODE (*node) == VAR_DECL)
-    DECL_COMMON (*node) = 1;
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "noreturn" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_noreturn_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  tree type = TREE_TYPE (*node);
-
-  /* See FIXME comment in c_common_attribute_table.  */
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    TREE_THIS_VOLATILE (*node) = 1;
-  else if (TREE_CODE (type) == POINTER_TYPE
-          && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
-    TREE_TYPE (*node)
-      = build_pointer_type (build_type_variant (TREE_TYPE (type),
-                                               TREE_READONLY (TREE_TYPE (type)), 1));
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "unused" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_unused_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags;
-     bool *no_add_attrs;
-{
-  if (DECL_P (*node))
-    {
-      tree decl = *node;
-
-      if (TREE_CODE (decl) == PARM_DECL
-         || TREE_CODE (decl) == VAR_DECL
-         || TREE_CODE (decl) == FUNCTION_DECL
-         || TREE_CODE (decl) == LABEL_DECL
-         || TREE_CODE (decl) == TYPE_DECL)
-       TREE_USED (decl) = 1;
-      else
-       {
-         warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-         *no_add_attrs = true;
-       }
-    }
-  else
-    {
-      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-       *node = build_type_copy (*node);
-      TREE_USED (*node) = 1;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "const" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_const_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  tree type = TREE_TYPE (*node);
-
-  /* See FIXME comment on noreturn in c_common_attribute_table.  */
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    TREE_READONLY (*node) = 1;
-  else if (TREE_CODE (type) == POINTER_TYPE
-          && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
-    TREE_TYPE (*node)
-      = build_pointer_type (build_type_variant (TREE_TYPE (type), 1,
-                                               TREE_THIS_VOLATILE (TREE_TYPE (type))));
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "transparent_union" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_transparent_union_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags;
-     bool *no_add_attrs;
-{
-  tree decl = NULL_TREE;
-  tree *type = NULL;
-  int is_type = 0;
-
-  if (DECL_P (*node))
-    {
-      decl = *node;
-      type = &TREE_TYPE (decl);
-      is_type = TREE_CODE (*node) == TYPE_DECL;
-    }
-  else if (TYPE_P (*node))
-    type = node, is_type = 1;
-
-  if (is_type
-      && TREE_CODE (*type) == UNION_TYPE
-      && (decl == 0
-         || (TYPE_FIELDS (*type) != 0
-             && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))))
-    {
-      if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-       *type = build_type_copy (*type);
-      TYPE_TRANSPARENT_UNION (*type) = 1;
-    }
-  else if (decl != 0 && TREE_CODE (decl) == PARM_DECL
-          && TREE_CODE (*type) == UNION_TYPE
-          && TYPE_MODE (*type) == DECL_MODE (TYPE_FIELDS (*type)))
-    DECL_TRANSPARENT_UNION (decl) = 1;
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "constructor" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_constructor_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  tree decl = *node;
-  tree type = TREE_TYPE (decl);
-
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && TREE_CODE (type) == FUNCTION_TYPE
-      && decl_function_context (decl) == 0)
-    {
-      DECL_STATIC_CONSTRUCTOR (decl) = 1;
-      TREE_USED (decl) = 1;
-    }
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "destructor" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_destructor_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  tree decl = *node;
-  tree type = TREE_TYPE (decl);
-
-  if (TREE_CODE (decl) == FUNCTION_DECL
-      && TREE_CODE (type) == FUNCTION_TYPE
-      && decl_function_context (decl) == 0)
-    {
-      DECL_STATIC_DESTRUCTOR (decl) = 1;
-      TREE_USED (decl) = 1;
-    }
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "mode" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_mode_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  tree decl = *node;
-  tree type = TREE_TYPE (decl);
-
-  *no_add_attrs = true;
-
-  if (TREE_CODE (TREE_VALUE (args)) != IDENTIFIER_NODE)
-    warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-  else
-    {
-      int j;
-      const char *p = IDENTIFIER_POINTER (TREE_VALUE (args));
-      int len = strlen (p);
-      enum machine_mode mode = VOIDmode;
-      tree typefm;
-
-      if (len > 4 && p[0] == '_' && p[1] == '_'
-         && p[len - 1] == '_' && p[len - 2] == '_')
-       {
-         char *newp = (char *) alloca (len - 1);
-
-         strcpy (newp, &p[2]);
-         newp[len - 4] = '\0';
-         p = newp;
-       }
-
-      /* Give this decl a type with the specified mode.
-        First check for the special modes.  */
-      if (! strcmp (p, "byte"))
-       mode = byte_mode;
-      else if (!strcmp (p, "word"))
-       mode = word_mode;
-      else if (! strcmp (p, "pointer"))
-       mode = ptr_mode;
-      else
-       for (j = 0; j < NUM_MACHINE_MODES; j++)
-         if (!strcmp (p, GET_MODE_NAME (j)))
-           mode = (enum machine_mode) j;
-
-      if (mode == VOIDmode)
-       error ("unknown machine mode `%s'", p);
-      else if (0 == (typefm = type_for_mode (mode,
-                                            TREE_UNSIGNED (type))))
-       error ("no data type for mode `%s'", p);
-      else
-       {
-         if (TYPE_PRECISION (typefm) > (TREE_UNSIGNED (type)
-                                        ? TYPE_PRECISION(uintmax_type_node)
-                                        : TYPE_PRECISION(intmax_type_node))
-             && pedantic)
-           pedwarn ("type with more precision than %s",
-                    TREE_UNSIGNED (type) ? "uintmax_t" : "intmax_t");
-         TREE_TYPE (decl) = type = typefm;
-         DECL_SIZE (decl) = DECL_SIZE_UNIT (decl) = 0;
-         if (TREE_CODE (decl) != FIELD_DECL)
-           layout_decl (decl, 0);
-       }
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "section" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_section_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name ATTRIBUTE_UNUSED;
-     tree args;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  tree decl = *node;
-
-  if (targetm.have_named_sections)
-    {
-      if ((TREE_CODE (decl) == FUNCTION_DECL
-          || TREE_CODE (decl) == VAR_DECL)
-         && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
-       {
-         if (TREE_CODE (decl) == VAR_DECL
-             && current_function_decl != NULL_TREE
-             && ! TREE_STATIC (decl))
-           {
-             error_with_decl (decl,
-                              "section attribute cannot be specified for local variables");
-             *no_add_attrs = true;
-           }
-         /* The decl may have already been given a section attribute
-            from a previous declaration.  Ensure they match.  */
-         else if (DECL_SECTION_NAME (decl) != NULL_TREE
-                  && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
-                             TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
-           {
-             error_with_decl (*node,
-                              "section of `%s' conflicts with previous declaration");
-             *no_add_attrs = true;
-           }
-         else
-           DECL_SECTION_NAME (decl) = TREE_VALUE (args);
-       }
-      else
-       {
-         error_with_decl (*node,
-                          "section attribute not allowed for `%s'");
-         *no_add_attrs = true;
-       }
-    }
-  else
-    {
-      error_with_decl (*node,
-                      "section attributes are not supported for this target");
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "aligned" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_aligned_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name ATTRIBUTE_UNUSED;
-     tree args;
-     int flags;
-     bool *no_add_attrs;
-{
-  tree decl = NULL_TREE;
-  tree *type = NULL;
-  int is_type = 0;
-  tree align_expr = (args ? TREE_VALUE (args)
-                    : size_int (BIGGEST_ALIGNMENT / BITS_PER_UNIT));
-  int i;
-
-  if (DECL_P (*node))
-    {
-      decl = *node;
-      type = &TREE_TYPE (decl);
-      is_type = TREE_CODE (*node) == TYPE_DECL;
-    }
-  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");
-      *no_add_attrs = true;
-    }
-  else if ((i = tree_log2 (align_expr)) == -1)
-    {
-      error ("requested alignment is not a power of 2");
-      *no_add_attrs = true;
-    }
-  else if (i > HOST_BITS_PER_INT - 2)
-    {
-      error ("requested alignment is too large");
-      *no_add_attrs = true;
-    }
-  else if (is_type)
-    {
-      /* If we have a TYPE_DECL, then copy the type, so that we
-        don't accidentally modify a builtin type.  See pushdecl.  */
-      if (decl && TREE_TYPE (decl) != error_mark_node
-         && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
-       {
-         tree tt = TREE_TYPE (decl);
-         *type = build_type_copy (*type);
-         DECL_ORIGINAL_TYPE (decl) = tt;
-         TYPE_NAME (*type) = decl;
-         TREE_USED (*type) = TREE_USED (decl);
-         TREE_TYPE (decl) = *type;
-       }
-      else if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
-       *type = build_type_copy (*type);
-
-      TYPE_ALIGN (*type) = (1 << i) * BITS_PER_UNIT;
-      TYPE_USER_ALIGN (*type) = 1;
-    }
-  else if (TREE_CODE (decl) != VAR_DECL
-          && TREE_CODE (decl) != FIELD_DECL)
-    {
-      error_with_decl (decl,
-                      "alignment may not be specified for `%s'");
-      *no_add_attrs = true;
-    }
-  else
-    {
-      DECL_ALIGN (decl) = (1 << i) * BITS_PER_UNIT;
-      DECL_USER_ALIGN (decl) = 1;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "weak" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_weak_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name ATTRIBUTE_UNUSED;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs ATTRIBUTE_UNUSED;
-{
-  declare_weak (*node);
-
-  return NULL_TREE;
-}
-
-/* Handle an "alias" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_alias_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  tree decl = *node;
-
-  if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
-      || (TREE_CODE (decl) != FUNCTION_DECL && ! DECL_EXTERNAL (decl)))
-    {
-      error_with_decl (decl,
-                      "`%s' defined both normally and as an alias");
-      *no_add_attrs = true;
-    }
-  else if (decl_function_context (decl) == 0)
-    {
-      tree id;
-
-      id = TREE_VALUE (args);
-      if (TREE_CODE (id) != STRING_CST)
-       {
-         error ("alias arg not a string");
-         *no_add_attrs = true;
-         return NULL_TREE;
-       }
-      id = get_identifier (TREE_STRING_POINTER (id));
-      /* This counts as a use of the object pointed to.  */
-      TREE_USED (id) = 1;
-
-      if (TREE_CODE (decl) == FUNCTION_DECL)
-       DECL_INITIAL (decl) = error_mark_node;
-      else
-       DECL_EXTERNAL (decl) = 0;
-      assemble_alias (decl, id);
-    }
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "no_instrument_function" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_no_instrument_function_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  tree decl = *node;
-
-  if (TREE_CODE (decl) != FUNCTION_DECL)
-    {
-      error_with_decl (decl,
-                      "`%s' attribute applies only to functions",
-                      IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-  else if (DECL_INITIAL (decl))
-    {
-      error_with_decl (decl,
-                      "can't set `%s' attribute after definition",
-                      IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-  else
-    DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
-
-  return NULL_TREE;
-}
-
-/* Handle a "no_check_memory_usage" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_no_check_memory_usage_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  tree decl = *node;
-
-  if (TREE_CODE (decl) != FUNCTION_DECL)
-    {
-      error_with_decl (decl,
-                      "`%s' attribute applies only to functions",
-                      IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-  else if (DECL_INITIAL (decl))
-    {
-      error_with_decl (decl,
-                      "can't set `%s' attribute after definition",
-                      IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-  else
-    DECL_NO_CHECK_MEMORY_USAGE (decl) = 1;
-
-  return NULL_TREE;
-}
-
-/* Handle a "malloc" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_malloc_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    DECL_IS_MALLOC (*node) = 1;
-  /* ??? TODO: Support types.  */
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-
-  return NULL_TREE;
-}
-
-/* Handle a "no_limit_stack" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_no_limit_stack_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  tree decl = *node;
-
-  if (TREE_CODE (decl) != FUNCTION_DECL)
-    {
-      error_with_decl (decl,
-                      "`%s' attribute applies only to functions",
-                      IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-  else if (DECL_INITIAL (decl))
-    {
-      error_with_decl (decl,
-                      "can't set `%s' attribute after definition",
-                      IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
-    }
-  else
-    DECL_NO_LIMIT_STACK (decl) = 1;
-
-  return NULL_TREE;
-}
-
-/* Handle a "pure" attribute; arguments as in
-   struct attribute_spec.handler.  */
-
-static tree
-handle_pure_attribute (node, name, args, flags, no_add_attrs)
-     tree *node;
-     tree name;
-     tree args ATTRIBUTE_UNUSED;
-     int flags ATTRIBUTE_UNUSED;
-     bool *no_add_attrs;
-{
-  if (TREE_CODE (*node) == FUNCTION_DECL)
-    DECL_IS_PURE (*node) = 1;
-  /* ??? TODO: Support types.  */
-  else
-    {
-      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
-      *no_add_attrs = true;
+         TREE_CHAIN (saved_last_tree) = NULL_TREE;
+         last_tree = saved_last_tree;
+         saved_function_name_decls = tree_cons (decl, stmts,
+                                                saved_function_name_decls);
+       }
+      *fname_vars[ix].decl = decl;
     }
-
-  return NULL_TREE;
+  if (!ix && !current_function_decl)
+    pedwarn_with_decl (decl, "`%s' is not defined outside of function scope");
+  
+  return decl;
 }
 
-/* Split SPECS_ATTRS, a list of declspecs and prefix attributes, into two
-   lists.  SPECS_ATTRS may also be just a typespec (eg: RECORD_TYPE).
-
-   The head of the declspec list is stored in DECLSPECS.
-   The head of the attribute list is stored in PREFIX_ATTRIBUTES.
-
-   Note that attributes in SPECS_ATTRS are stored in the TREE_PURPOSE of
-   the list elements.  We drop the containing TREE_LIST nodes and link the
-   resulting attributes together the way decl_attributes expects them.  */
+/* Given a chain of STRING_CST nodes,
+   concatenate them into one STRING_CST
+   and give it a suitable array-of-chars data type.  */
 
-void
-split_specs_attrs (specs_attrs, declspecs, prefix_attributes)
-     tree specs_attrs;
-     tree *declspecs, *prefix_attributes;
+tree
+combine_strings (strings)
+     tree strings;
 {
-  tree t, s, a, next, specs, attrs;
-
-  /* This can happen after an __extension__ in pedantic mode.  */
-  if (specs_attrs != NULL_TREE 
-      && TREE_CODE (specs_attrs) == INTEGER_CST)
-    {
-      *declspecs = NULL_TREE;
-      *prefix_attributes = NULL_TREE;
-      return;
-    }
+  tree value, t;
+  int length = 1;
+  int wide_length = 0;
+  int wide_flag = 0;
+  int wchar_bytes = TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT;
+  int nchars;
+  const int nchars_max = flag_isoc99 ? 4095 : 509;
 
-  /* This can happen in c++ (eg: decl: typespec initdecls ';').  */
-  if (specs_attrs != NULL_TREE
-      && TREE_CODE (specs_attrs) != TREE_LIST)
+  if (TREE_CHAIN (strings))
     {
-      *declspecs = specs_attrs;
-      *prefix_attributes = NULL_TREE;
-      return;
-    }
-
-  /* Remember to keep the lists in the same order, element-wise.  */
+      /* More than one in the chain, so concatenate.  */
+      char *p, *q;
 
-  specs = s = NULL_TREE;
-  attrs = a = NULL_TREE;
-  for (t = specs_attrs; t; t = next)
-    {
-      next = TREE_CHAIN (t);
-      /* Declspecs have a non-NULL TREE_VALUE.  */
-      if (TREE_VALUE (t) != NULL_TREE)
+      /* Don't include the \0 at the end of each substring,
+        except for the last one.
+        Count wide strings and ordinary strings separately.  */
+      for (t = strings; t; t = TREE_CHAIN (t))
        {
-         if (specs == NULL_TREE)
-           specs = s = t;
-         else
+         if (TREE_TYPE (t) == wchar_array_type_node)
            {
-             TREE_CHAIN (s) = t;
-             s = t;
+             wide_length += (TREE_STRING_LENGTH (t) - wchar_bytes);
+             wide_flag = 1;
            }
-       }
-      /* The TREE_PURPOSE may also be empty in the case of
-        __attribute__(()).  */
-      else if (TREE_PURPOSE (t) != NULL_TREE)
-       {
-         if (attrs == NULL_TREE)
-           attrs = a = TREE_PURPOSE (t);
          else
            {
-             TREE_CHAIN (a) = TREE_PURPOSE (t);
-             a = TREE_PURPOSE (t);
+             length += (TREE_STRING_LENGTH (t) - 1);
+             if (C_ARTIFICIAL_STRING_P (t) && !in_system_header)
+               warning ("concatenation of string literals with __FUNCTION__ is deprecated.  This feature will be removed in future"); 
            }
-         /* More attrs can be linked here, move A to the end.  */
-         while (TREE_CHAIN (a) != NULL_TREE)
-           a = TREE_CHAIN (a);
        }
-    }
 
-  /* Terminate the lists.  */
-  if (s != NULL_TREE)
-    TREE_CHAIN (s) = NULL_TREE;
-  if (a != NULL_TREE)
-    TREE_CHAIN (a) = NULL_TREE;
+      /* If anything is wide, the non-wides will be converted,
+        which makes them take more space.  */
+      if (wide_flag)
+       length = length * wchar_bytes + wide_length;
 
-  /* All done.  */
-  *declspecs = specs;
-  *prefix_attributes = attrs;
-}
+      p = alloca (length);
+
+      /* Copy the individual strings into the new combined string.
+        If the combined string is wide, convert the chars to ints
+        for any individual strings that are not wide.  */
 
-/* Strip attributes from SPECS_ATTRS, a list of declspecs and attributes.
-   This function is used by the parser when a rule will accept attributes
-   in a particular position, but we don't want to support that just yet.
+      q = p;
+      for (t = strings; t; t = TREE_CHAIN (t))
+       {
+         int len = (TREE_STRING_LENGTH (t)
+                    - ((TREE_TYPE (t) == wchar_array_type_node)
+                       ? wchar_bytes : 1));
+         if ((TREE_TYPE (t) == wchar_array_type_node) == wide_flag)
+           {
+             memcpy (q, TREE_STRING_POINTER (t), len);
+             q += len;
+           }
+         else
+           {
+             int i, j;
+             for (i = 0; i < len; i++)
+               {
+                 if (BYTES_BIG_ENDIAN)
+                   {
+                     for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
+                       *q++ = 0;
+                     *q++ = TREE_STRING_POINTER (t)[i];
+                   }
+                 else
+                   {
+                     *q++ = TREE_STRING_POINTER (t)[i];
+                     for (j=0; j<(WCHAR_TYPE_SIZE / BITS_PER_UNIT)-1; j++)
+                       *q++ = 0;
+                   }
+               }
+           }
+       }
+      if (wide_flag)
+       {
+         int i;
+         for (i = 0; i < wchar_bytes; i++)
+           *q++ = 0;
+       }
+      else
+       *q = 0;
 
-   A warning is issued for every ignored attribute.  */
+      value = build_string (length, p);
+    }
+  else
+    {
+      value = strings;
+      length = TREE_STRING_LENGTH (value);
+      if (TREE_TYPE (value) == wchar_array_type_node)
+       wide_flag = 1;
+    }
 
-tree
-strip_attrs (specs_attrs)
-     tree specs_attrs;
-{
-  tree specs, attrs;
+  /* Compute the number of elements, for the array type.  */
+  nchars = wide_flag ? length / wchar_bytes : length;
 
-  split_specs_attrs (specs_attrs, &specs, &attrs);
+  if (pedantic && nchars - 1 > nchars_max && c_language == clk_c)
+    pedwarn ("string length `%d' is greater than the length `%d' ISO C%d compilers are required to support",
+            nchars - 1, nchars_max, flag_isoc99 ? 99 : 89);
 
-  while (attrs)
+  /* Create the array type for the string constant.
+     -Wwrite-strings says make the string constant an array of const char
+     so that copying it to a non-const pointer will get a warning.
+     For C++, this is the standard behavior.  */
+  if (flag_const_strings
+      && (! flag_traditional  && ! flag_writable_strings))
     {
-      warning ("`%s' attribute ignored",
-              IDENTIFIER_POINTER (TREE_PURPOSE (attrs)));
-      attrs = TREE_CHAIN (attrs);
+      tree elements
+       = build_type_variant (wide_flag ? wchar_type_node : char_type_node,
+                             1, 0);
+      TREE_TYPE (value)
+       = build_array_type (elements,
+                           build_index_type (build_int_2 (nchars - 1, 0)));
     }
+  else
+    TREE_TYPE (value)
+      = build_array_type (wide_flag ? wchar_type_node : char_type_node,
+                         build_index_type (build_int_2 (nchars - 1, 0)));
 
-  return specs;
+  TREE_CONSTANT (value) = 1;
+  TREE_READONLY (value) = ! flag_writable_strings;
+  TREE_STATIC (value) = 1;
+  return value;
 }
 \f
 static int is_valid_printf_arglist PARAMS ((tree));
 static rtx c_expand_builtin PARAMS ((tree, rtx, enum machine_mode, enum expand_modifier));
 static rtx c_expand_builtin_printf PARAMS ((tree, rtx, enum machine_mode,
-                                           enum expand_modifier, int));
+                                           enum expand_modifier, int, int));
 static rtx c_expand_builtin_fprintf PARAMS ((tree, rtx, enum machine_mode,
-                                            enum expand_modifier, int));
+                                            enum expand_modifier, int, int));
 \f
 /* Print a warning if a constant expression had overflow in folding.
    Invoke this function on every expression that the language
@@ -2066,7 +975,7 @@ warn_for_collisions (list)
     }
 }
 
-/* Return nonzero if X is a tree that can be verified by the sequence poitn
+/* Return nonzero if X is a tree that can be verified by the sequence point
    warnings.  */
 static int
 warning_candidate_p (x)
@@ -2323,7 +1232,8 @@ c_expand_expr_stmt (expr)
 {
   /* Do default conversion if safe and possibly important,
      in case within ({...}).  */
-  if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE && lvalue_p (expr))
+  if ((TREE_CODE (TREE_TYPE (expr)) == ARRAY_TYPE
+       && (flag_isoc99 || lvalue_p (expr)))
       || TREE_CODE (TREE_TYPE (expr)) == FUNCTION_TYPE)
     expr = default_conversion (expr);
 
@@ -2449,16 +1359,16 @@ type_for_mode (mode, unsignedp)
     return unsignedp ? widest_unsigned_literal_type_node
                      : widest_integer_literal_type_node;
 
-  if (mode == TYPE_MODE (intQI_type_node))
+  if (mode == QImode)
     return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
 
-  if (mode == TYPE_MODE (intHI_type_node))
+  if (mode == HImode)
     return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
 
-  if (mode == TYPE_MODE (intSI_type_node))
+  if (mode == SImode)
     return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
 
-  if (mode == TYPE_MODE (intDI_type_node))
+  if (mode == DImode)
     return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
 
 #if HOST_BITS_PER_WIDE_INT >= 64
@@ -2482,16 +1392,30 @@ type_for_mode (mode, unsignedp)
     return build_pointer_type (integer_type_node);
 
 #ifdef VECTOR_MODE_SUPPORTED_P
-  if (mode == TYPE_MODE (V4SF_type_node) && VECTOR_MODE_SUPPORTED_P (mode))
-    return V4SF_type_node;
-  if (mode == TYPE_MODE (V4SI_type_node) && VECTOR_MODE_SUPPORTED_P (mode))
-    return V4SI_type_node;
-  if (mode == TYPE_MODE (V2SI_type_node) && VECTOR_MODE_SUPPORTED_P (mode))
-    return V2SI_type_node;
-  if (mode == TYPE_MODE (V4HI_type_node) && VECTOR_MODE_SUPPORTED_P (mode))
-    return V4HI_type_node;
-  if (mode == TYPE_MODE (V8QI_type_node) && VECTOR_MODE_SUPPORTED_P (mode))
-    return V8QI_type_node;
+  if (VECTOR_MODE_SUPPORTED_P (mode))
+    {
+      switch (mode)
+       {
+       case V16QImode:
+         return unsignedp ? unsigned_V16QI_type_node : V16QI_type_node;
+       case V8HImode:
+         return unsignedp ? unsigned_V8HI_type_node : V8HI_type_node;
+       case V4SImode:
+         return unsignedp ? unsigned_V4SI_type_node : V4SI_type_node;
+       case V2SImode:
+         return unsignedp ? unsigned_V2SI_type_node : V2SI_type_node;
+       case V4HImode:
+         return unsignedp ? unsigned_V4HI_type_node : V4HI_type_node;
+       case V8QImode:
+         return unsignedp ? unsigned_V8QI_type_node : V8QI_type_node;
+       case V4SFmode:
+         return V4SF_type_node;
+       case V2SFmode:
+         return V2SF_type_node;
+       default:
+         break;
+       }
+    }
 #endif
 
   return 0;
@@ -2645,7 +1569,7 @@ void
 binary_op_error (code)
      enum tree_code code;
 {
-  register const char *opname;
+  const char *opname;
 
   switch (code)
     {
@@ -2724,7 +1648,7 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
      tree *restype_ptr;
      enum tree_code *rescode_ptr;
 {
-  register tree type;
+  tree type;
   tree op0 = *op0_ptr;
   tree op1 = *op1_ptr;
   int unsignedp0, unsignedp1;
@@ -2757,8 +1681,8 @@ shorten_compare (op0_ptr, op1_ptr, restype_ptr, rescode_ptr)
   if (TREE_CONSTANT (primop0)
       && ! integer_zerop (primop1) && ! real_zerop (primop1))
     {
-      register tree tem = primop0;
-      register int temi = unsignedp0;
+      tree tem = primop0;
+      int temi = unsignedp0;
       primop0 = primop1;
       primop1 = tem;
       tem = op0;
@@ -3112,7 +2036,7 @@ truthvalue_conversion (expr)
       return real_zerop (expr) ? boolean_false_node : boolean_true_node;
 
     case ADDR_EXPR:
-      /* If we are taking the address of a external decl, it might be zero
+      /* If we are taking the address of an external decl, it might be zero
         if it is weak, so we cannot optimize.  */
       if (DECL_P (TREE_OPERAND (expr, 0))
          && DECL_EXTERNAL (TREE_OPERAND (expr, 0)))
@@ -3274,28 +2198,10 @@ c_apply_type_quals_to_decl (type_quals, decl)
          || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (TREE_TYPE (decl))))
        error ("invalid use of `restrict'");
       else if (flag_strict_aliasing)
-       {
-         /* No two restricted pointers can point at the same thing.
-            However, a restricted pointer can point at the same thing
-            as an unrestricted pointer, if that unrestricted pointer
-            is based on the restricted pointer.  So, we make the
-            alias set for the restricted pointer a subset of the
-            alias set for the type pointed to by the type of the
-            decl.  */
-
-         HOST_WIDE_INT pointed_to_alias_set
-           = get_alias_set (TREE_TYPE (TREE_TYPE (decl)));
-
-         if (pointed_to_alias_set == 0)
-           /* It's not legal to make a subset of alias set zero.  */
-           ;
-         else
-           {
-             DECL_POINTER_ALIAS_SET (decl) = new_alias_set ();
-             record_alias_subset  (pointed_to_alias_set,
-                                   DECL_POINTER_ALIAS_SET (decl));
-           }
-       }
+       /* Indicate we need to make a unique alias set for this pointer.
+          We can't do it here because it might be pointing to an
+          incomplete type.  */
+       DECL_POINTER_ALIAS_SET (decl) = -2;
     }
 }
 
@@ -3304,7 +2210,7 @@ c_apply_type_quals_to_decl (type_quals, decl)
    or a type.  Return -1 if we don't do anything special.  */
 
 HOST_WIDE_INT
-lang_get_alias_set (t)
+c_common_get_alias_set (t)
      tree t;
 {
   tree u;
@@ -3359,7 +2265,7 @@ lang_get_alias_set (t)
 
         Technically, this approach is actually more conservative that
         it needs to be.  In particular, `const int *' and `int *'
-        chould be in different alias sets, according to the C and C++
+        should be in different alias sets, according to the C and C++
         standard, since their types are not the same, and so,
         technically, an `int **' and `const int **' cannot point at
         the same thing.
@@ -3379,10 +2285,6 @@ lang_get_alias_set (t)
       if (t1 != t)
        return get_alias_set (t1);
     }
-  /* It's not yet safe to use alias sets for classes in C++ because
-     the TYPE_FIELDs list for a class doesn't mention base classes.  */
-  else if (c_language == clk_cplusplus && AGGREGATE_TYPE_P (t))
-    return 0;
 
   return -1;
 }
@@ -3440,7 +2342,7 @@ c_alignof_expr (expr)
       t = size_one_node;
     }
   else if (TREE_CODE (expr) == COMPONENT_REF
-      && TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL)
+          && TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL)
     t = size_int (DECL_ALIGN (TREE_OPERAND (expr, 1)) / BITS_PER_UNIT);
  
   else if (TREE_CODE (expr) == INDIRECT_REF)
@@ -3450,7 +2352,7 @@ c_alignof_expr (expr)
       int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
  
       while (TREE_CODE (t) == NOP_EXPR
-             && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
+            && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
        {
          int thisalign;
 
@@ -3467,6 +2369,19 @@ c_alignof_expr (expr)
   return fold (build1 (NOP_EXPR, c_size_type_node, t));
 }
 \f
+/* Give the specifications for the format attributes, used by C and all
+   descendents.  */
+
+static const struct attribute_spec c_format_attribute_table[] =
+{
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+  { "format",                 3, 3, false, true,  true,
+                             handle_format_attribute },
+  { "format_arg",             1, 1, false, true,  true,
+                             handle_format_arg_attribute },
+  { NULL,                     0, 0, false, false, false, NULL }
+};
+
 /* Build tree nodes and builtin functions common to both C and C++ language
    frontends.  */
 
@@ -3501,7 +2416,7 @@ c_common_nodes_and_builtins ()
 
   typedef enum builtin_type builtin_type;
 
-  tree builtin_types[(int)BT_LAST];
+  tree builtin_types[(int) BT_LAST];
   int wchar_type_size;
   tree array_domain_type;
   /* Either char* or void*.  */
@@ -3512,6 +2427,10 @@ c_common_nodes_and_builtins ()
   tree va_list_ref_type_node;
   tree va_list_arg_type_node;
 
+  /* We must initialize this before any builtin functions (which might have
+     attributes) are declared.  (c_common_init is too late.)  */
+  format_attribute_table = c_format_attribute_table;
+
   /* Define `int' and `char' first so that dbx will output them first.  */
   record_builtin_type (RID_INT, NULL, integer_type_node);
   record_builtin_type (RID_CHAR, "char", char_type_node);
@@ -3842,6 +2761,53 @@ build_va_arg (expr, type)
 }
 
 
+/* Linked list of disabled built-in functions.  */
+
+typedef struct disabled_builtin
+{
+  const char *name;
+  struct disabled_builtin *next;
+} disabled_builtin;
+static disabled_builtin *disabled_builtins = NULL;
+
+static bool builtin_function_disabled_p PARAMS ((const char *));
+
+/* Disable a built-in function specified by -fno-builtin-NAME.  If NAME
+   begins with "__builtin_", give an error.  */
+
+void
+disable_builtin_function (name)
+     const char *name;
+{
+  if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0)
+    error ("cannot disable built-in function `%s'", name);
+  else
+    {
+      disabled_builtin *new = xmalloc (sizeof (disabled_builtin));
+      new->name = name;
+      new->next = disabled_builtins;
+      disabled_builtins = new;
+    }
+}
+
+
+/* Return true if the built-in function NAME has been disabled, false
+   otherwise.  */
+
+static bool
+builtin_function_disabled_p (name)
+     const char *name;
+{
+  disabled_builtin *p;
+  for (p = disabled_builtins; p != NULL; p = p->next)
+    {
+      if (strcmp (name, p->name) == 0)
+       return true;
+    }
+  return false;
+}
+
+
 /* 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).
@@ -3882,7 +2848,8 @@ builtin_function_2 (builtin_name, name, builtin_type, type, function_code,
          TREE_SIDE_EFFECTS (bdecl) = 1;
        }
     }
-  if (name != 0 && !flag_no_builtin && !(nonansi_p && flag_no_nonansi_builtin))
+  if (name != 0 && !flag_no_builtin && !builtin_function_disabled_p (name)
+      && !(nonansi_p && flag_no_nonansi_builtin))
     {
       decl = builtin_function (name, type, function_code, class, NULL);
       if (nonansi_p)
@@ -3962,10 +2929,10 @@ int
 self_promoting_args_p (parms)
      tree parms;
 {
-  register tree t;
+  tree t;
   for (t = parms; t; t = TREE_CHAIN (t))
     {
-      register tree type = TREE_VALUE (t);
+      tree type = TREE_VALUE (t);
 
       if (TREE_CHAIN (t) == 0 && type != void_type_node)
        return 0;
@@ -4455,9 +3422,8 @@ mark_stmt_tree (p)
 
 void
 c_mark_lang_decl (c)
-     struct c_lang_decl *c;
+     struct c_lang_decl *c ATTRIBUTE_UNUSED;
 {
-  ggc_mark_tree (c->saved_tree);
 }
 
 /* Mark F for GC.  */
@@ -4496,6 +3462,27 @@ c_expand_expr (exp, target, tmode, modifier)
           STMT_EXPR.  */
        push_temp_slots ();
        rtl_expr = expand_start_stmt_expr ();
+
+       /* If we want the result of this expression, find the last
+           EXPR_STMT in the COMPOUND_STMT and mark it as addressable.  */
+       if (target != const0_rtx
+           && TREE_CODE (STMT_EXPR_STMT (exp)) == COMPOUND_STMT
+           && TREE_CODE (COMPOUND_BODY (STMT_EXPR_STMT (exp))) == SCOPE_STMT)
+         {
+           tree expr = COMPOUND_BODY (STMT_EXPR_STMT (exp));
+           tree last = TREE_CHAIN (expr);
+
+           while (TREE_CHAIN (last))
+             {
+               expr = last;
+               last = TREE_CHAIN (last);
+             }
+
+           if (TREE_CODE (last) == SCOPE_STMT
+               && TREE_CODE (expr) == EXPR_STMT)
+             TREE_ADDRESSABLE (expr) = 1;
+         }
+
        expand_stmt (STMT_EXPR_STMT (exp));
        expand_end_stmt_expr (rtl_expr);
        result = expand_expr (rtl_expr, target, tmode, modifier);
@@ -4514,10 +3501,19 @@ c_expand_expr (exp, target, tmode, modifier)
                == BUILT_IN_FRONTEND))
          return c_expand_builtin (exp, target, tmode, modifier);
        else
-         abort();
+         abort ();
       }
       break;
 
+    case COMPOUND_LITERAL_EXPR:
+      {
+       /* Initialize the anonymous variable declared in the compound
+          literal, then return the variable.  */
+       tree decl = COMPOUND_LITERAL_EXPR_DECL (exp);
+       emit_local_var (decl);
+       return expand_expr (decl, target, tmode, modifier);
+      }
+
     default:
       abort ();
     }
@@ -4568,11 +3564,23 @@ c_unsafe_for_reeval (exp)
   return -1;
 }
 
+/* Hook used by staticp to handle language-specific tree codes.  */
+
+int
+c_staticp (exp)
+     tree exp;
+{
+  if (TREE_CODE (exp) == COMPOUND_LITERAL_EXPR
+      && TREE_STATIC (COMPOUND_LITERAL_EXPR_DECL (exp)))
+    return 1;
+  return 0;
+}
+
 /* Tree code classes.  */
 
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) TYPE,
 
-static char c_tree_code_type[] = {
+static const char c_tree_code_type[] = {
   'x',
 #include "c-common.def"
 };
@@ -4584,7 +3592,7 @@ static char c_tree_code_type[] = {
 
 #define DEFTREECODE(SYM, NAME, TYPE, LENGTH) LENGTH,
 
-static int c_tree_code_length[] = {
+static const int c_tree_code_length[] = {
   0,
 #include "c-common.def"
 };
@@ -4608,13 +3616,13 @@ add_c_tree_codes ()
 {
   memcpy (tree_code_type + (int) LAST_AND_UNUSED_TREE_CODE,
          c_tree_code_type,
-         (int)LAST_C_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE);
+         (int) LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE);
   memcpy (tree_code_length + (int) LAST_AND_UNUSED_TREE_CODE,
          c_tree_code_length,
-         (LAST_C_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
+         (LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE) * sizeof (int));
   memcpy (tree_code_name + (int) LAST_AND_UNUSED_TREE_CODE,
          c_tree_code_name,
-         (LAST_C_TREE_CODE - (int)LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
+         (LAST_C_TREE_CODE - (int) LAST_AND_UNUSED_TREE_CODE) * sizeof (char *));
   lang_unsafe_for_reeval = c_unsafe_for_reeval;
 }
 
@@ -4646,14 +3654,28 @@ c_expand_builtin (exp, target, tmode, modifier)
     {
     case BUILT_IN_PRINTF:
       target = c_expand_builtin_printf (arglist, target, tmode,
-                                       modifier, ignore);
+                                       modifier, ignore, /*unlocked=*/ 0);
+      if (target)
+       return target;
+      break;
+
+    case BUILT_IN_PRINTF_UNLOCKED:
+      target = c_expand_builtin_printf (arglist, target, tmode,
+                                       modifier, ignore, /*unlocked=*/ 1);
       if (target)
        return target;
       break;
 
     case BUILT_IN_FPRINTF:
       target = c_expand_builtin_fprintf (arglist, target, tmode,
-                                        modifier, ignore);
+                                        modifier, ignore, /*unlocked=*/ 0);
+      if (target)
+       return target;
+      break;
+
+    case BUILT_IN_FPRINTF_UNLOCKED:
+      target = c_expand_builtin_fprintf (arglist, target, tmode,
+                                        modifier, ignore, /*unlocked=*/ 1);
       if (target)
        return target;
       break;
@@ -4673,19 +3695,27 @@ c_expand_builtin (exp, target, tmode, modifier)
    following it.  */
 static int
 is_valid_printf_arglist (arglist)
-  tree arglist;
+     tree arglist;
 {
   /* Save this value so we can restore it later.  */
   const int SAVE_pedantic = pedantic;
   int diagnostic_occurred = 0;
+  tree attrs;
 
   /* Set this to a known value so the user setting won't affect code
      generation.  */
   pedantic = 1;
   /* Check to make sure there are no format specifier errors.  */
-  check_function_format (&diagnostic_occurred,
-                        maybe_get_identifier("printf"),
-                        NULL_TREE, arglist);
+  attrs = tree_cons (get_identifier ("format"),
+                    tree_cons (NULL_TREE,
+                               get_identifier ("printf"),
+                               tree_cons (NULL_TREE,
+                                          integer_one_node,
+                                          tree_cons (NULL_TREE,
+                                                     build_int_2 (2, 0),
+                                                     NULL_TREE))),
+                    NULL_TREE);
+  check_function_format (&diagnostic_occurred, attrs, arglist);
 
   /* Restore the value of `pedantic'.  */
   pedantic = SAVE_pedantic;
@@ -4698,15 +3728,18 @@ is_valid_printf_arglist (arglist)
 /* If the arguments passed to printf are suitable for optimizations,
    we attempt to transform the call.  */
 static rtx
-c_expand_builtin_printf (arglist, target, tmode, modifier, ignore)
+c_expand_builtin_printf (arglist, target, tmode, modifier, ignore, unlocked)
      tree arglist;
      rtx target;
      enum machine_mode tmode;
      enum expand_modifier modifier;
      int ignore;
+     int unlocked;
 {
-  tree fn_putchar = built_in_decls[BUILT_IN_PUTCHAR],
-    fn_puts = built_in_decls[BUILT_IN_PUTS];
+  tree fn_putchar = unlocked ?
+    built_in_decls[BUILT_IN_PUTCHAR_UNLOCKED] : built_in_decls[BUILT_IN_PUTCHAR];
+  tree fn_puts = unlocked ?
+    built_in_decls[BUILT_IN_PUTS_UNLOCKED] : built_in_decls[BUILT_IN_PUTS];
   tree fn, format_arg, stripped_string;
 
   /* If the return value is used, or the replacement _DECL isn't
@@ -4749,7 +3782,7 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore)
     }
   else
     {
-     /* We can't handle anything else with % args or %% ... yet.  */
+      /* We can't handle anything else with % args or %% ... yet.  */
       if (strchr (TREE_STRING_POINTER (stripped_string), '%'))
        return 0;
       
@@ -4799,15 +3832,18 @@ c_expand_builtin_printf (arglist, target, tmode, modifier, ignore)
 /* If the arguments passed to fprintf are suitable for optimizations,
    we attempt to transform the call.  */
 static rtx
-c_expand_builtin_fprintf (arglist, target, tmode, modifier, ignore)
+c_expand_builtin_fprintf (arglist, target, tmode, modifier, ignore, unlocked)
      tree arglist;
      rtx target;
      enum machine_mode tmode;
      enum expand_modifier modifier;
      int ignore;
+     int unlocked;
 {
-  tree fn_fputc = built_in_decls[BUILT_IN_FPUTC],
-    fn_fputs = built_in_decls[BUILT_IN_FPUTS];
+  tree fn_fputc = unlocked ?
+    built_in_decls[BUILT_IN_FPUTC_UNLOCKED] : built_in_decls[BUILT_IN_FPUTC];
+  tree fn_fputs = unlocked ?
+    built_in_decls[BUILT_IN_FPUTS_UNLOCKED] : built_in_decls[BUILT_IN_FPUTS];
   tree fn, format_arg, stripped_string;
 
   /* If the return value is used, or the replacement _DECL isn't
@@ -4859,7 +3895,7 @@ c_expand_builtin_fprintf (arglist, target, tmode, modifier, ignore)
     }
   else
     {
-     /* We can't handle anything else with % args or %% ... yet.  */
+      /* We can't handle anything else with % args or %% ... yet.  */
       if (strchr (TREE_STRING_POINTER (stripped_string), '%'))
        return 0;
       
@@ -4917,13 +3953,67 @@ boolean_increment (code, arg)
   return val;
 }
 \f
+/* Handle C and C++ default attributes.  */
+
+enum built_in_attribute
+{
+#define DEF_ATTR_NULL_TREE(ENUM) ENUM,
+#define DEF_ATTR_INT(ENUM, VALUE) ENUM,
+#define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
+#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No entry needed in enum.  */
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+#undef DEF_FN_ATTR
+  ATTR_LAST
+};
+
+static tree built_in_attributes[(int) ATTR_LAST];
+
+static bool c_attrs_initialized = false;
+
+static void c_init_attributes PARAMS ((void));
 
-/* Do the parts of lang_init common to C and C++.  */
+/* Common initialization before parsing options.  */
 void
-c_common_lang_init ()
+c_common_init_options (lang)
+     enum c_language_kind lang;
 {
+  c_language = lang;
+  parse_in = cpp_create_reader (lang == clk_c ? CLK_GNUC89:
+                               lang == clk_cplusplus ? CLK_GNUCXX: CLK_OBJC);
+
+  /* Mark as "unspecified" (see c_common_post_options).  */
+  flag_bounds_check = -1;
+}
+
+/* Post-switch processing.  */
+void
+c_common_post_options ()
+{
+  cpp_post_options (parse_in);
+
+  /* Use tree inlining if possible.  Function instrumentation is only
+     done in the RTL level, so we disable tree inlining.  */
+  if (! flag_instrument_function_entry_exit)
+    {
+      if (!flag_no_inline)
+       {
+         flag_inline_trees = 1;
+         flag_no_inline = 1;
+       }
+      if (flag_inline_functions)
+       {
+         flag_inline_trees = 2;
+         flag_inline_functions = 0;
+       }
+    }
+
   /* If still "unspecified", make it match -fbounded-pointers.  */
-  if (flag_bounds_check < 0)
+  if (flag_bounds_check == -1)
     flag_bounds_check = flag_bounded_pointers;
 
   /* Special format checking options don't work without -Wformat; warn if
@@ -4939,3 +4029,98 @@ c_common_lang_init ()
   if (warn_missing_format_attribute && !warn_format)
     warning ("-Wmissing-format-attribute ignored without -Wformat");
 }
+
+/* Front end initialization common to C, ObjC and C++.  */
+const char *
+c_common_init (filename)
+     const char *filename;
+{
+  /* Do this before initializing pragmas, as then cpplib's hash table
+     has been set up.  */
+  filename = init_c_lex (filename);
+
+  init_pragma ();
+
+  if (!c_attrs_initialized)
+    c_init_attributes ();
+
+  return filename;
+}
+
+/* Common finish hook for the C, ObjC and C++ front ends.  */
+void
+c_common_finish ()
+{
+  cpp_finish (parse_in);
+
+  /* For performance, avoid tearing down cpplib's internal structures.
+     Call cpp_errors () instead of cpp_destroy ().  */
+  errorcount += cpp_errors (parse_in);
+}
+
+static void
+c_init_attributes ()
+{
+  /* Fill in the built_in_attributes array.  */
+#define DEF_ATTR_NULL_TREE(ENUM)               \
+  built_in_attributes[(int) ENUM] = NULL_TREE;
+#define DEF_ATTR_INT(ENUM, VALUE)                                           \
+  built_in_attributes[(int) ENUM] = build_int_2 (VALUE, VALUE < 0 ? -1 : 0);
+#define DEF_ATTR_IDENT(ENUM, STRING)                           \
+  built_in_attributes[(int) ENUM] = get_identifier (STRING);
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)        \
+  built_in_attributes[(int) ENUM]                      \
+    = tree_cons (built_in_attributes[(int) PURPOSE],   \
+                built_in_attributes[(int) VALUE],      \
+                built_in_attributes[(int) CHAIN]);
+#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE) /* No initialization needed.  */
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+#undef DEF_FN_ATTR
+  ggc_add_tree_root (built_in_attributes, (int) ATTR_LAST);
+  c_attrs_initialized = true;
+}
+
+/* Depending on the name of DECL, apply default attributes to it.  */
+
+void
+c_common_insert_default_attributes (decl)
+     tree decl;
+{
+  tree name = DECL_NAME (decl);
+
+  if (!c_attrs_initialized)
+    c_init_attributes ();
+
+#define DEF_ATTR_NULL_TREE(ENUM) /* Nothing needed after initialization.  */
+#define DEF_ATTR_INT(ENUM, VALUE)
+#define DEF_ATTR_IDENT(ENUM, STRING)
+#define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN)
+#define DEF_FN_ATTR(NAME, ATTRS, PREDICATE)                    \
+  if ((PREDICATE) && name == built_in_attributes[(int) NAME])  \
+    decl_attributes (&decl, built_in_attributes[(int) ATTRS],  \
+                    ATTR_FLAG_BUILT_IN);
+#include "builtin-attrs.def"
+#undef DEF_ATTR_NULL_TREE
+#undef DEF_ATTR_INT
+#undef DEF_ATTR_IDENT
+#undef DEF_ATTR_TREE_LIST
+#undef DEF_FN_ATTR
+}
+
+/* Output a -Wshadow warning MSGID about NAME, an IDENTIFIER_NODE, and
+   additionally give the location of the previous declaration DECL.  */
+void
+shadow_warning (msgid, name, decl)
+     const char *msgid;
+     tree name, decl;
+{
+  warning ("declaration of `%s' shadows %s", IDENTIFIER_POINTER (name), msgid);
+  warning_with_file_and_line (DECL_SOURCE_FILE (decl),
+                             DECL_SOURCE_LINE (decl),
+                             "shadowed declaration is here");
+}
+