OSDN Git Service

2003-07-29 Geoffrey Keating <geoffk@apple.com>
[pf3gnuchains/gcc-fork.git] / gcc / c-decl.c
index a9c10dc..6a87c42 100644 (file)
@@ -88,8 +88,8 @@ static int enum_overflow;
 
 static tree last_function_parms;
 
-/* Parsing a function declarator leaves a chain of structure
-   and enum types declared in the parmlist here.  */
+/* ... and a chain of structure and enum types declared in the
+   parmlist here.  */
 
 static tree last_function_parm_tags;
 
@@ -166,67 +166,57 @@ static int current_extern_inline;
  */
 
 struct c_scope GTY(())
-  {
-    /* A chain of _DECL nodes for all variables, constants, functions,
-       and typedef types.  These are in the reverse of the order supplied.
-     */
-    tree names;
-
-    /* A list of structure, union and enum definitions,
-     * for looking up tag names.
-     * It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name,
-     * or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE,
-     * or ENUMERAL_TYPE node.
-     */
-    tree tags;
-
-    /* For each scope, a list of shadowed outer-scope definitions
-       to be restored when this scope is popped.
-       Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
-       whose TREE_VALUE is its old definition (a kind of ..._DECL node).  */
-    tree shadowed;
-
-    /* For each scope, a list of shadowed outer-scope tag definitions
-       to be restored when this scope is popped.
-       Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
-       whose TREE_VALUE is its old definition (a kind of ..._TYPE node).  */
-    tree shadowed_tags;
-
-    /* For each scope (except not the global one),
-       a chain of BLOCK nodes for all the scopes
-       that were entered and exited one level down.  */
-    tree blocks;
-
-    /* The scope containing this one.  */
-    struct c_scope *outer;
-
-    /* The next outermost function scope.  */
-    struct c_scope *outer_function;
-
-    /* True if we are currently filling this scope with parameter
-       declarations.  */
-    bool parm_flag : 1;
-
-    /* True if this is the outermost block scope of a function body.
-       This scope contains both the parameters and the local variables
-       declared in the outermost block.  */
-    bool function_body : 1;
-
-    /* True means make a BLOCK for this scope regardless of all else.  */
-    bool keep : 1;
-
-    /* True means make a BLOCK if this scope has any subblocks.  */
-    bool keep_if_subblocks : 1;
-
-    /* List of decls in `names' that have incomplete structure or
-       union types.  */
-    tree incomplete_list;
-
-    /* A list of decls giving the (reversed) specified order of parms,
-       not including any forward-decls in the parmlist.
-       This is so we can put the parms in proper order for assign_parms.  */
-    tree parm_order;
-  };
+{
+  /* The scope containing this one.  */
+  struct c_scope *outer;
+
+  /* The next outermost function scope.  */
+  struct c_scope *outer_function;
+
+  /* All variables, constants, functions, labels, and typedef names.
+     They are in the reverse of the order supplied.  */
+  tree names;
+
+  /* All structure, union, and enum type tags.  */
+  tree tags;
+
+  /* For each scope, a list of shadowed outer-scope definitions
+     to be restored when this scope is popped.
+     Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
+     whose TREE_VALUE is its old definition (a kind of ..._DECL node).  */
+  tree shadowed;
+
+  /* For each scope, a list of shadowed outer-scope tag definitions
+     to be restored when this scope is popped.
+     Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
+     whose TREE_VALUE is its old definition (a kind of ..._TYPE node).  */
+  tree shadowed_tags;
+
+  /* For each scope (except the global one), a chain of BLOCK nodes
+     for all the scopes that were entered and exited one level down.  */
+  tree blocks;
+
+  /* Variable declarations with incomplete type in this scope.  */
+  tree incomplete_list;
+
+  /* A list of decls giving the (reversed) specified order of parms,
+     not including any forward-decls in the parmlist.
+     This is so we can put the parms in proper order for assign_parms.  */
+  tree parm_order;
+
+  /* True if we are currently filling this scope with parameter
+     declarations.  */
+  bool parm_flag : 1;
+
+  /* True if this is the outermost block scope of a function body.
+     This scope contains the parameters, the local variables declared
+     in the outermost block, and all the labels (except those in
+     nested functions, or declared at block scope with __label__).  */
+  bool function_body : 1;
+
+  /* True means make a BLOCK for this scope no matter what.  */
+  bool keep : 1;
+};
 
 /* The scope currently in effect.  */
 
@@ -239,6 +229,7 @@ static GTY((deletable (""))) struct c_scope *scope_freelist;
 /* The innermost function scope.  Ordinary (not explicitly declared)
    labels, bindings to error_mark_node, and the lazily-created
    bindings of __func__ and its friends get this scope.  */
+
 static GTY(()) struct c_scope *current_function_scope;
 
 /* The outermost scope, corresponding to the C "file scope".  This is
@@ -250,9 +241,11 @@ static GTY(()) struct c_scope *global_scope;
 
 static bool keep_next_level_flag;
 
-/* True means make a BLOCK for the next scope pushed if it has subblocks.  */
+/* True means the next call to pushlevel will be the outermost scope
+   of a function body, so do not push a new scope, merely cease
+   expecting parameter decls.  */
 
-static bool keep_next_if_subblocks;
+static bool next_is_function_body;
 
 /* Functions called automatically at the beginning and end of execution.  */
 
@@ -275,6 +268,8 @@ static tree lookup_name_current_level (tree);
 static tree grokdeclarator (tree, tree, enum decl_context, int);
 static tree grokparms (tree, int);
 static void layout_array_type (tree);
