OSDN Git Service

* attribs.c (decl_attributes): Possibly call
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index 3de4592..f3ad82e 100644 (file)
@@ -2,22 +2,22 @@
    Copyright (C) 1988, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
    2001 Free Software Foundation, Inc.
 
-This file is part of GNU CC.
+This file is part of GCC.
 
-GNU CC is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2, or (at your option)
-any later version.
+GCC is free software; you can redistribute it and/or modify it under
+the terms of the GNU General Public License as published by the Free
+Software Foundation; either version 2, or (at your option) any later
+version.
 
-GNU CC is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-GNU General Public License for more details.
+GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+WARRANTY; without even the implied warranty of MERCHANTABILITY or
+FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+for more details.
 
 You should have received a copy of the GNU General Public License
-along with GNU CC; see the file COPYING.  If not, write to
-the Free Software Foundation, 59 Temple Place - Suite 330,
-Boston, MA 02111-1307, USA.  */
+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.  */
 
 /* Process declarations and symbol lookup for C front end.
    Also constructs types; the standard scalar types at initialization,
@@ -41,6 +41,8 @@ Boston, MA 02111-1307, USA.  */
 #include "ggc.h"
 #include "tm_p.h"
 #include "cpplib.h"
+#include "target.h"
+#include "debug.h"
 
 /* In grokdeclarator, distinguish syntactic contexts of declarators.  */
 enum decl_context
@@ -447,7 +449,6 @@ c_decode_option (argc, argv)
      char **argv;
 {
   int strings_processed;
-  const char *option_value = NULL;
   char *p = argv[0];
 
   strings_processed = cpp_handle_option (parse_in, argc, argv);
@@ -489,7 +490,7 @@ c_decode_option (argc, argv)
         -std=gnu89             default, iso9899:1990 + gnu extensions
         -std=gnu99             iso9899:1999 + gnu extensions
       */
-      const char *argstart = &p[5];
+      const char *const argstart = &p[5];
 
       if (!strcmp (argstart, "iso9899:1990")
          || !strcmp (argstart, "c89"))
@@ -593,14 +594,8 @@ c_decode_option (argc, argv)
     flag_no_builtin = 0;
   else if (!strcmp (p, "-fno-builtin"))
     flag_no_builtin = 1;
-  else if ((option_value
-           = skip_leading_substring (p, "-fdump-translation-unit-")))
-    {
-      if (p[22] == '\0')
-       error ("no file specified with -fdump-translation-unit");
-      else
-       flag_dump_translation_unit = option_value;
-    }
+  else if (p[0] == '-' && p[1] == 'f' && dump_switch_p (p + 2))
+    ;
   else if (!strcmp (p, "-ansi"))
     goto iso_1990;
   else if (!strcmp (p, "-Werror-implicit-function-declaration"))
@@ -1409,8 +1404,8 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
   int errmsg = 0;
 
   if (DECL_P (olddecl))
-    DECL_MACHINE_ATTRIBUTES (newdecl)
-      = merge_machine_decl_attributes (olddecl, newdecl);
+    DECL_ATTRIBUTES (newdecl)
+      = (*targetm.merge_decl_attributes) (olddecl, newdecl);
 
   if (TREE_CODE (newtype) == ERROR_MARK
       || TREE_CODE (oldtype) == ERROR_MARK)
@@ -1966,7 +1961,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
         been written out yet.  */
       if (new_is_definition && DECL_INITIAL (olddecl) && TREE_USED (olddecl))
        {
-         note_outlining_of_inline_function (olddecl);
+         (*debug_hooks->outlining_inline_function) (olddecl);
 
          /* The new defn must not be inline.  */
          DECL_INLINE (newdecl) = 0;
@@ -2035,7 +2030,7 @@ duplicate_decls (newdecl, olddecl, different_binding_level)
 
   /* NEWDECL contains the merged attribute lists.
      Update OLDDECL to be the same.  */
-  DECL_MACHINE_ATTRIBUTES (olddecl) = DECL_MACHINE_ATTRIBUTES (newdecl);
+  DECL_ATTRIBUTES (olddecl) = DECL_ATTRIBUTES (newdecl);
 
   return 1;
 }
@@ -2510,7 +2505,7 @@ tree
 implicitly_declare (functionid)
      tree functionid;
 {
-  register tree decl;
+  tree decl;
   int traditional_warning = 0;
   /* Only one "implicit declaration" warning per identifier.  */
   int implicit_warning;
@@ -2560,6 +2555,9 @@ implicitly_declare (functionid)
 
   gen_aux_info_record (decl, 0, 1, 0);
 
+  /* Possibly apply some default attributes to this implicit declaration.  */
+  decl_attributes (&decl, NULL_TREE, 0);
+
   return decl;
 }
 
@@ -3056,46 +3054,11 @@ init_decl_processing ()
                            g77_ulongint_type_node));
     }
 
-  builtin_function ("__builtin_aggregate_incoming_address",
-                   build_function_type (ptr_type_node, NULL_TREE),
-                   BUILT_IN_AGGREGATE_INCOMING_ADDRESS,
-                   BUILT_IN_NORMAL, NULL);
-
-  /* Hooks for the DWARF 2 __throw routine.  */
-  builtin_function ("__builtin_unwind_init",
-                   build_function_type (void_type_node, endlink),
-                   BUILT_IN_UNWIND_INIT, BUILT_IN_NORMAL, NULL);
-  builtin_function ("__builtin_dwarf_cfa", ptr_ftype_void,
-                   BUILT_IN_DWARF_CFA, BUILT_IN_NORMAL, NULL);
-  builtin_function ("__builtin_dwarf_fp_regnum",
-                   build_function_type (unsigned_type_node, endlink),
-                   BUILT_IN_DWARF_FP_REGNUM, BUILT_IN_NORMAL, NULL);
-  builtin_function ("__builtin_init_dwarf_reg_size_table", void_ftype_ptr,
-                   BUILT_IN_INIT_DWARF_REG_SIZES, BUILT_IN_NORMAL, NULL);
-  builtin_function ("__builtin_frob_return_addr", ptr_ftype_ptr,
-                   BUILT_IN_FROB_RETURN_ADDR, BUILT_IN_NORMAL, NULL);
-  builtin_function ("__builtin_extract_return_addr", ptr_ftype_ptr,
-                   BUILT_IN_EXTRACT_RETURN_ADDR, BUILT_IN_NORMAL, NULL);
-  builtin_function
-    ("__builtin_eh_return",
-     build_function_type (void_type_node,
-                         tree_cons (NULL_TREE,
-                                    type_for_mode (ptr_mode, 0),
-                                    tree_cons (NULL_TREE,
-                                               ptr_type_node,
-                                               endlink))),
-     BUILT_IN_EH_RETURN, BUILT_IN_NORMAL, NULL);
-
   pedantic_lvalues = pedantic;
 
   make_fname_decl = c_make_fname_decl;
   start_fname_decls ();
 
-  start_identifier_warnings ();
-
-  /* Prepare to check format strings against argument lists.  */
-  init_function_format_info ();
-
   incomplete_decl_finalize_hook = finish_incomplete_decl;
 
   /* Record our roots.  */
@@ -3135,7 +3098,7 @@ c_make_fname_decl (id, type_dep)
           build_index_type (size_int (length)));
 
   decl = build_decl (VAR_DECL, id, type);
-  /* We don't push the decl, so have to set its context here. */
+  /* We don't push the decl, so have to set its context here.  */
   DECL_CONTEXT (decl) = current_function_decl;
   
   TREE_STATIC (decl) = 1;
@@ -3189,8 +3152,23 @@ builtin_function (name, type, function_code, class, library_name)
   if (name[0] != '_' || name[1] != '_')
     C_DECL_ANTICIPATED (decl) = 1;
 
+  /* Possibly apply some default attributes to this built-in function.  */
+  decl_attributes (&decl, NULL_TREE, 0);
+
   return decl;
 }
+
+/* Apply default attributes to a function, if a system function with default
+   attributes.  */
+
+void
+insert_default_attributes (decl)
+     tree decl;
+{
+  if (!TREE_PUBLIC (decl))
+    return;
+  c_common_insert_default_attributes (decl);
+}
 \f
 /* Called when a declaration is seen that contains no names to declare.
    If its type is a reference to a structure, union or enum inherited
@@ -3278,6 +3256,60 @@ shadow_tag_warned (declspecs, warned)
     }
 }
 \f
+/* Construct an array declarator.  EXPR is the expression inside [], or
+   NULL_TREE.  QUALS are the type qualifiers inside the [] (to be applied
+   to the pointer to which a parameter array is converted).  STATIC_P is
+   non-zero if "static" is inside the [], zero otherwise.  VLA_UNSPEC_P
+   is non-zero is the array is [*], a VLA of unspecified length which is
+   nevertheless a complete type (not currently implemented by GCC),
+   zero otherwise.  The declarator is constructed as an ARRAY_REF
+   (to be decoded by grokdeclarator), whose operand 0 is what's on the
+   left of the [] (filled by in set_array_declarator_type) and operand 1
+   is the expression inside; whose TREE_TYPE is the type qualifiers and
+   which has TREE_STATIC set if "static" is used.  */
+
+tree
+build_array_declarator (expr, quals, static_p, vla_unspec_p)
+     tree expr;
+     tree quals;
+     int static_p;
+     int vla_unspec_p;
+{
+  tree decl;
+  decl = build_nt (ARRAY_REF, NULL_TREE, expr);
+  TREE_TYPE (decl) = quals;
+  TREE_STATIC (decl) = (static_p ? 1 : 0);
+  if (pedantic && !flag_isoc99)
+    {
+      if (static_p || quals != NULL_TREE)
+       pedwarn ("ISO C89 does not support `static' or type qualifiers in parameter array declarators");
+      if (vla_unspec_p)
+       pedwarn ("ISO C89 does not support `[*]' array declarators");
+    }
+  if (vla_unspec_p)
+    warning ("GCC does not yet properly implement `[*]' array declarators");
+  return decl;
+}
+
+/* Set the type of an array declarator.  DECL is the declarator, as
+   constructed by build_array_declarator; TYPE is what appears on the left
+   of the [] and goes in operand 0.  ABSTRACT_P is non-zero if it is an
+   abstract declarator, zero otherwise; this is used to reject static and
+   type qualifiers in abstract declarators, where they are not in the
+   C99 grammar.  */
+
+tree
+set_array_declarator_type (decl, type, abstract_p)
+     tree decl;
+     tree type;
+     int abstract_p;
+{
+  TREE_OPERAND (decl, 0) = type;
+  if (abstract_p && (TREE_TYPE (decl) != NULL_TREE || TREE_STATIC (decl)))
+    error ("static or type qualifiers in abstract declarator");
+  return decl;
+}
+\f
 /* Decode a "typename", such as "int **", returning a ..._TYPE node.  */
 
 tree
@@ -3320,13 +3352,13 @@ groktypename_in_parm_context (typename)
    grokfield and not through here.  */
 
 tree
-start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
+start_decl (declarator, declspecs, initialized, attributes)
      tree declarator, declspecs;
      int initialized;
-     tree attributes, prefix_attributes;
+     tree attributes;
 {
-  register tree decl = grokdeclarator (declarator, declspecs,
-                                      NORMAL, initialized);
+  tree decl = grokdeclarator (declarator, declspecs,
+                             NORMAL, initialized);
   register tree tem;
 
   if (warn_main > 0 && TREE_CODE (decl) != FUNCTION_DECL
@@ -3431,12 +3463,8 @@ start_decl (declarator, declspecs, initialized, attributes, prefix_attributes)
   if (! flag_no_common || ! TREE_PUBLIC (decl))
     DECL_COMMON (decl) = 1;
 
-#ifdef SET_DEFAULT_DECL_ATTRIBUTES
-  SET_DEFAULT_DECL_ATTRIBUTES (decl, attributes);
-#endif
-
   /* Set attributes here so if duplicate decl, will have proper attributes.  */
-  decl_attributes (decl, attributes, prefix_attributes);
+  decl_attributes (&decl, attributes, 0);
 
   /* Add this decl to the current binding level.
      TEM may equal DECL or it may be a previous decl of the same name.  */
@@ -3616,11 +3644,30 @@ finish_decl (decl, init, asmspec_tree)
        }
       else
        {
+         /* This is a local variable.  If there is an ASMSPEC, the
+            user has requested that we handle it specially.  */
          if (asmspec)
            {
-             SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
-             DECL_C_HARD_REGISTER (decl) = 1;
+             /* In conjunction with an ASMSPEC, the `register'
+                keyword indicates that we should place the variable
+                in a particular register.  */
+             if (DECL_REGISTER (decl))
+               DECL_C_HARD_REGISTER (decl) = 1;
+
+             /* If this is not a static variable, issue a warning.
+                It doesn't make any sense to give an ASMSPEC for an
+                ordinary, non-register local variable.  Historically,
+                GCC has accepted -- but ignored -- the ASMSPEC in
+                this case.  */
+             if (TREE_CODE (decl) == VAR_DECL 
+                 && !DECL_REGISTER (decl)
+                 && !TREE_STATIC (decl))
+               warning_with_decl (decl,
+                                  "ignoring asm-specifier for non-static local variable `%s'");
+             else
+               SET_DECL_ASSEMBLER_NAME (decl, get_identifier (asmspec));
            }
+
          add_decl_stmt (decl);
        }
 
@@ -3681,8 +3728,7 @@ push_parm_decl (parm)
 
   decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
                         TREE_PURPOSE (TREE_PURPOSE (parm)), PARM, 0);
-  decl_attributes (decl, TREE_VALUE (TREE_VALUE (parm)),
-                  TREE_PURPOSE (TREE_VALUE (parm)));
+  decl_attributes (&decl, TREE_VALUE (parm), 0);
 
 #if 0
   if (DECL_NAME (decl))
@@ -3841,7 +3887,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
   enum tree_code innermost_code = ERROR_MARK;
   int bitfield = 0;
   int size_varies = 0;
-  tree decl_machine_attr = NULL_TREE;
+  tree decl_attr = NULL_TREE;
+  tree array_ptr_quals = NULL_TREE;
+  int array_parm_static = 0;
+  tree returned_attrs = NULL_TREE;
 
   if (decl_context == BITFIELD)
     bitfield = 1, decl_context = FIELD;
@@ -3865,6 +3914,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          decl = TREE_OPERAND (decl, 0);
          break;
 
+       case TREE_LIST:
+         decl = TREE_VALUE (decl);
+         break;
+
        case IDENTIFIER_NODE:
          name = IDENTIFIER_POINTER (decl);
          decl = 0;
@@ -3946,7 +3999,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       else if (TREE_CODE (id) == TYPE_DECL)
        {
          type = TREE_TYPE (id);
-         decl_machine_attr = DECL_MACHINE_ATTRIBUTES (id);
+         decl_attr = DECL_ATTRIBUTES (id);
          typedef_decl = id;
        }
       /* Built-in types come as identifiers.  */
@@ -4259,6 +4312,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       /* Each level of DECLARATOR is either an ARRAY_REF (for ...[..]),
         an INDIRECT_REF (for *...),
         a CALL_EXPR (for ...(...)),
+        a TREE_LIST (for nested attributes),
         an identifier (for the name being declared)
         or a null pointer (for the place in an absolute declarator
         where the name was omitted).
@@ -4270,13 +4324,49 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
         array or function or pointer, and DECLARATOR has had its
         outermost layer removed.  */
 
-      if (TREE_CODE (declarator) == ARRAY_REF)
+      if (array_ptr_quals != NULL_TREE || array_parm_static)
+       {
+         /* Only the innermost declarator (making a parameter be of
+            array type which is converted to pointer type)
+            may have static or type qualifiers.  */
+         error ("static or type qualifiers in non-parameter array declarator");
+         array_ptr_quals = NULL_TREE;
+         array_parm_static = 0;
+       }
+
+      if (TREE_CODE (declarator) == TREE_LIST)
+       {
+         /* We encode a declarator with embedded attributes using
+            a TREE_LIST.  */
+         tree attrs = TREE_PURPOSE (declarator);
+         tree inner_decl;
+         int attr_flags = 0;
+         declarator = TREE_VALUE (declarator);
+         inner_decl = declarator;
+         while (inner_decl != NULL_TREE
+                && TREE_CODE (inner_decl) == TREE_LIST)
+           inner_decl = TREE_VALUE (inner_decl);
+         if (inner_decl == NULL_TREE
+             || TREE_CODE (inner_decl) == IDENTIFIER_NODE)
+           attr_flags |= (int) ATTR_FLAG_DECL_NEXT;
+         if (TREE_CODE (inner_decl) == CALL_EXPR)
+           attr_flags |= (int) ATTR_FLAG_FUNCTION_NEXT;
+         if (TREE_CODE (inner_decl) == ARRAY_REF)
+           attr_flags |= (int) ATTR_FLAG_ARRAY_NEXT;
+         returned_attrs = decl_attributes (&type,
+                                           chainon (returned_attrs, attrs),
+                                           attr_flags);
+       }
+      else if (TREE_CODE (declarator) == ARRAY_REF)
        {
          register tree itype = NULL_TREE;
          register tree size = TREE_OPERAND (declarator, 1);
          /* The index is a signed object `sizetype' bits wide.  */
          tree index_type = signed_type (sizetype);
 
+         array_ptr_quals = TREE_TYPE (declarator);
+         array_parm_static = TREE_STATIC (declarator);
+
          declarator = TREE_OPERAND (declarator, 0);
 
          /* Check for some types that there cannot be arrays of.  */
@@ -4308,8 +4398,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              /* Strip NON_LVALUE_EXPRs since we aren't using as an lvalue.  */
              STRIP_TYPE_NOPS (size);
 
-             if (TREE_CODE (TREE_TYPE (size)) != INTEGER_TYPE
-                 && TREE_CODE (TREE_TYPE (size)) != ENUMERAL_TYPE)
+             if (! INTEGRAL_TYPE_P (TREE_TYPE (size)))
                {
                  error ("size of array `%s' has non-integer type", name);
                  size = integer_one_node;
@@ -4426,6 +4515,13 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              TYPE_SIZE (type) = bitsize_zero_node;
              TYPE_SIZE_UNIT (type) = size_zero_node;
            }
+         if (decl_context != PARM
+             && (array_ptr_quals != NULL_TREE || array_parm_static))
+           {
+             error ("static or type qualifiers in non-parameter array declarator");
+             array_ptr_quals = NULL_TREE;
+             array_parm_static = 0;
+           }
        }
       else if (TREE_CODE (declarator) == CALL_EXPR)
        {
@@ -4605,6 +4701,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
       if ((specbits & (1 << (int) RID_SIGNED))
          || (typedef_decl && C_TYPEDEF_EXPLICITLY_SIGNED (typedef_decl)))
        C_TYPEDEF_EXPLICITLY_SIGNED (decl) = 1;
+      decl_attributes (&decl, returned_attrs, 0);
       return decl;
     }
 
