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;
*/
struct c_scope GTY(())
- {
- /* A chain of _DECL nodes for all variables, constants, functions,
- and typedef types. These are in the reverse of the order supplied.
- */
- tree names;
-
- /* A list of structure, union and enum definitions,
- * for looking up tag names.
- * It is a chain of TREE_LIST nodes, each of whose TREE_PURPOSE is a name,
- * or NULL_TREE; and whose TREE_VALUE is a RECORD_TYPE, UNION_TYPE,
- * or ENUMERAL_TYPE node.
- */
- tree tags;
-
- /* For each scope, a list of shadowed outer-scope definitions
- to be restored when this scope is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
- tree shadowed;
-
- /* For each scope, a list of shadowed outer-scope tag definitions
- to be restored when this scope is popped.
- Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
- whose TREE_VALUE is its old definition (a kind of ..._TYPE node). */
- tree shadowed_tags;
-
- /* For each scope (except not the global one),
- a chain of BLOCK nodes for all the scopes
- that were entered and exited one level down. */
- tree blocks;
-
- /* The scope containing this one. */
- struct c_scope *outer;
-
- /* The next outermost function scope. */
- struct c_scope *outer_function;
-
- /* True if we are currently filling this scope with parameter
- declarations. */
- bool parm_flag : 1;
-
- /* True if this is the outermost block scope of a function body.
- This scope contains both the parameters and the local variables
- declared in the outermost block. */
- bool function_body : 1;
-
- /* True means make a BLOCK for this scope regardless of all else. */
- bool keep : 1;
-
- /* True means make a BLOCK if this scope has any subblocks. */
- bool keep_if_subblocks : 1;
-
- /* List of decls in `names' that have incomplete structure or
- union types. */
- tree incomplete_list;
-
- /* A list of decls giving the (reversed) specified order of parms,
- not including any forward-decls in the parmlist.
- This is so we can put the parms in proper order for assign_parms. */
- tree parm_order;
- };
+{
+ /* The scope containing this one. */
+ struct c_scope *outer;
+
+ /* The next outermost function scope. */
+ struct c_scope *outer_function;
+
+ /* All variables, constants, functions, labels, and typedef names.
+ They are in the reverse of the order supplied. */
+ tree names;
+
+ /* All structure, union, and enum type tags. */
+ tree tags;
+
+ /* For each scope, a list of shadowed outer-scope definitions
+ to be restored when this scope is popped.
+ Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
+ whose TREE_VALUE is its old definition (a kind of ..._DECL node). */
+ tree shadowed;
+
+ /* For each scope, a list of shadowed outer-scope tag definitions
+ to be restored when this scope is popped.
+ Each link is a TREE_LIST whose TREE_PURPOSE is an identifier and
+ whose TREE_VALUE is its old definition (a kind of ..._TYPE node). */
+ tree shadowed_tags;
+
+ /* For each scope (except the global one), a chain of BLOCK nodes
+ for all the scopes that were entered and exited one level down. */
+ tree blocks;
+
+ /* Variable declarations with incomplete type in this scope. */
+ tree incomplete_list;
+
+ /* A list of decls giving the (reversed) specified order of parms,
+ not including any forward-decls in the parmlist.
+ This is so we can put the parms in proper order for assign_parms. */
+ tree parm_order;
+
+ /* True if we are currently filling this scope with parameter
+ declarations. */
+ bool parm_flag : 1;
+
+ /* True if this is the outermost block scope of a function body.
+ This scope contains the parameters, the local variables declared
+ in the outermost block, and all the labels (except those in
+ nested functions, or declared at block scope with __label__). */
+ bool function_body : 1;
+
+ /* True means make a BLOCK for this scope no matter what. */
+ bool keep : 1;
+};
/* The scope currently in effect. */
/* The innermost function scope. Ordinary (not explicitly declared)
labels, bindings to error_mark_node, and the lazily-created
bindings of __func__ and its friends get this scope. */
+
static GTY(()) struct c_scope *current_function_scope;
/* The outermost scope, corresponding to the C "file scope". This is
static bool keep_next_level_flag;
-/* True means make a BLOCK for the next scope pushed if it has subblocks. */
+/* True means the next call to pushlevel will be the outermost scope
+ of a function body, so do not push a new scope, merely cease
+ expecting parameter decls. */
-static bool keep_next_if_subblocks;
+static bool next_is_function_body;
/* Functions called automatically at the beginning and end of execution. */
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);
return current_scope->parm_flag;
}
-/* Enter a new scope. */
+/* Enter a new scope. The dummy parameter is for signature
+ compatibility with lang_hooks.decls.pushlevel. */
void
pushlevel (int dummy ATTRIBUTE_UNUSED)
{
- if (keep_next_if_subblocks)
+ if (next_is_function_body)
{
/* This is the transition from the parameters to the top level
of the function body. These are the same scope
(C99 6.2.1p4,6) so we do not push another scope structure.
+ next_is_function_body is set only by store_parm_decls, which
+ in turn is called when and only when we are about to
+ encounter the opening curly brace for the function body.
- XXX Note kludge - keep_next_if_subblocks is set only by
- store_parm_decls, which in turn is called when and only
- when we are about to encounter the opening curly brace for
- the function body. */
+ The outermost block of a function always gets a BLOCK node,
+ because the debugging output routines expect that each
+ function has at least one BLOCK. */
current_scope->parm_flag = false;
current_scope->function_body = true;
- current_scope->keep |= keep_next_level_flag;
- current_scope->keep_if_subblocks = true;
+ current_scope->keep = true;
current_scope->outer_function = current_function_scope;
current_function_scope = current_scope;
keep_next_level_flag = false;
- keep_next_if_subblocks = false;
+ next_is_function_body = false;
}
else
{
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)
if (keep == KEEP_MAYBE)
keep = (current_scope->names || current_scope->tags);
-
- keep |= (current_scope->keep || functionbody
- || (subblocks && current_scope->keep_if_subblocks));
+
+ keep |= current_scope->keep;
+ keep |= functionbody;
/* We used to warn about unused variables in expand_end_bindings,
i.e. while generating RTL. But in function-at-a-time mode we may
{
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;
/* 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_scope->outer->parm_flag))
+ || (TREE_CODE (x) == PARM_DECL && current_scope->outer->parm_flag))
return;
name = IDENTIFIER_POINTER (DECL_NAME (x));
-
if (TREE_CODE (old) == PARM_DECL)
shadow_warning (SW_PARAM, name, old);
else if (C_DECL_FILE_SCOPE (old))
/* 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)))
{
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. */
/* No label binding for that identifier; make one. */
label = make_label (name, input_location);
- /* Ordinary labels go in the current function scope, which is
- not necessarily the current label scope. */
+ /* Ordinary labels go in the current function scope. */
bind_label (name, label, current_function_scope);
return label;
}
|| (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. */
+ /* Ordinary labels go in the current function scope. */
bind_label (name, label, current_function_scope);
}
}
\f
/* Return the list of declarations of the current scope.
- Note that this list is in reverse order unless/until
- you nreverse it; and when you do nreverse it, you must
- store the result back using `storedecls' or you will lose. */
+ Note that this list is in reverse order. */
tree
getdecls (void)
/* Adds some ggc roots, and reserved words for c-parse.in. */
c_parse_init ();
- current_function_decl = NULL;
- current_scope = NULL;
- current_function_scope = NULL;
- scope_freelist = NULL;
+ current_function_decl = 0;
/* Make the c_scope structure for global names. */
pushlevel (0);
global_scope = current_scope;
+
/* Declarations from c_common_nodes_and_builtins must not be associated
with this input file, lest we get differences between using and not
using preprocessed headers. */
&& 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);
}
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_scope->parm_order
= tree_cons (NULL_TREE, decl, current_scope->parm_order);
- /* Add this decl to the current scope. */
finish_decl (decl, NULL_TREE, NULL_TREE);
+
+ immediate_size_expand = save_immediate_size_expand;
}
/* Clear the given order of parms in `parm_order'.
}
/* 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;
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'.
return 1;
}
\f
-/* Store the parameter declarations into the current function declaration.
- This is called after parsing the parameter declarations, before
- digesting the body of the function.
-
- For an old-style definition, modify the function's type
- to specify at least the number of arguments. */
-
-void
-store_parm_decls (void)
+/* Subroutine of store_parm_decls which handles new-style function
+ definitions (prototype format). The parms already have decls, so we
+ need only record them as in effect and complain if any redundant
+ old-style parm decls were written. */
+static void
+store_parm_decls_newstyle (void)
{
+ tree decl, next;
tree fndecl = current_function_decl;
- tree parm;
+ tree parms = current_function_parms;
+ tree tags = current_function_parm_tags;
- /* This is either a chain of PARM_DECLs (if a prototype was used)
- or a list of IDENTIFIER_NODEs (for an old-fashioned C definition). */
- tree specparms = current_function_parms;
+ /* This is anything which appeared in current_function_parms that
+ wasn't a PARM_DECL. */
+ tree nonparms = 0;
- /* This is a list of types declared among parms in a prototype. */
- tree parmtags = current_function_parm_tags;
+ if (current_scope->names || current_scope->tags)
+ {
+ error ("%Hold-style parameter declarations in prototyped "
+ "function definition", &DECL_SOURCE_LOCATION (fndecl));
- /* This is a chain of PARM_DECLs from old-style parm declarations. */
- tree parmdecls = getdecls ();
+ /* Get rid of the old-style declarations. */
+ poplevel (0, 0, 0);
+ pushlevel (0);
+ }
- /* This is a chain of any other decls that came in among the parm
- declarations. If a parm is declared with enum {foo, bar} x;
- then CONST_DECLs for foo and bar are put here. */
- tree nonparms = 0;
+ /* Now make all the parameter declarations visible in the function body. */
+ parms = nreverse (parms);
+ for (decl = parms; decl; decl = next)
+ {
+ next = TREE_CHAIN (decl);
+ if (TREE_CODE (decl) != PARM_DECL)
+ {
+ /* If we find an enum constant or a type tag,
+ put it aside for the moment. */
+ TREE_CHAIN (decl) = 0;
+ nonparms = chainon (nonparms, decl);
+ continue;
+ }
- /* The function containing FNDECL, if any. */
- tree context = decl_function_context (fndecl);
+ if (DECL_NAME (decl) == 0)
+ error ("%Hparameter name omitted", &DECL_SOURCE_LOCATION (decl));
+ else
+ pushdecl (decl);
+ }
- /* Nonzero if this definition is written with a prototype. */
- int prototype = 0;
+ /* Record the parameter list in the function declaration. */
+ DECL_ARGUMENTS (fndecl) = getdecls ();
- bool saved_warn_shadow = warn_shadow;
+ /* Now make all the ancillary declarations visible, likewise. */
+ for (decl = nonparms; decl; decl = TREE_CHAIN (decl))
+ if (DECL_NAME (decl) != 0
+ && TYPE_MAIN_VARIANT (TREE_TYPE (decl)) != void_type_node)
+ pushdecl (decl);
- /* Don't re-emit shadow warnings. */
- warn_shadow = false;
+ /* And all the tag declarations. */
+ storetags (tags);
+}
- if (specparms != 0 && TREE_CODE (specparms) != TREE_LIST)
- {
- /* This case is when the function was defined with an ANSI prototype.
- The parms already have decls, so we need not do anything here
- except record them as in effect
- and complain if any redundant old-style parm decls were written. */
+/* Subroutine of store_parm_decls which handles old-style function
+ definitions (separate parameter list and declarations). */
- tree next;
- tree others = 0;
+static void
+store_parm_decls_oldstyle (void)
+{
+ tree parm, decl, next;
+ tree fndecl = current_function_decl;
- prototype = 1;
+ /* This is the identifier list from the function declarator. */
+ tree parmids = current_function_parms;
- if (parmdecls != 0)
+ /* This is anything which appeared in current_scope->names that
+ wasn't a PARM_DECL. */
+ tree nonparms;
+
+ /* We use DECL_WEAK as a flag to show which parameters have been
+ seen already, since it is not used on PARM_DECL or CONST_DECL. */
+ for (parm = current_scope->names; parm; parm = TREE_CHAIN (parm))
+ DECL_WEAK (parm) = 0;
+
+ /* Match each formal parameter name with its declaration. Save each
+ decl in the appropriate TREE_PURPOSE slot of the parmids chain. */
+ for (parm = parmids; parm; parm = TREE_CHAIN (parm))
+ {
+ if (TREE_VALUE (parm) == 0)
{
- tree decl, link;
-
- error ("%Hparm types given both in parmlist and separately",
- &DECL_SOURCE_LOCATION (fndecl));
- /* Get rid of the erroneous decls; don't keep them on
- the list of parms, since they might not be PARM_DECLs. */
- for (decl = current_scope->names;
- decl; decl = TREE_CHAIN (decl))
- if (DECL_NAME (decl))
- IDENTIFIER_SYMBOL_VALUE (DECL_NAME (decl)) = 0;
- for (link = current_scope->shadowed;
- link; link = TREE_CHAIN (link))
- IDENTIFIER_SYMBOL_VALUE (TREE_PURPOSE (link)) = TREE_VALUE (link);
- current_scope->names = 0;
- current_scope->shadowed = 0;
+ error ("%Hparameter name missing from parameter list",
+ &DECL_SOURCE_LOCATION (fndecl));
+ TREE_PURPOSE (parm) = 0;
+ continue;
}
- specparms = nreverse (specparms);
- for (parm = specparms; parm; parm = next)
+ decl = IDENTIFIER_SYMBOL_VALUE (TREE_VALUE (parm));
+ if (decl && DECL_CONTEXT (decl) == fndecl)
{
- const location_t *locus = &DECL_SOURCE_LOCATION (parm);
- next = TREE_CHAIN (parm);
- if (TREE_CODE (parm) == PARM_DECL)
+ const location_t *locus = &DECL_SOURCE_LOCATION (decl);
+ /* If we got something other than a PARM_DECL it is an error. */
+ if (TREE_CODE (decl) != PARM_DECL)
+ error ("%H\"%D\" declared as a non-parameter", locus, decl);
+ /* If the declaration is already marked, we have a duplicate
+ name. Complain and ignore the duplicate. */
+ else if (DECL_WEAK (decl))
{
- if (DECL_NAME (parm) == 0)
- error ("%Hparameter name omitted", locus);
- else if (TREE_CODE (TREE_TYPE (parm)) != ERROR_MARK
- && VOID_TYPE_P (TREE_TYPE (parm)))
- {
- error ("%Hparameter '%D' declared void", locus, parm);
- /* Change the type to error_mark_node so this parameter
- will be ignored by assign_parms. */
- TREE_TYPE (parm) = error_mark_node;
- }
- pushdecl (parm);
+ error ("%Hmultiple parameters named \"%D\"", locus, decl);
+ TREE_PURPOSE (parm) = 0;
+ continue;
}
- else
+ /* If the declaration says "void", complain and turn it into
+ an int. */
+ else if (VOID_TYPE_P (TREE_TYPE (decl)))
{
- /* If we find an enum constant or a type tag,
- put it aside for the moment. */
- TREE_CHAIN (parm) = 0;
- others = chainon (others, parm);
+ error ("%Hparameter \"%D\" declared void", locus, decl);
+ TREE_TYPE (decl) = integer_type_node;
+ DECL_ARG_TYPE (decl) = integer_type_node;
+ layout_decl (decl, 0);
}
}
-
- /* Get the decls in their original chain order
- and record in the function. */
- DECL_ARGUMENTS (fndecl) = getdecls ();
-
- /* Now pushdecl the enum constants. */
- for (parm = others; parm; parm = next)
+ /* If no declaration found, default to int. */
+ else
{
- next = TREE_CHAIN (parm);
- if (DECL_NAME (parm) == 0)
- ;
- else if (TYPE_MAIN_VARIANT (TREE_TYPE (parm)) == void_type_node)
- ;
- else if (TREE_CODE (parm) != PARM_DECL)
- pushdecl (parm);
+ const location_t *locus = &DECL_SOURCE_LOCATION (fndecl);
+ decl = build_decl (PARM_DECL, TREE_VALUE (parm), integer_type_node);
+ DECL_ARG_TYPE (decl) = TREE_TYPE (decl);
+ DECL_SOURCE_LOCATION (decl) = *locus;
+ pushdecl (decl);
+
+ if (flag_isoc99)
+ pedwarn ("%Htype of \"%D\" defaults to \"int\"", locus, decl);
+ else if (extra_warnings)
+ warning ("%Htype of \"%D\" defaults to \"int\"", locus, decl);
}
- storetags (chainon (parmtags, gettags ()));
+ TREE_PURPOSE (parm) = decl;
+ DECL_WEAK (decl) = 1;
}
- else
- {
- /* SPECPARMS is an identifier list--a chain of TREE_LIST nodes
- each with a parm name as the TREE_VALUE.
-
- PARMDECLS is a chain of declarations for parameters.
- Warning! It can also contain CONST_DECLs which are not parameters
- but are names of enumerators of any enum types
- declared among the parameters.
- First match each formal parameter name with its declaration.
- Associate decls with the names and store the decls
- into the TREE_PURPOSE slots. */
+ /* Put anything which is in current_scope->names and which is
+ not a PARM_DECL onto the list NONPARMS. (The types of
+ non-parm things which might appear on the list include
+ enumerators and NULL-named TYPE_DECL nodes.) Complain about
+ any actual PARM_DECLs not matched with any names. */
- /* We use DECL_WEAK as a flag to show which parameters have been
- seen already since it is not used on PARM_DECL or CONST_DECL. */
- for (parm = parmdecls; parm; parm = TREE_CHAIN (parm))
- DECL_WEAK (parm) = 0;
+ nonparms = 0;
+ for (parm = current_scope->names; parm; parm = next)
+ {
+ const location_t *locus = &DECL_SOURCE_LOCATION (parm);
+ next = TREE_CHAIN (parm);
+ TREE_CHAIN (parm) = 0;
- for (parm = specparms; parm; parm = TREE_CHAIN (parm))
+ if (TREE_CODE (parm) != PARM_DECL)
{
- tree tail, found = NULL;
-
- if (TREE_VALUE (parm) == 0)
- {
- error ("%Hparameter name missing from parameter list",
- &DECL_SOURCE_LOCATION (fndecl));
- TREE_PURPOSE (parm) = 0;
- continue;
- }
-
- /* See if any of the parmdecls specifies this parm by name.
- Ignore any enumerator decls. */
- for (tail = parmdecls; tail; tail = TREE_CHAIN (tail))
- if (DECL_NAME (tail) == TREE_VALUE (parm)
- && TREE_CODE (tail) == PARM_DECL)
- {
- found = tail;
- break;
- }
-
- /* If declaration already marked, we have a duplicate name.
- Complain, and don't use this decl twice. */
- if (found && DECL_WEAK (found))
- {
- error ("%Hmultiple parameters named '%D'",
- &DECL_SOURCE_LOCATION (found), found);
- found = 0;
- }
-
- /* If the declaration says "void", complain and ignore it. */
- if (found && VOID_TYPE_P (TREE_TYPE (found)))
- {
- error ("%Hparameter '%D' declared void",
- &DECL_SOURCE_LOCATION (found), found);
- TREE_TYPE (found) = integer_type_node;
- DECL_ARG_TYPE (found) = integer_type_node;
- layout_decl (found, 0);
- }
-
- /* If no declaration found, default to int. */
- if (!found)
- {
- found = build_decl (PARM_DECL, TREE_VALUE (parm),
- integer_type_node);
- DECL_ARG_TYPE (found) = TREE_TYPE (found);
- DECL_SOURCE_LOCATION (found) = DECL_SOURCE_LOCATION (fndecl);
- if (flag_isoc99)
- pedwarn ("%Htype of '%D' defaults to `int'",
- &DECL_SOURCE_LOCATION (found), found);
- else if (extra_warnings)
- warning ("%Htype of '%D' defaults to `int'",
- &DECL_SOURCE_LOCATION (found), found);
- pushdecl (found);
- }
-
- TREE_PURPOSE (parm) = found;
-
- /* Mark this decl as "already found". */
- DECL_WEAK (found) = 1;
+ nonparms = chainon (nonparms, parm);
+ continue;
}
- /* Put anything which is on the parmdecls chain and which is
- not a PARM_DECL onto the list NONPARMS. (The types of
- non-parm things which might appear on the list include
- enumerators and NULL-named TYPE_DECL nodes.) Complain about
- any actual PARM_DECLs not matched with any names. */
-
- nonparms = 0;
- for (parm = parmdecls; parm;)
+ if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
{
- const location_t *locus = &DECL_SOURCE_LOCATION (parm);
- tree next = TREE_CHAIN (parm);
- TREE_CHAIN (parm) = 0;
-
- if (TREE_CODE (parm) != PARM_DECL)
- nonparms = chainon (nonparms, parm);
- else
- {
- /* Complain about args with incomplete types. */
- if (!COMPLETE_TYPE_P (TREE_TYPE (parm)))
- {
- error ("%Hparameter '%D' has incomplete type", locus, parm);
- TREE_TYPE (parm) = error_mark_node;
- }
+ error ("%Hparameter \"%D\" has incomplete type", locus, parm);
+ TREE_TYPE (parm) = error_mark_node;
+ }
- if (! DECL_WEAK (parm))
- {
- error ("%Hdeclaration for parameter '%D' but no such "
- "parameter", locus, parm);
- /* Pretend the parameter was not missing.
- This gets us to a standard state and minimizes
- further error messages. */
- specparms
- = chainon (specparms,
- tree_cons (parm, NULL_TREE, NULL_TREE));
- }
- }
+ if (! DECL_WEAK (parm))
+ {
+ error ("%Hdeclaration for parameter \"%D\" but no such parameter",
+ locus, parm);
- parm = next;
+ /* Pretend the parameter was not missing.
+ This gets us to a standard state and minimizes
+ further error messages. */
+ parmids = chainon (parmids, tree_cons (parm, 0, 0));
}
+ }
- /* Chain the declarations together in the order of the list of
- names. Store that chain in the function decl, replacing the
- list of names. */
- parm = specparms;
- DECL_ARGUMENTS (fndecl) = 0;
+ /* Chain the declarations together in the order of the list of
+ names. Store that chain in the function decl, replacing the
+ list of names. */
+ DECL_ARGUMENTS (fndecl) = 0;
+ {
+ tree last;
+ for (parm = parmids; parm; parm = TREE_CHAIN (parm))
+ if (TREE_PURPOSE (parm))
+ break;
+ if (parm && TREE_PURPOSE (parm))
{
- tree last;
- for (last = 0; parm; parm = TREE_CHAIN (parm))
+ last = TREE_PURPOSE (parm);
+ DECL_ARGUMENTS (fndecl) = last;
+ DECL_WEAK (last) = 0;
+
+ for (parm = TREE_CHAIN (parm); parm; parm = TREE_CHAIN (parm))
if (TREE_PURPOSE (parm))
{
- if (last == 0)
- DECL_ARGUMENTS (fndecl) = TREE_PURPOSE (parm);
- else
- TREE_CHAIN (last) = TREE_PURPOSE (parm);
+ TREE_CHAIN (last) = TREE_PURPOSE (parm);
last = TREE_PURPOSE (parm);
- TREE_CHAIN (last) = 0;
+ DECL_WEAK (last) = 0;
}
+ TREE_CHAIN (last) = 0;
}
+ }
- /* If there was a previous prototype,
- set the DECL_ARG_TYPE of each argument according to
- the type previously specified, and report any mismatches. */
+ /* If there was a previous prototype,
+ set the DECL_ARG_TYPE of each argument according to
+ the type previously specified, and report any mismatches. */
- if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+ if (TYPE_ARG_TYPES (TREE_TYPE (fndecl)))
+ {
+ tree type;
+ for (parm = DECL_ARGUMENTS (fndecl),
+ type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
+ parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
+ != void_type_node));
+ parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
{
- tree type;
- for (parm = DECL_ARGUMENTS (fndecl),
- type = TYPE_ARG_TYPES (TREE_TYPE (fndecl));
- parm || (type && (TYPE_MAIN_VARIANT (TREE_VALUE (type))
- != void_type_node));
- parm = TREE_CHAIN (parm), type = TREE_CHAIN (type))
+ if (parm == 0 || type == 0
+ || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
{
- if (parm == 0 || type == 0
- || TYPE_MAIN_VARIANT (TREE_VALUE (type)) == void_type_node)
- {
- error ("number of arguments doesn't match prototype");
- error ("%Hprototype declaration",
- ¤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)
{
- /* 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
- {
- 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)));
+}
- /* Make sure the scope for the top of the function body
- gets a BLOCK if there are any in the function.
- Otherwise, the dbx output is wrong. */
+/* Store the parameter declarations into the current function declaration.
+ This is called after parsing the parameter declarations, before
+ digesting the body of the function.
- keep_next_if_subblocks = 1;
+ For an old-style definition, construct a prototype out of the old-style
+ parameter declarations and inject it into the function's type. */
+
+void
+store_parm_decls (void)
+{
+ tree fndecl = current_function_decl;
+
+ /* The function containing FNDECL, if any. */
+ tree context = decl_function_context (fndecl);
+
+ /* True if this definition is written with a prototype. */
+ bool prototype = (current_function_parms
+ && TREE_CODE (current_function_parms) != TREE_LIST);
+
+ /* Don't re-emit shadow warnings. */
+ bool saved_warn_shadow = warn_shadow;
+ warn_shadow = false;
+
+ if (prototype)
+ store_parm_decls_newstyle ();
+ else
+ store_parm_decls_oldstyle ();
+
+ /* The next call to pushlevel will be a function body. */
+
+ next_is_function_body = true;
/* Write a record describing this function definition to the prototypes
file (if requested). */
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 scope stack out of sync. Detect this situation by
- noticing that current_scope is still as
- store_parm_decls left it, and do a dummy push/pop to get back to
- consistency. Note that the call to pushlevel does not actually
- push another scope - see there for details. */
- if (current_scope->parm_flag && keep_next_if_subblocks)
+ the scope stack out of sync. Detect this situation by noticing
+ that current_scope is still as store_parm_decls left it, and do
+ a dummy push/pop to get back to consistency.
+ Note that the call to pushlevel does not actually push another
+ scope - see there for details. */
+
+ if (current_scope->parm_flag && next_is_function_body)
{
pushlevel (0);
- poplevel (1, 0, 1);
+ poplevel (0, 0, 0);
}
BLOCK_SUPERCONTEXT (DECL_INITIAL (fndecl)) = fndecl;
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 c_scope *scope;
};
/* 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->scope = current_scope;
}
/* 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_scope = p->scope;
f->language = NULL;
}