mirror of
https://github.com/golang/go
synced 2024-11-25 11:57:58 -07:00
better handling of mistaken top-level variable
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
This commit is contained in:
parent
4fd7a908bb
commit
d515063588
@ -463,9 +463,15 @@ oldname(Sym *s)
|
|||||||
n->op = ONONAME;
|
n->op = ONONAME;
|
||||||
s->def = n;
|
s->def = n;
|
||||||
}
|
}
|
||||||
|
if(n->oldref < 100)
|
||||||
|
n->oldref++;
|
||||||
if(n->funcdepth > 0 && n->funcdepth != funcdepth && n->op == ONAME) {
|
if(n->funcdepth > 0 && n->funcdepth != funcdepth && n->op == ONAME) {
|
||||||
// inner func is referring to var
|
// inner func is referring to var in outer func.
|
||||||
// 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) {
|
if(n->closure == N || n->closure->funcdepth != funcdepth) {
|
||||||
// create new closure var.
|
// create new closure var.
|
||||||
c = nod(ONAME, N, N);
|
c = nod(ONAME, N, N);
|
||||||
@ -554,6 +560,12 @@ colasdefn(NodeList *left, Node *defn)
|
|||||||
}
|
}
|
||||||
if(n->sym->block == block)
|
if(n->sym->block == block)
|
||||||
continue;
|
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++;
|
nnew++;
|
||||||
n = newname(n->sym);
|
n = newname(n->sym);
|
||||||
declare(n, dclcontext);
|
declare(n, dclcontext);
|
||||||
|
@ -202,6 +202,7 @@ struct Node
|
|||||||
uchar initorder;
|
uchar initorder;
|
||||||
uchar dodata; // compile literal assignment as data statement
|
uchar dodata; // compile literal assignment as data statement
|
||||||
uchar used;
|
uchar used;
|
||||||
|
uchar oldref;
|
||||||
|
|
||||||
// most nodes
|
// most nodes
|
||||||
Node* left;
|
Node* left;
|
||||||
@ -247,7 +248,6 @@ struct Node
|
|||||||
Node* outer; // outer PPARAMREF in nested closure
|
Node* outer; // outer PPARAMREF in nested closure
|
||||||
Node* closure; // ONAME/PHEAP <-> ONAME/PPARAMREF
|
Node* closure; // ONAME/PHEAP <-> ONAME/PPARAMREF
|
||||||
|
|
||||||
char* pline;
|
|
||||||
Sym* sym; // various
|
Sym* sym; // various
|
||||||
int32 vargen; // unique name for OTYPE/ONAME
|
int32 vargen; // unique name for OTYPE/ONAME
|
||||||
int32 lineno;
|
int32 lineno;
|
||||||
@ -696,8 +696,6 @@ EXTERN int noargnames;
|
|||||||
EXTERN int funcdepth;
|
EXTERN int funcdepth;
|
||||||
EXTERN int typecheckok;
|
EXTERN int typecheckok;
|
||||||
|
|
||||||
EXTERN char* importline;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* y.tab.c
|
* y.tab.c
|
||||||
*/
|
*/
|
||||||
|
@ -178,7 +178,6 @@ import_stmt:
|
|||||||
pack = nod(OPACK, N, N);
|
pack = nod(OPACK, N, N);
|
||||||
pack->sym = import;
|
pack->sym = import;
|
||||||
pack->lineno = $1;
|
pack->lineno = $1;
|
||||||
pack->pline = importline;
|
|
||||||
|
|
||||||
if(my == S)
|
if(my == S)
|
||||||
my = import;
|
my = import;
|
||||||
@ -189,15 +188,10 @@ import_stmt:
|
|||||||
if(my->name[0] == '_' && my->name[1] == '\0')
|
if(my->name[0] == '_' && my->name[1] == '\0')
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// TODO(rsc): this line is needed for a package
|
if(my->def) {
|
||||||
// which does bytes := in a function, which creates
|
lineno = $1;
|
||||||
// an ONONAME for bytes, but then a different file
|
redeclare(my, "as imported package name");
|
||||||
// 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;
|
|
||||||
|
|
||||||
my->def = pack;
|
my->def = pack;
|
||||||
my->lastlineno = $1;
|
my->lastlineno = $1;
|
||||||
import->block = 1; // at top level
|
import->block = 1; // at top level
|
||||||
@ -223,8 +217,6 @@ import_here:
|
|||||||
$$ = parserline();
|
$$ = parserline();
|
||||||
pkgimportname = S;
|
pkgimportname = S;
|
||||||
pkgmyname = $1;
|
pkgmyname = $1;
|
||||||
if($1->def && ($1->name[0] != '_' || $1->name[1] != '\0'))
|
|
||||||
redeclare($1, "as imported package name");
|
|
||||||
importfile(&$2, $$);
|
importfile(&$2, $$);
|
||||||
}
|
}
|
||||||
| '.' LLITERAL
|
| '.' LLITERAL
|
||||||
|
@ -267,13 +267,7 @@ importfile(Val *f, int line)
|
|||||||
int32 c;
|
int32 c;
|
||||||
int len;
|
int len;
|
||||||
|
|
||||||
// Once we push the new file, we will not be able
|
// TODO(rsc): don't bother reloading imports more than once
|
||||||
// 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
|
|
||||||
|
|
||||||
if(f->ctype != CTSTR) {
|
if(f->ctype != CTSTR) {
|
||||||
yyerror("import statement not a string");
|
yyerror("import statement not a string");
|
||||||
@ -300,12 +294,10 @@ importfile(Val *f, int line)
|
|||||||
// assume .a files move (get installed)
|
// assume .a files move (get installed)
|
||||||
// so don't record the full path.
|
// so don't record the full path.
|
||||||
p = file + len - f->u.sval->len - 2;
|
p = file + len - f->u.sval->len - 2;
|
||||||
linehist(p, 0, 0);
|
|
||||||
linehist(p, -1, 1); // acts as #pragma lib
|
linehist(p, -1, 1); // acts as #pragma lib
|
||||||
} else {
|
} else {
|
||||||
// assume .6 files don't move around
|
// assume .6 files don't move around
|
||||||
// so do record the full path
|
// so do record the full path
|
||||||
linehist(file, 0, 0);
|
|
||||||
linehist(file, -1, 0);
|
linehist(file, -1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -339,8 +331,6 @@ importfile(Val *f, int line)
|
|||||||
void
|
void
|
||||||
unimportfile(void)
|
unimportfile(void)
|
||||||
{
|
{
|
||||||
linehist(nil, 0, 0);
|
|
||||||
|
|
||||||
if(curio.bin != nil) {
|
if(curio.bin != nil) {
|
||||||
Bterm(curio.bin);
|
Bterm(curio.bin);
|
||||||
curio.bin = nil;
|
curio.bin = nil;
|
||||||
@ -357,7 +347,6 @@ void
|
|||||||
cannedimports(char *file, char *cp)
|
cannedimports(char *file, char *cp)
|
||||||
{
|
{
|
||||||
lexlineno++; // if sys.6 is included on line 1,
|
lexlineno++; // if sys.6 is included on line 1,
|
||||||
linehist(file, 0, 0); // the debugger gets confused
|
|
||||||
|
|
||||||
pushedio = curio;
|
pushedio = curio;
|
||||||
curio.bin = nil;
|
curio.bin = nil;
|
||||||
@ -1018,7 +1007,7 @@ getc(void)
|
|||||||
if(c != 0) {
|
if(c != 0) {
|
||||||
curio.peekc = curio.peekc1;
|
curio.peekc = curio.peekc1;
|
||||||
curio.peekc1 = 0;
|
curio.peekc1 = 0;
|
||||||
if(c == '\n')
|
if(c == '\n' && pushedio.bin == nil)
|
||||||
lexlineno++;
|
lexlineno++;
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@ -1038,7 +1027,8 @@ getc(void)
|
|||||||
return EOF;
|
return EOF;
|
||||||
|
|
||||||
case '\n':
|
case '\n':
|
||||||
lexlineno++;
|
if(pushedio.bin == nil)
|
||||||
|
lexlineno++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
@ -1049,7 +1039,7 @@ ungetc(int c)
|
|||||||
{
|
{
|
||||||
curio.peekc1 = curio.peekc;
|
curio.peekc1 = curio.peekc;
|
||||||
curio.peekc = c;
|
curio.peekc = c;
|
||||||
if(c == '\n')
|
if(c == '\n' && pushedio.bin == nil)
|
||||||
lexlineno--;
|
lexlineno--;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1487,7 +1477,7 @@ mkpackage(char* pkg)
|
|||||||
// name, so that the name cannot be redeclared
|
// name, so that the name cannot be redeclared
|
||||||
// as a non-package in other files.
|
// as a non-package in other files.
|
||||||
if(!s->def->used) {
|
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++;
|
nerrors++;
|
||||||
}
|
}
|
||||||
s->def = N;
|
s->def = N;
|
||||||
@ -1497,7 +1487,7 @@ mkpackage(char* pkg)
|
|||||||
// throw away top-level name left over
|
// throw away top-level name left over
|
||||||
// from previous import . "x"
|
// from previous import . "x"
|
||||||
if(s->def->pack != N && !s->def->pack->used) {
|
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++;
|
nerrors++;
|
||||||
s->def->pack->used = 1;
|
s->def->pack->used = 1;
|
||||||
}
|
}
|
||||||
|
@ -269,7 +269,7 @@ importdot(Sym *opkg, Node *pack)
|
|||||||
}
|
}
|
||||||
if(n == 0) {
|
if(n == 0) {
|
||||||
// can't possibly be used - there were no symbols
|
// 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++;
|
nerrors++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user