@@ -4635,6 +4732,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
        pedwarn ("ISO C forbids const or volatile function types");
       if (type_quals)
        type = c_build_qualified_type (type, type_quals);
+      decl_attributes (&type, returned_attrs, 0);
       return type;
     }
 
@@ -4659,11 +4757,11 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
      or a FUNCTION_DECL, depending on DECL_CONTEXT and TYPE.  */
 
   {
-    register tree decl;
+    tree decl;
 
     if (decl_context == PARM)
       {
-       tree type_as_written = type;
+       tree type_as_written;
        tree promoted_type;
 
        /* A parameter declared as an array of T is really a pointer to T.
@@ -4677,6 +4775,44 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
              type = c_build_qualified_type (type, type_quals);
            type = build_pointer_type (type);
            type_quals = TYPE_UNQUALIFIED;
+           if (array_ptr_quals)
+             {
+               tree new_ptr_quals, new_ptr_attrs;
+               int erred = 0;
+               split_specs_attrs (array_ptr_quals, &new_ptr_quals, &new_ptr_attrs);
+               /* We don't yet implement attributes in this context.  */
+               if (new_ptr_attrs != NULL_TREE)
+                 warning ("attributes in parameter array declarator ignored");
+
+               constp = 0;
+               volatilep = 0;
+               restrictp = 0;
+               for (; new_ptr_quals; new_ptr_quals = TREE_CHAIN (new_ptr_quals))
+                 {
+                   tree qualifier = TREE_VALUE (new_ptr_quals);
+
+                   if (C_IS_RESERVED_WORD (qualifier))
+                     {
+                       if (C_RID_CODE (qualifier) == RID_CONST)
+                         constp++;
+                       else if (C_RID_CODE (qualifier) == RID_VOLATILE)
+                         volatilep++;
+                       else if (C_RID_CODE (qualifier) == RID_RESTRICT)
+                         restrictp++;
+                       else
+                         erred++;
+                     }
+                   else
+                     erred++;
+                 }
+
+               if (erred)
+                 error ("invalid type modifier within array declarator");
+
+               type_quals = ((constp ? TYPE_QUAL_CONST : 0)
+                             | (restrictp ? TYPE_QUAL_RESTRICT : 0)
+                             | (volatilep ? TYPE_QUAL_VOLATILE : 0));
+             }
            size_varies = 0;
          }
        else if (TREE_CODE (type) == FUNCTION_TYPE)
@@ -4688,6 +4824,10 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            type = build_pointer_type (type);
            type_quals = TYPE_UNQUALIFIED;
          }
+       else if (type_quals)
+         type = c_build_qualified_type (type, type_quals);
+         
+       type_as_written = type;
 
        decl = build_decl (PARM_DECL, declarator, type);
        if (size_varies)
@@ -4766,7 +4906,7 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
          pedwarn ("invalid storage class for function `%s'", name);
 
        decl = build_decl (FUNCTION_DECL, declarator, type);
-       decl = build_decl_attribute_variant (decl, decl_machine_attr);
+       decl = build_decl_attribute_variant (decl, decl_attr);
 
        if (pedantic && type_quals && ! DECL_IN_SYSTEM_HEADER (decl))
          pedwarn ("ISO C forbids qualified function types");
@@ -4814,7 +4954,9 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
            type_quals = TYPE_UNQUALIFIED;
 #endif
          }
-
+       else if (type_quals)
+         type = c_build_qualified_type (type, type_quals);
+         
        decl = build_decl (VAR_DECL, declarator, type);
        if (size_varies)
          C_DECL_VARIABLE_SIZE (decl) = 1;
@@ -4857,6 +4999,8 @@ grokdeclarator (declarator, declspecs, decl_context, initialized)
     if (C_TYPE_FIELDS_VOLATILE (TREE_TYPE (decl)))
       mark_addressable (decl);
 
+    decl_attributes (&decl, returned_attrs, 0);
+
     return decl;
   }
 }
