fixed bugs with prototype scopes
This commit is contained in:
parent
bd18f6c521
commit
e144c7cc4c
6 changed files with 55 additions and 25 deletions
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue