c-decl.c (last_function_parm_vars, [...]): New static variables.
authorZack Weinberg <zack@gcc.gnu.org>
Tue, 29 Jul 2003 23:58:08 +0000 (23:58 +0000)
committerZack Weinberg <zack@gcc.gnu.org>
Tue, 29 Jul 2003 23:58:08 +0000 (23:58 +0000)
* c-decl.c (last_function_parm_vars, current_function_parm_vars):
New static variables.
(struct c_scope): Add parms and warned_forward_parm_decls
fields; remove parm_order.
(storedecls, storetags): Delete.
(poplevel): Also clear bindings on the parms chain.
(pushdecl): Handle forward declarations of parameters, and
chain PARM_DECLs on the parms list, not the names list.
(lookup_name_current_level): Check for PARM_DECLs on the parms
list too.
(push_parm_decl): Don't update parm_order.
(clear_parm_order): Rename mark_forward_parm_decls.  Issue the
warning, only once per parameter list, and set TREE_ASM_WRITTEN
on the decls here.  Then move the forward decls to the names list.
(grokparms): Set last_function_parm_vars.
(get_parm_info): Don't use gettags or getdecls.  No need to
extract non-parms from the parms list, or reorganize the parms
list.  Feed nonparms back in the TREE_TYPE of the list node
returned.  Issue only one error per parameter list for "void"
appearing more than once in said parameter list.  Collapse
parmlist_tags_warning into this function to avoid double scan
of tags list.
(start_function): Set current_function_parm_vars.
(store_parm_decls_newstyle): Bypass pushdecl, manipulate scope
directly.  Get non-parms from current_function_parm_vars; no
need to extract them from the parms chain.  Properly bind tags
in the new scope.
(store_parm_decls_oldstyle): No need to extract non-parameters
from the parms chain, nor to store them back afterward.  Move
declaration to top of function, restructure code reordering
DECL_ARGUMENTS.
(store_parm_decls): No need to save and restore warn_shadow.
* c-parse.in: Don't call parmlist_tags_warning nor
clear_parm_order.  Call mark_forward_parm_decls when forward
parm decls are encountered.
* c-tree.h: Prototype mark_forward_parm_decls; not
clear_parm_order or parmlist_tags_warning.

testsuite:
* gcc.dg/struct-in-proto-1.c: New test.

From-SVN: r69945

gcc/ChangeLog
gcc/c-decl.c
gcc/c-parse.in
gcc/c-tree.h
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/struct-in-proto-1.c [new file with mode: 0644]

index b4327db660b41665b3371ea7f960d22be3d15cf7..419fba7e80d0c5ecfb0cafef97cd6c07d214da65 100644 (file)
@@ -1,3 +1,43 @@
+2003-07-29  Zack Weinberg  <zack@codesourcery.com>
+
+       * c-decl.c (last_function_parm_vars, current_function_parm_vars):
+       New static variables.
+       (struct c_scope): Add parms and warned_forward_parm_decls
+       fields; remove parm_order.
+       (storedecls, storetags): Delete.
+       (poplevel): Also clear bindings on the parms chain.
+       (pushdecl): Handle forward declarations of parameters, and
+       chain PARM_DECLs on the parms list, not the names list.
+       (lookup_name_current_level): Check for PARM_DECLs on the parms
+       list too.
+       (push_parm_decl): Don't update parm_order.
+       (clear_parm_order): Rename mark_forward_parm_decls.  Issue the
+       warning, only once per parameter list, and set TREE_ASM_WRITTEN
+       on the decls here.  Then move the forward decls to the names list.
+       (grokparms): Set last_function_parm_vars.
+       (get_parm_info): Don't use gettags or getdecls.  No need to
+       extract non-parms from the parms list, or reorganize the parms
+       list.  Feed nonparms back in the TREE_TYPE of the list node
+       returned.  Issue only one error per parameter list for "void"
+       appearing more than once in said parameter list.  Collapse
+       parmlist_tags_warning into this function to avoid double scan
+       of tags list.
+       (start_function): Set current_function_parm_vars.
+       (store_parm_decls_newstyle): Bypass pushdecl, manipulate scope
+       directly.  Get non-parms from current_function_parm_vars; no
+       need to extract them from the parms chain.  Properly bind tags
+       in the new scope.
+       (store_parm_decls_oldstyle): No need to extract non-parameters
+       from the parms chain, nor to store them back afterward.  Move
+       declaration to top of function, restructure code reordering
+       DECL_ARGUMENTS.
+       (store_parm_decls): No need to save and restore warn_shadow.
+       * c-parse.in: Don't call parmlist_tags_warning nor
+       clear_parm_order.  Call mark_forward_parm_decls when forward
+       parm decls are encountered.
+       * c-tree.h: Prototype mark_forward_parm_decls; not
+       clear_parm_order or parmlist_tags_warning.
+
 2003-07-29  Geoffrey Keating  <geoffk@apple.com>
 
        * c-common.c (allow_pch): Remove.
index 6a87c427295db56324bb9a9772c5d32816e9ce72..8259fb9ff559131aa5c073ca4a55edba04491131 100644 (file)
@@ -93,6 +93,11 @@ static tree last_function_parms;
 
 static tree last_function_parm_tags;
 
+/* ... and a chain of all non-parameter declarations (such as
+   CONST_DECLs from enumerations) here.  */
+
+static tree last_function_parm_vars;
+
 /* After parsing the declarator that starts a function definition,
    `start_function' puts the list of parameter names or chain of decls here
    for `store_parm_decls' to find.  */
@@ -103,6 +108,10 @@ static tree current_function_parms;
 
 static tree current_function_parm_tags;
 
+/* And for last_function_parm_vars.  */
+
+static tree current_function_parm_vars;
+
 /* Similar, for the file and line that the prototype came from if this is
    an old-style definition.  */
 
@@ -177,6 +186,10 @@ struct c_scope GTY(())
      They are in the reverse of the order supplied.  */
   tree names;
 
+  /* All parameter declarations.  Used only in the outermost scope of
+     a function.  Again, in the reverse of the order supplied.  */
+  tree parms;
+
   /* All structure, union, and enum type tags.  */
   tree tags;
 
@@ -199,15 +212,15 @@ struct c_scope GTY(())
   /* 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 we already complained about forward parameter decls
+     in this scope.  This prevents double warnings on
+     foo (int a; int b; ...)  */
+  bool warned_forward_parm_decls : 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
@@ -261,8 +274,6 @@ static int redeclaration_error_message (tree, tree);
 static tree make_label (tree, location_t);
 static void bind_label (tree, tree, struct c_scope *);
 static void implicit_decl_warning (tree);
-static void storedecls (tree);
-static void storetags (tree);
 static tree lookup_tag (enum tree_code, tree, int);
 static tree lookup_name_current_level (tree);
 static tree grokdeclarator (tree, tree, enum decl_context, int);
@@ -525,6 +536,12 @@ poplevel (int keep, int reverse, int functionbody)
        TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (link)) = 1;
     }
 
+  /* Clear out the parameter bindings declared in this scope.
+     Unused-parameter warnings are handled by function.c.  */
+  for (link = current_scope->parms; link; link = TREE_CHAIN (link))
+    if (DECL_NAME (link))
+      IDENTIFIER_SYMBOL_VALUE (DECL_NAME (link)) = 0;
+
   /* Clear out the tag-meanings declared in this scope.  */
   for (link = tags; link; link = TREE_CHAIN (link))
     if (TREE_PURPOSE (link))
@@ -1657,7 +1674,24 @@ pushdecl (tree x)
 
       old = lookup_name_current_level (name);
       if (old && duplicate_decls (x, old, 0, false))
-       return old;
+       {
+         /* For PARM_DECLs, old may be a forward declaration.
+            If so, we want to remove it from its old location
+            (in the variables chain) and rechain it in the
+            location given by the new declaration.  */
+         if (TREE_CODE (x) == PARM_DECL)
+           {
+             tree *p;
+             for (p = &scope->names; *p; p = &TREE_CHAIN (*p))
+               if (*p == old)
+                 {
+                   *p = TREE_CHAIN (old);
+                   TREE_CHAIN (old) = scope->parms;
+                   scope->parms = old;
+                 }
+           }
+         return old;
+       }
       if (DECL_EXTERNAL (x) || scope == global_scope)
        {
          /* Find and check against a previous, not-in-scope, external
@@ -1720,8 +1754,16 @@ pushdecl (tree x)
 
   /* Put decls on list in reverse order.
      We will reverse them later if necessary.  */
-  TREE_CHAIN (x) = scope->names;
-  scope->names = x;
+  if (TREE_CODE (x) == PARM_DECL)
+    {
+      TREE_CHAIN (x) = scope->parms;
+      scope->parms = x;
+    }
+  else
+    {
+      TREE_CHAIN (x) = scope->names;
+      scope->names = x;
+    }
 
   return x;
 }
