static tree last_function_parms;
-/* Parsing a function declarator leaves a chain of structure
- and enum types declared in the parmlist here. */
+/* ... and a chain of structure and enum types declared in the
+ parmlist here. */
static tree last_function_parm_tags;
static int current_extern_inline;
\f
-/* For each binding contour we allocate a binding_level structure
+/* For each binding contour we allocate a c_scope structure
* which records the names defined in that contour.
* Contours include:
* 0) the global one
* 2) one for each compound statement,
* to record its declarations.
*
- * The current meaning of a name can be found by searching the levels from
- * the current one out to the global one.
+ * The current meaning of a name can be found by searching the nested
+ * scopes from the current one out to the global one.
*/
-struct binding_level GTY(())
- {
- /* A chain of _DECL nodes for all variables, constants, functions,
- and typedef types. These are in the reverse of the order supplied.
- */
- tree names;
-
- /* A list of structure, union and enum definitions,
- * for looking up tag names.
- * It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name,
- * or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE,
- * or ENUMERAL_TYPE node.
- */
- tree tags;
-
- /* For each level, a list of shadowed outer-level definitions
- to be restored when this level is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
- tree shadowed;
-
- /* For each level, a list of shadowed outer-level tag definitions
- to be restored when this level is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._TYPE node). */
- tree shadowed_tags;
-
- /* For each level (except not the global one),
- a chain of BLOCK nodes for all the levels
- that were entered and exited one level down. */
- tree blocks;
-
- /* The scope containing this one. */
- struct binding_level *outer;
-
- /* The next outermost function scope. */
- struct binding_level *outer_function;
-
- /* True if we are currently filling this level with parameter
- declarations. */
- bool parm_flag : 1;
-
- /* True if this is the outermost block scope of a function body.
- This scope contains both the parameters and the local variables
- declared in the outermost block. */
- bool function_body : 1;
-
- /* True means make a BLOCK for this level regardless of all else. */
- bool keep : 1;
-
- /* True means make a BLOCK if this level has any subblocks. */
- bool keep_if_subblocks : 1;
-
- /* List of decls in `names' that have incomplete structure or
- union types. */
- tree incomplete_list;
-
- /* A list of decls giving the (reversed) specified order of parms,
- not including any forward-decls in the parmlist.
- This is so we can put the parms in proper order for assign_parms. */
- tree parm_order;
- };
-
-#define NULL_BINDING_LEVEL (struct binding_level *) NULL
+struct c_scope GTY(())
+{
+ /* The scope containing this one. */
+ struct c_scope *outer;
+
+ /* The next outermost function scope. */
+ struct c_scope *outer_function;
+
+ /* All variables, constants, functions, labels, and typedef names.
+ They are in the reverse of the order supplied. */
+ tree names;
+
+ /* All structure, union, and enum type tags. */
+ tree tags;
+
+ /* For each scope, a list of shadowed outer-scope definitions
+ to be restored when this scope is popped.
+ Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
+ whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
+ tree shadowed;
+
+ /* For each scope, a list of shadowed outer-scope tag definitions
+ to be restored when this scope is popped.
+ Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
+ whose TREE_VALUE is its old definition (a kind of ..._TYPE node). */
+ tree shadowed_tags;
+
+ /* For each scope (except the global one), a chain of BLOCK nodes
+ for all the scopes that were entered and exited one level down. */
+ tree blocks;
+
+ /* Variable declarations with incomplete type in this scope. */
+ tree incomplete_list;
+
+ /* A list of decls giving the (reversed) specified order of parms,
+ not including any forward-decls in the parmlist.
+ This is so we can put the parms in proper order for assign_parms. */
+ tree parm_order;
+
+ /* True if we are currently filling this scope with parameter
+ declarations. */
+ bool parm_flag : 1;
+
+ /* True if this is the outermost block scope of a function body.
+ This scope contains the parameters, the local variables declared
+ in the outermost block, and all the labels (except those in
+ nested functions, or declared at block scope with __label__). */
+ bool function_body : 1;
+
+ /* True means make a BLOCK for this scope no matter what. */
+ bool keep : 1;
+};
-/* The binding level currently in effect. */
+/* The scope currently in effect. */
-static GTY(()) struct binding_level *current_binding_level;
+static GTY(()) struct c_scope *current_scope;
-/* A chain of binding_level structures awaiting reuse. */
+/* A chain of c_scope structures awaiting reuse. */
-static GTY((deletable (""))) struct binding_level *free_binding_level;
+static GTY((deletable (""))) struct c_scope *scope_freelist;
/* The innermost function scope. Ordinary (not explicitly declared)
labels, bindings to error_mark_node, and the lazily-created
bindings of __func__ and its friends get this scope. */
-static GTY(()) struct binding_level *current_function_level;
-/* The outermost binding level, for names of file scope.
- This is created when the compiler is started and exists
- through the entire run. */
+static GTY(()) struct c_scope *current_function_scope;
-static GTY(()) struct binding_level *global_binding_level;
+/* The outermost scope, corresponding to the C "file scope". This is
+ created when the compiler is started and exists through the entire run. */
-/* True means unconditionally make a BLOCK for the next level pushed. */
+static GTY(()) struct c_scope *global_scope;
+
+/* True means unconditionally make a BLOCK for the next scope pushed. */
static bool keep_next_level_flag;
-/* True means make a BLOCK for the next level pushed if it has subblocks. */
+/* True means the next call to pushlevel will be the outermost scope
+ of a function body, so do not push a new scope, merely cease
+ expecting parameter decls. */
-static bool keep_next_if_subblocks;
+static bool next_is_function_body;
/* Functions called automatically at the beginning and end of execution. */
/* Forward declarations. */
-static struct binding_level *make_binding_level (void);
-static void pop_binding_level (void);
+static struct c_scope *make_scope (void);
+static void pop_scope (void);
+static tree match_builtin_function_types (tree, tree);
static int duplicate_decls (tree, tree, int, int);
static int redeclaration_error_message (tree, tree);
static tree make_label (tree, location_t);
-static void bind_label (tree, tree, struct binding_level *);
+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 grokdeclarator (tree, tree, enum decl_context, int);
static tree grokparms (tree, int);
static void layout_array_type (tree);
+static void store_parm_decls_newstyle (void);
+static void store_parm_decls_oldstyle (void);
static tree c_make_fname_decl (tree, int);
static void c_expand_body_1 (tree, int);
static tree any_external_decl (tree);
}
\f
/* Hook called at end of compilation to assume 1 elt
- for a top-level tentative array defn that wasn't complete before. */
+ for a file-scope tentative array defn that wasn't complete before. */
void
c_finish_incomplete_decl (tree decl)
}
}
\f
-/* Reuse or create a struct for this binding level. */
+/* Reuse or create a struct for this scope. */
-static struct binding_level *
-make_binding_level (void)
+static struct c_scope *
+make_scope (void)
{
- struct binding_level *result;
- if (free_binding_level)
+ struct c_scope *result;
+ if (scope_freelist)
{
- result = free_binding_level;
- free_binding_level = result->outer;
+ result = scope_freelist;
+ scope_freelist = result->outer;
}
else
- result = ggc_alloc_cleared (sizeof (struct binding_level));
+ result = ggc_alloc_cleared (sizeof (struct c_scope));
return result;
}
-/* Remove the topmost binding level from the stack and add it to the
- free list, updating current_function_level if necessary. */
+/* Remove the topmost scope from the stack and add it to the
+ free list, updating current_function_scope if necessary. */
static void
-pop_binding_level (void)
+pop_scope (void)
{
- struct binding_level *scope = current_binding_level;
+ struct c_scope *scope = current_scope;
- current_binding_level = scope->outer;
+ current_scope = scope->outer;
if (scope->function_body)
- current_function_level = scope->outer_function;
+ current_function_scope = scope->outer_function;
- memset (scope, 0, sizeof (struct binding_level));
- scope->outer = free_binding_level;
- free_binding_level = scope;
+ memset (scope, 0, sizeof (struct c_scope));
+ scope->outer = scope_freelist;
+ scope_freelist = scope;
}
-/* Nonzero if we are currently in the global binding level. */
+/* Nonzero if we are currently in the global scope. */
int
global_bindings_p (void)
{
- return current_binding_level == global_binding_level;
+ return current_scope == global_scope;
}
void
keep_next_level_flag = true;
}
-/* Identify this binding level as a level of parameters. */
+/* Identify this scope as currently being filled with parameters. */
void
declare_parm_level (void)
{
- current_binding_level->parm_flag = true;
+ current_scope->parm_flag = true;
}
/* Nonzero if currently making parm declarations. */
int
in_parm_level_p (void)
{
- return current_binding_level->parm_flag;
+ return current_scope->parm_flag;
}
-/* Enter a new binding level. */
+/* Enter a new scope. The dummy parameter is for signature
+ compatibility with lang_hooks.decls.pushlevel. */
void
pushlevel (int dummy ATTRIBUTE_UNUSED)
{
- if (keep_next_if_subblocks)
+ if (next_is_function_body)
{
/* This is the transition from the parameters to the top level
of the function body. These are the same scope
- (C99 6.2.1p4,6) so we do not push another binding level.
-
- XXX Note kludge - keep_next_if_subblocks is set only by
- store_parm_decls, which in turn is called when and only
- when we are about to encounter the opening curly brace for
- the function body. */
- current_binding_level->parm_flag = false;
- current_binding_level->function_body = true;
- current_binding_level->keep |= keep_next_level_flag;
- current_binding_level->keep_if_subblocks = true;
- current_binding_level->outer_function = current_function_level;
- current_function_level = current_binding_level;
+ (C99 6.2.1p4,6) so we do not push another scope structure.
+ next_is_function_body is set only by store_parm_decls, which
+ in turn is called when and only when we are about to
+ encounter the opening curly brace for the function body.
+
+ The outermost block of a function always gets a BLOCK node,
+ because the debugging output routines expect that each
+ function has at least one BLOCK. */
+ current_scope->parm_flag = false;
+ current_scope->function_body = true;
+ current_scope->keep = true;
+ current_scope->outer_function = current_function_scope;
+ current_function_scope = current_scope;
keep_next_level_flag = false;
- keep_next_if_subblocks = false;
+ next_is_function_body = false;
}
else
{
- struct binding_level *newlevel = make_binding_level ();
+ struct c_scope *scope = make_scope ();
- newlevel->keep = keep_next_level_flag;
- newlevel->outer = current_binding_level;
- current_binding_level = newlevel;
- keep_next_level_flag = false;
+ scope->keep = keep_next_level_flag;
+ scope->outer = current_scope;
+ current_scope = scope;
+ keep_next_level_flag = false;
}
}
-/* Exit a binding level.
- Pop the level off, and restore the state of the identifier-decl mappings
- that were in effect when this level was entered.
+/* Exit a scope. Restore the state of the identifier-decl mappings
+ that were in effect when this scope was entered.
- If KEEP is nonzero, this level had explicit declarations, so
- and create a "block" (a BLOCK node) for the level
- to record its declarations and subblocks for symbol table output.
+ If KEEP is KEEP_YES (1), this scope had explicit declarations, so
+ create a BLOCK node to record its declarations and subblocks for
+ debugging output. If KEEP is KEEP_MAYBE, do so only if the names
+ or tags lists are nonempty.
+
+ If REVERSE is nonzero, reverse the order of decls before putting
+ them into the BLOCK.
If FUNCTIONBODY is nonzero, this level is the body of a function,
- so create a block as if KEEP were set and also clear out all
- label names.
+ even if current_scope->function_body is not set. This is used
+ by language-independent code that generates synthetic functions,
+ and cannot set current_scope->function_body.
- If REVERSE is nonzero, reverse the order of decls before putting
- them into the BLOCK. */
+ FIXME: Eliminate the need for all arguments. */
tree
poplevel (int keep, int reverse, int functionbody)
tree link;
tree block;
tree decl;
- tree decls = current_binding_level->names;
- tree tags = current_binding_level->tags;
- tree subblocks = current_binding_level->blocks;
+ tree decls = current_scope->names;
+ tree tags = current_scope->tags;
+ tree subblocks = current_scope->blocks;
- functionbody |= current_binding_level->function_body;
+ functionbody |= current_scope->function_body;
if (keep == KEEP_MAYBE)
- keep = (current_binding_level->names || current_binding_level->tags);
-
- keep |= (current_binding_level->keep || functionbody
- || (subblocks && current_binding_level->keep_if_subblocks));
+ keep = (current_scope->names || current_scope->tags);
+
+ keep |= current_scope->keep;
+ keep |= functionbody;
/* We used to warn about unused variables in expand_end_bindings,
i.e. while generating RTL. But in function-at-a-time mode we may
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 (current_binding_level != global_binding_level)
+ if (current_scope != global_scope)
warn_about_unused_variables (decls);
- /* Clear out the name-meanings declared on this level.
+ /* Clear out the name-meanings declared in this scope.
Propagate TREE_ADDRESSABLE from nested functions to their
containing functions. */
for (link = decls; link; link = TREE_CHAIN (link))
else if (DECL_NAME (link) != 0)
{
if (DECL_EXTERNAL (link)
- && current_binding_level != global_binding_level)
+ && current_scope != global_scope)
/* External decls stay in the symbol-value slot but are
inaccessible. */
C_DECL_INVISIBLE (link) = 1;
TREE_ADDRESSABLE (DECL_ABSTRACT_ORIGIN (link)) = 1;
}
- /* Clear out the tag-meanings declared on this level. */
+ /* Clear out the tag-meanings declared in this scope. */
for (link = tags; link; link = TREE_CHAIN (link))
if (TREE_PURPOSE (link))
IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = 0;
- /* Restore all name- and label-meanings of the outer levels
- that were shadowed by this level. */
+ /* Restore all name- and label-meanings from outer scopes that were
+ shadowed by this scope. */
- for (link = current_binding_level->shadowed; link; link = TREE_CHAIN (link))
+ for (link = current_scope->shadowed; link; link = TREE_CHAIN (link))
if (TREE_VALUE (link) && TREE_CODE (TREE_VALUE (link)) == LABEL_DECL)
IDENTIFIER_LABEL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
else
IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- /* Restore all tag-meanings of the outer levels
- that were shadowed by this level. */
+ /* Restore all tag-meanings from outer scopes that were shadowed by
+ this scope. */
- for (link = current_binding_level->shadowed_tags; link;
+ for (link = current_scope->shadowed_tags; link;
link = TREE_CHAIN (link))
IDENTIFIER_TAG_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- /* If this is the top level block of a function, remove all
- PARM_DECLs from current_binding_level->names; they are already
+ /* 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
}
/* Get the decls in the order they were written.
- Usually current_binding_level->names is in reverse order.
+ Usually current_scope->names is in reverse order.
But parameter decls were previously put in forward order. */
if (reverse)
decls = nreverse (decls);
- /* If there were any declarations or structure tags in that level,
- or if this level is a function body,
- create a BLOCK to record them for the life of this function. */
+ /* If appropriate, create a BLOCK to record the decls for the life
+ of this function. */
block = 0;
if (keep)
for (link = tags; link; link = TREE_CHAIN (link))
TYPE_CONTEXT (TREE_VALUE (link)) = decl;
- /* Pop the current level, and free the structure for reuse. */
- pop_binding_level ();
+ /* Pop the current scope, and free the structure for reuse. */
+ 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_binding_level)
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
- /* If we did not make a block for the level just exited,
- any blocks made for inner levels
- (since they cannot be recorded as subblocks in that level)
- must be carried forward so they will later become subblocks
+ 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_binding_level->blocks
- = chainon (current_binding_level->blocks, subblocks);
+ current_scope->blocks
+ = chainon (current_scope->blocks, subblocks);
return block;
}
-/* Insert BLOCK at the end of the list of subblocks of the
- current binding level. This is used when a BIND_EXPR is expanded,
- to handle the BLOCK node inside the BIND_EXPR. */
+/* Insert BLOCK at the end of the list of subblocks of the current
+ scope. This is used when a BIND_EXPR is expanded, to handle the
+ BLOCK node inside the BIND_EXPR. */
void
insert_block (tree block)
{
TREE_USED (block) = 1;
- current_binding_level->blocks
- = chainon (current_binding_level->blocks, block);
+ current_scope->blocks
+ = chainon (current_scope->blocks, block);
}
/* Set the BLOCK node for the innermost scope (the one we are
void
pushtag (tree name, tree type)
{
- struct binding_level *b = current_binding_level;
+ struct c_scope *b = current_scope;
+ /* Record the identifier as the type's name if it has none. */
if (name)
{
- /* Record the identifier as the type's name if it has none. */
-
if (TYPE_NAME (type) == 0)
TYPE_NAME (type) = name;
b->tags = tree_cons (name, type, b->tags);
/* Create a fake NULL-named TYPE_DECL node whose TREE_TYPE will be the
- tagged type we just added to the current binding level. This fake
+ tagged type we just added to the current scope. This fake
NULL-named TYPE_DECL node helps dwarfout.c to know when it needs
to output a representation of a tagged type, and it also gives
us a convenient place to record the "scope start" address for the
TYPE_CONTEXT (type) = DECL_CONTEXT (TYPE_STUB_DECL (type));
}
\f
+/* Subroutine of duplicate_decls. Allow harmless mismatches in return
+ and argument types provided that the type modes match. This function
+ return a unified type given a suitable match, and 0 otherwise. */
+
+static tree
+match_builtin_function_types (tree oldtype, tree newtype)
+{
+ tree newrettype, oldrettype;
+ tree newargs, oldargs;
+ tree trytype, tryargs;
+
+ /* Accept the return type of the new declaration if same modes. */
+ oldrettype = TREE_TYPE (oldtype);
+ newrettype = TREE_TYPE (newtype);
+
+ if (TYPE_MODE (oldrettype) != TYPE_MODE (newrettype))
+ return 0;
+
+ oldargs = TYPE_ARG_TYPES (oldtype);
+ newargs = TYPE_ARG_TYPES (newtype);
+ tryargs = newargs;
+
+ while (oldargs || newargs)
+ {
+ if (! oldargs
+ || ! newargs
+ || ! TREE_VALUE (oldargs)
+ || ! TREE_VALUE (newargs)
+ || TYPE_MODE (TREE_VALUE (oldargs))
+ != TYPE_MODE (TREE_VALUE (newargs)))
+ return 0;
+
+ oldargs = TREE_CHAIN (oldargs);
+ newargs = TREE_CHAIN (newargs);
+ }
+
+ trytype = build_function_type (newrettype, tryargs);
+ return build_type_attribute_variant (trytype, TYPE_ATTRIBUTES (oldtype));
+}
+
/* Handle when a new declaration NEWDECL
has the same name as an old one OLDDECL
in the same binding contour.
Otherwise, return 0.
When DIFFERENT_BINDING_LEVEL is true, NEWDECL is an external declaration,
- and OLDDECL is in an outer binding level and should thus not be changed. */
+ and OLDDECL is in an outer scope and should thus not be changed. */
static int
duplicate_decls (tree newdecl, tree olddecl, int different_binding_level,
/* Discard the old built-in function. */
return 0;
}
- else if (!types_match)
+ if (!types_match)
{
- /* Accept the return type of the new declaration if same modes. */
- tree oldreturntype = TREE_TYPE (oldtype);
- tree newreturntype = TREE_TYPE (newtype);
-
- if (TYPE_MODE (oldreturntype) == TYPE_MODE (newreturntype))
- {
- /* Function types may be shared, so we can't just modify
- the return type of olddecl's function type. */
- tree trytype
- = build_function_type (newreturntype,
- TYPE_ARG_TYPES (oldtype));
- trytype = build_type_attribute_variant (trytype,
- TYPE_ATTRIBUTES (oldtype));
-
- types_match = comptypes (newtype, trytype, comptype_flags);
- if (types_match)
- oldtype = trytype;
- }
- /* Accept harmless mismatch in first argument type also.
+ /* Accept harmless mismatch in function types.
This is for the ffs and fprintf builtins. */
- if (TYPE_ARG_TYPES (TREE_TYPE (newdecl)) != 0
- && TYPE_ARG_TYPES (oldtype) != 0
- && TREE_VALUE (TYPE_ARG_TYPES (newtype)) != 0
- && TREE_VALUE (TYPE_ARG_TYPES (oldtype)) != 0
- && (TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (newtype)))
- == TYPE_MODE (TREE_VALUE (TYPE_ARG_TYPES (oldtype)))))
- {
- /* Function types may be shared, so we can't just modify
- the return type of olddecl's function type. */
- tree trytype
- = build_function_type (TREE_TYPE (oldtype),
- tree_cons (NULL_TREE,
- TREE_VALUE (TYPE_ARG_TYPES (newtype)),
- TREE_CHAIN (TYPE_ARG_TYPES (oldtype))));
- trytype = build_type_attribute_variant (trytype,
- TYPE_ATTRIBUTES (oldtype));
+ tree trytype = match_builtin_function_types (oldtype, newtype);
+ if (trytype)
+ {
types_match = comptypes (newtype, trytype, comptype_flags);
if (types_match)
oldtype = trytype;
+ if (! different_binding_level)
+ TREE_TYPE (olddecl) = oldtype;
}
- if (! different_binding_level)
- TREE_TYPE (olddecl) = oldtype;
- }
- else if (TYPE_ARG_TYPES (oldtype) == NULL
- && TYPE_ARG_TYPES (newtype) != NULL)
- {
- /* For bcmp, bzero, fputs the builtin type has arguments not
- specified. Use the ones from the prototype so that type checking
- is done for them. */
- tree trytype
- = build_function_type (TREE_TYPE (oldtype),
- TYPE_ARG_TYPES (newtype));
- trytype = build_type_attribute_variant (trytype,
- TYPE_ATTRIBUTES (oldtype));
-
- oldtype = trytype;
- if (! different_binding_level)
- TREE_TYPE (olddecl) = oldtype;
}
if (!types_match)
{
locus = &DECL_SOURCE_LOCATION (olddecl);
if (DECL_INITIAL (olddecl)
- && current_binding_level == global_binding_level)
+ && current_scope == global_scope)
error ("%H'%D' previously defined here", locus, olddecl);
else
error ("%H'%D' previously declared here", locus, olddecl);
warning ("%Hredefinition of '%D'", locus, newdecl);
locus = &DECL_SOURCE_LOCATION (olddecl);
if (DECL_INITIAL (olddecl)
- && current_binding_level == global_binding_level)
+ && current_scope == global_scope)
warning ("%H'%D' previously defined here", locus, olddecl);
else
warning ("%H'%D' previously declared here", locus, olddecl);
/* Warn about mismatches in various flags. */
else
{
+ const location_t *locus = &DECL_SOURCE_LOCATION (newdecl);
+
/* Warn if function is now inline
but was previously declared not inline and has been called. */
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& DECL_DECLARED_INLINE_P (newdecl)
&& TREE_USED (olddecl))
warning ("%H'%D' declared inline after being called",
- &DECL_SOURCE_LOCATION (newdecl), newdecl);
+ locus, newdecl);
if (TREE_CODE (olddecl) == FUNCTION_DECL
&& ! DECL_DECLARED_INLINE_P (olddecl)
&& DECL_DECLARED_INLINE_P (newdecl)
&& DECL_INITIAL (olddecl) != 0)
warning ("%H'%D' declared inline after its definition",
- &DECL_SOURCE_LOCATION (newdecl), newdecl);
+ locus, newdecl);
/* If pedantic, warn when static declaration follows a non-static
- declaration. Otherwise, do so only for functions. */
+ declaration. Otherwise, do so only for functions. */
if ((pedantic || TREE_CODE (olddecl) == FUNCTION_DECL)
&& TREE_PUBLIC (olddecl)
&& !TREE_PUBLIC (newdecl))
warning ("%Hstatic declaration for '%D' follows non-static",
- &DECL_SOURCE_LOCATION (newdecl), newdecl);
+ locus, newdecl);
/* If warn_traditional, warn when a non-static function
- declaration follows a static one. */
+ declaration follows a static one. */
if (warn_traditional && !in_system_header
&& TREE_CODE (olddecl) == FUNCTION_DECL
&& !TREE_PUBLIC (olddecl)
&& TREE_PUBLIC (newdecl))
warning ("%Hnon-static declaration for '%D' follows static",
- &DECL_SOURCE_LOCATION (newdecl), newdecl);
+ locus, newdecl);
/* Warn when const declaration follows a non-const
declaration, but not for functions. */
&& !TREE_READONLY (olddecl)
&& TREE_READONLY (newdecl))
warning ("%Hconst declaration for '%D' follows non-const",
- &DECL_SOURCE_LOCATION (newdecl), newdecl);
+ locus, newdecl);
/* These bits are logically part of the type, for variables.
But not for functions
(where qualifiers are not valid ANSI anyway). */
&& (TREE_READONLY (newdecl) != TREE_READONLY (olddecl)
|| TREE_THIS_VOLATILE (newdecl) != TREE_THIS_VOLATILE (olddecl)))
pedwarn ("%Htype qualifiers for '%D' conflict with previous "
- "declaration", &DECL_SOURCE_LOCATION (newdecl), newdecl);
+ "declaration", locus, newdecl);
}
}
It would be nice to avoid warning in any function
declarator in a declaration, as opposed to a definition,
but there is no way to tell it's not a definition. */
- || (TREE_CODE (x) == PARM_DECL
- && current_binding_level->outer->parm_flag))
+ || (TREE_CODE (x) == PARM_DECL && current_scope->outer->parm_flag))
return;
name = IDENTIFIER_POINTER (DECL_NAME (x));
-
if (TREE_CODE (old) == PARM_DECL)
shadow_warning (SW_PARAM, name, old);
else if (C_DECL_FILE_SCOPE (old))
pushdecl (tree x)
{
tree name = DECL_NAME (x);
- struct binding_level *scope = current_binding_level;
+ struct c_scope *scope = current_scope;
#ifdef ENABLE_CHECKING
if (error_mark_node == 0)
tree old;
if (warn_nested_externs
- && scope != global_binding_level
+ && scope != global_scope
&& DECL_EXTERNAL (x)
&& !DECL_IN_SYSTEM_HEADER (x))
warning ("nested extern declaration of `%s'",
old = lookup_name_current_level (name);
if (old && duplicate_decls (x, old, 0, false))
return old;
- if (DECL_EXTERNAL (x) || scope == global_binding_level)
+ if (DECL_EXTERNAL (x) || scope == global_scope)
{
/* Find and check against a previous, not-in-scope, external
decl for this identifier. (C99 s???: If two declarations
tree ext = any_external_decl (name);
if (ext)
{
- if (duplicate_decls (x, ext, scope != global_binding_level,
+ if (duplicate_decls (x, ext, scope != global_scope,
false))
x = copy_node (ext);
}
/* If storing a local value, there may already be one
(inherited). If so, record it for restoration when this
- binding level ends. Take care not to do this if we are
- replacing an older decl in the same binding level (i.e.
- duplicate_decls returned false, above). */
- if (scope != global_binding_level
+ scope ends. Take care not to do this if we are replacing an
+ older decl in the same scope (i.e. duplicate_decls returned
+ false, above). */
+ if (scope != global_scope
&& IDENTIFIER_SYMBOL_VALUE (name)
&& IDENTIFIER_SYMBOL_VALUE (name) != old)
{
scope->shadowed);
}
- /* Install the new declaration in the requested binding level. */
+ /* Install the new declaration in the requested scope. */
IDENTIFIER_SYMBOL_VALUE (name) = x;
C_DECL_INVISIBLE (x) = 0;
- /* Keep list of variables in this level with incomplete type.
+ /* Keep list of variables in this scope with incomplete type.
If the input is erroneous, we can have error_mark in the type
slot (e.g. "f(void a, ...)") - that doesn't count as an
- incomplete type. */
+ incomplete type.
+
+ FIXME: Chain these off the TYPE_DECL for the incomplete type,
+ then we don't have to do (potentially quite costly) searches
+ in finish_struct. */
if (TREE_TYPE (x) != error_mark_node
&& !COMPLETE_TYPE_P (TREE_TYPE (x)))
{
DECL_CONTEXT (x) = current_file_decl;
IDENTIFIER_SYMBOL_VALUE (name) = x;
- TREE_CHAIN (x) = global_binding_level->names;
- global_binding_level->names = x;
+ TREE_CHAIN (x) = global_scope->names;
+ global_scope->names = x;
return x;
}
static void
pushdecl_function_level (tree x, tree name)
{
- struct binding_level *scope = current_function_level;
+ struct c_scope *scope = current_function_scope;
if (x == error_mark_node)
scope->shadowed = tree_cons (name, IDENTIFIER_SYMBOL_VALUE (name),
C_DECL_IMPLICIT (decl) = 1;
}
/* If this function is global, then it must already be in the
- global binding level, so there's no need to push it again. */
- if (current_binding_level == global_binding_level)
+ global scope, so there's no need to push it again. */
+ if (current_scope == global_scope)
return decl;
/* If this is a local declaration, make a copy; we can't have
- the same DECL listed in two different binding levels. */
+ the same DECL listed in two different scopes. */
return pushdecl (copy_node (decl));
}
C_DECL_IMPLICIT (decl) = 1;
implicit_decl_warning (functionid);
- /* ANSI standard says implicit declarations are in the innermost block.
+ /* C89 says implicit declarations are in the innermost block.
So we record the decl in the standard fashion. */
decl = pushdecl (decl);
/* No need to call objc_check_decl here - it's a function type. */
rest_of_decl_compilation (decl, NULL, 0, 0);
- /* Write a record describing this implicit function declaration to the
- prototypes file (if requested). */
-
+ /* Write a record describing this implicit function declaration
+ to the prototypes file (if requested). */
gen_aux_info_record (decl, 0, 1, 0);
/* Possibly apply some default attributes to this implicit declaration. */
}
else if (C_DECL_FILE_SCOPE (newdecl))
{
- /* Objects declared at top level: */
+ /* Objects declared at file scope: */
/* If at least one is a reference, it's ok. */
if (DECL_EXTERNAL (newdecl) || DECL_EXTERNAL (olddecl))
return 0;
return 3;
return 0;
}
- else if (current_binding_level->parm_flag
+ else if (current_scope->parm_flag
&& TREE_ASM_WRITTEN (olddecl) && !TREE_ASM_WRITTEN (newdecl))
return 0;
else
set up the binding of name to LABEL_DECL in the given SCOPE. */
static void
-bind_label (tree name, tree label, struct binding_level *scope)
+bind_label (tree name, tree label, struct c_scope *scope)
{
if (IDENTIFIER_LABEL_VALUE (name))
scope->shadowed = tree_cons (name, IDENTIFIER_LABEL_VALUE (name),
/* No label binding for that identifier; make one. */
label = make_label (name, input_location);
- /* Ordinary labels go in the current function scope, which is
- not necessarily the current label scope. */
- bind_label (name, label, current_function_level);
+ /* Ordinary labels go in the current function scope. */
+ bind_label (name, label, current_function_scope);
return label;
}
/* Check to make sure that the label hasn't already been declared
at this scope */
- for (dup = current_binding_level->names; dup; dup = TREE_CHAIN (dup))
+ for (dup = current_scope->names; dup; dup = TREE_CHAIN (dup))
if (dup == label)
{
error ("duplicate label declaration `%s'", IDENTIFIER_POINTER (name));
C_DECLARED_LABEL_FLAG (label) = 1;
/* Declared labels go in the current scope. */
- bind_label (name, label, current_binding_level);
+ bind_label (name, label, current_scope);
return label;
}
|| (DECL_CONTEXT (label) != current_function_decl
&& C_DECLARED_LABEL_FLAG (label))))
{
+ location_t *prev_loc = &DECL_SOURCE_LOCATION (label);
error ("%Hduplicate label `%D'", &location, label);
if (DECL_INITIAL (label))
- error ("%H`%D' previously defined here",
- &DECL_SOURCE_LOCATION (label), label);
+ error ("%H`%D' previously defined here", prev_loc, label);
else
- error ("%H`%D' previously declared here",
- &DECL_SOURCE_LOCATION (label), label);
+ error ("%H`%D' previously declared here", prev_loc, label);
return 0;
}
else if (label && DECL_CONTEXT (label) == current_function_decl)
/* No label binding for that identifier; make one. */
label = make_label (name, location);
- /* Ordinary labels go in the current function scope, which is
- not necessarily the current label scope. */
- bind_label (name, label, current_function_level);
+ /* Ordinary labels go in the current function scope. */
+ bind_label (name, label, current_function_scope);
}
if (warn_traditional && !in_system_header && lookup_name (name))
return label;
}
\f
-/* Return the list of declarations of the current level.
- Note that this list is in reverse order unless/until
- you nreverse it; and when you do nreverse it, you must
- store the result back using `storedecls' or you will lose. */
+/* Return the list of declarations of the current scope.
+ Note that this list is in reverse order. */
tree
getdecls (void)
{
- return current_binding_level->names;
+ return current_scope->names;
}
-/* Return the list of type-tags (for structs, etc) of the current level. */
+/* Return the list of type-tags (for structs, etc) of the current scope. */
tree
gettags (void)
{
- return current_binding_level->tags;
+ return current_scope->tags;
}
-/* Store the list of declarations of the current level.
+/* 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_binding_level->names = decls;
+ current_scope->names = decls;
}
-/* Similarly, store the list of tags of the current level. */
+/* Similarly, store the list of tags of the current scope. */
static void
storetags (tree tags)
{
- current_binding_level->tags = tags;
+ current_scope->tags = tags;
}
\f
/* Given NAME, an IDENTIFIER_NODE,
return the structure (or union or enum) definition for that name.
- If THISLEVEL_ONLY is nonzero, searches only the current_binding_level.
+ If THISLEVEL_ONLY is nonzero, searches only the current_scope.
CODE says which kind of type the caller wants;
it is RECORD_TYPE or UNION_TYPE or ENUMERAL_TYPE.
If the wrong kind of type is found, an error is reported. */
thislevel_only was set or it might be a type clash. */
if (thislevel_only || TREE_CODE (tag) != code)
{
- if (current_binding_level == global_binding_level
- || purpose_member (name, current_binding_level->tags))
+ if (current_scope == global_scope
+ || purpose_member (name, current_scope->tags))
thislevel = 1;
}
}
\f
-/* Look up NAME in the current binding level and its superiors
+/* Look up NAME in the current scope and its superiors
in the namespace of variables, functions and typedefs.
Return a ..._DECL node of some kind representing its definition,
or return 0 if it is undefined. */
return decl;
}
-/* Similar to `lookup_name' but look only at the current binding level. */
+/* Similar to `lookup_name' but look only at the current scope. */
static tree
lookup_name_current_level (tree name)
if (decl == 0 || decl == error_mark_node || C_DECL_INVISIBLE (decl))
return 0;
- if (current_binding_level == global_binding_level)
+ if (current_scope == global_scope)
return decl;
/* Scan the current scope for a decl with name NAME. */
- if (chain_member (decl, current_binding_level->names))
+ if (chain_member (decl, current_scope->names))
return decl;
return 0;
\f
/* Create the predefined scalar types of C,
and some nodes representing standard constants (0, 1, (void *) 0).
- Initialize the global binding level.
+ Initialize the global scope.
Make definitions for built-in primitive functions. */
void
/* Adds some ggc roots, and reserved words for c-parse.in. */
c_parse_init ();
- current_function_decl = NULL;
- current_binding_level = NULL_BINDING_LEVEL;
- free_binding_level = NULL_BINDING_LEVEL;
+ current_function_decl = 0;
- /* Make the binding_level structure for global names. */
+ /* Make the c_scope structure for global names. */
pushlevel (0);
- global_binding_level = current_binding_level;
+ global_scope = current_scope;
+
/* Declarations from c_common_nodes_and_builtins must not be associated
with this input file, lest we get differences between using and not
using preprocessed headers. */
c_common_nodes_and_builtins ();
- boolean_type_node = integer_type_node;
- boolean_true_node = integer_one_node;
- boolean_false_node = integer_zero_node;
+ /* In C, comparisons and TRUTH_* expressions have type int. */
+ truthvalue_type_node = integer_type_node;
+ truthvalue_true_node = integer_one_node;
+ truthvalue_false_node = integer_zero_node;
- c_bool_type_node = make_unsigned_type (BOOL_TYPE_SIZE);
- TREE_SET_CODE (c_bool_type_node, BOOLEAN_TYPE);
- TYPE_MAX_VALUE (c_bool_type_node) = build_int_2 (1, 0);
- TREE_TYPE (TYPE_MAX_VALUE (c_bool_type_node)) = c_bool_type_node;
- TYPE_PRECISION (c_bool_type_node) = 1;
+ /* Even in C99, which has a real boolean type. */
pushdecl (build_decl (TYPE_DECL, get_identifier ("_Bool"),
- c_bool_type_node));
- c_bool_false_node = build_int_2 (0, 0);
- TREE_TYPE (c_bool_false_node) = c_bool_type_node;
- c_bool_true_node = build_int_2 (1, 0);
- TREE_TYPE (c_bool_true_node) = c_bool_type_node;
+ boolean_type_node));
endlink = void_list_node;
ptr_ftype_void = build_function_type (ptr_type_node, endlink);
make_fname_decl = c_make_fname_decl;
start_fname_decls ();
- builtin_decls = global_binding_level->names;
+ builtin_decls = global_scope->names;
}
/* Create the VAR_DECL for __FUNCTION__ etc. ID is the name to give the
if (initialized)
{
DECL_EXTERNAL (decl) = 0;
- if (current_binding_level == global_binding_level)
+ if (current_scope == global_scope)
TREE_STATIC (decl) = 1;
/* Tell `pushdecl' this is an initialized decl
warning ("%Hinline function '%D' given attribute noinline",
&DECL_SOURCE_LOCATION (decl), decl);
- /* Add this decl to the current binding level.
+ /* Add this decl to the current scope.
TEM may equal DECL or it may be a previous decl of the same name. */
tem = pushdecl (decl);
/* For a local variable, define the RTL now. */
- if (current_binding_level != global_binding_level
+ if (current_scope != global_scope
/* But not if this is a duplicate decl
and we preserved the rtl from the previous one
(which may or may not happen). */
&& C_DECL_FILE_SCOPE (tem))
{
if (TREE_TYPE (tem) != error_mark_node
- && COMPLETE_TYPE_P (TREE_TYPE (tem)))
- expand_decl (tem);
- else if (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
- && DECL_INITIAL (tem) != 0)
+ && (COMPLETE_TYPE_P (TREE_TYPE (tem))
+ || (TREE_CODE (TREE_TYPE (tem)) == ARRAY_TYPE
+ && DECL_INITIAL (tem) != 0)))
expand_decl (tem);
}
const char *asmspec = 0;
/* If a name was specified, get the string. */
- if (current_binding_level == global_binding_level)
+ if (current_scope == global_scope)
asmspec_tree = maybe_apply_renaming_pragma (decl, asmspec_tree);
if (asmspec_tree)
asmspec = TREE_STRING_POINTER (asmspec_tree);
}
/* If #pragma weak was used, mark the decl weak now. */
- if (current_binding_level == global_binding_level)
+ if (current_scope == global_scope)
maybe_apply_pragma_weak (decl);
/* Output the assembler code and/or RTL code for variables and functions,
/* At the end of a declaration, throw away any variable type sizes
of types defined inside that declaration. There is no use
computing them in the following function definition. */
- if (current_binding_level == global_binding_level)
+ if (current_scope == global_scope)
get_pending_sizes ();
/* Install a cleanup (aka destructor) if one was given. */
}
/* Given a parsed parameter declaration,
- decode it into a PARM_DECL and push that on the current binding level.
+ 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'. */
push_parm_decl (tree parm)
{
tree decl;
- int old_immediate_size_expand = immediate_size_expand;
- /* Don't try computing parm sizes now -- wait till fn is called. */
+
+ /* Don't attempt to expand sizes while parsing this decl.
+ (We can get here with i_s_e 1 somehow from Objective-C.) */
+ int save_immediate_size_expand = immediate_size_expand;
immediate_size_expand = 0;
decl = grokdeclarator (TREE_VALUE (TREE_PURPOSE (parm)),
decl = pushdecl (decl);
- immediate_size_expand = old_immediate_size_expand;
-
- current_binding_level->parm_order
- = tree_cons (NULL_TREE, decl, current_binding_level->parm_order);
+ current_scope->parm_order
+ = tree_cons (NULL_TREE, decl, current_scope->parm_order);
- /* Add this decl to the current binding level. */
finish_decl (decl, NULL_TREE, NULL_TREE);
+
+ immediate_size_expand = save_immediate_size_expand;
}
/* Clear the given order of parms in `parm_order'.
void
clear_parm_order (void)
{
- current_binding_level->parm_order = NULL_TREE;
+ current_scope->parm_order = NULL_TREE;
}
\f
static GTY(()) int compound_literal_number;
tree stmt;
DECL_EXTERNAL (decl) = 0;
TREE_PUBLIC (decl) = 0;
- TREE_STATIC (decl) = (current_binding_level == global_binding_level);
+ TREE_STATIC (decl) = (current_scope == global_scope);
DECL_CONTEXT (decl) = current_function_decl;
TREE_USED (decl) = 1;
TREE_TYPE (decl) = type;
if (funcdef_flag && innermost_code != CALL_EXPR)
return 0;
- /* Anything declared one level down from the top level
- must be one of the parameters of a function
- (because the body is at least two levels down). */
-
/* If this looks like a function definition, make it one,
even if it occurs where parms are expected.
Then store_parm_decls will reject it and not use it as a parm. */
if (decl_context == NORMAL && !funcdef_flag
- && current_binding_level->parm_flag)
+ && current_scope->parm_flag)
decl_context = PARM;
/* Look through the decl specs and record which ones appear.
| (1 << (int) RID_THREAD))))
{
if (specbits & 1 << (int) RID_AUTO
- && (pedantic || current_binding_level == global_binding_level))
+ && (pedantic || current_scope == global_scope))
pedwarn ("function definition declared `auto'");
if (specbits & 1 << (int) RID_REGISTER)
error ("function definition declared `register'");
}
else if (specbits & 1 << (int) RID_EXTERN && initialized && ! funcdef_flag)
{
- /* `extern' with initialization is invalid if not at top level. */
- if (current_binding_level == global_binding_level)
+ /* `extern' with initialization is invalid if not at file scope. */
+ if (current_scope == global_scope)
warning ("`%s' initialized and declared `extern'", name);
else
error ("`%s' has both `extern' and initializer", name);
}
- else if (current_binding_level == global_binding_level)
+ else if (current_scope == global_scope)
{
if (specbits & 1 << (int) RID_AUTO)
- error ("top-level declaration of `%s' specifies `auto'", name);
+ error ("file-scope declaration of `%s' specifies `auto'", name);
}
else
{
if (VOID_TYPE_P (type) && decl_context != PARM
&& ! ((decl_context != FIELD && TREE_CODE (type) != FUNCTION_TYPE)
&& ((specbits & (1 << (int) RID_EXTERN))
- || (current_binding_level == global_binding_level
+ || (current_scope == global_scope
&& !(specbits
& ((1 << (int) RID_STATIC) | (1 << (int) RID_REGISTER)))))))
{
}
/* Move type qualifiers down to element of an array. */
if (TREE_CODE (type) == ARRAY_TYPE && type_quals)
- {
- type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
- type_quals),
- TYPE_DOMAIN (type));
- }
+ type = build_array_type (c_build_qualified_type (TREE_TYPE (type),
+ type_quals),
+ TYPE_DOMAIN (type));
decl = build_decl (FIELD_DECL, declarator, type);
DECL_NONADDRESSABLE_P (decl) = bitfield;
That is a case not specified by ANSI C,
and we use it for forward declarations for nested functions. */
int extern_ref = (!(specbits & (1 << (int) RID_AUTO))
- || current_binding_level == global_binding_level);
+ || current_scope == global_scope);
if (specbits & (1 << (int) RID_AUTO)
- && (pedantic || current_binding_level == global_binding_level))
+ && (pedantic || current_scope == global_scope))
pedwarn ("invalid storage class for function `%s'", name);
if (specbits & (1 << (int) RID_REGISTER))
error ("invalid storage class for function `%s'", name);
if (specbits & (1 << (int) RID_THREAD))
error ("invalid storage class for function `%s'", name);
- /* Function declaration not at top level.
+ /* Function declaration not at file scope.
Storage classes other than `extern' are not allowed
and `extern' makes no difference. */
- if (current_binding_level != global_binding_level
+ if (current_scope != global_scope
&& (specbits & ((1 << (int) RID_STATIC) | (1 << (int) RID_INLINE)))
&& pedantic)
pedwarn ("invalid storage class for function `%s'", name);
/* It is invalid to create an `extern' declaration for a
variable if there is a global declaration that is
`static'. */
- if (extern_ref && current_binding_level != global_binding_level)
+ if (extern_ref && current_scope != global_scope)
{
tree global_decl;
DECL_EXTERNAL (decl) = extern_ref;
- /* At top level, the presence of a `static' or `register' storage
+ /* At file scope, the presence of a `static' or `register' storage
class specifier, or the absence of all storage class specifiers
makes this declaration a definition (perhaps tentative). Also,
the absence of both `static' and `register' makes it public. */
- if (current_binding_level == global_binding_level)
+ if (current_scope == global_scope)
{
TREE_PUBLIC (decl) = !(specbits & ((1 << (int) RID_STATIC)
| (1 << (int) RID_REGISTER)));
TREE_STATIC (decl) = !extern_ref;
}
- /* Not at top level, only `static' makes a static definition. */
+ /* Not at file scope, only `static' makes a static definition. */
else
{
TREE_STATIC (decl) = (specbits & (1 << (int) RID_STATIC)) != 0;
These tags can never be defined in the scope of the declaration,
so the types can never be completed,
and no call can be compiled successfully. */
+
for (parm = last_function_parms, typelt = first_parm;
parm;
parm = TREE_CHAIN (parm))
}
/* Return a tree_list node with info on a parameter list just parsed.
- The TREE_PURPOSE is a chain of decls of those parms.
+ The TREE_PURPOSE is a list of decls of those parms.
The TREE_VALUE is a list of structure, union and enum tags defined.
The TREE_CHAIN is a list of argument types to go in the FUNCTION_TYPE.
This tree_list node is later fed to `grokparms'.
tree tags = gettags ();
tree parms = getdecls ();
tree new_parms = 0;
- tree order = current_binding_level->parm_order;
+ 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
new_parms = chainon (order ? nreverse (TREE_VALUE (order)) : 0,
new_parms);
- /* Store the parmlist in the binding level since the old one
+ /* 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);
tree elt;
static int already;
- for (elt = current_binding_level->tags; elt; elt = TREE_CHAIN (elt))
+ for (elt = current_scope->tags; elt; elt = TREE_CHAIN (elt))
{
enum tree_code code = TREE_CODE (TREE_VALUE (elt));
/* An anonymous union parm type is meaningful as a GNU extension.
/* If this is the right type of tag, return what we found.
(This reference will be shadowed by shadow_tag later if appropriate.)
If this is the wrong type of tag, do not return it. If it was the
- wrong type in the same binding level, we will have had an error
- message already; if in a different binding level and declaring
+ wrong type in the same scope, we will have had an error
+ message already; if in a different scope and declaring
a name, pending_xref_error will give an error message; but if in a
- different binding level and not declaring a name, this tag should
+ different scope and not declaring a name, this tag should
shadow the previous declaration of a different type of tag, and
this would not work properly if we return the reference found.
(For example, with "struct foo" in an outer scope, "union foo;"
return ref;
}
\f
-/* Make sure that the tag NAME is defined *in the current binding level*
+/* Make sure that the tag NAME is defined *in the current scope*
at least as a forward reference.
CODE says which kind of tag NAME ought to be. */
tree
start_struct (enum tree_code code, tree name)
{
- /* If there is already a tag defined at this binding level
+ /* If there is already a tag defined at this scope
(as a forward reference), just return it. */
tree ref = 0;
finish_struct (tree t, tree fieldlist, tree attributes)
{
tree x;
- int toplevel = global_binding_level == current_binding_level;
+ int toplevel = global_scope == current_scope;
int saw_named_field;
/* If this type was previously laid out as a forward reference,
if (DECL_INITIAL (x) && pedantic
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != integer_type_node
&& TYPE_MAIN_VARIANT (TREE_TYPE (x)) != unsigned_type_node
- && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != c_bool_type_node
+ && TYPE_MAIN_VARIANT (TREE_TYPE (x)) != boolean_type_node
/* Accept an enum that's equivalent to int or unsigned int. */
&& !(TREE_CODE (TREE_TYPE (x)) == ENUMERAL_TYPE
&& (TYPE_PRECISION (TREE_TYPE (x))
if (DECL_INITIAL (x))
{
int max_width
- = (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == c_bool_type_node
+ = (TYPE_MAIN_VARIANT (TREE_TYPE (x)) == boolean_type_node
? CHAR_TYPE_SIZE : TYPE_PRECISION (TREE_TYPE (x)));
if (tree_int_cst_sgn (DECL_INITIAL (x)) < 0)
{
field_array[len++] = x;
- /* if there is anonymous struct or union break out of the loop */
+ /* If there is anonymous struct or union, break out of the loop. */
if (DECL_NAME (x) == NULL)
break;
}
- /* found no anonymous struct/union add the TYPE_LANG_SPECIFIC. */
+ /* Found no anonymous struct/union. Add the TYPE_LANG_SPECIFIC. */
if (x == NULL)
{
TYPE_LANG_SPECIFIC (t) = space;
/* If this structure or union completes the type of any previous
variable declaration, lay it out and output its rtl. */
- if (current_binding_level->incomplete_list != NULL_TREE)
+ if (current_scope->incomplete_list != NULL_TREE)
{
tree prev = NULL_TREE;
- for (x = current_binding_level->incomplete_list; x; x = TREE_CHAIN (x))
+ for (x = current_scope->incomplete_list; x; x = TREE_CHAIN (x))
{
tree decl = TREE_VALUE (x);
if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (x);
else
- current_binding_level->incomplete_list = TREE_CHAIN (x);
+ current_scope->incomplete_list = TREE_CHAIN (x);
}
else if (!COMPLETE_TYPE_P (TREE_TYPE (decl))
&& TREE_CODE (TREE_TYPE (decl)) == ARRAY_TYPE)
if (prev)
TREE_CHAIN (prev) = TREE_CHAIN (x);
else
- current_binding_level->incomplete_list = TREE_CHAIN (x);
+ current_scope->incomplete_list = TREE_CHAIN (x);
}
}
}
tree pair, tem;
tree minnode = 0, maxnode = 0, enum_value_type;
int precision, unsign;
- int toplevel = (global_binding_level == current_binding_level);
+ int toplevel = (global_scope == current_scope);
if (in_parm_level_p ())
warning ("enum defined inside parms");
#endif
/* If #pragma weak was used, mark the decl weak now. */
- if (current_binding_level == global_binding_level)
+ if (current_scope == global_scope)
maybe_apply_pragma_weak (decl1);
/* Warn for unlikely, improbable, or stupid declarations of `main'. */
return 1;
}
\f
-/* Store the parameter declarations into the current function declaration.
- This is called after parsing the parameter declarations, before
- digesting the body of the function.
-
- For an old-style definition, modify the function's type
- to specify at least the number of arguments. */
-
-void
-store_parm_decls (void)
+/* Subroutine of store_parm_decls which handles new-style function
+ definitions (prototype format). The parms already have decls, so we
+ need only record them as in effect and complain if any redundant
+ old-style parm decls were written. */
+static void
+store_parm_decls_newstyle (void)
{
+ tree decl, next;
tree fndecl = current_function_decl;
- tree parm;
+ tree parms = current_function_parms;
+ tree tags = current_function_parm_tags;
- /* This is either a chain of PARM_DECLs (if a prototype was used)
- or a list of IDENTIFIER_NODEs (for an old-fashioned C definition). */
- tree specparms = current_function_parms;
+ /* This is anything which appeared in current_function_parms that
+ wasn't a PARM_DECL. */
+ tree nonparms = 0;
- /* This is a list of types declared among parms in a prototype. */
- tree parmtags = current_function_parm_tags;
+ if (current_scope->names || current_scope->tags)
+ {
+ error ("%Hold-style parameter declarations in prototyped "
+ "function definition", &DECL_SOURCE_LOCATION (fndecl));
- /* This is a chain of PARM_DECLs from old-style parm declarations. */
- tree parmdecls = getdecls ();
+ /* Get rid of the old-style declarations. */
+ poplevel (0, 0, 0);
+ pushlevel (0);
+ }
- /* This is a chain of any other decls that came in among the parm
- declarations. If a parm is declared with enum {foo, bar} x;
- then CONST_DECLs for foo and bar are put here. */
- tree nonparms = 0;
+ /* Now make all the parameter declarations visible in the function body. */
+ parms = nreverse (parms);
+ for (decl = parms; decl; decl = next)
+ {
+ next = TREE_CHAIN (decl);
+ if (TREE_CODE (decl) != PARM_DECL)
+ {
+ /* If we find an enum constant or a type tag,
+ put it aside for the moment. */
+ TREE_CHAIN (decl) = 0;
+ nonparms = chainon (nonparms, decl);
+ continue;
+ }
- /* The function containing FNDECL, if any. */
- tree context = decl_function_context (fndecl);
+ if (DECL_NAME (decl) == 0)
+ error ("%Hparameter name omitted", &DECL_SOURCE_LOCATION (decl));
+ else
+ pushdecl (decl);
+ }
- /* Nonzero if this definition is written with a prototype. */
- int prototype = 0;
+ /* Record the parameter list in the function declaration. */
+ DECL_ARGUMENTS (fndecl) = getdecls ();
- bool saved_warn_shadow = warn_shadow;
+ /* Now make all the ancillary declarations visible, likewise. */
+ for (decl = nonparms; decl; decl = TREE_CHAIN (decl))
+ if (DECL_NAME (decl) != 0
+ && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) != void_type_node)
+ pushdecl (decl);
- /* Don't re-emit shadow warnings. */
- warn_shadow = false;
+ /* And all the tag declarations. */
+ storetags (tags);
+}
- if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
- {
- /* This case is when the function was defined with an ANSI prototype.
- The parms already have decls, so we need not do anything here
- except record them as in effect
- and complain if any redundant old-style parm decls were written. */
+/* Subroutine of store_parm_decls which handles old-style function
+ definitions (separate parameter list and declarations). */
- tree next;
- tree others = 0;
+static void
+store_parm_decls_oldstyle (void)
+{
+ tree parm, decl, next;
+ tree fndecl = current_function_decl;
- prototype = 1;
+ /* This is the identifier list from the function declarator. */
+ tree parmids = current_function_parms;
- if (parmdecls != 0)
+ /* This is anything which appeared in current_scope->names that
+ wasn't a PARM_DECL. */
+ tree nonparms;
+
+ /* We use DECL_WEAK as a flag to show which parameters have been
+ seen already, since it is not used on PARM_DECL or CONST_DECL. */
+ for (parm = current_scope->names; parm; parm = TREE_CHAIN (parm))
+ DECL_WEAK (parm) = 0;
+
+ /* Match each formal parameter name with its declaration. Save each
+ decl in the appropriate TREE_PURPOSE slot of the parmids chain. */
+ for (parm = parmids; parm; parm = TREE_CHAIN (parm))
+ {
+ if (TREE_VALUE (parm) == 0)
{
- tree decl, link;
-
- error ("%Hparm types given both in parmlist and separately",
- &DECL_SOURCE_LOCATION (fndecl));
- /* Get rid of the erroneous decls; don't keep them on
- the list of parms, since they might not be PARM_DECLs. */
- for (decl = current_binding_level->names;
- decl; decl = TREE_CHAIN (decl))
- if (DECL_NAME (decl))
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = 0;
- for (link = current_binding_level->shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- current_binding_level->names = 0;
- current_binding_level->shadowed = 0;
+ error ("%Hparameter name missing from parameter list",
+ &DECL_SOURCE_LOCATION (fndecl));
+ TREE_PURPOSE (parm) = 0;
+ continue;
}
- specparms = nreverse (specparms);
- for (parm = specparms; parm; parm = next)
+ decl = IDENTIFIER_SYMBOL_VALUE (TREE_VALUE (parm));
+ if (decl && DECL_CONTEXT (decl) == fndecl)
{
- const location_t *locus = &DECL_SOURCE_LOCATION (parm);
- next = TREE_CHAIN (parm);
- if (TREE_CODE (parm) == PARM_DECL)
+ const location_t *locus = &DECL_SOURCE_LOCATION (decl);
+ /* If we got something other than a PARM_DECL it is an error. */
+ if (TREE_CODE (decl) != PARM_DECL)
+ error ("%H\"%D\" declared as a non-parameter", locus, decl);
+ /* If the declaration is already marked, we have a duplicate
+ name. Complain and ignore the duplicate. */
+ else if (DECL_WEAK (decl))
{
- if (DECL_NAME (parm) == 0)
- error ("%Hparameter name omitted", locus);
- else if (TREE_CODE (TREE_TYPE (parm)) != ERROR_MARK
- && VOID_TYPE_P (TREE_TYPE (parm)))
- {
- error ("%Hparameter '%D' declared void", locus, parm);
- /* Change the type to error_mark_node so this parameter
- will be ignored by assign_parms. */
- TREE_TYPE (parm) = error_mark_node;
- }
- pushdecl (parm);
+ error ("%Hmultiple parameters named \"%D\"", locus, decl);
+ TREE_PURPOSE (parm) = 0;
+ continue;
}
- else
+ /* If the declaration says "void", complain and turn it into
+ an int. */
+ else if (VOID_TYPE_P (TREE_TYPE (decl)))
{
- /* If we find an enum constant or a type tag,
- put it aside for the moment. */
- TREE_CHAIN (parm) = 0;
- others = chainon (others, parm);
+ error ("%Hparameter \"%D\" declared void", locus, decl);
+ TREE_TYPE (decl) = integer_type_node;
+ DECL_ARG_TYPE (decl) = integer_type_node;
+ layout_decl (decl, 0);
}
}
-
- /* Get the decls in their original chain order
- and record in the function. */
- DECL_ARGUMENTS (fndecl) = getdecls ();
-
- /* Now pushdecl the enum constants. */
- for (parm = others; parm; parm = next)
+ /* If no declaration found, default to int. */
+ else
{
- next = TREE_CHAIN (parm);
- if (DECL_NAME (parm) == 0)
- ;
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
- ;
- else if (TREE_CODE (parm) != PARM_DECL)
- pushdecl (parm);
+ const location_t *locus = &DECL_SOURCE_LOCATION (fndecl);
+ decl = build_decl (PARM_DECL, TREE_VALUE (parm), integer_type_node);
+ DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
+ DECL_SOURCE_LOCATION (decl) = *locus;
+ pushdecl (decl);
+
+ if (flag_isoc99)
+ pedwarn ("%Htype of \"%D\" defaults to \"int\"", locus, decl);
+ else if (extra_warnings)
+ warning ("%Htype of \"%D\" defaults to \"int\"", locus, decl);
}
- storetags (chainon (parmtags, gettags ()));
+ TREE_PURPOSE (parm) = decl;
+ DECL_WEAK (decl) = 1;
}
- else
- {
- /* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
- each with a parm name as the TREE_VALUE.
- PARMDECLS is a chain of declarations for parameters.
- Warning! It can also contain CONST_DECLs which are not parameters
- but are names of enumerators of any enum types
- declared among the parameters.
+ /* 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. */
- First match each formal parameter name with its declaration.
- Associate decls with the names and store the decls
- into the TREE_PURPOSE slots. */
-
- /* We use DECL_WEAK as a flag to show which parameters have been
- seen already since it is not used on PARM_DECL or CONST_DECL. */
- for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
- DECL_WEAK (parm) = 0;
+ nonparms = 0;
+ for (parm = current_scope->names; parm; parm = next)
+ {
+ const location_t *locus = &DECL_SOURCE_LOCATION (parm);
+ next = TREE_CHAIN (parm);
+ TREE_CHAIN (parm) = 0;
- for (parm = specparms; parm; parm = TREE_CHAIN (parm))
+ if (TREE_CODE (parm) != PARM_DECL)
{
- tree tail, found = NULL;
-
- if (TREE_VALUE (parm) == 0)
- {
- error ("%Hparameter name missing from parameter list",
- &DECL_SOURCE_LOCATION (fndecl));
- TREE_PURPOSE (parm) = 0;
- continue;
- }
-
- /* See if any of the parmdecls specifies this parm by name.
- Ignore any enumerator decls. */
- for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
- if (DECL_NAME (tail) == TREE_VALUE (parm)
- && TREE_CODE (tail) == PARM_DECL)
- {
- found = tail;
- break;
- }
-
- /* If declaration already marked, we have a duplicate name.
- Complain, and don't use this decl twice. */
- if (found && DECL_WEAK (found))
- {
- error ("%Hmultiple parameters named '%D'",
- &DECL_SOURCE_LOCATION (found), found);
- found = 0;
- }
-
- /* If the declaration says "void", complain and ignore it. */
- if (found && VOID_TYPE_P (TREE_TYPE (found)))
- {
- error ("%Hparameter '%D' declared void",
- &DECL_SOURCE_LOCATION (found), found);
- TREE_TYPE (found) = integer_type_node;
- DECL_ARG_TYPE (found) = integer_type_node;
- layout_decl (found, 0);
- }
-
- /* If no declaration found, default to int. */
- if (!found)
- {
- found = build_decl (PARM_DECL, TREE_VALUE (parm),
- integer_type_node);
- DECL_ARG_TYPE (found) = TREE_TYPE (found);
- DECL_SOURCE_LOCATION (found) = DECL_SOURCE_LOCATION (fndecl);
- if (flag_isoc99)
- pedwarn ("%Htype of '%D' defaults to `int'",
- &DECL_SOURCE_LOCATION (found), found);
- else if (extra_warnings)
- warning ("%Htype of '%D' defaults to `int'",
- &DECL_SOURCE_LOCATION (found), found);
- pushdecl (found);
- }
-
- TREE_PURPOSE (parm) = found;
-
- /* Mark this decl as "already found". */
- DECL_WEAK (found) = 1;
+ nonparms = chainon (nonparms, parm);
+ continue;
}
- /* Put anything which is on the parmdecls chain and which is
- not a PARM_DECL onto the list NONPARMS. (The types of
- non-parm things which might appear on the list include
- enumerators and NULL-named TYPE_DECL nodes.) Complain about
- any actual PARM_DECLs not matched with any names. */
-
- nonparms = 0;
- for (parm = parmdecls; parm;)
+ if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
- const location_t *locus = &DECL_SOURCE_LOCATION (parm);
- tree next = TREE_CHAIN (parm);
- TREE_CHAIN (parm) = 0;
-
- if (TREE_CODE (parm) != PARM_DECL)
- nonparms = chainon (nonparms, parm);
- else
- {
- /* Complain about args with incomplete types. */
- if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
- {
- error ("%Hparameter '%D' has incomplete type", locus, parm);
- TREE_TYPE (parm) = error_mark_node;
- }
+ error ("%Hparameter \"%D\" has incomplete type", locus, parm);
+ TREE_TYPE (parm) = error_mark_node;
+ }
- if (! DECL_WEAK (parm))
- {
- error ("%Hdeclaration for parameter '%D' but no such "
- "parameter", locus, parm);
- /* Pretend the parameter was not missing.
- This gets us to a standard state and minimizes
- further error messages. */
- specparms
- = chainon (specparms,
- tree_cons (parm, NULL_TREE, NULL_TREE));
- }
- }
+ if (! DECL_WEAK (parm))
+ {
+ error ("%Hdeclaration for parameter \"%D\" but no such parameter",
+ locus, parm);
- parm = next;
+ /* Pretend the parameter was not missing.
+ This gets us to a standard state and minimizes
+ further error messages. */
+ parmids = chainon (parmids, tree_cons (parm, 0, 0));
}
+ }
- /* Chain the declarations together in the order of the list of
- names. Store that chain in the function decl, replacing the
- list of names. */
- parm = specparms;
- DECL_ARGUMENTS (fndecl) = 0;
+ /* Chain the declarations together in the order of the list of
+ names. Store that chain in the function decl, replacing the
+ list of names. */
+ DECL_ARGUMENTS (fndecl) = 0;
+ {
+ tree last;
+ for (parm = parmids; parm; parm = TREE_CHAIN (parm))
+ if (TREE_PURPOSE (parm))
+ break;
+ if (parm && TREE_PURPOSE (parm))
{
- tree last;
- for (last = 0; parm; parm = TREE_CHAIN (parm))
+ last = TREE_PURPOSE (parm);
+ DECL_ARGUMENTS (fndecl) = last;
+ DECL_WEAK (last) = 0;
+
+ for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
if (TREE_PURPOSE (parm))
{
- if (last == 0)
- DECL_ARGUMENTS (fndecl) = TREE_PURPOSE (parm);
- else
- TREE_CHAIN (last) = TREE_PURPOSE (parm);
+ TREE_CHAIN (last) = TREE_PURPOSE (parm);
last = TREE_PURPOSE (parm);
- TREE_CHAIN (last) = 0;
+ DECL_WEAK (last) = 0;
}
+ TREE_CHAIN (last) = 0;
}
+ }
- /* If there was a previous prototype,
- set the DECL_ARG_TYPE of each argument according to
- the type previously specified, and report any mismatches. */
+ /* If there was a previous prototype,
+ set the DECL_ARG_TYPE of each argument according to
+ the type previously specified, and report any mismatches. */
- if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+ if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+ {
+ tree type;
+ for (parm = DECL_ARGUMENTS (fndecl),
+ type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
+ != void_type_node));
+ parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
{
- tree type;
- for (parm = DECL_ARGUMENTS (fndecl),
- type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
- != void_type_node));
- parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
+ if (parm == 0 || type == 0
+ || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
- if (parm == 0 || type == 0
- || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
- {
- error ("number of arguments doesn't match prototype");
- error ("%Hprototype declaration",
- ¤t_function_prototype_locus);
- break;
- }
- /* Type for passing arg must be consistent with that
- declared for the arg. ISO C says we take the unqualified
- type for parameters declared with qualified type. */
- if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
- TYPE_MAIN_VARIANT (TREE_VALUE (type)),
- COMPARE_STRICT))
+ error ("number of arguments doesn't match prototype");
+ error ("%Hprototype declaration",
+ ¤t_function_prototype_locus);
+ break;
+ }
+ /* Type for passing arg must be consistent with that
+ declared for the arg. ISO C says we take the unqualified
+ type for parameters declared with qualified type. */
+ if (! comptypes (TYPE_MAIN_VARIANT (DECL_ARG_TYPE (parm)),
+ TYPE_MAIN_VARIANT (TREE_VALUE (type)),
+ COMPARE_STRICT))
+ {
+ if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
+ == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
{
- if (TYPE_MAIN_VARIANT (TREE_TYPE (parm))
- == TYPE_MAIN_VARIANT (TREE_VALUE (type)))
- {
- /* Adjust argument to match prototype. E.g. a previous
- `int foo(float);' prototype causes
- `int foo(x) float x; {...}' to be treated like
- `int foo(float x) {...}'. This is particularly
- useful for argument types like uid_t. */
- DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
-
- if (PROMOTE_PROTOTYPES
- && INTEGRAL_TYPE_P (TREE_TYPE (parm))
- && TYPE_PRECISION (TREE_TYPE (parm))
- < TYPE_PRECISION (integer_type_node))
- DECL_ARG_TYPE (parm) = integer_type_node;
-
- if (pedantic)
- {
- pedwarn ("promoted argument `%s' doesn't match prototype",
- IDENTIFIER_POINTER (DECL_NAME (parm)));
- warning ("%Hprototype declaration",
- ¤t_function_prototype_locus);
- }
- }
- else
+ /* Adjust argument to match prototype. E.g. a previous
+ `int foo(float);' prototype causes
+ `int foo(x) float x; {...}' to be treated like
+ `int foo(float x) {...}'. This is particularly
+ useful for argument types like uid_t. */
+ DECL_ARG_TYPE (parm) = TREE_TYPE (parm);
+
+ if (PROMOTE_PROTOTYPES
+ && INTEGRAL_TYPE_P (TREE_TYPE (parm))
+ && TYPE_PRECISION (TREE_TYPE (parm))
+ < TYPE_PRECISION (integer_type_node))
+ DECL_ARG_TYPE (parm) = integer_type_node;
+
+ if (pedantic)
{
- error ("argument `%s' doesn't match prototype",
- IDENTIFIER_POINTER (DECL_NAME (parm)));
- error ("%Hprototype declaration",
- ¤t_function_prototype_locus);
+ pedwarn ("promoted argument \"%D\" "
+ "doesn't match prototype", parm);
+ pedwarn ("%Hprototype declaration",
+ ¤t_function_prototype_locus);
}
}
+ else
+ {
+ error ("argument \"%D\" doesn't match prototype", parm);
+ error ("%Hprototype declaration",
+ ¤t_function_prototype_locus);
+ }
}
- TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0;
}
+ TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = 0;
+ }
- /* Otherwise, create a prototype that would match. */
+ /* Otherwise, create a prototype that would match. */
- else
- {
- tree actual = 0, last = 0, type;
+ else
+ {
+ tree actual = 0, last = 0, type;
- for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
- {
- type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
- if (last)
- TREE_CHAIN (last) = type;
- else
- actual = type;
- last = type;
- }
- type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+ for (parm = DECL_ARGUMENTS (fndecl); parm; parm = TREE_CHAIN (parm))
+ {
+ type = tree_cons (NULL_TREE, DECL_ARG_TYPE (parm), NULL_TREE);
if (last)
TREE_CHAIN (last) = type;
else
actual = type;
+ last = type;
+ }
+ type = tree_cons (NULL_TREE, void_type_node, NULL_TREE);
+ if (last)
+ TREE_CHAIN (last) = type;
+ else
+ actual = type;
- /* We are going to assign a new value for the TYPE_ACTUAL_ARG_TYPES
- of the type of this function, but we need to avoid having this
- affect the types of other similarly-typed functions, so we must
- first force the generation of an identical (but separate) type
- node for the relevant function type. The new node we create
- will be a variant of the main variant of the original function
- type. */
+ /* We are going to assign a new value for the TYPE_ACTUAL_ARG_TYPES
+ of the type of this function, but we need to avoid having this
+ affect the types of other similarly-typed functions, so we must
+ first force the generation of an identical (but separate) type
+ node for the relevant function type. The new node we create
+ will be a variant of the main variant of the original function
+ type. */
- TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl));
+ TREE_TYPE (fndecl) = build_type_copy (TREE_TYPE (fndecl));
- TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
- }
+ TYPE_ACTUAL_ARG_TYPES (TREE_TYPE (fndecl)) = actual;
+ }
- /* Now store the final chain of decls for the arguments
- as the decl-chain of the current lexical scope.
- Put the enumerators in as well, at the front so that
- DECL_ARGUMENTS is not modified. */
+ /* Now store the final chain of decls for the arguments
+ as the decl-chain of the current lexical scope.
+ Put the enumerators in as well, at the front so that
+ DECL_ARGUMENTS is not modified. */
- storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
- }
+ storedecls (chainon (nonparms, DECL_ARGUMENTS (fndecl)));
+}
+
+/* Store the parameter declarations into the current function declaration.
+ This is called after parsing the parameter declarations, before
+ digesting the body of the function.
- /* Make sure the binding level for the top of the function body
- gets a BLOCK if there are any in the function.
- Otherwise, the dbx output is wrong. */
+ For an old-style definition, construct a prototype out of the old-style
+ parameter declarations and inject it into the function's type. */
- keep_next_if_subblocks = 1;
+void
+store_parm_decls (void)
+{
+ tree fndecl = current_function_decl;
+
+ /* The function containing FNDECL, if any. */
+ tree context = decl_function_context (fndecl);
+
+ /* True if this definition is written with a prototype. */
+ bool prototype = (current_function_parms
+ && TREE_CODE (current_function_parms) != TREE_LIST);
+
+ /* Don't re-emit shadow warnings. */
+ bool saved_warn_shadow = warn_shadow;
+ warn_shadow = false;
+
+ if (prototype)
+ store_parm_decls_newstyle ();
+ else
+ store_parm_decls_oldstyle ();
+
+ /* The next call to pushlevel will be a function body. */
+
+ next_is_function_body = true;
/* Write a record describing this function definition to the prototypes
file (if requested). */
init_function_start (fndecl);
/* Begin the statement tree for this function. */
- begin_stmt_tree (&DECL_SAVED_TREE (current_function_decl));
+ begin_stmt_tree (&DECL_SAVED_TREE (fndecl));
/* If this is a nested function, save away the sizes of any
variable-size types so that we can expand them when generating
void foo(void) { }
(the argument list is irrelevant) the compstmt rule will not
bother calling pushlevel/poplevel, which means we get here with
- the binding_level stack out of sync. Detect this situation by
- noticing that the current_binding_level is still as
- store_parm_decls left it, and do a dummy push/pop to get back to
- consistency. Note that the call to pushlevel does not actually
- push another binding level - see there for details. */
- if (current_binding_level->parm_flag && keep_next_if_subblocks)
+ the scope stack out of sync. Detect this situation by noticing
+ that current_scope is still as store_parm_decls left it, and do
+ a dummy push/pop to get back to consistency.
+ Note that the call to pushlevel does not actually push another
+ scope - see there for details. */
+
+ if (current_scope->parm_flag && next_is_function_body)
{
pushlevel (0);
- poplevel (1, 0, 1);
+ poplevel (0, 0, 0);
}
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
to run global initializers, etc. */
if (DECL_NAME (fndecl)
&& MAIN_NAME_P (DECL_NAME (fndecl))
- && DECL_CONTEXT (fndecl) == NULL_TREE)
+ && C_DECL_FILE_SCOPE (fndecl))
expand_main_function ();
/* Generate the RTL for this function. */
int returns_abnormally;
int warn_about_return_type;
int extern_inline;
- struct binding_level *binding_level;
};
/* Save and reinitialize the variables
p->returns_abnormally = current_function_returns_abnormally;
p->warn_about_return_type = warn_about_return_type;
p->extern_inline = current_extern_inline;
- p->binding_level = current_binding_level;
}
/* Restore the variables used during compilation of a C function. */
current_function_returns_abnormally = p->returns_abnormally;
warn_about_return_type = p->warn_about_return_type;
current_extern_inline = p->extern_inline;
- current_binding_level = p->binding_level;
f->language = NULL;
}
return decl;
/* Shadowed by something else; find the true global value. */
- for (decl = global_binding_level->names; decl; decl = TREE_CHAIN (decl))
+ for (decl = global_scope->names; decl; decl = TREE_CHAIN (decl))
if (DECL_NAME (decl) == t)
return decl;
}
/* A wrapper around lhd_set_decl_assembler_name that gives static
- variables their C names if they are at the top level and only one
+ variables their C names if they are at file scope and only one
translation unit is being compiled, for backwards compatibility
with certain bizzare assembler hacks (like crtstuff.c). */
c_static_assembler_name (tree decl)
{
if (num_in_fnames == 1
- && TREE_STATIC (decl) && !TREE_PUBLIC (decl) && DECL_CONTEXT (decl)
+ && !TREE_PUBLIC (decl) && DECL_CONTEXT (decl)
&& TREE_CODE (DECL_CONTEXT (decl)) == TRANSLATION_UNIT_DECL)
SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
else
/* Create the BLOCK that poplevel would have created, but don't
actually call poplevel since that's expensive. */
block = make_node (BLOCK);
- BLOCK_VARS (block) = current_binding_level->names;
+ BLOCK_VARS (block) = current_scope->names;
TREE_USED (block) = 1;
DECL_INITIAL (current_file_decl) = block;
tree link;
tree file_scope_decl;
- /* Pop the global binding level. */
- if (current_binding_level != global_binding_level)
- current_binding_level = global_binding_level;
+ /* Pop the global scope. */
+ if (current_scope != global_scope)
+ current_scope = global_scope;
file_scope_decl = current_file_decl;
DECL_INITIAL (file_scope_decl) = poplevel (1, 0, 0);
truly_local_externals = NULL_TREE;
/* Start a new global binding level. */
pushlevel (0);
- global_binding_level = current_binding_level;
+ global_scope = current_scope;
current_file_decl = build_decl (TRANSLATION_UNIT_DECL, NULL, NULL);
TREE_CHAIN (current_file_decl) = file_scope_decl;