Commit f91f41b2 by Zack Weinberg

c-decl.c (gettags, [...]): Delete.

	* c-decl.c (gettags, pushdecl_function_level): Delete.
	(last_function_parm_vars): Rename last_function_parm_others.
	(current_function_parm_vars): Rename current_function_parm_others.
	(struct c_scope): Rewrite comment explaining this data structure.
	Add names_last, blocks_last, parms_last fields.  Rename
	incomplete_list to incomplete.
	(SCOPE_LIST_APPEND, SCOPE_LIST_CONCAT): New macros.
	(poplevel): Ignore second argument.  No need to nreverse
	anything.  Restructure such that each list is processed
	exactly once.  Use 'const location_t *locus' syntactic sugar
	variable where useful.  Issue unused variable warnings
	ourselves, do not rely on function.c.
	(insert_block, pushdecl, bind_label): Use SCOPE_LIST_APPEND.
	(pushdecl_top_level): Likewise.  Don't call duplicate_decls.
	(implicitly_declare): decl cannot be error_mark_node.
	(undeclared_variable): Manipulate scope structure directly.
	(c_make_fname_decl): Likewise.
	(getdecls, c_init_decl_processing): Fix comment.
	(mark_forward_parm_decls): Use SCOPE_LIST_CONCAT.  No need
	for 'last' variable.
	(grokparms): No need to nreverse parms list.
	(store_parm_decls_newstyle): Set up the parms_last and
	names_last fields of the new scope too.
	(store_parm_decls_oldstyle): Can assume DECL_WEAK is not set
	on parms to begin with; check this under ENABLE_CHECKING.  Set
	up parms_last.
	(check_for_loop_decls): Refer directly to current_scope->tags.
	Use consistent quote style in diagnostics.
	(c_write_global_declarations): The names list is not backward.

	* c-common.h: Don't prototype gettags.
	* c-parse.in: Call poplevel with second argument 0 always.