+static void store_parm_decls_newstyle (void);
+static void store_parm_decls_oldstyle (void);
 static tree c_make_fname_decl (tree, int);
 static void c_expand_body_1 (tree, int);
 static tree any_external_decl (tree);
@@ -401,30 +396,32 @@ in_parm_level_p (void)
   return current_scope->parm_flag;
 }
 
-/* Enter a new scope.  */
+/* Enter a new scope.  The dummy parameter is for signature
+   compatibility with lang_hooks.decls.pushlevel.  */
 
 void
 pushlevel (int dummy ATTRIBUTE_UNUSED)
 {
-  if (keep_next_if_subblocks)
+  if (next_is_function_body)
     {
       /* This is the transition from the parameters to the top level
         of the function body.  These are the same scope
         (C99 6.2.1p4,6) so we do not push another scope structure.
+        next_is_function_body is set only by store_parm_decls, which
+        in turn is called when and only when we are about to
+        encounter the opening curly brace for the function body.
 
-        XXX Note kludge - keep_next_if_subblocks is set only by
-        store_parm_decls, which in turn is called when and only
-        when we are about to encounter the opening curly brace for
-        the function body.  */
+        The outermost block of a function always gets a BLOCK node,
+        because the debugging output routines expect that each
+        function has at least one BLOCK. */
       current_scope->parm_flag         = false;
       current_scope->function_body     = true;
-      current_scope->keep             |= keep_next_level_flag;
-      current_scope->keep_if_subblocks = true;
+      current_scope->keep              = true;
       current_scope->outer_function    = current_function_scope;
       current_function_scope           = current_scope;
 
       keep_next_level_flag = false;
-      keep_next_if_subblocks = false;
+      next_is_function_body = false;
     }
   else
     {
@@ -445,12 +442,15 @@ pushlevel (int dummy ATTRIBUTE_UNUSED)
    debugging output.  If KEEP is KEEP_MAYBE, do so only if the names
    or tags lists are nonempty.
 
+   If REVERSE is nonzero, reverse the order of decls before putting
+   them into the BLOCK.
+
    If FUNCTIONBODY is nonzero, this level is the body of a function,
-   so create a block as if KEEP were set and also clear out all
-   label names.
+   even if current_scope->function_body is not set.  This is used
+   by language-independent code that generates synthetic functions,
+   and cannot set current_scope->function_body.
 
-   If REVERSE is nonzero, reverse the order of decls before putting
-   them into the BLOCK.  */
+   FIXME: Eliminate the need for all arguments.  */
 
 tree
 poplevel (int keep, int reverse, int functionbody)
@@ -466,9 +466,9 @@ poplevel (int keep, int reverse, int functionbody)
 
   if (keep == KEEP_MAYBE)
     keep = (current_scope->names || current_scope->tags);
-  
-  keep |= (current_scope->keep || functionbody
-          || (subblocks && current_scope->keep_if_subblocks));
+
+  keep |= current_scope->keep;
+  keep |= functionbody;
 
   /* We used to warn about unused variables in expand_end_bindings,
      i.e. while generating RTL.  But in function-at-a-time mode we may
@@ -663,10 +663,9 @@ pushtag (tree name, tree type)
 {
   struct c_scope *b = current_scope;
 
+  /* Record the identifier as the type's name if it has none.  */
   if (name)
     {
-      /* Record the identifier as the type's name if it has none.  */
-
       if (TYPE_NAME (type) == 0)
        TYPE_NAME (type) = name;
 
@@ -1122,6 +1121,8 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
       /* Warn about mismatches in various flags.  */
       else
        {
+         const location_t *locus = &DECL_SOURCE_LOCATION (newdecl);
+
          /* Warn if function is now inline
             but was previously declared not inline and has been called.  */
          if (TREE_CODE (olddecl) == FUNCTION_DECL
@@ -1129,30 +1130,30 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
              && DECL_DECLARED_INLINE_P (newdecl)
              && TREE_USED (olddecl))
            warning ("%H'%D' declared inline after being called",
-                     &DECL_SOURCE_LOCATION (newdecl), newdecl);
+                    locus, newdecl);
          if (TREE_CODE (olddecl) == FUNCTION_DECL
              && ! DECL_DECLARED_INLINE_P (olddecl)
              && DECL_DECLARED_INLINE_P (newdecl)
              && DECL_INITIAL (olddecl) != 0)
            warning ("%H'%D' declared inline after its definition",
-                     &DECL_SOURCE_LOCATION (newdecl), newdecl);
+                    locus, newdecl);
 
          /* If pedantic, warn when static declaration follows a non-static
-            declaration.  Otherwise, do so only for functions.  */
+            declaration.  Otherwise, do so only for functions.  */
          if ((pedantic || TREE_CODE (olddecl) == FUNCTION_DECL)
              && TREE_PUBLIC (olddecl)
              && !TREE_PUBLIC (newdecl))
            warning ("%Hstatic declaration for '%D' follows non-static",
-                     &DECL_SOURCE_LOCATION (newdecl), newdecl);
+                    locus, newdecl);
 
          /* If warn_traditional, warn when a non-static function
-            declaration follows a static one.  */
+            declaration follows a static one.  */
          if (warn_traditional && !in_system_header
              && TREE_CODE (olddecl) == FUNCTION_DECL
              && !TREE_PUBLIC (olddecl)
              && TREE_PUBLIC (newdecl))
            warning ("%Hnon-static declaration for '%D' follows static",
-                     &DECL_SOURCE_LOCATION (newdecl), newdecl);
+                    locus, newdecl);
 
          /* Warn when const declaration follows a non-const
             declaration, but not for functions.  */