@@ -2125,24 +2167,6 @@ gettags (void)
 {
   return current_scope->tags;
 }
-
-/* Store the list of declarations of the current scope.
-   This is done for the parameter declarations of a function being defined,
-   after they are modified in the light of any missing parameters.  */
-
-static void
-storedecls (tree decls)
-{
-  current_scope->names = decls;
-}
-
-/* Similarly, store the list of tags of the current scope.  */
-
-static void
-storetags (tree tags)
-{
-  current_scope->tags = tags;
-}
 \f
 /* Given NAME, an IDENTIFIER_NODE,
    return the structure (or union or enum) definition for that name.
@@ -2233,7 +2257,12 @@ lookup_name_current_level (tree name)
   if (current_scope == global_scope)
     return decl;
 
-  /* Scan the current scope for a decl with name NAME.  */
+  /* Scan the current scope for a decl with name NAME.
+     For PARM_DECLs, we have to look at both ->parms and ->names, since
+     forward parameter declarations wind up on the ->names list.  */
+  if (TREE_CODE (decl) == PARM_DECL
+      && chain_member (decl, current_scope->parms))
+    return decl;
   if (chain_member (decl, current_scope->names))
     return decl;
 
@@ -2987,10 +3016,8 @@ finish_decl (tree decl, tree init, tree asmspec_tree)
     }
 }
 
-/* Given a parsed parameter declaration,
-   decode it into a PARM_DECL and push that on the current scope.
-   Also, for the sake of forward parm decls,
-   record the given order of parms in `parm_order'.  */
+/* Given a parsed parameter declaration, decode it into a PARM_DECL
+   and push that on the current scope.  */
 
 void
 push_parm_decl (tree parm)
@@ -3008,22 +3035,34 @@ push_parm_decl (tree parm)
 
   decl = pushdecl (decl);
 
-  current_scope->parm_order
-    = tree_cons (NULL_TREE, decl, current_scope->parm_order);
-
   finish_decl (decl, NULL_TREE, NULL_TREE);
 
   immediate_size_expand = save_immediate_size_expand;
 }
 
-/* Clear the given order of parms in `parm_order'.
-   Used at start of parm list,
-   and also at semicolon terminating forward decls.  */
+/* Shift all the existing parameter decls to the variables list,
+   and reset the parameters list.  Used when a ; terminating
+   forward parameter decls is encountered.  */
 
 void
-clear_parm_order (void)
+mark_forward_parm_decls (void)
 {
-  current_scope->parm_order = NULL_TREE;
+  tree parm, last;
+
+  if (pedantic && !current_scope->warned_forward_parm_decls)
+    {
+      pedwarn ("ISO C forbids forward parameter declarations");
+      current_scope->warned_forward_parm_decls = true;
+    }
+
+  for (last = 0, parm = current_scope->parms;
+       parm;
+       last = parm, parm = TREE_CHAIN (parm))
+    TREE_ASM_WRITTEN (parm) = 1;
+
+  TREE_CHAIN (last)    = current_scope->names;
+  current_scope->names = current_scope->parms;
+  current_scope->parms = 0;
 }
 \f
 static GTY(()) int compound_literal_number;
@@ -4476,6 +4515,7 @@ grokparms (tree parms_info, int funcdef_flag)
 
   last_function_parms = TREE_PURPOSE (parms_info);
   last_function_parm_tags = TREE_VALUE (parms_info);
+  last_function_parm_vars = TREE_TYPE (parms_info);
 
   if (warn_strict_prototypes && first_parm == 0 && !funcdef_flag
       && !in_system_header)
@@ -4534,6 +4574,8 @@ grokparms (tree parms_info, int funcdef_flag)
    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.
