From e144c7cc4c57edff8134fc76cd2fab88e00b589b Mon Sep 17 00:00:00 2001 From: eck Date: Wed, 12 Sep 1990 16:36:16 +0000 Subject: [PATCH] fixed bugs with prototype scopes --- lang/cem/cemcom.ansi/code.c | 20 +++++++++++++++++++- lang/cem/cemcom.ansi/declar.g | 1 - lang/cem/cemcom.ansi/declarator.c | 11 ++++++++++- lang/cem/cemcom.ansi/idf.c | 10 +++++++--- lang/cem/cemcom.ansi/program.g | 19 ++++++++++++++++++- lang/cem/cemcom.ansi/proto.c | 19 +------------------ 6 files changed, 55 insertions(+), 25 deletions(-) diff --git a/lang/cem/cemcom.ansi/code.c b/lang/cem/cemcom.ansi/code.c index a6be75a16..c079145ce 100644 --- a/lang/cem/cemcom.ansi/code.c +++ b/lang/cem/cemcom.ansi/code.c @@ -142,8 +142,9 @@ prepend_scopes() 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 @@ -201,6 +202,23 @@ begin_proc(ds, idf) /* to be called when entering a procedure */ 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 diff --git a/lang/cem/cemcom.ansi/declar.g b/lang/cem/cemcom.ansi/declar.g index 6d3b5712d..837007a3f 100644 --- a/lang/cem/cemcom.ansi/declar.g +++ b/lang/cem/cemcom.ansi/declar.g @@ -193,7 +193,6 @@ init_declarator(register struct decspecs *ds;) declarator(&Dc) { reject_params(&Dc); - def_proto(&Dc); declare_idf(ds, &Dc, level); #ifdef LINT lint_declare_idf(Dc.dc_idf, ds->ds_sc); diff --git a/lang/cem/cemcom.ansi/declarator.c b/lang/cem/cemcom.ansi/declarator.c index ae3897d60..bbb19506d 100644 --- a/lang/cem/cemcom.ansi/declarator.c +++ b/lang/cem/cemcom.ansi/declarator.c @@ -97,13 +97,22 @@ reject_params(dc) 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) diff --git a/lang/cem/cemcom.ansi/idf.c b/lang/cem/cemcom.ansi/idf.c index 58316a3ab..b889feb62 100644 --- a/lang/cem/cemcom.ansi/idf.c +++ b/lang/cem/cemcom.ansi/idf.c @@ -288,10 +288,13 @@ declare_idf(ds, dc, lvl) } #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. @@ -350,7 +353,6 @@ declare_idf(ds, dc, lvl) 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); @@ -415,6 +417,7 @@ global_redecl(idf, new_sc, tp) */ 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; @@ -551,6 +554,7 @@ init_idf(idf) */ 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) { diff --git a/lang/cem/cemcom.ansi/program.g b/lang/cem/cemcom.ansi/program.g index e50865db1..cd7adfb82 100644 --- a/lang/cem/cemcom.ansi/program.g +++ b/lang/cem/cemcom.ansi/program.g @@ -111,6 +111,24 @@ program: 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 @@ -156,7 +174,6 @@ 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) diff --git a/lang/cem/cemcom.ansi/proto.c b/lang/cem/cemcom.ansi/proto.c index 44c545bcd..c639f60a2 100644 --- a/lang/cem/cemcom.ansi/proto.c +++ b/lang/cem/cemcom.ansi/proto.c @@ -88,8 +88,6 @@ add_proto(pl, ds, dc, lvl) /* 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); @@ -247,21 +245,6 @@ declare_protos(dc) } -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; { @@ -368,7 +351,7 @@ remove_proto_idfs(pl) 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); } -- 2.34.1