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 idf *id = se->se_idf;
|
||||||
register struct def *df = id->id_def;
|
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);
|
code_scope(id->id_text, df);
|
||||||
|
}
|
||||||
se = se->next;
|
se = se->next;
|
||||||
}
|
}
|
||||||
#ifdef USE_TMP
|
#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 char *name = idf->id_text;
|
||||||
register struct def *def = idf->id_def;
|
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
|
#ifndef PREPEND_SCOPES
|
||||||
code_scope(name, def);
|
code_scope(name, def);
|
||||||
#endif PREPEND_SCOPES
|
#endif PREPEND_SCOPES
|
||||||
|
|
|
@ -193,7 +193,6 @@ init_declarator(register struct decspecs *ds;)
|
||||||
declarator(&Dc)
|
declarator(&Dc)
|
||||||
{
|
{
|
||||||
reject_params(&Dc);
|
reject_params(&Dc);
|
||||||
def_proto(&Dc);
|
|
||||||
declare_idf(ds, &Dc, level);
|
declare_idf(ds, &Dc, level);
|
||||||
#ifdef LINT
|
#ifdef LINT
|
||||||
lint_declare_idf(Dc.dc_idf, ds->ds_sc);
|
lint_declare_idf(Dc.dc_idf, ds->ds_sc);
|
||||||
|
|
|
@ -97,13 +97,22 @@ reject_params(dc)
|
||||||
register struct declarator *dc;
|
register struct declarator *dc;
|
||||||
{
|
{
|
||||||
/* The declarator is checked to have no parameters, if it
|
/* 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) {
|
if (dc->dc_formal) {
|
||||||
error("non_empty formal parameter pack");
|
error("non_empty formal parameter pack");
|
||||||
free_formals(dc->dc_formal);
|
free_formals(dc->dc_formal);
|
||||||
dc->dc_formal = 0;
|
dc->dc_formal = 0;
|
||||||
}
|
}
|
||||||
|
while (du) {
|
||||||
|
if (du->du_fund == FUNCTION)
|
||||||
|
remove_proto_idfs(du->du_proto);
|
||||||
|
du = du->next;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
check_array_subscript(expr)
|
check_array_subscript(expr)
|
||||||
|
|
|
@ -288,10 +288,13 @@ declare_idf(ds, dc, lvl)
|
||||||
}
|
}
|
||||||
#endif LINT
|
#endif LINT
|
||||||
|
|
||||||
if (def &&
|
if ((def &&
|
||||||
( def->df_level == lvl ||
|
( def->df_level == lvl ||
|
||||||
( lvl != L_GLOBAL && 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
|
/* There is already a declaration for idf on this
|
||||||
level, or even more inside.
|
level, or even more inside.
|
||||||
|
@ -350,7 +353,6 @@ declare_idf(ds, dc, lvl)
|
||||||
newdef->df_set = (type->tp_fund == ARRAY);
|
newdef->df_set = (type->tp_fund == ARRAY);
|
||||||
/* newdef->df_firstbrace = 0; */
|
/* newdef->df_firstbrace = 0; */
|
||||||
#endif LINT
|
#endif LINT
|
||||||
|
|
||||||
/* link it into the name list in the proper place */
|
/* link it into the name list in the proper place */
|
||||||
idf->id_def = newdef;
|
idf->id_def = newdef;
|
||||||
update_ahead(idf);
|
update_ahead(idf);
|
||||||
|
@ -415,6 +417,7 @@ global_redecl(idf, new_sc, tp)
|
||||||
*/
|
*/
|
||||||
register struct def *def = idf->id_def;
|
register struct def *def = idf->id_def;
|
||||||
|
|
||||||
|
while (def->df_level != L_GLOBAL) def = def->next;
|
||||||
if (!equal_type(tp, def->df_type, 0)) {
|
if (!equal_type(tp, def->df_type, 0)) {
|
||||||
error("redeclaration of %s with different type", idf->id_text);
|
error("redeclaration of %s with different type", idf->id_text);
|
||||||
return;
|
return;
|
||||||
|
@ -551,6 +554,7 @@ init_idf(idf)
|
||||||
*/
|
*/
|
||||||
register struct def *def = idf->id_def; /* the topmost */
|
register struct def *def = idf->id_def; /* the topmost */
|
||||||
|
|
||||||
|
while (def->df_level <= L_PROTO) def = def->next;
|
||||||
if (def->df_initialized)
|
if (def->df_initialized)
|
||||||
error("multiple initialization of %s", idf->id_text);
|
error("multiple initialization of %s", idf->id_text);
|
||||||
if (def->df_sc == TYPEDEF) {
|
if (def->df_sc == TYPEDEF) {
|
||||||
|
|
|
@ -111,6 +111,24 @@ program:
|
||||||
used again and again, while the declarator is stored in a struct
|
used again and again, while the declarator is stored in a struct
|
||||||
declarator, only to be passed to declare_idf together with the
|
declarator, only to be passed to declare_idf together with the
|
||||||
struct decspecs.
|
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
|
external_definition
|
||||||
|
@ -156,7 +174,6 @@ external_definition
|
||||||
non_function(register struct decspecs *ds; register struct declarator *dc;)
|
non_function(register struct decspecs *ds; register struct declarator *dc;)
|
||||||
:
|
:
|
||||||
{ reject_params(dc);
|
{ reject_params(dc);
|
||||||
def_proto(dc);
|
|
||||||
}
|
}
|
||||||
[
|
[
|
||||||
initializer(dc->dc_idf, ds->ds_sc)
|
initializer(dc->dc_idf, ds->ds_sc)
|
||||||
|
|
|
@ -88,8 +88,6 @@ add_proto(pl, ds, dc, lvl)
|
||||||
/* Perform some special conversions for parameters.
|
/* Perform some special conversions for parameters.
|
||||||
*/
|
*/
|
||||||
if (type->tp_fund == FUNCTION) {
|
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);
|
type = construct_type(POINTER, type, 0, (arith) 0, NO_PROTO);
|
||||||
} else if (type->tp_fund == ARRAY) {
|
} else if (type->tp_fund == ARRAY) {
|
||||||
type = construct_type(POINTER, type->tp_up, 0, (arith) 0, NO_PROTO);
|
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)
|
update_proto(tp, otp)
|
||||||
register struct type *tp, *otp;
|
register struct type *tp, *otp;
|
||||||
{
|
{
|
||||||
|
@ -368,7 +351,7 @@ remove_proto_idfs(pl)
|
||||||
pl->pl_idf->id_text);
|
pl->pl_idf->id_text);
|
||||||
#endif
|
#endif
|
||||||
def = pl->pl_idf->id_def;
|
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;
|
pl->pl_idf->id_def = def->next;
|
||||||
free_def(def);
|
free_def(def);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue