Commit 66db6b62 by Zack Weinberg

c-decl.c (store_parm_decls_newstyle, [...]): New functions split out of store_parm_decls.

	* c-decl.c (store_parm_decls_newstyle, store_parm_decls_oldstyle):
	New functions split out of store_parm_decls.
	Avoid unnecessary work. Use local variables consistently.
	(store_parm_decls): Likewise.

	(finish_function): No need to set functionbody flag on call to
	poplevel.
	(struct language_function): Remove scope field.
	(c_push_function_context, c_pop_function_context): No need to
	save and restore current_scope.

From-SVN: r69862
parent f1716368
2003-07-27 Zack Weinberg <zack@codesourcery.com>
* c-decl.c (store_parm_decls_newstyle, store_parm_decls_oldstyle):
New functions split out of store_parm_decls.
Avoid unnecessary work. Use local variables consistently.
(store_parm_decls): Likewise.
(finish_function): No need to set functionbody flag on call to
poplevel.
(struct language_function): Remove scope field.
(c_push_function_context, c_pop_function_context): No need to
save and restore current_scope.
2003-07-27 Nathan Sidwell <nathan@codesourcery.com> 2003-07-27 Nathan Sidwell <nathan@codesourcery.com>
* doc/extend.texi (Deprecated Features): Implicit typename is * doc/extend.texi (Deprecated Features): Implicit typename is
......
...@@ -275,6 +275,8 @@ static tree lookup_name_current_level (tree); ...@@ -275,6 +275,8 @@ static tree lookup_name_current_level (tree);
static tree grokdeclarator (tree, tree, enum decl_context, int); static tree grokdeclarator (tree, tree, enum decl_context, int);
static tree grokparms (tree, int); static tree grokparms (tree, int);
static void layout_array_type (tree); 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 tree c_make_fname_decl (tree, int);
static void c_expand_body_1 (tree, int); static void c_expand_body_1 (tree, int);
static tree any_external_decl (tree); static tree any_external_decl (tree);
...@@ -5724,145 +5726,90 @@ start_function (tree declspecs, tree declarator, tree attributes) ...@@ -5724,145 +5726,90 @@ start_function (tree declspecs, tree declarator, tree attributes)
return 1; return 1;
} }
/* Store the parameter declarations into the current function declaration. /* Subroutine of store_parm_decls which handles new-style function
This is called after parsing the parameter declarations, before definitions (prototype format). The parms already have decls, so we
digesting the body of the function. need only record them as in effect and complain if any redundant
old-style parm decls were written. */
For an old-style definition, modify the function's type static void
to specify at least the number of arguments. */ store_parm_decls_newstyle (void)
void
store_parm_decls (void)
{ {
tree decl, next;
tree fndecl = current_function_decl; 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 a list of types declared among parms in a prototype. */
tree parmtags = current_function_parm_tags;
/* This is a chain of PARM_DECLs from old-style parm declarations. */
tree parmdecls = getdecls ();
/* This is a chain of any other decls that came in among the parm /* This is anything which appeared in current_function_parms that
declarations. If a parm is declared with enum {foo, bar} x; wasn't a PARM_DECL. */
then CONST_DECLs for foo and bar are put here. */
tree nonparms = 0; tree nonparms = 0;
/* The function containing FNDECL, if any. */ if (current_scope->names || current_scope->tags)
tree context = decl_function_context (fndecl);
/* Nonzero if this definition is written with a prototype. */
int prototype = 0;
bool saved_warn_shadow = warn_shadow;
/* Don't re-emit shadow warnings. */
warn_shadow = false;
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. */
tree next;
tree others = 0;
prototype = 1;
if (parmdecls != 0)
{ {
tree decl, link; error ("%Hold-style parameter declarations in prototyped "
"function definition", &DECL_SOURCE_LOCATION (fndecl));
error ("%Hparm types given both in parmlist and separately", /* Get rid of the old-style declarations. */
&DECL_SOURCE_LOCATION (fndecl)); poplevel (0, 0, 0);
/* Get rid of the erroneous decls; don't keep them on pushlevel (0);
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;
} }
specparms = nreverse (specparms); /* Now make all the parameter declarations visible in the function body. */
for (parm = specparms; parm; parm = next) parms = nreverse (parms);
{ for (decl = parms; decl; decl = next)
const location_t *locus = &DECL_SOURCE_LOCATION (parm);
next = TREE_CHAIN (parm);
if (TREE_CODE (parm) == PARM_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); next = TREE_CHAIN (decl);
/* Change the type to error_mark_node so this parameter if (TREE_CODE (decl) != PARM_DECL)
will be ignored by assign_parms. */
TREE_TYPE (parm) = error_mark_node;
}
pushdecl (parm);
}
else
{ {
/* If we find an enum constant or a type tag, /* If we find an enum constant or a type tag,
put it aside for the moment. */ put it aside for the moment. */
TREE_CHAIN (parm) = 0; TREE_CHAIN (decl) = 0;
others = chainon (others, parm); nonparms = chainon (nonparms, decl);
continue;
} }
if (DECL_NAME (decl) == 0)
error ("%Hparameter name omitted", &DECL_SOURCE_LOCATION (decl));
else
pushdecl (decl);
} }
/* Get the decls in their original chain order /* Record the parameter list in the function declaration. */
and record in the function. */
DECL_ARGUMENTS (fndecl) = getdecls (); DECL_ARGUMENTS (fndecl) = getdecls ();
/* Now pushdecl the enum constants. */ /* Now make all the ancillary declarations visible, likewise. */
for (parm = others; parm; parm = next) for (decl = nonparms; decl; decl = TREE_CHAIN (decl))
{ if (DECL_NAME (decl) != 0
next = TREE_CHAIN (parm); && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) != void_type_node)
if (DECL_NAME (parm) == 0) pushdecl (decl);
;
else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
;
else if (TREE_CODE (parm) != PARM_DECL)
pushdecl (parm);
}
storetags (chainon (parmtags, gettags ())); /* And all the tag declarations. */
} storetags (tags);
else }
{
/* SPECPARMS is an identifier list--a chain of TREE_LIST nodes /* Subroutine of store_parm_decls which handles old-style function
each with a parm name as the TREE_VALUE. definitions (separate parameter list and declarations). */
static void
store_parm_decls_oldstyle (void)
{
tree parm, decl, next;
tree fndecl = current_function_decl;
PARMDECLS is a chain of declarations for parameters. /* This is the identifier list from the function declarator. */
Warning! It can also contain CONST_DECLs which are not parameters tree parmids = current_function_parms;
but are names of enumerators of any enum types
declared among the parameters.
First match each formal parameter name with its declaration. /* This is anything which appeared in current_scope->names that
Associate decls with the names and store the decls wasn't a PARM_DECL. */
into the TREE_PURPOSE slots. */ tree nonparms;
/* We use DECL_WEAK as a flag to show which parameters have been /* 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. */ seen already, since it is not used on PARM_DECL or CONST_DECL. */
for (parm = parmdecls; parm; parm = TREE_CHAIN (parm)) for (parm = current_scope->names; parm; parm = TREE_CHAIN (parm))
DECL_WEAK (parm) = 0; DECL_WEAK (parm) = 0;
for (parm = specparms; parm; parm = TREE_CHAIN (parm)) /* 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))
{ {
tree tail, found = NULL;
if (TREE_VALUE (parm) == 0) if (TREE_VALUE (parm) == 0)
{ {
error ("%Hparameter name missing from parameter list", error ("%Hparameter name missing from parameter list",
...@@ -5871,112 +5818,109 @@ store_parm_decls (void) ...@@ -5871,112 +5818,109 @@ store_parm_decls (void)
continue; continue;
} }
/* See if any of the parmdecls specifies this parm by name. decl = IDENTIFIER_SYMBOL_VALUE (TREE_VALUE (parm));
Ignore any enumerator decls. */ if (decl && DECL_CONTEXT (decl) == fndecl)
for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
if (DECL_NAME (tail) == TREE_VALUE (parm)
&& TREE_CODE (tail) == PARM_DECL)
{ {
found = tail; const location_t *locus = &DECL_SOURCE_LOCATION (decl);
break; /* 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 declaration already marked, we have a duplicate name. /* If the declaration is already marked, we have a duplicate
Complain, and don't use this decl twice. */ name. Complain and ignore the duplicate. */
if (found && DECL_WEAK (found)) else if (DECL_WEAK (decl))
{ {
error ("%Hmultiple parameters named '%D'", error ("%Hmultiple parameters named \"%D\"", locus, decl);
&DECL_SOURCE_LOCATION (found), found); TREE_PURPOSE (parm) = 0;
found = 0; continue;
} }
/* If the declaration says "void", complain and turn it into
/* If the declaration says "void", complain and ignore it. */ an int. */
if (found && VOID_TYPE_P (TREE_TYPE (found))) else if (VOID_TYPE_P (TREE_TYPE (decl)))
{ {
error ("%Hparameter '%D' declared void", error ("%Hparameter \"%D\" declared void", locus, decl);
&DECL_SOURCE_LOCATION (found), found); TREE_TYPE (decl) = integer_type_node;
TREE_TYPE (found) = integer_type_node; DECL_ARG_TYPE (decl) = integer_type_node;
DECL_ARG_TYPE (found) = integer_type_node; layout_decl (decl, 0);
layout_decl (found, 0); }
} }
/* If no declaration found, default to int. */ /* If no declaration found, default to int. */
if (!found) else
{ {
found = build_decl (PARM_DECL, TREE_VALUE (parm), const location_t *locus = &DECL_SOURCE_LOCATION (fndecl);
integer_type_node); decl = build_decl (PARM_DECL, TREE_VALUE (parm), integer_type_node);
DECL_ARG_TYPE (found) = TREE_TYPE (found); DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
DECL_SOURCE_LOCATION (found) = DECL_SOURCE_LOCATION (fndecl); DECL_SOURCE_LOCATION (decl) = *locus;
pushdecl (decl);
if (flag_isoc99) if (flag_isoc99)
pedwarn ("%Htype of '%D' defaults to `int'", pedwarn ("%Htype of \"%D\" defaults to \"int\"", locus, decl);
&DECL_SOURCE_LOCATION (found), found);
else if (extra_warnings) else if (extra_warnings)
warning ("%Htype of '%D' defaults to `int'", warning ("%Htype of \"%D\" defaults to \"int\"", locus, decl);
&DECL_SOURCE_LOCATION (found), found);
pushdecl (found);
} }
TREE_PURPOSE (parm) = found; TREE_PURPOSE (parm) = decl;
DECL_WEAK (decl) = 1;
/* Mark this decl as "already found". */
DECL_WEAK (found) = 1;
} }
/* Put anything which is on the parmdecls chain and which is /* Put anything which is in current_scope->names and which is
not a PARM_DECL onto the list NONPARMS. (The types of not a PARM_DECL onto the list NONPARMS. (The types of
non-parm things which might appear on the list include non-parm things which might appear on the list include
enumerators and NULL-named TYPE_DECL nodes.) Complain about enumerators and NULL-named TYPE_DECL nodes.) Complain about
any actual PARM_DECLs not matched with any names. */ any actual PARM_DECLs not matched with any names. */
nonparms = 0; nonparms = 0;
for (parm = parmdecls; parm;) for (parm = current_scope->names; parm; parm = next)
{ {
const location_t *locus = &DECL_SOURCE_LOCATION (parm); const location_t *locus = &DECL_SOURCE_LOCATION (parm);
tree next = TREE_CHAIN (parm); next = TREE_CHAIN (parm);
TREE_CHAIN (parm) = 0; TREE_CHAIN (parm) = 0;
if (TREE_CODE (parm) != PARM_DECL) if (TREE_CODE (parm) != PARM_DECL)
nonparms = chainon (nonparms, parm);
else
{ {
/* Complain about args with incomplete types. */ nonparms = chainon (nonparms, parm);
continue;
}
if (!COMPLETE_TYPE_P (TREE_TYPE (parm))) if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
{ {
error ("%Hparameter '%D' has incomplete type", locus, parm); error ("%Hparameter \"%D\" has incomplete type", locus, parm);
TREE_TYPE (parm) = error_mark_node; TREE_TYPE (parm) = error_mark_node;
} }
if (! DECL_WEAK (parm)) if (! DECL_WEAK (parm))
{ {
error ("%Hdeclaration for parameter '%D' but no such " error ("%Hdeclaration for parameter \"%D\" but no such parameter",
"parameter", locus, parm); locus, parm);
/* Pretend the parameter was not missing. /* Pretend the parameter was not missing.
This gets us to a standard state and minimizes This gets us to a standard state and minimizes
further error messages. */ further error messages. */
specparms parmids = chainon (parmids, tree_cons (parm, 0, 0));
= chainon (specparms,
tree_cons (parm, NULL_TREE, NULL_TREE));
} }
} }
parm = next;
}
/* Chain the declarations together in the order of the list of /* Chain the declarations together in the order of the list of
names. Store that chain in the function decl, replacing the names. Store that chain in the function decl, replacing the
list of names. */ list of names. */
parm = specparms;
DECL_ARGUMENTS (fndecl) = 0; DECL_ARGUMENTS (fndecl) = 0;
{ {
tree last; tree last;
for (last = 0; parm; parm = TREE_CHAIN (parm)) 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)) 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); last = TREE_PURPOSE (parm);
DECL_WEAK (last) = 0;
}
TREE_CHAIN (last) = 0; TREE_CHAIN (last) = 0;
} }
} }
...@@ -6027,16 +5971,15 @@ store_parm_decls (void) ...@@ -6027,16 +5971,15 @@ store_parm_decls (void)
if (pedantic) if (pedantic)
{ {
pedwarn ("promoted argument `%s' doesn't match prototype", pedwarn ("promoted argument \"%D\" "
IDENTIFIER_POINTER (DECL_NAME (parm))); "doesn't match prototype", parm);
warning ("%Hprototype declaration", pedwarn ("%Hprototype declaration",
&current_function_prototype_locus); &current_function_prototype_locus);
} }
} }
else else
{ {
error ("argument `%s' doesn't match prototype", error ("argument \"%D\" doesn't match prototype", parm);
IDENTIFIER_POINTER (DECL_NAME (parm)));
error ("%Hprototype declaration", error ("%Hprototype declaration",
&current_function_prototype_locus); &current_function_prototype_locus);
} }
...@@ -6085,7 +6028,35 @@ store_parm_decls (void) ...@@ -6085,7 +6028,35 @@ store_parm_decls (void)
DECL_ARGUMENTS is not modified. */ DECL_ARGUMENTS is not modified. */
storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl))); storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
} }
/* 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, 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 ();
/* Make sure the scope for the top of the function body /* Make sure the scope for the top of the function body
gets a BLOCK if there are any in the function. gets a BLOCK if there are any in the function.
...@@ -6102,7 +6073,7 @@ store_parm_decls (void) ...@@ -6102,7 +6073,7 @@ store_parm_decls (void)
init_function_start (fndecl); init_function_start (fndecl);
/* Begin the statement tree for this function. */ /* 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 /* If this is a nested function, save away the sizes of any
variable-size types so that we can expand them when generating variable-size types so that we can expand them when generating
...@@ -6158,7 +6129,7 @@ finish_function (int nested, int can_defer_p) ...@@ -6158,7 +6129,7 @@ finish_function (int nested, int can_defer_p)
if (current_scope->parm_flag && keep_next_if_subblocks) if (current_scope->parm_flag && keep_next_if_subblocks)
{ {
pushlevel (0); pushlevel (0);
poplevel (1, 0, 1); poplevel (1, 0, 0);
} }
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl; BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
...@@ -6560,7 +6531,6 @@ struct language_function GTY(()) ...@@ -6560,7 +6531,6 @@ struct language_function GTY(())
int returns_abnormally; int returns_abnormally;
int warn_about_return_type; int warn_about_return_type;
int extern_inline; int extern_inline;
struct c_scope *scope;
}; };
/* Save and reinitialize the variables /* Save and reinitialize the variables
...@@ -6580,7 +6550,6 @@ c_push_function_context (struct function *f) ...@@ -6580,7 +6550,6 @@ c_push_function_context (struct function *f)
p->returns_abnormally = current_function_returns_abnormally; p->returns_abnormally = current_function_returns_abnormally;
p->warn_about_return_type = warn_about_return_type; p->warn_about_return_type = warn_about_return_type;
p->extern_inline = current_extern_inline; p->extern_inline = current_extern_inline;
p->scope = current_scope;
} }
/* Restore the variables used during compilation of a C function. */ /* Restore the variables used during compilation of a C function. */
...@@ -6607,7 +6576,6 @@ c_pop_function_context (struct function *f) ...@@ -6607,7 +6576,6 @@ c_pop_function_context (struct function *f)
current_function_returns_abnormally = p->returns_abnormally; current_function_returns_abnormally = p->returns_abnormally;
warn_about_return_type = p->warn_about_return_type; warn_about_return_type = p->warn_about_return_type;
current_extern_inline = p->extern_inline; current_extern_inline = p->extern_inline;
current_scope = p->scope;
f->language = NULL; f->language = NULL;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment