]> Cypherpunks repositories - gostls13.git/commitdiff
better handling of mistaken top-level variable
authorRuss Cox <rsc@golang.org>
Wed, 7 Oct 2009 21:55:12 +0000 (14:55 -0700)
committerRuss Cox <rsc@golang.org>
Wed, 7 Oct 2009 21:55:12 +0000 (14:55 -0700)
references during the parsing of :=.  the base
problem is that when reading

a,b,c,d

the parser makes those refer to existing variables,
which might create a few stub top-level ones
for undefined names, but then if a := is the next
token, we need to undo those stubs.

this was causing problems in multifile packages
in which one file used a := variable named rpc
and the other imported a package named rpc.

R=ken
OCL=35446
CL=35446

src/cmd/gc/dcl.c
src/cmd/gc/go.h
src/cmd/gc/go.y
src/cmd/gc/lex.c
src/cmd/gc/subr.c

index bc8362d284ef890af56d5c7e744ba2fb2eb94bf8..37177c58d98cc6d448098fef8cf1e7865cae4416 100644 (file)
@@ -463,9 +463,15 @@ oldname(Sym *s)
                n->op = ONONAME;
                s->def = n;
        }
+       if(n->oldref < 100)
+               n->oldref++;
        if(n->funcdepth > 0 && n->funcdepth != funcdepth && n->op == ONAME) {
-               // inner func is referring to var
-               // in outer func.
+               // inner func is referring to var in outer func.
+               //
+               // TODO(rsc): If there is an outer variable x and we
+               // are parsing x := 5 inside the closure, until we get to
+               // the := it looks like a reference to the outer x so we'll
+               // make x a closure variable unnecessarily.
                if(n->closure == N || n->closure->funcdepth != funcdepth) {
                        // create new closure var.
                        c = nod(ONAME, N, N);
@@ -554,6 +560,12 @@ colasdefn(NodeList *left, Node *defn)
                }
                if(n->sym->block == block)
                        continue;
+
+               // If we created an ONONAME just for this :=,
+               // delete it, to avoid confusion with top-level imports.
+               if(n->op == ONONAME && n->oldref < 100 && --n->oldref == 0)
+                       n->sym->def = N;
+
                nnew++;
                n = newname(n->sym);
                declare(n, dclcontext);
index 8c01ad9a3094584b09b7e990735a53659ae1a0ac..2d88342841af09ecfc8c6f4efa2d16f9d0b0a207 100644 (file)
@@ -202,6 +202,7 @@ struct      Node
        uchar   initorder;
        uchar   dodata;         // compile literal assignment as data statement
        uchar   used;
+       uchar   oldref;
 
        // most nodes
        Node*   left;
@@ -247,7 +248,6 @@ struct      Node
        Node*   outer;  // outer PPARAMREF in nested closure
        Node*   closure;        // ONAME/PHEAP <-> ONAME/PPARAMREF
 
-       char*   pline;
        Sym*    sym;            // various
        int32   vargen;         // unique name for OTYPE/ONAME
        int32   lineno;
@@ -696,8 +696,6 @@ EXTERN      int     noargnames;
 EXTERN int     funcdepth;
 EXTERN int     typecheckok;
 
-EXTERN char*   importline;
-
 /*
  *     y.tab.c
  */
index bf46f6c1ccaba659542a0ff752c14512b49d332d..93d25674cb7cb3ed2a480c44e80a81151c5dcb84 100644 (file)
@@ -178,7 +178,6 @@ import_stmt:
                pack = nod(OPACK, N, N);
                pack->sym = import;
                pack->lineno = $1;
-               pack->pline = importline;
 
                if(my == S)
                        my = import;
@@ -189,15 +188,10 @@ import_stmt:
                if(my->name[0] == '_' && my->name[1] == '\0')
                        break;
 
-               // TODO(rsc): this line is needed for a package
-               // which does bytes := in a function, which creates
-               // an ONONAME for bytes, but then a different file
-               // imports "bytes".  more generally we need to figure out
-               // what it means if one file imports "bytes" and another
-               // declares a top-level name.
-               if(my->def && my->def->op == ONONAME)
-                       my->def = N;
-
+               if(my->def) {
+                       lineno = $1;
+                       redeclare(my, "as imported package name");
+               }
                my->def = pack;
                my->lastlineno = $1;
                import->block = 1;      // at top level
@@ -223,8 +217,6 @@ import_here:
                $$ = parserline();
                pkgimportname = S;
                pkgmyname = $1;
-               if($1->def && ($1->name[0] != '_' || $1->name[1] != '\0'))
-                       redeclare($1, "as imported package name");
                importfile(&$2, $$);
        }
 |      '.' LLITERAL
index 827a351a7f56b692bb9dce496b4f6f7f8fcf7383..b89f26b5b16edabcd5c5fba7fe99011e76972f69 100644 (file)
@@ -267,13 +267,7 @@ importfile(Val *f, int line)
        int32 c;
        int len;
 
-       // Once we push the new file, we will not be able
-       // to print the current lineno correctly with %L.
-       // In case that line is the line of the import (likely),
-       // save the text for use in error messages.
-       importline = smprint("%L", line);
-
-// TODO: don't bother reloading imports more than once
+       // TODO(rsc): don't bother reloading imports more than once
 
        if(f->ctype != CTSTR) {
                yyerror("import statement not a string");
@@ -300,12 +294,10 @@ importfile(Val *f, int line)
                // assume .a files move (get installed)
                // so don't record the full path.
                p = file + len - f->u.sval->len - 2;
-               linehist(p, 0, 0);
                linehist(p, -1, 1);     // acts as #pragma lib
        } else {
                // assume .6 files don't move around
                // so do record the full path
-               linehist(file, 0, 0);
                linehist(file, -1, 0);
        }
 
@@ -339,8 +331,6 @@ importfile(Val *f, int line)
 void
 unimportfile(void)
 {
-       linehist(nil, 0, 0);
-
        if(curio.bin != nil) {
                Bterm(curio.bin);
                curio.bin = nil;
@@ -357,7 +347,6 @@ void
 cannedimports(char *file, char *cp)
 {
        lexlineno++;            // if sys.6 is included on line 1,
-       linehist(file, 0, 0);   // the debugger gets confused
 
        pushedio = curio;
        curio.bin = nil;
@@ -1018,7 +1007,7 @@ getc(void)
        if(c != 0) {
                curio.peekc = curio.peekc1;
                curio.peekc1 = 0;
-               if(c == '\n')
+               if(c == '\n' && pushedio.bin == nil)
                        lexlineno++;
                return c;
        }
@@ -1038,7 +1027,8 @@ getc(void)
                return EOF;
 
        case '\n':
-               lexlineno++;
+               if(pushedio.bin == nil)
+                       lexlineno++;
                break;
        }
        return c;
@@ -1049,7 +1039,7 @@ ungetc(int c)
 {
        curio.peekc1 = curio.peekc;
        curio.peekc = c;
-       if(c == '\n')
+       if(c == '\n' && pushedio.bin == nil)
                lexlineno--;
 }
 
@@ -1487,7 +1477,7 @@ mkpackage(char* pkg)
                                        // name, so that the name cannot be redeclared
                                        // as a non-package in other files.
                                        if(!s->def->used) {
-                                               print("%s: imported and not used: %s\n", s->def->pline, s->def->sym->name);
+                                               print("%L: imported and not used: %s\n", s->def->lineno, s->def->sym->name);
                                                nerrors++;
                                        }
                                        s->def = N;
@@ -1497,7 +1487,7 @@ mkpackage(char* pkg)
                                        // throw away top-level name left over
                                        // from previous import . "x"
                                        if(s->def->pack != N && !s->def->pack->used) {
-                                               print("%s: imported and not used: %s\n", s->def->pack->pline, s->def->pack->sym->name);
+                                               print("%L: imported and not used: %s\n", s->def->pack->lineno, s->def->pack->sym->name);
                                                nerrors++;
                                                s->def->pack->used = 1;
                                        }
index 97fdc4f19291a47e358923e59640e66f0288249f..007344e93b33531c480f900a684487b353382d0c 100644 (file)
@@ -269,7 +269,7 @@ importdot(Sym *opkg, Node *pack)
        }
        if(n == 0) {
                // can't possibly be used - there were no symbols
-               print("%L: imported and not used: %s\n", pack->pline, pack->sym->name);
+               print("%L: imported and not used: %s\n", pack->lineno, pack->sym->name);
                nerrors++;
        }
 }