@@ -1160,7 +1161,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
              && !TREE_READONLY (olddecl)
              && TREE_READONLY (newdecl))
            warning ("%Hconst declaration for '%D' follows non-const",
-                     &DECL_SOURCE_LOCATION (newdecl), newdecl);
+                    locus, newdecl);
          /* These bits are logically part of the type, for variables.
             But not for functions
             (where qualifiers are not valid ANSI anyway).  */
@@ -1168,7 +1169,7 @@ duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
              && (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
                  || TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl)))
            pedwarn ("%Htype qualifiers for '%D' conflict with previous "
-                     "declaration", &DECL_SOURCE_LOCATION (newdecl), newdecl);
+                    "declaration", locus, newdecl);
        }
     }
 
@@ -1532,12 +1533,10 @@ warn_if_shadowing (tree x, tree old)
         It would be nice to avoid warning in any function
         declarator in a declaration, as opposed to a definition,
         but there is no way to tell it's not a definition.  */
-      || (TREE_CODE (x) == PARM_DECL
-         && current_scope->outer->parm_flag))
+      || (TREE_CODE (x) == PARM_DECL && current_scope->outer->parm_flag))
     return;
 
   name = IDENTIFIER_POINTER (DECL_NAME (x));
-
   if (TREE_CODE (old) == PARM_DECL)
     shadow_warning (SW_PARAM, name, old);
   else if (C_DECL_FILE_SCOPE (old))
@@ -1700,7 +1699,11 @@ pushdecl (tree x)
       /* Keep list of variables in this scope with incomplete type.
         If the input is erroneous, we can have error_mark in the type
         slot (e.g. "f(void a, ...)") - that doesn't count as an
-        incomplete type.  */
+        incomplete type.
+
+        FIXME: Chain these off the TYPE_DECL for the incomplete type,
+        then we don't have to do (potentially quite costly) searches
+        in finish_struct.  */
       if (TREE_TYPE (x) != error_mark_node
          && !COMPLETE_TYPE_P (TREE_TYPE (x)))
        {
@@ -1824,16 +1827,15 @@ implicitly_declare (tree functionid)
   C_DECL_IMPLICIT (decl) = 1;
   implicit_decl_warning (functionid);
 
-  /* ANSI standard says implicit declarations are in the innermost block.
+  /* C89 says implicit declarations are in the innermost block.
      So we record the decl in the standard fashion.  */
   decl = pushdecl (decl);
 
   /* No need to call objc_check_decl here - it's a function type.  */
   rest_of_decl_compilation (decl, NULL, 0, 0);
 
-  /* Write a record describing this implicit function declaration to the
-     prototypes file (if requested).  */
-
+  /* Write a record describing this implicit function declaration
+     to the prototypes file (if requested).  */
   gen_aux_info_record (decl, 0, 1, 0);
 
   /* Possibly apply some default attributes to this implicit declaration.  */
@@ -2012,8 +2014,7 @@ lookup_label (tree name)
   /* No label binding for that identifier; make one.  */
   label = make_label (name, input_location);
 
-  /* Ordinary labels go in the current function scope, which is
-     not necessarily the current label scope.  */
+  /* Ordinary labels go in the current function scope.  */
   bind_label (name, label, current_function_scope);
   return label;
 }
@@ -2074,13 +2075,12 @@ define_label (location_t location, tree name)
          || (DECL_CONTEXT (label) != current_function_decl
              && C_DECLARED_LABEL_FLAG (label))))
     {
+      location_t *prev_loc = &DECL_SOURCE_LOCATION (label);
       error ("%Hduplicate label `%D'", &location, label);
       if (DECL_INITIAL (label))
-       error ("%H`%D' previously defined here",
-              &DECL_SOURCE_LOCATION (label), label);
+       error ("%H`%D' previously defined here", prev_loc, label);
       else
-       error ("%H`%D' previously declared here",
-              &DECL_SOURCE_LOCATION (label), label);
+       error ("%H`%D' previously declared here", prev_loc, label);
       return 0;
     }
   else if (label && DECL_CONTEXT (label) == current_function_decl)
@@ -2095,8 +2095,7 @@ define_label (location_t location, tree name)
       /* No label binding for that identifier; make one.  */
       label = make_label (name, location);
 
-      /* Ordinary labels go in the current function scope, which is
-        not necessarily the current label scope.  */
+      /* Ordinary labels go in the current function scope.  */
       bind_label (name, label, current_function_scope);
     }
 
@@ -2111,9 +2110,7 @@ define_label (location_t location, tree name)
 }
 \f
 /* Return the list of declarations of the current scope.
-   Note that this list is in reverse order unless/until
-   you nreverse it; and when you do nreverse it, you must
-   store the result back using `storedecls' or you will lose.  */
+   Note that this list is in reverse order.  */
 
 tree
 getdecls (void)
@@ -2258,14 +2255,12 @@ c_init_decl_processing (void)
   /* Adds some ggc roots, and reserved words for c-parse.in.  */
   c_parse_init ();
 
-  current_function_decl = NULL;
-  current_scope = NULL;
-  current_function_scope = NULL;
-  scope_freelist = NULL;
+  current_function_decl = 0;
 
   /* Make the c_scope structure for global names.  */
   pushlevel (0);
   global_scope = current_scope;
+
   /* Declarations from c_common_nodes_and_builtins must not be associated
      with this input file, lest we get differences between using and not
      using preprocessed headers.  */