+   The TREE_TYPE is a list of non-parameter decls which appeared with the
+   parameters.
    This tree_list node is later fed to `grokparms'.
 
    VOID_AT_END nonzero means append `void' to the end of the type-list.
@@ -4542,144 +4584,124 @@ grokparms (tree parms_info, int funcdef_flag)
 tree
 get_parm_info (int void_at_end)
 {
-  tree decl, t;
+  tree decl, type, list;
   tree types = 0;
-  int erred = 0;
-  tree tags = gettags ();
-  tree parms = getdecls ();
-  tree new_parms = 0;
-  tree order = current_scope->parm_order;
-
-  /* Just `void' (and no ellipsis) is special.  There are really no parms.
-     But if the `void' is qualified (by `const' or `volatile') or has a
-     storage class specifier (`register'), then the behavior is undefined;
-     by not counting it as the special case of `void' we will cause an
-     error later.  Typedefs for `void' are OK (see DR#157).  */
+  tree *last_type = &types;
+  tree tags = current_scope->tags;
+  tree parms = current_scope->parms;
+  tree others = current_scope->names;
+  static bool explained_incomplete_types = false;
+  bool gave_void_only_once_err = false;
+
+  /* Just "void" (and no ellipsis) is special.  There are really no parms.
+     But if the "void" is qualified (by "const" or "volatile"), or has a
+     storage class specifier ("register"), then the behavior is undefined;
+     issue an error.  Typedefs for "void" are OK (see DR#157).  */
   if (void_at_end && parms != 0
       && TREE_CHAIN (parms) == 0
       && VOID_TYPE_P (TREE_TYPE (parms))
-      && ! TREE_THIS_VOLATILE (parms)
-      && ! TREE_READONLY (parms)
-      && ! DECL_REGISTER (parms)
-      && DECL_NAME (parms) == 0)
+      && !DECL_NAME (parms))
     {
-      parms = NULL_TREE;
-      storedecls (NULL_TREE);
-      return tree_cons (NULL_TREE, NULL_TREE,
-                       tree_cons (NULL_TREE, void_type_node, NULL_TREE));
+      if (TREE_THIS_VOLATILE (parms)
+         || TREE_READONLY (parms)
+         || DECL_REGISTER (parms))
+       error ("\"void\" as only parameter may not be qualified");
+
+      return tree_cons (0, 0, tree_cons (0, void_type_node, 0));
     }
 