@@ -5054,8 +5198,7 @@ get_parm_info (void_at_end)
        tree type = TREE_TYPE (decl);
        DECL_ARG_TYPE (decl) = type;
        if (PROMOTE_PROTOTYPES
-           && (TREE_CODE (type) == INTEGER_TYPE
-               || TREE_CODE (type) == ENUMERAL_TYPE)
+           && INTEGRAL_TYPE_P (type)
            && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
          DECL_ARG_TYPE (decl) = integer_type_node;
 
@@ -5127,11 +5270,18 @@ xref_tag (code, name)
      already defined for this tag and return it.  */
 
   register tree ref = lookup_tag (code, name, current_binding_level, 0);
-  /* Even if this is the wrong type of tag, return what we found.
-     There will be an error message anyway, from pending_xref_error.
-     If we create an empty xref just for an invalid use of the type,
-     the main result is to create lots of superfluous error messages.  */
-  if (ref)
+  /* If this is the right type of tag, return what we found.
+     (This reference will be shadowed by shadow_tag later if appropriate.)
+     If this is the wrong type of tag, do not return it.  If it was the
+     wrong type in the same binding level, we will have had an error
+     message already; if in a different binding level and declaring
+     a name, pending_xref_error will give an error message; but if in a
+     different binding level and not declaring a name, this tag should
+     shadow the previous declaration of a different type of tag, and
+     this would not work properly if we return the reference found.
+     (For example, with "struct foo" in an outer scope, "union foo;"
+     must shadow that tag with a new one of union type.)  */
+  if (ref && TREE_CODE (ref) == code)
     return ref;
 
   /* If no such tag is yet defined, create a forward-reference node
@@ -5239,7 +5389,7 @@ finish_struct (t, fieldlist, attributes)
 
   TYPE_SIZE (t) = 0;
 
-  decl_attributes (t, attributes, NULL_TREE);
+  decl_attributes (&t, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
 
   /* Nameless union parm types are useful as GCC extension.  */
   if (! (TREE_CODE (t) == UNION_TYPE && TYPE_NAME (t) == 0) && !pedantic)
@@ -5603,7 +5753,7 @@ finish_enum (enumtype, values, attributes)
   if (in_parm_level_p ())
     warning ("enum defined inside parms");
 
-  decl_attributes (enumtype, attributes, NULL_TREE);
+  decl_attributes (&enumtype, attributes, (int) ATTR_FLAG_TYPE_IN_PLACE);
 
   /* Calculate the maximum value of any enumerator in this type.  */
 
@@ -5787,7 +5937,7 @@ build_enumerator (name, value)
 
 \f
 /* Create the FUNCTION_DECL for a function definition.
-   DECLSPECS, DECLARATOR, PREFIX_ATTRIBUTES and ATTRIBUTES are the parts of
+   DECLSPECS, DECLARATOR and ATTRIBUTES are the parts of
    the declaration; they describe the function's name and the type it returns,
    but twisted together in a fashion that parallels the syntax of C.
 
@@ -5799,8 +5949,8 @@ build_enumerator (name, value)
    yyparse to report a parse error.  */
 
 int
-start_function (declspecs, declarator, prefix_attributes, attributes)
-     tree declarator, declspecs, prefix_attributes, attributes;
+start_function (declspecs, declarator, attributes)
+     tree declarator, declspecs, attributes;
 {
   tree decl1, old_decl;
   tree restype;
@@ -5827,7 +5977,7 @@ start_function (declspecs, declarator, prefix_attributes, attributes)
       return 0;
     }
 
-  decl_attributes (decl1, prefix_attributes, attributes);
+  decl_attributes (&decl1, attributes, 0);
 
   announce_function (decl1);
 
@@ -5916,10 +6066,6 @@ start_function (declspecs, declarator, prefix_attributes, attributes)
      except for defining how to inline.  So set DECL_EXTERNAL in that case.  */
   DECL_EXTERNAL (decl1) = current_extern_inline;
 
-#ifdef SET_DEFAULT_DECL_ATTRIBUTES
-  SET_DEFAULT_DECL_ATTRIBUTES (decl1, attributes);
-#endif
-
   /* This function exists in static storage.
      (This does not mean `static' in the C sense!)  */
   TREE_STATIC (decl1) = 1;
@@ -6067,6 +6213,9 @@ store_parm_decls ()
   /* Nonzero if this definition is written with a prototype.  */
   int prototype = 0;
 
+  /* The function containing FNDECL, if any.  */
+  tree context = decl_function_context (fndecl);
+
   if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
     {
       /* This case is when the function was defined with an ANSI prototype.
@@ -6327,9 +6476,11 @@ store_parm_decls ()
                                            "prototype declaration");
                  break;
                }
-             /* Type for passing arg must be consistent
-                with that declared for the arg.  */
-             if (! comptypes (DECL_ARG_TYPE (parm), TREE_VALUE (type)))
+             /* Type for passing arg must be consistent with that
+                declared for the arg.  ISO C says we take the unqualified
+                type for parameters declared with qualified type.  */
+             if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+                              TYPE_MAIN_VARIANT (TREE_VALUE (type))))
                {
                  if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
                      == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
@@ -6342,8 +6493,7 @@ store_parm_decls ()
                      DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
 
                      if (PROMOTE_PROTOTYPES
-                         && (TREE_CODE (TREE_TYPE (parm)) == INTEGER_TYPE
-                             || TREE_CODE (TREE_TYPE (parm)) == ENUMERAL_TYPE)
+                         && INTEGRAL_TYPE_P (TREE_TYPE (parm))
                          && TYPE_PRECISION (TREE_TYPE (parm))
                          < TYPE_PRECISION (integer_type_node))
                        DECL_ARG_TYPE (parm) = integer_type_node;
@@ -6435,14 +6585,28 @@ store_parm_decls ()
   gen_aux_info_record (fndecl, 1, 0, prototype);
 
   /* Initialize the RTL code for the function.  */
-
   init_function_start (fndecl, input_filename, lineno);
 
   /* Begin the statement tree for this function.  */
   DECL_LANG_SPECIFIC (current_function_decl)
-    =((struct lang_decl *) ggc_alloc (sizeof (struct lang_decl)));
+    =((struct lang_decl *) ggc_alloc_cleared (sizeof (struct lang_decl)));
   begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
 
+  /* If this is a nested function, save away the sizes of any
+     variable-size types so that we can expand them when generating
+     RTL.  */
+  if (context)
+    {
+      tree t;
+
+      DECL_LANG_SPECIFIC (fndecl)->pending_sizes 
+       = nreverse (get_pending_sizes ());
+      for (t = DECL_LANG_SPECIFIC (fndecl)->pending_sizes;
+          t;
+          t = TREE_CHAIN (t))
+       SAVE_EXPR_CONTEXT (TREE_VALUE (t)) = context;
+    }
+
   /* This function is being processed in whole-function mode.  */
   cfun->x_whole_function_mode_p = 1;
 
@@ -6454,149 +6618,6 @@ store_parm_decls ()
   cfun->x_dont_save_pending_sizes_p = 1;
 }
 \f