@@ -2709,10 +2704,9 @@ start_decl (tree declarator, tree declspecs, int initialized, tree attributes)
       && C_DECL_FILE_SCOPE (tem))
     {
       if (TREE_TYPE (tem) != error_mark_node
-         && COMPLETE_TYPE_P (TREE_TYPE (tem)))
-       expand_decl (tem);
-      else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
-              && DECL_INITIAL (tem) != 0)
+         && (COMPLETE_TYPE_P (TREE_TYPE (tem))
+             || (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
+                 && DECL_INITIAL (tem) != 0)))
        expand_decl (tem);
     }
 
@@ -3002,8 +2996,10 @@ void
 push_parm_decl (tree parm)
 {
   tree decl;
-  int old_immediate_size_expand = immediate_size_expand;
-  /* Don't try computing parm sizes now -- wait till fn is called.  */
+
+  /* Don't attempt to expand sizes while parsing this decl.
+     (We can get here with i_s_e 1 somehow from Objective-C.)  */
+  int save_immediate_size_expand = immediate_size_expand;
   immediate_size_expand = 0;
 
   decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
@@ -3012,13 +3008,12 @@ push_parm_decl (tree parm)
 
   decl = pushdecl (decl);
 
-  immediate_size_expand = old_immediate_size_expand;
-
   current_scope->parm_order
     = tree_cons (NULL_TREE, decl, current_scope->parm_order);
 
-  /* Add this decl to the current scope.  */
   finish_decl (decl, NULL_TREE, NULL_TREE);
+
+  immediate_size_expand = save_immediate_size_expand;
 }
 
 /* Clear the given order of parms in `parm_order'.
@@ -4266,11 +4261,9 @@ grokdeclarator (tree declarator, tree declspecs,
          }
        /* Move type qualifiers down to element of an array.  */
        if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
-         {
-           type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
-                                                            type_quals),
-                                    TYPE_DOMAIN (type));
-         }
+         type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+                                                          type_quals),
+                                  TYPE_DOMAIN (type));
        decl = build_decl (FIELD_DECL, declarator, type);
        DECL_NONADDRESSABLE_P (decl) = bitfield;
 
@@ -4506,6 +4499,7 @@ grokparms (tree parms_info, int funcdef_flag)
         These tags can never be defined in the scope of the declaration,
         so the types can never be completed,
         and no call can be compiled successfully.  */
+
       for (parm = last_function_parms, typelt = first_parm;
           parm;
           parm = TREE_CHAIN (parm))
@@ -4537,7 +4531,7 @@ grokparms (tree parms_info, int funcdef_flag)
 }
 
 /* Return a tree_list node with info on a parameter list just parsed.
-   The TREE_PURPOSE is a chain of decls of those parms.
+   The TREE_PURPOSE is a list of decls of those parms.
    The TREE_VALUE is a list of structure, union and enum tags defined.
    The TREE_CHAIN is a list of argument types to go in the FUNCTION_TYPE.
    This tree_list node is later fed to `grokparms'.
@@ -5724,374 +5718,341 @@ start_function (tree declspecs, tree declarator, tree attributes)
   return 1;
 }
 \f
-/* Store the parameter declarations into the current function declaration.
-   This is called after parsing the parameter declarations, before
-   digesting the body of the function.
-
-   For an old-style definition, modify the function's type
-   to specify at least the number of arguments.  */
-
-void
-store_parm_decls (void)
+/* Subroutine of store_parm_decls which handles new-style function
+   definitions (prototype format). The parms already have decls, so we
+   need only record them as in effect and complain if any redundant
+   old-style parm decls were written.  */
+static void
+store_parm_decls_newstyle (void)
 {
+  tree decl, next;
   tree fndecl = current_function_decl;
-  tree parm;
+  tree parms = current_function_parms;
+  tree tags = current_function_parm_tags;
 
-  /* This is either a chain of PARM_DECLs (if a prototype was used)
-     or a list of IDENTIFIER_NODEs (for an old-fashioned C definition).  */
-  tree specparms = current_function_parms;
+  /* This is anything which appeared in current_function_parms that
+     wasn't a PARM_DECL.  */
+  tree nonparms = 0;
 
-  /* This is a list of types declared among parms in a prototype.  */
-  tree parmtags = current_function_parm_tags;
+  if (current_scope->names || current_scope->tags)
+    {
+      error ("%Hold-style parameter declarations in prototyped "
+            "function definition", &DECL_SOURCE_LOCATION (fndecl));
 
-  /* This is a chain of PARM_DECLs from old-style parm declarations.  */
-  tree parmdecls = getdecls ();
+      /* Get rid of the old-style declarations.  */
+      poplevel (0, 0, 0);
+      pushlevel (0);
+    }
 
-  /* This is a chain of any other decls that came in among the parm
-     declarations.  If a parm is declared with  enum {foo, bar} x;
-     then CONST_DECLs for foo and bar are put here.  */
-  tree nonparms = 0;
+  /* Now make all the parameter declarations visible in the function body.  */
+  parms = nreverse (parms);
+  for (decl = parms; decl; decl = next)
+    {
+      next = TREE_CHAIN (decl);
+      if (TREE_CODE (decl) != PARM_DECL)
+       {
+         /* If we find an enum constant or a type tag,
+            put it aside for the moment.  */
+         TREE_CHAIN (decl) = 0;
+         nonparms = chainon (nonparms, decl);
+         continue;
+       }
 
-  /* The function containing FNDECL, if any.  */
-  tree context = decl_function_context (fndecl);
+      if (DECL_NAME (decl) == 0)
+       error ("%Hparameter name omitted", &DECL_SOURCE_LOCATION (decl));
+      else
+       pushdecl (decl);
+    }
 
-  /* Nonzero if this definition is written with a prototype.  */
-  int prototype = 0;
+  /* Record the parameter list in the function declaration.  */
+  DECL_ARGUMENTS (fndecl) = getdecls ();
 
-  bool saved_warn_shadow = warn_shadow;
+  /* Now make all the ancillary declarations visible, likewise.  */
+  for (decl = nonparms; decl; decl = TREE_CHAIN (decl))
+    if (DECL_NAME (decl) != 0
+       && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) != void_type_node)
+      pushdecl (decl);
 