-  /* Extract enumerator values and other non-parms declared with the parms.
-     Likewise any forward parm decls that didn't have real parm decls.  */
-  for (decl = parms; decl;)
-    {
-      tree next = TREE_CHAIN (decl);
+  if (parms)
+    current_scope->parms = parms = nreverse (parms);
 
+  /* Sanity check all of the parameter declarations.  */
+  for (decl = parms; decl; decl = TREE_CHAIN (decl))
+    {
       if (TREE_CODE (decl) != PARM_DECL)
+       abort ();
+      if (TREE_ASM_WRITTEN (decl))
+       abort ();
+
+      /* Since there is a prototype, args are passed in their
+        declared types.  The back end may override this.  */
+      type = TREE_TYPE (decl);
+      DECL_ARG_TYPE (decl) = type;
+      if (PROMOTE_PROTOTYPES
+         && INTEGRAL_TYPE_P (type)
+         && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
+       DECL_ARG_TYPE (decl) = integer_type_node;
+
+      /* Check for (..., void, ...) and issue an error.  */
+      if (VOID_TYPE_P (type) && !DECL_NAME (decl) && !gave_void_only_once_err)
        {
-         TREE_CHAIN (decl) = new_parms;
-         new_parms = decl;
-       }
-      else if (TREE_ASM_WRITTEN (decl))
-       {
-         error ("%Hparameter '%D' has just a forward declaration",
-                 &DECL_SOURCE_LOCATION (decl), decl);
-         TREE_CHAIN (decl) = new_parms;
-         new_parms = decl;
+         error ("\"void\" must be the only parameter");
+         gave_void_only_once_err = true;
        }
-      decl = next;
-    }
 
-  /* Put the parm decls back in the order they were in in the parm list.  */
-  for (t = order; t; t = TREE_CHAIN (t))
-    {
-      if (TREE_CHAIN (t))
-       TREE_CHAIN (TREE_VALUE (t)) = TREE_VALUE (TREE_CHAIN (t));
-      else
-       TREE_CHAIN (TREE_VALUE (t)) = 0;
+      type = build_tree_list (0, type);
+      *last_type = type;
+      last_type = &TREE_CHAIN (type);
     }
 
-  new_parms = chainon (order ? nreverse (TREE_VALUE (order)) : 0,
-                      new_parms);
-
-  /* Store the parmlist in the scope structure since the old one
-     is no longer a valid list.  (We have changed the chain pointers.)  */
-  storedecls (new_parms);
-
-  for (decl = new_parms; decl; decl = TREE_CHAIN (decl))
-    /* There may also be declarations for enumerators if an enumeration
-       type is declared among the parms.  Ignore them here.  */
+  /* Check the list of non-parameter decls for any forward parm decls
+     that never got real decls.  */
+  for (decl = others; decl; decl = TREE_CHAIN (decl))
     if (TREE_CODE (decl) == PARM_DECL)
       {
-       /* Since there is a prototype,
-          args are passed in their declared types.  */
-       tree type = TREE_TYPE (decl);
-       DECL_ARG_TYPE (decl) = type;
-       if (PROMOTE_PROTOTYPES
-           && INTEGRAL_TYPE_P (type)
-           && TYPE_PRECISION (type) < TYPE_PRECISION (integer_type_node))
-         DECL_ARG_TYPE (decl) = integer_type_node;
-
-       types = tree_cons (NULL_TREE, TREE_TYPE (decl), types);
-       if (VOID_TYPE_P (TREE_VALUE (types)) && ! erred
-           && DECL_NAME (decl) == 0)
-         {
-           error ("`void' in parameter list must be the entire list");
-           erred = 1;
-         }
-      }
-
-  if (void_at_end)
-    return tree_cons (new_parms, tags,
-                     nreverse (tree_cons (NULL_TREE, void_type_node, types)));
-
-  return tree_cons (new_parms, tags, nreverse (types));
-}
-
-/* At end of parameter list, warn about any struct, union or enum tags
-   defined within.  Do so because these types cannot ever become complete.  */
+       if (!TREE_ASM_WRITTEN (decl))
+         abort ();
 
-void
-parmlist_tags_warning (void)
-{
-  tree elt;
-  static int already;
+         error ("%Hparameter \"%D\" has just a forward declaration",
+                &DECL_SOURCE_LOCATION (decl), decl);
+      }
 
-  for (elt = current_scope->tags; elt; elt = TREE_CHAIN (elt))
+  /* Warn about any struct, union or enum tags defined within this
+     list.  The scope of such types is limited to this declaration,
+     which is rarely if ever desirable (it's impossible to call such
+     a function with type-correct arguments).  */
+  for (decl = tags; decl; decl = TREE_CHAIN (decl))
     {
-      enum tree_code code = TREE_CODE (TREE_VALUE (elt));
+      enum tree_code code = TREE_CODE (TREE_VALUE (decl));
+      const char *keyword;
       /* An anonymous union parm type is meaningful as a GNU extension.
         So don't warn for that.  */
-      if (code == UNION_TYPE && TREE_PURPOSE (elt) == 0 && !pedantic)
+      if (code == UNION_TYPE && TREE_PURPOSE (decl) == 0 && !pedantic)
        continue;
-      if (TREE_PURPOSE (elt) != 0)
-        {
-          if (code == RECORD_TYPE)
-            warning ("`struct %s' declared inside parameter list",
-                     IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
-          else if (code == UNION_TYPE)
-            warning ("`union %s' declared inside parameter list",
-                     IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
-          else
-            warning ("`enum %s' declared inside parameter list",
-                     IDENTIFIER_POINTER (TREE_PURPOSE (elt)));
-        }
-      else
+
+      /* The keyword should not be translated.  */
+      switch (code)
        {
-         /* For translation these need to be separate warnings */
-         if (code == RECORD_TYPE)
-           warning ("anonymous struct declared inside parameter list");
-         else if (code == UNION_TYPE)
-           warning ("anonymous union declared inside parameter list");
-         else
-           warning ("anonymous enum declared inside parameter list");
+       case RECORD_TYPE:   keyword = "struct"; break;
+       case UNION_TYPE:    keyword = "union";  break;
+       case ENUMERAL_TYPE: keyword = "enum";   break;
+       default: abort ();
        }
-      if (! already)
+
+      if (TREE_PURPOSE (decl)) 
+       /* The first %s will be one of 'struct', 'union', or 'enum'.  */
+       warning ("\"%s %s\" declared inside parameter list",
+                keyword, IDENTIFIER_POINTER (TREE_PURPOSE (decl)));
+      else
+       /* The %s will be one of 'struct', 'union', or 'enum'.  */
+       warning ("anonymous %s declared inside parameter list", keyword);
+
+      if (! explained_incomplete_types)
        {
-         warning ("its scope is only this definition or declaration, which is probably not what you want");
-         already = 1;
+         warning ("its scope is only this definition or declaration,"
+                  " which is probably not what you want");
+         explained_incomplete_types = true;
        }
     }
+
+
+  if (void_at_end)
+    {
+      type = build_tree_list (0, void_type_node);
+      *last_type = type;
+    }
+
+  list = tree_cons (parms, tags, types);
+  TREE_TYPE (list) = others;
+  return list;
 }
 \f
 /* Get the struct, enum or union (CODE says which) with tag NAME.
@@ -5544,6 +5566,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
      where store_parm_decls will find them.  */
   current_function_parms = last_function_parms;
   current_function_parm_tags = last_function_parm_tags;
+  current_function_parm_vars = last_function_parm_vars;
 
   /* Make the init_value nonzero so pushdecl knows this is not tentative.
      error_mark_node is replaced below (in poplevel) with the BLOCK.  */
@@ -5725,16 +5748,13 @@ start_function (tree declspecs, tree declarator, tree attributes)
 static void
 store_parm_decls_newstyle (void)
 {
-  tree decl, next;
+  tree decl;
   tree fndecl = current_function_decl;
   tree parms = current_function_parms;
   tree tags = current_function_parm_tags;
+  tree vars = current_function_parm_vars;
 
-  /* This is anything which appeared in current_function_parms that
-     wasn't a PARM_DECL.  */
-  tree nonparms = 0;
-
-  if (current_scope->names || current_scope->tags)
+  if (current_scope->parms || current_scope->names || current_scope->tags)
     {
       error ("%Hold-style parameter declarations in prototyped "
             "function definition", &DECL_SOURCE_LOCATION (fndecl));
@@ -5744,37 +5764,58 @@ store_parm_decls_newstyle (void)
       pushlevel (0);
     }
 
-  /* Now make all the parameter declarations visible in the function body.  */
-  parms = nreverse (parms);
-  for (decl = parms; decl; decl = next)
+  /* Now make all the parameter declarations visible in the function body.
+     We can bypass most of the grunt work of pushdecl.  */
+  for (decl = parms; decl; decl = TREE_CHAIN (decl))
     {
-      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;
-       }
+      DECL_CONTEXT (decl) = current_function_decl;
 
       if (DECL_NAME (decl) == 0)
        error ("%Hparameter name omitted", &DECL_SOURCE_LOCATION (decl));
       else
-       pushdecl (decl);
+       {
+         if (IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)))
+           current_scope->shadowed
+             = tree_cons (DECL_NAME (decl),
+                          IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)),
+                          current_scope->shadowed);
+         IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl;
+       }
     }
