register struct idf *id = se->se_idf;
register struct def *df = id->id_def;
- if (df && (df->df_initialized || df->df_used || df->df_alloc))
+ if (df && (df->df_initialized || df->df_used || df->df_alloc)) {
code_scope(id->id_text, df);
+ }
se = se->next;
}
#ifdef USE_TMP
register char *name = idf->id_text;
register struct def *def = idf->id_def;
+ /* idf->id_def does not indicate the right def structure
+ * when the function being defined has a parameter of the
+ * same name in an old-style function definition.
+ */
+ while (def->df_level != L_GLOBAL) def = def->next;
+
+ /* When we have a new-style function definition, the parameters
+ * are defined first, which means that it may look as if they have
+ * the greatest scope. Correct this.
+ */
+ if (idf->id_def == def && def->next && def->next->df_level == L_PROTO) {
+ struct def *tmpdef = def->next;
+
+ def->next = tmpdef->next;
+ tmpdef->next = def;
+ idf->id_def = tmpdef;
+ }
#ifndef PREPEND_SCOPES
code_scope(name, def);
#endif PREPEND_SCOPES
declarator(&Dc)
{
reject_params(&Dc);
- def_proto(&Dc);
declare_idf(ds, &Dc, level);
#ifdef LINT
lint_declare_idf(Dc.dc_idf, ds->ds_sc);
register struct declarator *dc;
{
/* The declarator is checked to have no parameters, if it
- is a function.
+ is an old-style function. If it is a new-style function,
+ the identifiers are removed. The function is not called in
+ case of a function definition.
*/
+ register struct decl_unary *du = dc->dc_decl_unary;
+
if (dc->dc_formal) {
error("non_empty formal parameter pack");
free_formals(dc->dc_formal);
dc->dc_formal = 0;
}
+ while (du) {
+ if (du->du_fund == FUNCTION)
+ remove_proto_idfs(du->du_proto);
+ du = du->next;
+ }
}
check_array_subscript(expr)
}
#endif LINT
- if (def &&
+ if ((def &&
( def->df_level == lvl ||
( lvl != L_GLOBAL && def->df_level > lvl )
- )
+ ))
+ || (lvl == L_GLOBAL
+ && def && def->df_level == L_PROTO
+ && def->next && def->next->df_level == L_GLOBAL)
) {
/* There is already a declaration for idf on this
level, or even more inside.
newdef->df_set = (type->tp_fund == ARRAY);
/* newdef->df_firstbrace = 0; */
#endif LINT
-
/* link it into the name list in the proper place */
idf->id_def = newdef;
update_ahead(idf);
*/
register struct def *def = idf->id_def;
+ while (def->df_level != L_GLOBAL) def = def->next;
if (!equal_type(tp, def->df_type, 0)) {
error("redeclaration of %s with different type", idf->id_text);
return;
*/
register struct def *def = idf->id_def; /* the topmost */
+ while (def->df_level <= L_PROTO) def = def->next;
if (def->df_initialized)
error("multiple initialization of %s", idf->id_text);
if (def->df_sc == TYPEDEF) {
used again and again, while the declarator is stored in a struct
declarator, only to be passed to declare_idf together with the
struct decspecs.
+
+ With the introduction of prototypes, extra problems for the scope
+ administration were introduced as well. We can have, for example,
+ int x(double x);
+ and
+ int x(double x) { ... use(x) ... }
+ In the first case, the parameter name can be forgotten, whereas in
+ the second case, the parameter should have a block scope. The
+ problem lies in the fact that the parameter's type is known before
+ the type of the function, which causes the def structure to be on
+ the end of the list. Our solution is as follows:
+ 1- In case of a declaration, throw the parameter identifier away
+ before the declaration of the outer x.
+ 2- In case of a definition, the function begin_proc() changes the
+ def list for the identifier. This means that declare_idf()
+ contains an extra test in case we already saw a declaration of
+ such a function, because this function is called before
+ begin_proc().
*/
external_definition
non_function(register struct decspecs *ds; register struct declarator *dc;)
:
{ reject_params(dc);
- def_proto(dc);
}
[
initializer(dc->dc_idf, ds->ds_sc)
/* Perform some special conversions for parameters.
*/
if (type->tp_fund == FUNCTION) {
- if (type->tp_proto)
- remove_proto_idfs(type->tp_proto);
type = construct_type(POINTER, type, 0, (arith) 0, NO_PROTO);
} else if (type->tp_fund == ARRAY) {
type = construct_type(POINTER, type->tp_up, 0, (arith) 0, NO_PROTO);
}
-def_proto(dc)
- register struct declarator *dc;
-{
- /* Prototype declarations may have arguments, but the idf's
- in the parameter type list can be ignored.
- */
- register struct decl_unary *du = dc->dc_decl_unary;
-
- while (du) {
- if (du->du_fund == FUNCTION)
- remove_proto_idfs(du->du_proto);
- du = du->next;
- }
-}
-
update_proto(tp, otp)
register struct type *tp, *otp;
{
pl->pl_idf->id_text);
#endif
def = pl->pl_idf->id_def;
- if (def && def->df_level <= L_PROTO){
+ if (def && def->df_level <= L_PROTO) {
pl->pl_idf->id_def = def->next;
free_def(def);
}