-/* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
-   each with a parm name as the TREE_VALUE.  A null pointer as TREE_VALUE
-   stands for an ellipsis in the identifier list.
-
-   PARMLIST is the data returned by get_parm_info for the
-   parmlist that follows the semicolon.
-
-   We return a value of the same sort that get_parm_info returns,
-   except that it describes the combination of identifiers and parmlist.  */
-
-tree
-combine_parm_decls (specparms, parmlist, void_at_end)
-     tree specparms, parmlist;
-     int void_at_end;
-{
-  register tree fndecl = current_function_decl;
-  register tree parm;
-
-  tree parmdecls = TREE_PURPOSE (parmlist);
-
-  /* This is a chain of any other decls that came in among the parm
-     declarations.  They were separated already by get_parm_info,
-     so we just need to keep them separate.  */
-  tree nonparms = TREE_VALUE (parmlist);
-
-  tree types = 0;
-
-  for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
-    DECL_WEAK (parm) = 0;
-
-  for (parm = specparms; parm; parm = TREE_CHAIN (parm))
-    {
-      register tree tail, found = NULL;
-
-      /* See if any of the parmdecls specifies this parm by name.  */
-      for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
-       if (DECL_NAME (tail) == TREE_VALUE (parm))
-         {
-           found = tail;
-           break;
-         }
-
-      /* If declaration already marked, we have a duplicate name.
-        Complain, and don't use this decl twice.   */
-      if (found && DECL_WEAK (found))
-       {
-         error_with_decl (found, "multiple parameters named `%s'");
-         found = 0;
-       }
-
-      /* If the declaration says "void", complain and ignore it.  */
-      if (found && VOID_TYPE_P (TREE_TYPE (found)))
-       {
-         error_with_decl (found, "parameter `%s' declared void");
-         TREE_TYPE (found) = integer_type_node;
-         DECL_ARG_TYPE (found) = integer_type_node;
-         layout_decl (found, 0);
-       }
-
-      /* Traditionally, a parm declared float is actually a double.  */
-      if (found && flag_traditional
-         && TYPE_MAIN_VARIANT (TREE_TYPE (found)) == float_type_node)
-       {
-         TREE_TYPE (found) = double_type_node;
-         DECL_ARG_TYPE (found) = double_type_node;
-         layout_decl (found, 0);
-       }
-
-      /* If no declaration found, default to int.  */
-      if (!found)
-       {
-         found = build_decl (PARM_DECL, TREE_VALUE (parm),
-                             integer_type_node);
-         DECL_ARG_TYPE (found) = TREE_TYPE (found);
-         DECL_SOURCE_LINE (found) = DECL_SOURCE_LINE (fndecl);
-         DECL_SOURCE_FILE (found) = DECL_SOURCE_FILE (fndecl);
-         error_with_decl (found, "type of parameter `%s' is not declared");
-         pushdecl (found);
-       }
-
-      TREE_PURPOSE (parm) = found;
-
-      /* Mark this decl as "already found".  */
-      DECL_WEAK (found) = 1;
-    }
-
-  /* Complain about any actual PARM_DECLs not matched with any names.  */
-
-  for (parm = parmdecls; parm;)
-    {
-      tree next = TREE_CHAIN (parm);
-      TREE_CHAIN (parm) = 0;
-
-      /* Complain about args with incomplete types.  */
-      if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
-       {
-         error_with_decl (parm, "parameter `%s' has incomplete type");
-         TREE_TYPE (parm) = error_mark_node;
-       }
-
-      if (! DECL_WEAK (parm))
-       {
-         error_with_decl (parm,
-                          "declaration for parameter `%s' but no such parameter");
-         /* Pretend the parameter was not missing.
-            This gets us to a standard state and minimizes
-            further error messages.  */
-         specparms
-           = chainon (specparms,
-                      tree_cons (parm, NULL_TREE, NULL_TREE));
-       }
-
-      parm = next;
-    }
-
-  /* Chain the declarations together in the order of the list of names.
-     At the same time, build up a list of their types, in reverse order.  */
-
-  parm = specparms;
-  parmdecls = 0;
-  {
-    register tree last;
-    for (last = 0; parm; parm = TREE_CHAIN (parm))
-      if (TREE_PURPOSE (parm))
-       {
-         if (last == 0)
-           parmdecls = TREE_PURPOSE (parm);
-         else
-           TREE_CHAIN (last) = TREE_PURPOSE (parm);
-         last = TREE_PURPOSE (parm);
-         TREE_CHAIN (last) = 0;
-
-         types = tree_cons (NULL_TREE, TREE_TYPE (parm), types);
-       }
-  }
-
-  if (void_at_end)
-    return tree_cons (parmdecls, nonparms,
-                     nreverse (tree_cons (NULL_TREE, void_type_node, types)));
-
-  return tree_cons (parmdecls, nonparms, nreverse (types));
-}
-\f
 /* Finish up a function declaration and compile that function
    all the way to assembler language output.  The free the storage
    for the function definition.
@@ -6687,9 +6708,14 @@ c_expand_body (fndecl, nested_p)
   if (flag_syntax_only)
     return;
 
-  /* Squirrel away our current state.  */
   if (nested_p)
-    push_function_context ();
+    {
+      /* Make sure that we will evaluate variable-sized types involved
+        in our function's type.  */
+      expand_pending_sizes (DECL_LANG_SPECIFIC (fndecl)->pending_sizes);
+      /* Squirrel away our current state.  */
+      push_function_context ();
+    }
 
   /* Initialize the RTL code for the function.  */
   current_function_decl = fndecl;
@@ -6724,7 +6750,7 @@ c_expand_body (fndecl, nested_p)
   /* Allow the body of the function to be garbage collected.  */
   DECL_SAVED_TREE (fndecl) = NULL_TREE;
 
-  /* We hard-wired immediate_size_expand to zero in start_function.
+  /* We hard-wired immediate_size_expand to zero above.
      expand_function_end will decrement this variable.  So, we set the
      variable to one here, so that after the decrement it will remain
      zero.  */
@@ -6798,38 +6824,25 @@ c_expand_body (fndecl, nested_p)
 
   if (DECL_STATIC_CONSTRUCTOR (fndecl))
     {
-#ifndef ASM_OUTPUT_CONSTRUCTOR
-      if (! flag_gnu_linker)
-       static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
+      if (targetm.have_ctors_dtors)
+       (* targetm.asm_out.constructor) (XEXP (DECL_RTL (fndecl), 0),
+                                        DEFAULT_INIT_PRIORITY);
       else
-#endif
-       assemble_constructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
-
+       static_ctors = tree_cons (NULL_TREE, fndecl, static_ctors);
     }
+
   if (DECL_STATIC_DESTRUCTOR (fndecl))
     {
-#ifndef ASM_OUTPUT_DESTRUCTOR
-      if (! flag_gnu_linker)
-       static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
+      if (targetm.have_ctors_dtors)
+       (* targetm.asm_out.destructor) (XEXP (DECL_RTL (fndecl), 0),
+                                       DEFAULT_INIT_PRIORITY);
       else
-#endif
-       assemble_destructor (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (fndecl)));
+       static_dtors = tree_cons (NULL_TREE, fndecl, static_dtors);
     }
 
   if (nested_p)
-    {
-      /* Return to the enclosing function.  */
-      pop_function_context ();
-      /* If the nested function was inline, write it out if that is
-        necessary.  */
-      if (!TREE_ASM_WRITTEN (fndecl) && TREE_ADDRESSABLE (fndecl))
-       {
-         push_function_context ();
-         output_inline_function (fndecl);
-         pop_function_context ();
-       }
-    }
-
+    /* Return to the enclosing function.  */
+    pop_function_context ();
 }
 \f
 /* Check the declarations given in a for-loop for satisfying the C99
@@ -7017,6 +7030,7 @@ lang_mark_tree (t)
     {
       ggc_mark (DECL_LANG_SPECIFIC (t));
       c_mark_lang_decl (&DECL_LANG_SPECIFIC (t)->base);
+      ggc_mark_tree (DECL_LANG_SPECIFIC (t)->pending_sizes);
     }
 }