From-SVN: r70061
parent a8eb1db5
2003-08-01 Zack Weinberg <zack@codesourcery.com>
* c-decl.c (gettags, pushdecl_function_level): Delete.
(last_function_parm_vars): Rename last_function_parm_others.
(current_function_parm_vars): Rename current_function_parm_others.
(struct c_scope): Rewrite comment explaining this data structure.
Add names_last, blocks_last, parms_last fields. Rename
incomplete_list to incomplete.
(SCOPE_LIST_APPEND, SCOPE_LIST_CONCAT): New macros.
(poplevel): Ignore second argument. No need to nreverse
anything. Restructure such that each list is processed
exactly once. Use 'const location_t *locus' syntactic sugar
variable where useful. Issue unused variable warnings
ourselves, do not rely on function.c.
(insert_block, pushdecl, bind_label): Use SCOPE_LIST_APPEND.
(pushdecl_top_level): Likewise. Don't call duplicate_decls.
(implicitly_declare): decl cannot be error_mark_node.
(undeclared_variable): Manipulate scope structure directly.
(c_make_fname_decl): Likewise.
(getdecls, c_init_decl_processing): Fix comment.
(mark_forward_parm_decls): Use SCOPE_LIST_CONCAT. No need
for 'last' variable.
(grokparms): No need to nreverse parms list.
(store_parm_decls_newstyle): Set up the parms_last and
names_last fields of the new scope too.
(store_parm_decls_oldstyle): Can assume DECL_WEAK is not set
on parms to begin with; check this under ENABLE_CHECKING. Set
up parms_last.
(check_for_loop_decls): Refer directly to current_scope->tags.
Use consistent quote style in diagnostics.
(c_write_global_declarations): The names list is not backward.
* c-common.h: Don't prototype gettags.
* c-parse.in: Call poplevel with second argument 0 always.
2003-08-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu> 2003-08-01 Kaveh R. Ghazi <ghazi@caip.rutgers.edu>
* builtins.def: Resort builtins. * builtins.def: Resort builtins.
......
...@@ -318,7 +318,6 @@ struct c_language_function GTY(()) { ...@@ -318,7 +318,6 @@ struct c_language_function GTY(()) {
extern void (*lang_expand_stmt) (tree); extern void (*lang_expand_stmt) (tree);
extern void (*lang_expand_decl_stmt) (tree); extern void (*lang_expand_decl_stmt) (tree);
extern void (*lang_expand_function_end) (void); extern void (*lang_expand_function_end) (void);
extern tree gettags (void);
/* Callback that determines if it's ok for a function to have no /* Callback that determines if it's ok for a function to have no
noreturn attribute. */ noreturn attribute. */
......
...@@ -97,7 +97,7 @@ static tree last_function_parm_tags; ...@@ -97,7 +97,7 @@ static tree last_function_parm_tags;
/* ... and a chain of all non-parameter declarations (such as /* ... and a chain of all non-parameter declarations (such as
CONST_DECLs from enumerations) here. */ CONST_DECLs from enumerations) here. */
static tree last_function_parm_vars; static tree last_function_parm_others;
/* After parsing the declarator that starts a function definition, /* After parsing the declarator that starts a function definition,
`start_function' puts the list of parameter names or chain of decls here `start_function' puts the list of parameter names or chain of decls here
...@@ -109,9 +109,9 @@ static tree current_function_parms; ...@@ -109,9 +109,9 @@ static tree current_function_parms;
static tree current_function_parm_tags; static tree current_function_parm_tags;
/* And for last_function_parm_vars. */ /* And for last_function_parm_others. */
static tree current_function_parm_vars; static tree current_function_parm_others;
/* Similar, for the file and line that the prototype came from if this is /* Similar, for the file and line that the prototype came from if this is
an old-style definition. */ an old-style definition. */
...@@ -162,18 +162,30 @@ static int warn_about_return_type; ...@@ -162,18 +162,30 @@ static int warn_about_return_type;
static int current_extern_inline; static int current_extern_inline;
/* For each binding contour we allocate a c_scope structure /* Each c_scope structure describes the complete contents of one scope.
* which records the names defined in that contour. Three scopes are distinguished specially: the innermost or current
* Contours include: scope, the innermost function scope, and the outermost or file scope.
* 0) the global one
* 1) one for each function definition, Most declarations are recorded in the current scope.
* where internal declarations of the parameters appear.
* 2) one for each compound statement, All normal label declarations are recorded in the innermost
* to record its declarations. function scope, as are bindings of undeclared identifiers to
* error_mark_node. (GCC permits nested functions as an extension,
* The current meaning of a name can be found by searching the nested hence the 'innermost' qualifier.) Explicitly declared labels
* scopes from the current one out to the global one. (using the __label__ extension) appear in the current scope.
*/
Being in the global scope (current_scope == global_scope) causes
special behavior in several places below. Also, under some
conditions the Objective-C front end records declarations in the
global scope even though that isn't the current scope.
The order of the names, parms, and blocks lists matters, and they
are frequently appended to. To avoid having to walk all the way to
the end of the list on each insertion, or reverse the lists later,
we maintain a pointer to the last list entry for each of the lists.
The order of the tags, shadowed, shadowed_tags, and incomplete
lists does not matter, so we just prepend to these lists. */
struct c_scope GTY(()) struct c_scope GTY(())
{ {
...@@ -183,13 +195,14 @@ struct c_scope GTY(()) ...@@ -183,13 +195,14 @@ struct c_scope GTY(())
/* The next outermost function scope. */ /* The next outermost function scope. */
struct c_scope *outer_function; struct c_scope *outer_function;
/* All variables, constants, functions, labels, and typedef names. /* All variables, constants, functions, labels, and typedef names. */
They are in the reverse of the order supplied. */
tree names; tree names;
tree names_last;
/* All parameter declarations. Used only in the outermost scope of /* All parameter declarations. Used only in the outermost scope of
a function. Again, in the reverse of the order supplied. */ a function. */
tree parms; tree parms;
tree parms_last;
/* All structure, union, and enum type tags. */ /* All structure, union, and enum type tags. */
tree tags; tree tags;
...@@ -209,9 +222,10 @@ struct c_scope GTY(()) ...@@ -209,9 +222,10 @@ struct c_scope GTY(())
/* For each scope (except the global one), a chain of BLOCK nodes /* For each scope (except the global one), a chain of BLOCK nodes
for all the scopes that were entered and exited one level down. */ for all the scopes that were entered and exited one level down. */
tree blocks; tree blocks;
tree blocks_last;
/* Variable declarations with incomplete type in this scope. */ /* Variable declarations with incomplete type in this scope. */
tree incomplete_list; tree incomplete;
/* True if we are currently filling this scope with parameter /* True if we are currently filling this scope with parameter
declarations. */ declarations. */
...@@ -251,6 +265,28 @@ static GTY(()) struct c_scope *current_function_scope; ...@@ -251,6 +265,28 @@ static GTY(()) struct c_scope *current_function_scope;
static GTY(()) struct c_scope *global_scope; static GTY(()) struct c_scope *global_scope;
/* Append VAR to LIST in scope SCOPE. */ \
#define SCOPE_LIST_APPEND(scope, list, decl) do { \
struct c_scope *s_ = (scope); \
tree d_ = (decl); \
if (s_->list##_last) \
TREE_CHAIN (s_->list##_last) = d_; \
else \
s_->list = d_; \
s_->list##_last = d_; \
} while (0)
/* Concatenate FROM in scope FSCOPE onto TO in scope TSCOPE. */
#define SCOPE_LIST_CONCAT(tscope, to, fscope, from) do { \
struct c_scope *t_ = (tscope); \
struct c_scope *f_ = (fscope); \
if (t_->to##_last) \
TREE_CHAIN (t_->to##_last) = f_->from; \
else \
t_->to = f_->from; \
t_->to##_last = f_->from##_last; \
} while (0)
/* True means unconditionally make a BLOCK for the next scope pushed. */ /* True means unconditionally make a BLOCK for the next scope pushed. */
static bool keep_next_level_flag; static bool keep_next_level_flag;
...@@ -288,7 +324,6 @@ static tree any_external_decl (tree); ...@@ -288,7 +324,6 @@ static tree any_external_decl (tree);
static void record_external_decl (tree); static void record_external_decl (tree);
static void warn_if_shadowing (tree, tree); static void warn_if_shadowing (tree, tree);
static void clone_underlying_type (tree); static void clone_underlying_type (tree);
static void pushdecl_function_level (tree, tree);
static bool flexible_array_type_p (tree); static bool flexible_array_type_p (tree);
static hashval_t link_hash_hash (const void *); static hashval_t link_hash_hash (const void *);
static int link_hash_eq (const void *, const void *); static int link_hash_eq (const void *, const void *);
...@@ -454,8 +489,8 @@ pushlevel (int dummy ATTRIBUTE_UNUSED) ...@@ -454,8 +489,8 @@ pushlevel (int dummy ATTRIBUTE_UNUSED)
debugging output. If KEEP is KEEP_MAYBE, do so only if the names debugging output. If KEEP is KEEP_MAYBE, do so only if the names
or tags lists are nonempty. or tags lists are nonempty.
If REVERSE is nonzero, reverse the order of decls before putting The second parameter is ignored; it is present only for
them into the BLOCK. signature compatibility with lang_hooks.decls.poplevel.
If FUNCTIONBODY is nonzero, this level is the body of a function, If FUNCTIONBODY is nonzero, this level is the body of a function,
even if current_scope->function_body is not set. This is used even if current_scope->function_body is not set. This is used
...@@ -465,186 +500,165 @@ pushlevel (int dummy ATTRIBUTE_UNUSED) ...@@ -465,186 +500,165 @@ pushlevel (int dummy ATTRIBUTE_UNUSED)
FIXME: Eliminate the need for all arguments. */ FIXME: Eliminate the need for all arguments. */
tree tree
poplevel (int keep, int reverse, int functionbody) poplevel (int keep, int dummy ATTRIBUTE_UNUSED, int functionbody)
{ {
tree link; struct c_scope *scope = current_scope;
tree block; tree block;
tree decl; tree decl;
tree decls = current_scope->names; tree p;
tree tags = current_scope->tags;
tree subblocks = current_scope->blocks;
functionbody |= current_scope->function_body; scope->function_body |= functionbody;
if (keep == KEEP_MAYBE) if (keep == KEEP_MAYBE)
keep = (current_scope->names || current_scope->tags); keep = (scope->names || scope->tags);
keep |= current_scope->keep; keep |= scope->keep;
keep |= functionbody; keep |= scope->function_body;
/* We used to warn about unused variables in expand_end_bindings, /* If appropriate, create a BLOCK to record the decls for the life
i.e. while generating RTL. But in function-at-a-time mode we may of this function. */
choose to never expand a function at all (e.g. auto inlining), so block = 0;
we do this explicitly now. if (keep)
No warnings when the global scope is popped because the global {
scope isn't popped for the last translation unit, so the warnings block = make_node (BLOCK);
are done in c_write_global_declaration. */ BLOCK_VARS (block) = scope->names;
if (current_scope != global_scope) BLOCK_SUBBLOCKS (block) = scope->blocks;
warn_about_unused_variables (decls); TREE_USED (block) = 1;
}
/* In each subblock, record that this is its superior. */
for (p = scope->blocks; p; p = TREE_CHAIN (p))
BLOCK_SUPERCONTEXT (p) = block;
/* Clear out the variable bindings in this scope.
/* Clear out the name-meanings declared in this scope.
Propagate TREE_ADDRESSABLE from nested functions to their Propagate TREE_ADDRESSABLE from nested functions to their
containing functions. */ containing functions.
for (link = decls; link; link = TREE_CHAIN (link))
Issue warnings for unused variables and labels, and errors for
undefined labels, if there are any. */
for (p = scope->names; p; p = TREE_CHAIN (p))
{ {
if (TREE_CODE (link) == LABEL_DECL) const location_t *locus = &DECL_SOURCE_LOCATION (p);
switch (TREE_CODE (p))
{ {
if (TREE_USED (link) && DECL_INITIAL (link) == 0) case LABEL_DECL:
if (TREE_USED (p) && !DECL_INITIAL (p))
{ {
error ("%Hlabel `%D' used but not defined", error ("%Hlabel `%D' used but not defined", locus, p);
&DECL_SOURCE_LOCATION (link), link); DECL_INITIAL (p) = error_mark_node;
/* Avoid crashing later. */
DECL_INITIAL (link) = error_mark_node;
} }
else if (!TREE_USED (link) && warn_unused_label) else if (!TREE_USED (p) && warn_unused_label)
{ {
if (DECL_INITIAL (link) != 0) if (DECL_INITIAL (p))
warning ("%Hlabel `%D' defined but not used", warning ("%Hlabel `%D' defined but not used", locus, p);
&DECL_SOURCE_LOCATION (link), link);
else else
warning ("%Hlabel `%D' declared but not defined", warning ("%Hlabel `%D' declared but not defined", locus, p);
&DECL_SOURCE_LOCATION (link), link);
} }
IDENTIFIER_LABEL_VALUE (DECL_NAME (link)) = 0;
} IDENTIFIER_LABEL_VALUE (DECL_NAME (p)) = 0;
else if (DECL_NAME (link) != 0) break;
case FUNCTION_DECL:
if (! TREE_ASM_WRITTEN (p)
&& DECL_INITIAL (p) != 0
&& TREE_ADDRESSABLE (p)
&& DECL_ABSTRACT_ORIGIN (p) != 0
&& DECL_ABSTRACT_ORIGIN (p) != p)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (p)) = 1;
goto normal;
case VAR_DECL:
/* keep this in sync with stmt.c:warn_about_unused_variables.
No warnings when the global scope is popped because the
global scope isn't popped for the last translation unit,
so the warnings are done in c_write_global_declaration. */
if (warn_unused_variable && scope != global_scope
&& !TREE_USED (p)
&& !DECL_IN_SYSTEM_HEADER (p)
&& DECL_NAME (p)
&& !DECL_ARTIFICIAL (p))
warning ("%Hunused variable `%D'", locus, p);
/* fall through */
default:
normal:
if (DECL_NAME (p))
{ {
if (DECL_EXTERNAL (link) if (DECL_EXTERNAL (p) && scope != global_scope)
&& current_scope != global_scope)
/* External decls stay in the symbol-value slot but are /* External decls stay in the symbol-value slot but are
inaccessible. */ inaccessible. */
C_DECL_INVISIBLE (link) = 1; C_DECL_INVISIBLE (p) = 1;
else else
IDENTIFIER_SYMBOL_VALUE (DECL_NAME (link)) = 0; IDENTIFIER_SYMBOL_VALUE (DECL_NAME (p)) = 0;
}
break;
} }
if (TREE_CODE (link) == FUNCTION_DECL
&& ! TREE_ASM_WRITTEN (link)
&& DECL_INITIAL (link) != 0
&& TREE_ADDRESSABLE (link)
&& DECL_ABSTRACT_ORIGIN (link) != 0
&& DECL_ABSTRACT_ORIGIN (link) != link)
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (link)) = 1;
} }
/* Clear out the parameter bindings declared in this scope. /* Clear out the parameter bindings in this scope, if any.
Unused-parameter warnings are handled by function.c. */ Unused-parameter warnings are handled by function.c. */
for (link = current_scope->parms; link; link = TREE_CHAIN (link)) for (p = scope->parms; p; p = TREE_CHAIN (p))
if (DECL_NAME (link)) if (DECL_NAME (p))
IDENTIFIER_SYMBOL_VALUE (DECL_NAME (link)) = 0; IDENTIFIER_SYMBOL_VALUE (DECL_NAME (p)) = 0;
/* Clear out the tag-meanings declared in this scope. */ /* Clear out the tag-meanings declared in this scope.
for (link = tags; link; link = TREE_CHAIN (link))
if (TREE_PURPOSE (link)) Set the TYPE_CONTEXTs for all of the tagged types belonging to
IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = 0; this scope so that they point to the appropriate construct, i.e.
either to the current FUNCTION_DECL node, or else to the BLOCK
node we just constructed.
Note that for tagged types whose scope is just the formal
parameter list for some function type specification, we can't
properly set their TYPE_CONTEXTs here, because we don't have a
pointer to the appropriate FUNCTION_TYPE node readily available
to us. For those cases, the TYPE_CONTEXTs of the relevant tagged
type nodes get set in `grokdeclarator' as soon as we have created
the FUNCTION_TYPE node which will represent the "scope" for these
"parameter list local" tagged types. */
decl = scope->function_body ? current_function_decl : block;
for (p = scope->tags; p; p = TREE_CHAIN (p))
{
if (TREE_PURPOSE (p))
IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = 0;
if (decl)
TYPE_CONTEXT (TREE_VALUE (p)) = decl;
}
/* Restore all name- and label-meanings from outer scopes that were /* Restore all name- and label-meanings from outer scopes that were
shadowed by this scope. */ shadowed by this scope. */
for (p = scope->shadowed; p; p = TREE_CHAIN (p))
for (link = current_scope->shadowed; link; link = TREE_CHAIN (link)) if (TREE_VALUE (p) && TREE_CODE (TREE_VALUE (p)) == LABEL_DECL)
if (TREE_VALUE (link) && TREE_CODE (TREE_VALUE (link)) == LABEL_DECL) IDENTIFIER_LABEL_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
IDENTIFIER_LABEL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
else else
IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
/* Restore all tag-meanings from outer scopes that were shadowed by /* Restore all tag-meanings from outer scopes that were shadowed by
this scope. */ this scope. */
for (p = scope->shadowed_tags; p; p = TREE_CHAIN (p))
IDENTIFIER_TAG_VALUE (TREE_PURPOSE (p)) = TREE_VALUE (p);
for (link = current_scope->shadowed_tags; link; /* Dispose of the block that we just made inside some higher level. */
link = TREE_CHAIN (link)) if (scope->function_body)
IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link); DECL_INITIAL (current_function_decl) = block;
else if (scope->outer)
/* If this is the outermost block of a function, remove all
PARM_DECLs from current_scope->names; they are already
stored in DECL_ARGUMENTS of cfun->decl in proper order, should
not be put in BLOCK_VARS, and furthermore reversing them will
cause trouble later. They are all together at the end of the
list. */
if (functionbody && decls)
{
if (TREE_CODE (decls) == PARM_DECL)
decls = 0;
else
{
link = decls;
while (TREE_CHAIN (link)
&& TREE_CODE (TREE_CHAIN (link)) != PARM_DECL)
link = TREE_CHAIN (link);
TREE_CHAIN (link) = 0;
}
}
/* Get the decls in the order they were written.
Usually current_scope->names is in reverse order.
But parameter decls were previously put in forward order. */
if (reverse)
decls = nreverse (decls);
/* If appropriate, create a BLOCK to record the decls for the life
of this function. */
block = 0;
if (keep)
{ {
block = make_node (BLOCK); if (block)
BLOCK_VARS (block) = decls; SCOPE_LIST_APPEND (scope->outer, blocks, block);
BLOCK_SUBBLOCKS (block) = subblocks; /* If we did not make a block for the scope just exited, any
TREE_USED (block) = 1; blocks made for inner scopes must be carried forward so they
will later become subblocks of something else. */
else if (scope->blocks)
SCOPE_LIST_CONCAT (scope->outer, blocks, scope, blocks);
} }
/* In each subblock, record that this is its superior. */
for (link = subblocks; link; link = TREE_CHAIN (link))
BLOCK_SUPERCONTEXT (link) = block;
/* Set the TYPE_CONTEXTs for all of the tagged types belonging to this
binding contour so that they point to the appropriate construct, i.e.
either to the current FUNCTION_DECL node, or else to the BLOCK node
we just constructed.
Note that for tagged types whose scope is just the formal parameter
list for some function type specification, we can't properly set
their TYPE_CONTEXTs here, because we don't have a pointer to the
appropriate FUNCTION_TYPE node readily available to us. For those
cases, the TYPE_CONTEXTs of the relevant tagged type nodes get set
in `grokdeclarator' as soon as we have created the FUNCTION_TYPE
node which will represent the "scope" for these "parameter list local"
tagged types. */
decl = functionbody ? current_function_decl : block;
if (decl)
for (link = tags; link; link = TREE_CHAIN (link))
TYPE_CONTEXT (TREE_VALUE (link)) = decl;
/* Pop the current scope, and free the structure for reuse. */ /* Pop the current scope, and free the structure for reuse. */
pop_scope (); pop_scope ();
/* Dispose of the block that we just made inside some higher level. */
if (functionbody)
DECL_INITIAL (current_function_decl) = block;
else if (block && current_scope)
current_scope->blocks
= chainon (current_scope->blocks, block);
/* If we did not make a block for the scope just exited, any blocks
made for inner scopes (since they cannot be recorded as subblocks
here) must be carried forward so they will later become subblocks
of something else. */
else if (! block && subblocks)
current_scope->blocks
= chainon (current_scope->blocks, subblocks);
return block; return block;
} }
...@@ -656,8 +670,7 @@ void ...@@ -656,8 +670,7 @@ void
insert_block (tree block) insert_block (tree block)
{ {
TREE_USED (block) = 1; TREE_USED (block) = 1;
current_scope->blocks SCOPE_LIST_APPEND (current_scope, blocks, block);
= chainon (current_scope->blocks, block);
} }
/* Set the BLOCK node for the innermost scope (the one we are /* Set the BLOCK node for the innermost scope (the one we are
...@@ -1687,8 +1700,8 @@ pushdecl (tree x) ...@@ -1687,8 +1700,8 @@ pushdecl (tree x)
if (*p == old) if (*p == old)
{ {
*p = TREE_CHAIN (old); *p = TREE_CHAIN (old);
TREE_CHAIN (old) = scope->parms; SCOPE_LIST_APPEND (scope, parms, old);
scope->parms = old; break;
} }
} }
return old; return old;
...@@ -1748,88 +1761,41 @@ pushdecl (tree x) ...@@ -1748,88 +1761,41 @@ pushdecl (tree x)
element = TREE_TYPE (element); element = TREE_TYPE (element);
if (TREE_CODE (element) == RECORD_TYPE if (TREE_CODE (element) == RECORD_TYPE
|| TREE_CODE (element) == UNION_TYPE) || TREE_CODE (element) == UNION_TYPE)
scope->incomplete_list = tree_cons (NULL_TREE, x, scope->incomplete = tree_cons (NULL_TREE, x, scope->incomplete);
scope->incomplete_list);
} }
} }
/* Put decls on list in reverse order.
We will reverse them later if necessary. */
if (TREE_CODE (x) == PARM_DECL) if (TREE_CODE (x) == PARM_DECL)
{ SCOPE_LIST_APPEND (scope, parms, x);
TREE_CHAIN (x) = scope->parms;
scope->parms = x;
}
else else
{ SCOPE_LIST_APPEND (scope, names, x);
TREE_CHAIN (x) = scope->names;
scope->names = x;
}
return x; return x;
} }
/* Record X as belonging to the global scope (C99 "file scope"). /* Record X as belonging to the global scope (C99 "file scope").
This is used only internally by the Objective-C front end, This is used only internally by the Objective-C front end,
and is limited to its needs. It will hork if there is _any_ and is limited to its needs. duplicate_decls is not called;
visible binding for X (not just a global one). */ if there is any preexisting decl for this identifier, it is an ICE. */
tree tree
pushdecl_top_level (tree x) pushdecl_top_level (tree x)
{ {
tree name, old; tree name;
if (TREE_CODE (x) != VAR_DECL) if (TREE_CODE (x) != VAR_DECL)
abort (); abort ();
name = DECL_NAME (x); name = DECL_NAME (x);
old = IDENTIFIER_SYMBOL_VALUE (name);
if (old)
{
if (DECL_CONTEXT (old))
abort ();
if (!duplicate_decls (x, old, 0, false)) if (IDENTIFIER_SYMBOL_VALUE (name))
abort (); abort ();
return old;
}
DECL_CONTEXT (x) = current_file_decl; DECL_CONTEXT (x) = current_file_decl;
IDENTIFIER_SYMBOL_VALUE (name) = x; IDENTIFIER_SYMBOL_VALUE (name) = x;
TREE_CHAIN (x) = global_scope->names;
global_scope->names = x;
return x;
}
/* Record X as belonging to the outermost scope of the current
function. This is used only internally, by c_make_fname_decl and
undeclared_variable, and is limited to their needs. The NAME is
provided as a separate argument because undeclared_variable wants to
use error_mark_node for X. For VAR_DECLs, duplicate_decls is not
called; if there is any preexisting decl for this identifier, it is
an ICE. */
static void
pushdecl_function_level (tree x, tree name)
{
struct c_scope *scope = current_function_scope;
if (x == error_mark_node)
scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name),
scope->shadowed);
else if (TREE_CODE (x) == VAR_DECL)
{
if (name != DECL_NAME (x))
abort ();
if (IDENTIFIER_SYMBOL_VALUE (name))
abort ();
DECL_CONTEXT (x) = current_function_decl;
TREE_CHAIN (x) = scope->names;
scope->names = x;
}
IDENTIFIER_SYMBOL_VALUE (name) = x; SCOPE_LIST_APPEND (global_scope, names, x);
return x;
} }
/* Generate an implicit declaration for identifier FUNCTIONID as a /* Generate an implicit declaration for identifier FUNCTIONID as a
...@@ -1840,7 +1806,7 @@ implicitly_declare (tree functionid) ...@@ -1840,7 +1806,7 @@ implicitly_declare (tree functionid)
{ {
tree decl = any_external_decl (functionid); tree decl = any_external_decl (functionid);
if (decl && decl != error_mark_node) if (decl)
{ {
/* Implicit declaration of a function already declared /* Implicit declaration of a function already declared
(somehow) in a different scope, or as a built-in. (somehow) in a different scope, or as a built-in.
...@@ -1969,12 +1935,13 @@ void ...@@ -1969,12 +1935,13 @@ void
undeclared_variable (tree id) undeclared_variable (tree id)
{ {
static bool already = false; static bool already = false;
struct c_scope *scope;
if (current_function_decl == 0) if (current_function_decl == 0)
{ {
error ("`%s' undeclared here (not in a function)", error ("`%s' undeclared here (not in a function)",
IDENTIFIER_POINTER (id)); IDENTIFIER_POINTER (id));
IDENTIFIER_SYMBOL_VALUE (id) = error_mark_node; scope = current_scope;
} }
else else
{ {
...@@ -1988,8 +1955,12 @@ undeclared_variable (tree id) ...@@ -1988,8 +1955,12 @@ undeclared_variable (tree id)
already = true; already = true;
} }
pushdecl_function_level (error_mark_node, id); scope = current_function_scope;
} }
scope->shadowed = tree_cons (id, IDENTIFIER_SYMBOL_VALUE (id),
scope->shadowed);
IDENTIFIER_SYMBOL_VALUE (id) = error_mark_node;
} }
/* Subroutine of lookup_label, declare_label, define_label: construct a /* Subroutine of lookup_label, declare_label, define_label: construct a
...@@ -2018,8 +1989,7 @@ bind_label (tree name, tree label, struct c_scope *scope) ...@@ -2018,8 +1989,7 @@ bind_label (tree name, tree label, struct c_scope *scope)
scope->shadowed); scope->shadowed);
IDENTIFIER_LABEL_VALUE (name) = label; IDENTIFIER_LABEL_VALUE (name) = label;
TREE_CHAIN (label) = scope->names; SCOPE_LIST_APPEND (scope, names, label);
scope->names = label;
} }
/* Get the LABEL_DECL corresponding to identifier NAME as a label. /* Get the LABEL_DECL corresponding to identifier NAME as a label.
...@@ -2152,8 +2122,7 @@ define_label (location_t location, tree name) ...@@ -2152,8 +2122,7 @@ define_label (location_t location, tree name)
return label; return label;
} }
/* Return the list of declarations of the current scope. /* Return the list of declarations of the current scope. */
Note that this list is in reverse order. */
tree tree
getdecls (void) getdecls (void)
...@@ -2161,13 +2130,6 @@ getdecls (void) ...@@ -2161,13 +2130,6 @@ getdecls (void)
return current_scope->names; return current_scope->names;
} }
/* Return the list of type-tags (for structs, etc) of the current scope. */
tree
gettags (void)
{
return current_scope->tags;
}
/* Given NAME, an IDENTIFIER_NODE, /* Given NAME, an IDENTIFIER_NODE,
return the structure (or union or enum) definition for that name. return the structure (or union or enum) definition for that name.
...@@ -2334,8 +2296,7 @@ c_init_decl_processing (void) ...@@ -2334,8 +2296,7 @@ c_init_decl_processing (void)
NAME depended on the type of the function. As we don't yet implement NAME depended on the type of the function. As we don't yet implement
delayed emission of static data, we mark the decl as emitted delayed emission of static data, we mark the decl as emitted
so it is not placed in the output. Anything using it must therefore pull so it is not placed in the output. Anything using it must therefore pull
out the STRING_CST initializer directly. This does mean that these names out the STRING_CST initializer directly. FIXME. */
are string merging candidates, which is wrong for C99's __func__. FIXME. */
static tree static tree
c_make_fname_decl (tree id, int type_dep) c_make_fname_decl (tree id, int type_dep)
...@@ -2361,7 +2322,11 @@ c_make_fname_decl (tree id, int type_dep) ...@@ -2361,7 +2322,11 @@ c_make_fname_decl (tree id, int type_dep)
TREE_USED (decl) = 1; TREE_USED (decl) = 1;
if (current_function_decl) if (current_function_decl)
pushdecl_function_level (decl, DECL_NAME (decl)); {
DECL_CONTEXT (decl) = current_function_decl;
IDENTIFIER_SYMBOL_VALUE (id) = decl;
SCOPE_LIST_APPEND (current_function_scope, names, decl);
}
finish_decl (decl, init, NULL_TREE); finish_decl (decl, init, NULL_TREE);
...@@ -3041,14 +3006,14 @@ push_parm_decl (tree parm) ...@@ -3041,14 +3006,14 @@ push_parm_decl (tree parm)
immediate_size_expand = save_immediate_size_expand; immediate_size_expand = save_immediate_size_expand;
} }
/* Shift all the existing parameter decls to the variables list, /* Mark all the parameter declarations to date as forward decls,
and reset the parameters list. Used when a ; terminating shift them to the variables list, and reset the parameters list.
forward parameter decls is encountered. */ Also diagnose use of this extension. */
void void
mark_forward_parm_decls (void) mark_forward_parm_decls (void)
{ {
tree parm, last; tree parm;
if (pedantic && !current_scope->warned_forward_parm_decls) if (pedantic && !current_scope->warned_forward_parm_decls)
{ {
...@@ -3056,14 +3021,12 @@ mark_forward_parm_decls (void) ...@@ -3056,14 +3021,12 @@ mark_forward_parm_decls (void)
current_scope->warned_forward_parm_decls = true; current_scope->warned_forward_parm_decls = true;
} }
for (last = 0, parm = current_scope->parms; for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
parm;
last = parm, parm = TREE_CHAIN (parm))
TREE_ASM_WRITTEN (parm) = 1; TREE_ASM_WRITTEN (parm) = 1;
TREE_CHAIN (last) = current_scope->names; SCOPE_LIST_CONCAT (current_scope, names, current_scope, parms);
current_scope->names = current_scope->parms;
current_scope->parms = 0; current_scope->parms = 0;
current_scope->parms_last = 0;
} }
static GTY(()) int compound_literal_number; static GTY(()) int compound_literal_number;
...@@ -4516,7 +4479,7 @@ grokparms (tree parms_info, int funcdef_flag) ...@@ -4516,7 +4479,7 @@ grokparms (tree parms_info, int funcdef_flag)
last_function_parms = TREE_PURPOSE (parms_info); last_function_parms = TREE_PURPOSE (parms_info);
last_function_parm_tags = TREE_VALUE (parms_info); last_function_parm_tags = TREE_VALUE (parms_info);
last_function_parm_vars = TREE_TYPE (parms_info); last_function_parm_others = TREE_TYPE (parms_info);
if (warn_strict_prototypes && first_parm == 0 && !funcdef_flag if (warn_strict_prototypes && first_parm == 0 && !funcdef_flag
&& !in_system_header) && !in_system_header)
...@@ -4611,9 +4574,6 @@ get_parm_info (int void_at_end) ...@@ -4611,9 +4574,6 @@ get_parm_info (int void_at_end)
return tree_cons (0, 0, tree_cons (0, void_type_node, 0)); return tree_cons (0, 0, tree_cons (0, void_type_node, 0));
} }
if (parms)
current_scope->parms = parms = nreverse (parms);
/* Sanity check all of the parameter declarations. */ /* Sanity check all of the parameter declarations. */
for (decl = parms; decl; decl = TREE_CHAIN (decl)) for (decl = parms; decl; decl = TREE_CHAIN (decl))
{ {
...@@ -5196,11 +5156,11 @@ finish_struct (tree t, tree fieldlist, tree attributes) ...@@ -5196,11 +5156,11 @@ finish_struct (tree t, tree fieldlist, tree attributes)
/* If this structure or union completes the type of any previous /* If this structure or union completes the type of any previous
variable declaration, lay it out and output its rtl. */ variable declaration, lay it out and output its rtl. */
if (current_scope->incomplete_list != NULL_TREE) if (current_scope->incomplete != NULL_TREE)
{ {
tree prev = NULL_TREE; tree prev = NULL_TREE;
for (x = current_scope->incomplete_list; x; x = TREE_CHAIN (x)) for (x = current_scope->incomplete; x; x = TREE_CHAIN (x))
{ {
tree decl = TREE_VALUE (x); tree decl = TREE_VALUE (x);
...@@ -5218,7 +5178,7 @@ finish_struct (tree t, tree fieldlist, tree attributes) ...@@ -5218,7 +5178,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
if (prev) if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (x); TREE_CHAIN (prev) = TREE_CHAIN (x);
else else
current_scope->incomplete_list = TREE_CHAIN (x); current_scope->incomplete = TREE_CHAIN (x);
} }
else if (!COMPLETE_TYPE_P (TREE_TYPE (decl)) else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE) && TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
...@@ -5242,7 +5202,7 @@ finish_struct (tree t, tree fieldlist, tree attributes) ...@@ -5242,7 +5202,7 @@ finish_struct (tree t, tree fieldlist, tree attributes)
if (prev) if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (x); TREE_CHAIN (prev) = TREE_CHAIN (x);
else else
current_scope->incomplete_list = TREE_CHAIN (x); current_scope->incomplete = TREE_CHAIN (x);
} }
} }
} }
...@@ -5567,7 +5527,7 @@ start_function (tree declspecs, tree declarator, tree attributes) ...@@ -5567,7 +5527,7 @@ start_function (tree declspecs, tree declarator, tree attributes)
where store_parm_decls will find them. */ where store_parm_decls will find them. */
current_function_parms = last_function_parms; current_function_parms = last_function_parms;
current_function_parm_tags = last_function_parm_tags; current_function_parm_tags = last_function_parm_tags;
current_function_parm_vars = last_function_parm_vars; current_function_parm_others = last_function_parm_others;
/* Make the init_value nonzero so pushdecl knows this is not tentative. /* Make the init_value nonzero so pushdecl knows this is not tentative.
error_mark_node is replaced below (in poplevel) with the BLOCK. */ error_mark_node is replaced below (in poplevel) with the BLOCK. */
...@@ -5749,11 +5709,11 @@ start_function (tree declspecs, tree declarator, tree attributes) ...@@ -5749,11 +5709,11 @@ start_function (tree declspecs, tree declarator, tree attributes)
static void static void
store_parm_decls_newstyle (void) store_parm_decls_newstyle (void)
{ {
tree decl; tree decl, last;
tree fndecl = current_function_decl; tree fndecl = current_function_decl;
tree parms = current_function_parms; tree parms = current_function_parms;
tree tags = current_function_parm_tags; tree tags = current_function_parm_tags;
tree vars = current_function_parm_vars; tree others = current_function_parm_others;
if (current_scope->parms || current_scope->names || current_scope->tags) if (current_scope->parms || current_scope->names || current_scope->tags)
{ {
...@@ -5767,10 +5727,9 @@ store_parm_decls_newstyle (void) ...@@ -5767,10 +5727,9 @@ store_parm_decls_newstyle (void)
/* Now make all the parameter declarations visible in the function body. /* Now make all the parameter declarations visible in the function body.
We can bypass most of the grunt work of pushdecl. */ We can bypass most of the grunt work of pushdecl. */
for (decl = parms; decl; decl = TREE_CHAIN (decl)) for (last = 0, decl = parms; decl; last = decl, decl = TREE_CHAIN (decl))
{ {
DECL_CONTEXT (decl) = current_function_decl; DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl) == 0) if (DECL_NAME (decl) == 0)
error ("%Hparameter name omitted", &DECL_SOURCE_LOCATION (decl)); error ("%Hparameter name omitted", &DECL_SOURCE_LOCATION (decl));
else else
...@@ -5784,12 +5743,13 @@ store_parm_decls_newstyle (void) ...@@ -5784,12 +5743,13 @@ store_parm_decls_newstyle (void)
} }
} }
current_scope->parms = parms; current_scope->parms = parms;
current_scope->parms_last = last;
/* Record the parameter list in the function declaration. */ /* Record the parameter list in the function declaration. */
DECL_ARGUMENTS (fndecl) = parms; DECL_ARGUMENTS (fndecl) = parms;
/* Now make all the ancillary declarations visible, likewise. */ /* Now make all the ancillary declarations visible, likewise. */
for (decl = vars; decl; decl = TREE_CHAIN (decl)) for (last = 0, decl = others; decl; last = decl, decl = TREE_CHAIN (decl))
{ {
DECL_CONTEXT (decl) = current_function_decl; DECL_CONTEXT (decl) = current_function_decl;
if (DECL_NAME (decl) if (DECL_NAME (decl)
...@@ -5803,7 +5763,8 @@ store_parm_decls_newstyle (void) ...@@ -5803,7 +5763,8 @@ store_parm_decls_newstyle (void)
IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl; IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = decl;
} }
} }
current_scope->names = vars; current_scope->names = others;
current_scope->names_last = last;
/* And all the tag declarations. */ /* And all the tag declarations. */
for (decl = tags; decl; decl = TREE_CHAIN (decl)) for (decl = tags; decl; decl = TREE_CHAIN (decl))
...@@ -5832,9 +5793,12 @@ store_parm_decls_oldstyle (void) ...@@ -5832,9 +5793,12 @@ store_parm_decls_oldstyle (void)
tree parmids = current_function_parms; tree parmids = current_function_parms;
/* 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. */
#ifdef ENABLE_CHECKING
for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm)) for (parm = current_scope->parms; parm; parm = TREE_CHAIN (parm))
DECL_WEAK (parm) = 0; if (DECL_WEAK (parm))
abort ();
#endif
/* Match each formal parameter name with its declaration. Save each /* Match each formal parameter name with its declaration. Save each
decl in the appropriate TREE_PURPOSE slot of the parmids chain. */ decl in the appropriate TREE_PURPOSE slot of the parmids chain. */
...@@ -5939,6 +5903,7 @@ store_parm_decls_oldstyle (void) ...@@ -5939,6 +5903,7 @@ store_parm_decls_oldstyle (void)
last = TREE_PURPOSE (parm); last = TREE_PURPOSE (parm);
DECL_WEAK (last) = 0; DECL_WEAK (last) = 0;
} }
current_scope->parms_last = last;
TREE_CHAIN (last) = 0; TREE_CHAIN (last) = 0;
} }
...@@ -6472,7 +6437,7 @@ check_for_loop_decls (void) ...@@ -6472,7 +6437,7 @@ check_for_loop_decls (void)
/* If we get here, declarations have been used in a for loop without /* If we get here, declarations have been used in a for loop without
the C99 for loop scope. This doesn't make much sense, so don't the C99 for loop scope. This doesn't make much sense, so don't
allow it. */ allow it. */
error ("`for' loop initial declaration used outside C99 mode"); error ("'for' loop initial declaration used outside C99 mode");
return; return;
} }
/* C99 subclause 6.8.5 paragraph 3: /* C99 subclause 6.8.5 paragraph 3:
...@@ -6489,20 +6454,20 @@ check_for_loop_decls (void) ...@@ -6489,20 +6454,20 @@ check_for_loop_decls (void)
interpretation, to avoid creating an extension which later causes interpretation, to avoid creating an extension which later causes
problems. */ problems. */
for (t = gettags (); t; t = TREE_CHAIN (t)) for (t = current_scope->tags; t; t = TREE_CHAIN (t))
{ {
if (TREE_PURPOSE (t) != 0) if (TREE_PURPOSE (t) != 0)
{ {
enum tree_code code = TREE_CODE (TREE_VALUE (t)); enum tree_code code = TREE_CODE (TREE_VALUE (t));
if (code == RECORD_TYPE) if (code == RECORD_TYPE)
error ("`struct %s' declared in `for' loop initial declaration", error ("'struct %s' declared in 'for' loop initial declaration",
IDENTIFIER_POINTER (TREE_PURPOSE (t))); IDENTIFIER_POINTER (TREE_PURPOSE (t)));
else if (code == UNION_TYPE) else if (code == UNION_TYPE)
error ("`union %s' declared in `for' loop initial declaration", error ("'union %s' declared in 'for' loop initial declaration",
IDENTIFIER_POINTER (TREE_PURPOSE (t))); IDENTIFIER_POINTER (TREE_PURPOSE (t)));
else else
error ("`enum %s' declared in `for' loop initial declaration", error ("'enum %s' declared in 'for' loop initial declaration",
IDENTIFIER_POINTER (TREE_PURPOSE (t))); IDENTIFIER_POINTER (TREE_PURPOSE (t)));
} }
} }
...@@ -6885,11 +6850,10 @@ c_write_global_declarations(void) ...@@ -6885,11 +6850,10 @@ c_write_global_declarations(void)
int i; int i;
tree decl; tree decl;
/* Process the decls in reverse order--earliest first. /* Process the decls in the order they were written. */
Put them into VEC from back to front, then take out from front. */
for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl)) for (i = 0, decl = globals; i < len; i++, decl = TREE_CHAIN (decl))
vec[len - i - 1] = decl; vec[i] = decl;
wrapup_global_declarations (vec, len); wrapup_global_declarations (vec, len);
......
...@@ -2135,7 +2135,7 @@ compstmt_start: '{' { compstmt_count++; ...@@ -2135,7 +2135,7 @@ compstmt_start: '{' { compstmt_count++;
compstmt_nostart: '}' compstmt_nostart: '}'
{ $$ = convert (void_type_node, integer_zero_node); } { $$ = convert (void_type_node, integer_zero_node); }
| pushlevel maybe_label_decls compstmt_contents_nonempty '}' poplevel | pushlevel maybe_label_decls compstmt_contents_nonempty '}' poplevel
{ $$ = poplevel (KEEP_MAYBE, 1, 0); { $$ = poplevel (KEEP_MAYBE, 0, 0);
SCOPE_STMT_BLOCK (TREE_PURPOSE ($5)) SCOPE_STMT_BLOCK (TREE_PURPOSE ($5))
= SCOPE_STMT_BLOCK (TREE_VALUE ($5)) = SCOPE_STMT_BLOCK (TREE_VALUE ($5))
= $$; } = $$; }
......
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