+  current_scope->parms = parms;
 
   /* Record the parameter list in the function declaration.  */
-  DECL_ARGUMENTS (fndecl) = getdecls ();
+  DECL_ARGUMENTS (fndecl) = parms;
 
   /* 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);
+  for (decl = vars; decl; decl = TREE_CHAIN (decl))
+    {
+      DECL_CONTEXT (decl) = current_function_decl;
+      if (DECL_NAME (decl)
+         && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) != void_type_node)
+       {
+         if (IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)))
+           current_scope->shadowed
+             = tree_cons (DECL_NAME (decl),
+                          IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)),
+                          current_scope->shadowed);
+         IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl;
+       }
+    }
+  current_scope->names = vars;
 
   /* And all the tag declarations.  */
-  storetags (tags);
+  for (decl = tags; decl; decl = TREE_CHAIN (decl))
+    if (TREE_PURPOSE (decl))
+      {
+       if (IDENTIFIER_TAG_VALUE (TREE_PURPOSE (decl)))
+         current_scope->shadowed_tags
+           = tree_cons (TREE_PURPOSE (decl),
+                        IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (decl)),
+                        current_scope->shadowed_tags);
+       IDENTIFIER_TAG_VALUE (TREE_PURPOSE (decl)) = TREE_VALUE (decl);
+      }
+  current_scope->tags = tags;
 }
 
 /* Subroutine of store_parm_decls which handles old-style function
@@ -5783,19 +5824,15 @@ store_parm_decls_newstyle (void)
 static void
 store_parm_decls_oldstyle (void)
 {
-  tree parm, decl, next;
+  tree parm, decl, last;
   tree fndecl = current_function_decl;
 
   /* This is the identifier list from the function declarator.  */
   tree parmids = current_function_parms;
 
-  /* 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))
+  for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
     DECL_WEAK (parm) = 0;
 
   /* Match each formal parameter name with its declaration.  Save each
@@ -5854,24 +5891,12 @@ store_parm_decls_oldstyle (void)
       DECL_WEAK (decl) = 1;
     }
 
-  /* 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.  */
+  /* Now examine the parms chain for incomplete declarations
+     and declarations with no corresponding names.  */
 
-  nonparms = 0;
-  for (parm = current_scope->names; parm; parm = next)
+  for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
     {
       const location_t *locus = &DECL_SOURCE_LOCATION (parm);
-      next = TREE_CHAIN (parm);
-      TREE_CHAIN (parm) = 0;
-
-      if (TREE_CODE (parm) != PARM_DECL)
-       {
-         nonparms = chainon (nonparms, parm);
-         continue;
-       }
 
       if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
        {
@@ -5893,29 +5918,28 @@ store_parm_decls_oldstyle (void)
 
   /* Chain the declarations together in the order of the list of
      names.  Store that chain in the function decl, replacing the
-     list of names.  */
+     list of names.  Update the current scope to match.  */
   DECL_ARGUMENTS (fndecl) = 0;
-  {
-    tree last;
-    for (parm = parmids; parm; parm = TREE_CHAIN (parm))
-      if (TREE_PURPOSE (parm))
-       break;
-    if (parm && TREE_PURPOSE (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))
-           {
-             TREE_CHAIN (last) = TREE_PURPOSE (parm);
-             last = TREE_PURPOSE (parm);
-             DECL_WEAK (last) = 0;
-           }
-       TREE_CHAIN (last) = 0;
-      }
-  }
+  for (parm = parmids; parm; parm = TREE_CHAIN (parm))
+    if (TREE_PURPOSE (parm))
+      break;
+  if (parm && TREE_PURPOSE (parm))
+    {
+      last = TREE_PURPOSE (parm);
+      DECL_ARGUMENTS (fndecl) = last;
+      current_scope->parms = last;
+      DECL_WEAK (last) = 0;
+
+      for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
+       if (TREE_PURPOSE (parm))
+         {
+           TREE_CHAIN (last) = TREE_PURPOSE (parm);
+           last = TREE_PURPOSE (parm);
+           DECL_WEAK (last) = 0;
+         }
+      TREE_CHAIN (last) = 0;
+    }
 
   /* If there was a previous prototype,
      set the DECL_ARG_TYPE of each argument according to
@@ -6013,13 +6037,6 @@ store_parm_decls_oldstyle (void)
 
       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.  */
-
-  storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
 }
 
 /* Store the parameter declarations into the current function declaration.
@@ -6041,10 +6058,6 @@ store_parm_decls (void)
   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
@@ -6089,8 +6102,6 @@ store_parm_decls (void)
      not safe to try to expand expressions involving them.  */
   immediate_size_expand = 0;
   cfun->x_dont_save_pending_sizes_p = 1;
-
-  warn_shadow = saved_warn_shadow;
 }
 \f
 /* Finish up a function declaration and compile that function
index 22b1531afa1355e341c85feb9bb1f5109427228c..dfdd9abd22b2b995c506d804ca7d889438c239b4 100644 (file)
@@ -2478,24 +2478,16 @@ asm_clobbers:
 parmlist:
          maybe_attribute
                { pushlevel (0);
-                 clear_parm_order ();
                  declare_parm_level (); }
          parmlist_1
                { $$ = $3;
-                 parmlist_tags_warning ();
                  poplevel (0, 0, 0); }
        ;
 
 parmlist_1:
          parmlist_2 ')'
        | parms ';'
-               { tree parm;
-                 if (pedantic)
-                   pedwarn ("ISO C forbids forward parameter declarations");
-                 /* Mark the forward decls as such.  */
-                 for (parm = getdecls (); parm; parm = TREE_CHAIN (parm))
-                   TREE_ASM_WRITTEN (parm) = 1;
-                 clear_parm_order (); }
+               { mark_forward_parm_decls (); }
          maybe_attribute
                { /* Dummy action so attributes are in known place
                     on parser stack.  */ }
@@ -2600,11 +2592,9 @@ setspecs_fp:
 parmlist_or_identifiers:
          maybe_attribute
                { pushlevel (0);
-                 clear_parm_order ();
                  declare_parm_level (); }
          parmlist_or_identifiers_1
                { $$ = $3;
-                 parmlist_tags_warning ();
                  poplevel (0, 0, 0); }
        ;
 
index cbc83a523a0c57b314969b97d01892f38a18ce2e..f2f27de6ac3da53a2dcdb7cb8bf859549e636ebd 100644 (file)
@@ -193,7 +193,7 @@ extern void c_print_identifier (FILE *, tree, int);
 extern tree build_array_declarator (tree, tree, int, int);
 extern tree build_enumerator (tree, tree);
 extern void check_for_loop_decls (void);
-extern void clear_parm_order (void);
+extern void mark_forward_parm_decls (void);
 extern int  complete_array_type (tree, tree, int);
 extern void declare_parm_level (void);
 extern void undeclared_variable (tree);
@@ -211,7 +211,6 @@ extern tree implicitly_declare (tree);
 extern int  in_parm_level_p (void);
 extern void keep_next_level (void);
 extern tree lookup_name (tree);
-extern void parmlist_tags_warning (void);
 extern void pending_xref_error (void);
 extern void c_push_function_context (struct function *);
 extern void c_pop_function_context (struct function *);
index 3a0ae1f29e126d7bfeaff67b4a17bfeb0cb4fdd9..ce13803348cecaf7f4e2bfc6d168389e76e8c079 100644 (file)
@@ -1,3 +1,7 @@
+2003-07-29  Zack Weinberg  <zack@codesourcery.com>
+
+       * gcc.dg/struct-in-proto-1.c: New test.
+
 2003-07-29  Neil Booth  <neil@daikokuya.co.uk>
 
        * gcc.dg/cpp/include2.c: Only expect one message.
@@ -25,7 +29,7 @@
        PR c++/11667
        * g++.dg/init/enum2.C: New test.
        * g++.dg/template/overload1.C: Add "-w" option.
-       
+
 2003-07-28    <hp@bitrange.com>
 
        * gcc.dg/Wdeclaration-after-statement-1.c,
@@ -85,7 +89,7 @@
 
        PR c++/11517
        * g++.dg/expr/cond2.C: New test.
-       
+
        PR optimization/10679
        * g++.dg/opt/inline4.C: New test.
 
 2003-07-22  Nathan Sidwell  <nathan@codesourcery.com>
 
        * g++.dg/ext/flexary1.C: New test.
-       
+
 2003-07-22  Kriang Lerdsuwanakij  <lerdsuwa@users.sourceforge.net>
 
        PR c++/10793
 
 2003-07-21  Eric Botcazou  <ebotcazou@libertysurf.fr>
 
-        PR optimization/11536
+       PR optimization/11536
        * gcc.dg/20030721-1.c: New test.
 
 2003-07-19  Mark Mitchell  <mark@codesourcery.com>
diff --git a/gcc/testsuite/gcc.dg/struct-in-proto-1.c b/gcc/testsuite/gcc.dg/struct-in-proto-1.c
new file mode 100644 (file)
index 0000000..162ba91
--- /dev/null
@@ -0,0 +1,8 @@
+/* { dg-do compile } */
+/* { dg-options "-w" } */
+int foo(struct S { int i; } s) {
+  return sizeof(struct S); /* { dg-bogus "incomplete type" "S visible here" } */
+}
+int bar(void) {
+  return sizeof(struct S); /* { dg-error "incomplete type" "not here" } */
+}