-  /* Don't re-emit shadow warnings.  */
-  warn_shadow = false;
+  /* And all the tag declarations.  */
+  storetags (tags);
+}
 
-  if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
-    {
-      /* This case is when the function was defined with an ANSI prototype.
-        The parms already have decls, so we need not do anything here
-        except record them as in effect
-        and complain if any redundant old-style parm decls were written.  */
+/* Subroutine of store_parm_decls which handles old-style function
+   definitions (separate parameter list and declarations).  */
 
-      tree next;
-      tree others = 0;
+static void
+store_parm_decls_oldstyle (void)
+{
+  tree parm, decl, next;
+  tree fndecl = current_function_decl;
 
-      prototype = 1;
+  /* This is the identifier list from the function declarator.  */
+  tree parmids = current_function_parms;
 
-      if (parmdecls != 0)
+  /* This is anything which appeared in current_scope->names that
+     wasn't a PARM_DECL.  */
+  tree nonparms;
+  
+  /* We use DECL_WEAK as a flag to show which parameters have been
+     seen already, since it is not used on PARM_DECL or CONST_DECL.  */
+  for (parm = current_scope->names; parm; parm = TREE_CHAIN (parm))
+    DECL_WEAK (parm) = 0;
+
+  /* Match each formal parameter name with its declaration.  Save each
+     decl in the appropriate TREE_PURPOSE slot of the parmids chain.  */
+  for (parm = parmids; parm; parm = TREE_CHAIN (parm))
+    {
+      if (TREE_VALUE (parm) == 0)
        {
-         tree decl, link;
-
-         error ("%Hparm types given both in parmlist and separately",
-                 &DECL_SOURCE_LOCATION (fndecl));
-         /* Get rid of the erroneous decls; don't keep them on
-            the list of parms, since they might not be PARM_DECLs.  */
-         for (decl = current_scope->names;
-              decl; decl = TREE_CHAIN (decl))
-           if (DECL_NAME (decl))
-             IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = 0;
-         for (link = current_scope->shadowed;
-              link; link = TREE_CHAIN (link))
-           IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
-         current_scope->names = 0;
-         current_scope->shadowed = 0;
+         error ("%Hparameter name missing from parameter list",
+                &DECL_SOURCE_LOCATION (fndecl));
+         TREE_PURPOSE (parm) = 0;
+         continue;
        }
 
-      specparms = nreverse (specparms);
-      for (parm = specparms; parm; parm = next)
+      decl = IDENTIFIER_SYMBOL_VALUE (TREE_VALUE (parm));
+      if (decl && DECL_CONTEXT (decl) == fndecl)
        {
-          const location_t *locus = &DECL_SOURCE_LOCATION (parm);
-         next = TREE_CHAIN (parm);
-         if (TREE_CODE (parm) == PARM_DECL)
+         const location_t *locus = &DECL_SOURCE_LOCATION (decl);
+         /* If we got something other than a PARM_DECL it is an error.  */
+         if (TREE_CODE (decl) != PARM_DECL)
+           error ("%H\"%D\" declared as a non-parameter", locus, decl);
+         /* If the declaration is already marked, we have a duplicate
+            name.  Complain and ignore the duplicate.  */
+         else if (DECL_WEAK (decl))
            {
-             if (DECL_NAME (parm) == 0)
-                error ("%Hparameter name omitted", locus);
-             else if (TREE_CODE (TREE_TYPE (parm)) != ERROR_MARK
-                      && VOID_TYPE_P (TREE_TYPE (parm)))
-               {
-                 error ("%Hparameter '%D' declared void", locus, parm);
-                 /* Change the type to error_mark_node so this parameter
-                    will be ignored by assign_parms.  */
-                 TREE_TYPE (parm) = error_mark_node;
-               }
-             pushdecl (parm);
+             error ("%Hmultiple parameters named \"%D\"", locus, decl);
+             TREE_PURPOSE (parm) = 0;
+             continue;
            }
-         else
+         /* If the declaration says "void", complain and turn it into
+            an int.  */
+         else if (VOID_TYPE_P (TREE_TYPE (decl)))
            {
-             /* If we find an enum constant or a type tag,
-                put it aside for the moment.  */
-             TREE_CHAIN (parm) = 0;
-             others = chainon (others, parm);
+             error ("%Hparameter \"%D\" declared void", locus, decl);
+             TREE_TYPE (decl) = integer_type_node;
+             DECL_ARG_TYPE (decl) = integer_type_node;
+             layout_decl (decl, 0);
            }
        }
-
-      /* Get the decls in their original chain order
-        and record in the function.  */
-      DECL_ARGUMENTS (fndecl) = getdecls ();
-
-      /* Now pushdecl the enum constants.  */
-      for (parm = others; parm; parm = next)
+      /* If no declaration found, default to int.  */
+      else
        {
-         next = TREE_CHAIN (parm);
-         if (DECL_NAME (parm) == 0)
-           ;
-         else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
-           ;
-         else if (TREE_CODE (parm) != PARM_DECL)
-           pushdecl (parm);
+         const location_t *locus = &DECL_SOURCE_LOCATION (fndecl);
+         decl = build_decl (PARM_DECL, TREE_VALUE (parm), integer_type_node);
+         DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
+         DECL_SOURCE_LOCATION (decl) = *locus;
+         pushdecl (decl);
+
+         if (flag_isoc99)
+           pedwarn ("%Htype of \"%D\" defaults to \"int\"", locus, decl);
+         else if (extra_warnings)
+           warning ("%Htype of \"%D\" defaults to \"int\"", locus, decl);
        }
 
-      storetags (chainon (parmtags, gettags ()));
+      TREE_PURPOSE (parm) = decl;
+      DECL_WEAK (decl) = 1;
     }
-  else
-    {
-      /* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
-        each with a parm name as the TREE_VALUE.
-
-        PARMDECLS is a chain of declarations for parameters.
-        Warning! It can also contain CONST_DECLs which are not parameters
-        but are names of enumerators of any enum types
-        declared among the parameters.
 
-        First match each formal parameter name with its declaration.
-        Associate decls with the names and store the decls
-        into the TREE_PURPOSE slots.  */
+  /* Put anything which is in current_scope->names and which is
+     not a PARM_DECL onto the list NONPARMS.  (The types of
+     non-parm things which might appear on the list include
+     enumerators and NULL-named TYPE_DECL nodes.) Complain about
+     any actual PARM_DECLs not matched with any names.  */
 
-      /* We use DECL_WEAK as a flag to show which parameters have been
-        seen already since it is not used on PARM_DECL or CONST_DECL.  */
-      for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
-       DECL_WEAK (parm) = 0;
+  nonparms = 0;
+  for (parm = current_scope->names; parm; parm = next)
+    {
+      const location_t *locus = &DECL_SOURCE_LOCATION (parm);
+      next = TREE_CHAIN (parm);
+      TREE_CHAIN (parm) = 0;
 
-      for (parm = specparms; parm; parm = TREE_CHAIN (parm))
+      if (TREE_CODE (parm) != PARM_DECL)
        {
-         tree tail, found = NULL;
-
-         if (TREE_VALUE (parm) == 0)
-           {
-             error ("%Hparameter name missing from parameter list",
-                     &DECL_SOURCE_LOCATION (fndecl));
-             TREE_PURPOSE (parm) = 0;
-             continue;
-           }
-
-         /* See if any of the parmdecls specifies this parm by name.
-            Ignore any enumerator decls.  */
-         for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
-           if (DECL_NAME (tail) == TREE_VALUE (parm)
-               && TREE_CODE (tail) == PARM_DECL)
-             {
-               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 ("%Hmultiple parameters named '%D'",
-                     &DECL_SOURCE_LOCATION (found), found);
-             found = 0;
-           }
-
-         /* If the declaration says "void", complain and ignore it.  */
-         if (found && VOID_TYPE_P (TREE_TYPE (found)))
-           {
-             error ("%Hparameter '%D' declared void",
-                     &DECL_SOURCE_LOCATION (found), found);
-             TREE_TYPE (found) = integer_type_node;
-             DECL_ARG_TYPE (found) = integer_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_LOCATION (found) = DECL_SOURCE_LOCATION (fndecl);
-             if (flag_isoc99)
-               pedwarn ("%Htype of '%D' defaults to `int'",
-                         &DECL_SOURCE_LOCATION (found), found);
-             else if (extra_warnings)
-               warning ("%Htype of '%D' defaults to `int'",
-                         &DECL_SOURCE_LOCATION (found), found);
-             pushdecl (found);
-           }
-
-         TREE_PURPOSE (parm) = found;
-
-         /* Mark this decl as "already found".  */
-         DECL_WEAK (found) = 1;
+         nonparms = chainon (nonparms, parm);
+         continue;
        }
 
-      /* Put anything which is on the parmdecls chain and which is
-        not a PARM_DECL onto the list NONPARMS.  (The types of
-        non-parm things which might appear on the list include
-        enumerators and NULL-named TYPE_DECL nodes.) Complain about
-        any actual PARM_DECLs not matched with any names.  */
-
-      nonparms = 0;
-      for (parm = parmdecls; parm;)
+      if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
        {
-          const location_t *locus = &DECL_SOURCE_LOCATION (parm);
-         tree next = TREE_CHAIN (parm);
-         TREE_CHAIN (parm) = 0;
-
-         if (TREE_CODE (parm) != PARM_DECL)
-           nonparms = chainon (nonparms, parm);
-         else
-           {
-             /* Complain about args with incomplete types.  */
-             if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
-               {
-                 error ("%Hparameter '%D' has incomplete type", locus, parm);
-                 TREE_TYPE (parm) = error_mark_node;
-               }
+         error ("%Hparameter \"%D\" has incomplete type", locus, parm);
+         TREE_TYPE (parm) = error_mark_node;
+       }
 
-             if (! DECL_WEAK (parm))
-               {
-                 error ("%Hdeclaration for parameter '%D' but no such "
-                         "parameter", locus, parm);
-                 /* 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));
-               }
-           }
+      if (! DECL_WEAK (parm))
+       {
+         error ("%Hdeclaration for parameter \"%D\" but no such parameter",
+                locus, parm);
 
-         parm = next;
+         /* Pretend the parameter was not missing.
+            This gets us to a standard state and minimizes
+            further error messages.  */
+         parmids = chainon (parmids, tree_cons (parm, 0, 0));
        }
+    }
 
-      /* Chain the declarations together in the order of the list of
-         names.  Store that chain in the function decl, replacing the
-         list of names.  */
-      parm = specparms;
-      DECL_ARGUMENTS (fndecl) = 0;
+  /* Chain the declarations together in the order of the list of
+     names.  Store that chain in the function decl, replacing the
+     list of names.  */
+  DECL_ARGUMENTS (fndecl) = 0;
+  {
+    tree last;
+    for (parm = parmids; parm; parm = TREE_CHAIN (parm))
+      if (TREE_PURPOSE (parm))
+       break;
+    if (parm && TREE_PURPOSE (parm))
       {
-       tree last;
-       for (last = 0; parm; parm = TREE_CHAIN (parm))
+       last = TREE_PURPOSE (parm);
+       DECL_ARGUMENTS (fndecl) = last;
+       DECL_WEAK (last) = 0;
+
+       for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
          if (TREE_PURPOSE (parm))
            {
-             if (last == 0)
-               DECL_ARGUMENTS (fndecl) = TREE_PURPOSE (parm);
-             else
-               TREE_CHAIN (last) = TREE_PURPOSE (parm);
+             TREE_CHAIN (last) = TREE_PURPOSE (parm);
              last = TREE_PURPOSE (parm);
-             TREE_CHAIN (last) = 0;
+             DECL_WEAK (last) = 0;
            }
+       TREE_CHAIN (last) = 0;
       }
+  }
 
-      /* If there was a previous prototype,
-        set the DECL_ARG_TYPE of each argument according to
-        the type previously specified, and report any mismatches.  */
+  /* If there was a previous prototype,
+     set the DECL_ARG_TYPE of each argument according to
+     the type previously specified, and report any mismatches.  */
 
-      if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+  if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+    {
+      tree type;
+      for (parm = DECL_ARGUMENTS (fndecl),
+            type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+          parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
+                            != void_type_node));
+          parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
        {
-         tree type;
-         for (parm = DECL_ARGUMENTS (fndecl),
-              type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
-              parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
-                                != void_type_node));
-              parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
+         if (parm == 0 || type == 0
+             || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
            {
-             if (parm == 0 || type == 0
-                 || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
-               {
-                 error ("number of arguments doesn't match prototype");
-                 error ("%Hprototype declaration",
-                         &current_function_prototype_locus);
-                 break;
-               }
-             /* 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)),
-                              COMPARE_STRICT))
+             error ("number of arguments doesn't match prototype");
+             error ("%Hprototype declaration",
+                    &current_function_prototype_locus);
+             break;
+           }
+         /* 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)),
+                          COMPARE_STRICT))
+           {
+             if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
+                 == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
                {
-                 if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
-                     == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
+                 /* Adjust argument to match prototype.  E.g. a previous
+                    `int foo(float);' prototype causes
+                    `int foo(x) float x; {...}' to be treated like
+                    `int foo(float x) {...}'.  This is particularly
+                    useful for argument types like uid_t.  */
+                 DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
+
+                 if (PROMOTE_PROTOTYPES
+                     && INTEGRAL_TYPE_P (TREE_TYPE (parm))
+                     && TYPE_PRECISION (TREE_TYPE (parm))
+                     < TYPE_PRECISION (integer_type_node))
+                   DECL_ARG_TYPE (parm) = integer_type_node;
+
+                 if (pedantic)
                    {
-                     /* Adjust argument to match prototype.  E.g. a previous
-                        `int foo(float);' prototype causes
-                        `int foo(x) float x; {...}' to be treated like
-                        `int foo(float x) {...}'.  This is particularly
-                        useful for argument types like uid_t.  */
-                     DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
-
-                     if (PROMOTE_PROTOTYPES
-                         && INTEGRAL_TYPE_P (TREE_TYPE (parm))
-                         && TYPE_PRECISION (TREE_TYPE (parm))
-                         < TYPE_PRECISION (integer_type_node))
-                       DECL_ARG_TYPE (parm) = integer_type_node;
-
-                     if (pedantic)
-                       {
-                         pedwarn ("promoted argument `%s' doesn't match prototype",
-                                  IDENTIFIER_POINTER (DECL_NAME (parm)));
-                         warning ("%Hprototype declaration",
-                                   &current_function_prototype_locus);
-                       }
-                   }
-                 else
-                   {
-                     error ("argument `%s' doesn't match prototype",
-                            IDENTIFIER_POINTER (DECL_NAME (parm)));
-                     error ("%Hprototype declaration",
-                             &current_function_prototype_locus);
+                     pedwarn ("promoted argument \"%D\" "
+                              "doesn't match prototype", parm);
+                     pedwarn ("%Hprototype declaration",
+                              &current_function_prototype_locus);
                    }
                }
+             else
+               {
+                 error ("argument \"%D\" doesn't match prototype", parm);
+                 error ("%Hprototype declaration",
+                        &current_function_prototype_locus);
+               }
            }
-         TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0;
        }
+      TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0;
+    }
 
-      /* Otherwise, create a prototype that would match.  */
+  /* Otherwise, create a prototype that would match.  */
 
-      else
-       {
-         tree actual = 0, last = 0, type;
+  else
+    {
+      tree actual = 0, last = 0, type;
 
-         for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
-           {
-             type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
-             if (last)
-               TREE_CHAIN (last) = type;
-             else
-               actual = type;
-             last = type;
-           }
-         type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+      for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
+       {
+         type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
          if (last)
            TREE_CHAIN (last) = type;
          else
            actual = type;
+         last = type;
+       }
+      type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+      if (last)
+       TREE_CHAIN (last) = type;
+      else
+       actual = type;
 
-         /* We are going to assign a new value for the TYPE_ACTUAL_ARG_TYPES
-            of the type of this function, but we need to avoid having this
-            affect the types of other similarly-typed functions, so we must
-            first force the generation of an identical (but separate) type
-            node for the relevant function type.  The new node we create
-            will be a variant of the main variant of the original function
-            type.  */
+      /* We are going to assign a new value for the TYPE_ACTUAL_ARG_TYPES
+        of the type of this function, but we need to avoid having this
+        affect the types of other similarly-typed functions, so we must
+        first force the generation of an identical (but separate) type
+        node for the relevant function type.  The new node we create
+        will be a variant of the main variant of the original function
+        type.  */
 
-         TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl));
+      TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl));
 
-         TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
-       }
+      TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
+    }
 
-      /* Now store the final chain of decls for the arguments
-        as the decl-chain of the current lexical scope.
-        Put the enumerators in as well, at the front so that
-        DECL_ARGUMENTS is not modified.  */
+  /* Now store the final chain of decls for the arguments
+     as the decl-chain of the current lexical scope.
+     Put the enumerators in as well, at the front so that
+     DECL_ARGUMENTS is not modified.  */
 
-      storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
-    }
+  storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
+}
 
-  /* Make sure the scope for the top of the function body
-     gets a BLOCK if there are any in the function.
-     Otherwise, the dbx output is wrong.  */
+/* Store the parameter declarations into the current function declaration.
+   This is called after parsing the parameter declarations, before
+   digesting the body of the function.
 
-  keep_next_if_subblocks = 1;
+   For an old-style definition, construct a prototype out of the old-style
+   parameter declarations and inject it into the function's type.  */
+
+void
+store_parm_decls (void)
+{
+  tree fndecl = current_function_decl;
+
+  /* The function containing FNDECL, if any.  */
+  tree context = decl_function_context (fndecl);
+
+  /* True if this definition is written with a prototype.  */
+  bool prototype = (current_function_parms
+                   && TREE_CODE (current_function_parms) != TREE_LIST);
+
+  /* Don't re-emit shadow warnings.  */
+  bool saved_warn_shadow = warn_shadow;
+  warn_shadow = false;
+
+  if (prototype)
+    store_parm_decls_newstyle ();
+  else
+    store_parm_decls_oldstyle ();
+
+  /* The next call to pushlevel will be a function body.  */
+
+  next_is_function_body = true;
 
   /* Write a record describing this function definition to the prototypes
      file (if requested).  */
@@ -6102,7 +6063,7 @@ store_parm_decls (void)
   init_function_start (fndecl);
 
   /* Begin the statement tree for this function.  */
-  begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
+  begin_stmt_tree (&DECL_SAVED_TREE (fndecl));
 
   /* If this is a nested function, save away the sizes of any
      variable-size types so that we can expand them when generating
@@ -6150,15 +6111,16 @@ finish_function (int nested, int can_defer_p)
         void foo(void) { }
      (the argument list is irrelevant) the compstmt rule will not
      bother calling pushlevel/poplevel, which means we get here with
-     the scope stack out of sync.  Detect this situation by
-     noticing that current_scope is still as
-     store_parm_decls left it, and do a dummy push/pop to get back to
-     consistency.  Note that the call to pushlevel does not actually
-     push another scope - see there for details.  */
-  if (current_scope->parm_flag && keep_next_if_subblocks)
+     the scope stack out of sync.  Detect this situation by noticing
+     that current_scope is still as store_parm_decls left it, and do
+     a dummy push/pop to get back to consistency.
+     Note that the call to pushlevel does not actually push another
+     scope - see there for details.  */
+
+  if (current_scope->parm_flag && next_is_function_body)
     {
       pushlevel (0);
-      poplevel (1, 0, 1);
+      poplevel (0, 0, 0);
     }
 
   BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
@@ -6376,7 +6338,7 @@ c_expand_body_1 (tree fndecl, int nested_p)
      to run global initializers, etc.  */
   if (DECL_NAME (fndecl)
       && MAIN_NAME_P (DECL_NAME (fndecl))
-      && DECL_CONTEXT (fndecl) == NULL_TREE)
+      && C_DECL_FILE_SCOPE (fndecl))
     expand_main_function ();
 
   /* Generate the RTL for this function.  */
@@ -6560,7 +6522,6 @@ struct language_function GTY(())
   int returns_abnormally;
   int warn_about_return_type;
   int extern_inline;
-  struct c_scope *scope;
 };
 
 /* Save and reinitialize the variables
@@ -6580,7 +6541,6 @@ c_push_function_context (struct function *f)
   p->returns_abnormally = current_function_returns_abnormally;
   p->warn_about_return_type = warn_about_return_type;
   p->extern_inline = current_extern_inline;
-  p->scope = current_scope;
 }
 
 /* Restore the variables used during compilation of a C function.  */
@@ -6607,7 +6567,6 @@ c_pop_function_context (struct function *f)
   current_function_returns_abnormally = p->returns_abnormally;
   warn_about_return_type = p->warn_about_return_type;
   current_extern_inline = p->extern_inline;
-  current_scope = p->scope;
 
   f->language = NULL;
 }