fixed bugs with prototype scopes
authoreck <none@none>
Wed, 12 Sep 1990 16:36:16 +0000 (16:36 +0000)
committereck <none@none>
Wed, 12 Sep 1990 16:36:16 +0000 (16:36 +0000)
lang/cem/cemcom.ansi/code.c
lang/cem/cemcom.ansi/declar.g
lang/cem/cemcom.ansi/declarator.c
lang/cem/cemcom.ansi/idf.c
lang/cem/cemcom.ansi/program.g
lang/cem/cemcom.ansi/proto.c

index a6be75a..c079145 100644 (file)
@@ -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
index 6d3b571..837007a 100644 (file)
@@ -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);
index ae3897d..bbb1950 100644 (file)
@@ -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)
index 58316a3..b889feb 100644 (file)
@@ -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)      {
index e50865d..cd7adfb 100644 (file)
@@ -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)
index 44c545b..c639f60 100644 (file)
@@ -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);
                        }