mirror of https://github.com/golang/go.git
generate an error if the foreward
declaration of a func does not exactly
match the actual (or another foreward)
declaration. the reason is that when
there are 2 declarations of a function,
the names of the parameters are taken
from the first. thus
func x(a int);
followed by
func x(b int) { ... }
will have the parameter named "a" and
"b" will be undefined.
SVN=114788
This commit is contained in:
parent
87278c26e2
commit
5d6eba80f8
|
|
@ -283,6 +283,15 @@ funchdr(Node *n)
|
||||||
s = n->nname->sym;
|
s = n->nname->sym;
|
||||||
on = s->oname;
|
on = s->oname;
|
||||||
|
|
||||||
|
// check for same types
|
||||||
|
if(on != N) {
|
||||||
|
if(eqtype(n->type, on->type, 0)) {
|
||||||
|
if(!eqargs(n->type, on->type))
|
||||||
|
yyerror("foreward declarations not the same: %S", s);
|
||||||
|
} else
|
||||||
|
yyerror("redeclare of function: %S", s);
|
||||||
|
}
|
||||||
|
|
||||||
// check for foreward declaration
|
// check for foreward declaration
|
||||||
if(on == N || !eqtype(n->type, on->type, 0)) {
|
if(on == N || !eqtype(n->type, on->type, 0)) {
|
||||||
// initial declaration or redeclaration
|
// initial declaration or redeclaration
|
||||||
|
|
|
||||||
29
src/c/gen.c
29
src/c/gen.c
|
|
@ -87,9 +87,6 @@ loop:
|
||||||
dump("gen: unknown op", n);
|
dump("gen: unknown op", n);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ODCLTYPE:
|
|
||||||
break;
|
|
||||||
|
|
||||||
case OLIST:
|
case OLIST:
|
||||||
gen(n->left);
|
gen(n->left);
|
||||||
n = n->right;
|
n = n->right;
|
||||||
|
|
@ -216,8 +213,6 @@ loop:
|
||||||
cgen_asop(n->left, n->right, n->kaka);
|
cgen_asop(n->left, n->right, n->kaka);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ODCLVAR:
|
|
||||||
case OCOLAS:
|
|
||||||
case OAS:
|
case OAS:
|
||||||
cgen_as(n->left, n->right, n->op, n->kaka);
|
cgen_as(n->left, n->right, n->op, n->kaka);
|
||||||
break;
|
break;
|
||||||
|
|
@ -342,6 +337,19 @@ cgen(Node *n)
|
||||||
gopcode(PCONV, PTNIL, nod(OCONV, n->type, nl->type));
|
gopcode(PCONV, PTNIL, nod(OCONV, n->type, nl->type));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case OINDEXPTRSTR:
|
||||||
|
nl = n->left;
|
||||||
|
nr = n->right;
|
||||||
|
if(nl->addable) {
|
||||||
|
cgen(nr);
|
||||||
|
cgen(nl);
|
||||||
|
gopcode(PLOADI, PTADDR, N);
|
||||||
|
gopcodet(PINDEXZ, nr->type, N);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fatal("xxx");
|
||||||
|
break;
|
||||||
|
|
||||||
case OINDEXSTR:
|
case OINDEXSTR:
|
||||||
nl = n->left;
|
nl = n->left;
|
||||||
nr = n->right;
|
nr = n->right;
|
||||||
|
|
@ -357,7 +365,8 @@ cgen(Node *n)
|
||||||
gopcodet(PINDEXZ, nr->type, r);
|
gopcodet(PINDEXZ, nr->type, r);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case OSLICE:
|
case OSLICESTR:
|
||||||
|
case OSLICEPTRSTR:
|
||||||
nl = n->left; // name
|
nl = n->left; // name
|
||||||
nr = n->right;
|
nr = n->right;
|
||||||
|
|
||||||
|
|
@ -375,6 +384,9 @@ cgen(Node *n)
|
||||||
} else
|
} else
|
||||||
gopcode(PLOAD, PTADDR, nl);
|
gopcode(PLOAD, PTADDR, nl);
|
||||||
|
|
||||||
|
if(n->op == OSLICEPTRSTR)
|
||||||
|
gopcode(PLOADI, PTADDR, N);
|
||||||
|
|
||||||
// offset in int reg
|
// offset in int reg
|
||||||
cgen(nr->left);
|
cgen(nr->left);
|
||||||
|
|
||||||
|
|
@ -806,16 +818,13 @@ loop:
|
||||||
default:
|
default:
|
||||||
fatal("cgen_as: unknown op %O", op);
|
fatal("cgen_as: unknown op %O", op);
|
||||||
|
|
||||||
case ODCLVAR:
|
case OAS:
|
||||||
if(nr == N && nl->op == OLIST) {
|
if(nr == N && nl->op == OLIST) {
|
||||||
kaka = PAS_SINGLE;
|
kaka = PAS_SINGLE;
|
||||||
cgen_as(nl->left, nr, op, kaka);
|
cgen_as(nl->left, nr, op, kaka);
|
||||||
nl = nl->right;
|
nl = nl->right;
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
case OCOLAS:
|
|
||||||
case OAS:
|
|
||||||
switch(kaka) {
|
switch(kaka) {
|
||||||
default:
|
default:
|
||||||
yyerror("cgen_as: unknown param %d %d", kaka, PAS_CALLM);
|
yyerror("cgen_as: unknown param %d %d", kaka, PAS_CALLM);
|
||||||
|
|
|
||||||
11
src/c/go.h
11
src/c/go.h
|
|
@ -171,12 +171,11 @@ enum
|
||||||
|
|
||||||
ONAME,
|
ONAME,
|
||||||
ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
|
ODOT, ODOTPTR, ODOTMETH, ODOTINTER,
|
||||||
ODCLFUNC, ODCLCONST, ODCLVAR,
|
ODCLFUNC, ODCLFIELD, ODCLARG,
|
||||||
ODCLTYPE, ODCLFIELD, ODCLARG,
|
|
||||||
OLIST,
|
OLIST,
|
||||||
OPTR, OARRAY,
|
OPTR, OARRAY,
|
||||||
ORETURN, OFOR, OIF, OSWITCH,
|
ORETURN, OFOR, OIF, OSWITCH,
|
||||||
OAS, OASOP, OCOLAS, OCASE, OXCASE, OFALL, OXFALL,
|
OAS, OASOP, OCASE, OXCASE, OFALL, OXFALL,
|
||||||
OGOTO, OPROC, ONEW, OPANIC, OPRINT, OEMPTY,
|
OGOTO, OPROC, ONEW, OPANIC, OPRINT, OEMPTY,
|
||||||
|
|
||||||
OOROR,
|
OOROR,
|
||||||
|
|
@ -193,8 +192,9 @@ enum
|
||||||
OADDR,
|
OADDR,
|
||||||
OIND,
|
OIND,
|
||||||
OCALL, OCALLPTR, OCALLMETH, OCALLINTER,
|
OCALL, OCALLPTR, OCALLMETH, OCALLINTER,
|
||||||
OINDEX, OINDEXPTR, OINDEXSTR, OINDEXMAP, OINDEXPTRMAP,
|
OINDEX, OINDEXSTR, OINDEXMAP,
|
||||||
OSLICE,
|
OINDEXPTR, OINDEXPTRSTR, OINDEXPTRMAP,
|
||||||
|
OSLICE, OSLICESTR, OSLICEPTRSTR,
|
||||||
ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
|
ONOT, OCOM, OPLUS, OMINUS, OSEND, ORECV,
|
||||||
OLITERAL,
|
OLITERAL,
|
||||||
OCONV,
|
OCONV,
|
||||||
|
|
@ -400,6 +400,7 @@ int isptrto(Node*, int);
|
||||||
int isinter(Node*);
|
int isinter(Node*);
|
||||||
int isbytearray(Node*);
|
int isbytearray(Node*);
|
||||||
int eqtype(Node*, Node*, int);
|
int eqtype(Node*, Node*, int);
|
||||||
|
int eqargs(Node*, Node*);
|
||||||
ulong typehash(Node*, int);
|
ulong typehash(Node*, int);
|
||||||
void frame(int);
|
void frame(int);
|
||||||
Node* literal(long);
|
Node* literal(long);
|
||||||
|
|
|
||||||
35
src/c/go.y
35
src/c/go.y
|
|
@ -39,8 +39,6 @@
|
||||||
%type <node> name name_name new_name new_name_list_r
|
%type <node> name name_name new_name new_name_list_r
|
||||||
%type <node> type new_type
|
%type <node> type new_type
|
||||||
%type <node> vardcl_list_r vardcl
|
%type <node> vardcl_list_r vardcl
|
||||||
%type <node> constdcl_list_r constdcl
|
|
||||||
%type <node> typedcl_list_r typedcl
|
|
||||||
%type <node> interfacedcl_list_r interfacedcl
|
%type <node> interfacedcl_list_r interfacedcl
|
||||||
%type <node> structdcl_list_r structdcl
|
%type <node> structdcl_list_r structdcl
|
||||||
%type <node> export_list_r export
|
%type <node> export_list_r export
|
||||||
|
|
@ -142,21 +140,21 @@ common_dcl:
|
||||||
}
|
}
|
||||||
| LCONST constdcl
|
| LCONST constdcl
|
||||||
{
|
{
|
||||||
$$ = $2;
|
$$ = N;
|
||||||
iota = 0;
|
iota = 0;
|
||||||
}
|
}
|
||||||
| LCONST '(' constdcl_list_r osemi ')'
|
| LCONST '(' constdcl_list_r osemi ')'
|
||||||
{
|
{
|
||||||
$$ = rev($3);
|
$$ = N;
|
||||||
iota = 0;
|
iota = 0;
|
||||||
}
|
}
|
||||||
| LTYPE typedcl
|
| LTYPE typedcl
|
||||||
{
|
{
|
||||||
$$ = $2;
|
$$ = N;
|
||||||
}
|
}
|
||||||
| LTYPE '(' typedcl_list_r osemi ')'
|
| LTYPE '(' typedcl_list_r osemi ')'
|
||||||
{
|
{
|
||||||
$$ = rev($3);
|
$$ = N;
|
||||||
}
|
}
|
||||||
|
|
||||||
vardcl:
|
vardcl:
|
||||||
|
|
@ -165,16 +163,14 @@ vardcl:
|
||||||
$$ = rev($1);
|
$$ = rev($1);
|
||||||
dodclvar($$, $2);
|
dodclvar($$, $2);
|
||||||
|
|
||||||
$$ = nod(ODCLVAR, $$, N);
|
$$ = nod(OAS, $$, N);
|
||||||
$$->type = $2;
|
|
||||||
}
|
}
|
||||||
| new_name_list_r type '=' oexpr_list
|
| new_name_list_r type '=' oexpr_list
|
||||||
{
|
{
|
||||||
$$ = rev($1);
|
$$ = rev($1);
|
||||||
dodclvar($$, $2);
|
dodclvar($$, $2);
|
||||||
|
|
||||||
$$ = nod(ODCLVAR, $$, $4);
|
$$ = nod(OAS, $$, $4);
|
||||||
$$->type = $2;
|
|
||||||
}
|
}
|
||||||
| new_name '=' expr
|
| new_name '=' expr
|
||||||
{
|
{
|
||||||
|
|
@ -182,8 +178,7 @@ vardcl:
|
||||||
defaultlit($3);
|
defaultlit($3);
|
||||||
dodclvar($1, $3->type);
|
dodclvar($1, $3->type);
|
||||||
|
|
||||||
$$ = nod(ODCLVAR, $1, $3);
|
$$ = nod(OAS, $1, $3);
|
||||||
$$->type = $3->type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constdcl:
|
constdcl:
|
||||||
|
|
@ -191,8 +186,6 @@ constdcl:
|
||||||
{
|
{
|
||||||
walktype($3, 0);
|
walktype($3, 0);
|
||||||
dodclconst($1, $3);
|
dodclconst($1, $3);
|
||||||
|
|
||||||
$$ = nod(ODCLCONST, $1, $3);
|
|
||||||
iota += 1;
|
iota += 1;
|
||||||
}
|
}
|
||||||
| new_name type '=' expr
|
| new_name type '=' expr
|
||||||
|
|
@ -200,8 +193,6 @@ constdcl:
|
||||||
walktype($4, 0);
|
walktype($4, 0);
|
||||||
convlit($4, $2);
|
convlit($4, $2);
|
||||||
dodclconst($1, $4);
|
dodclconst($1, $4);
|
||||||
|
|
||||||
$$ = nod(ODCLCONST, $1, $4);
|
|
||||||
iota += 1;
|
iota += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -209,9 +200,6 @@ typedcl:
|
||||||
new_type type
|
new_type type
|
||||||
{
|
{
|
||||||
dodcltype($1, $2);
|
dodcltype($1, $2);
|
||||||
|
|
||||||
$$ = nod(ODCLTYPE, $1, N);
|
|
||||||
$$->type = $2;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -279,7 +267,8 @@ simple_stmt:
|
||||||
walktype($3, 0); // this is a little harry
|
walktype($3, 0); // this is a little harry
|
||||||
defaultlit($3);
|
defaultlit($3);
|
||||||
dodclvar($1, $3->type);
|
dodclvar($1, $3->type);
|
||||||
$$ = nod(OCOLAS, $1, $3);
|
|
||||||
|
$$ = nod(OAS, $1, $3);
|
||||||
}
|
}
|
||||||
|
|
||||||
complex_stmt:
|
complex_stmt:
|
||||||
|
|
@ -957,16 +946,10 @@ vardcl_list_r:
|
||||||
constdcl_list_r:
|
constdcl_list_r:
|
||||||
constdcl
|
constdcl
|
||||||
| constdcl_list_r ';' constdcl
|
| constdcl_list_r ';' constdcl
|
||||||
{
|
|
||||||
$$ = nod(OLIST, $1, $3);
|
|
||||||
}
|
|
||||||
|
|
||||||
typedcl_list_r:
|
typedcl_list_r:
|
||||||
typedcl
|
typedcl
|
||||||
| typedcl_list_r ';' typedcl
|
| typedcl_list_r ';' typedcl
|
||||||
{
|
|
||||||
$$ = nod(OLIST, $1, $3);
|
|
||||||
}
|
|
||||||
|
|
||||||
structdcl_list_r:
|
structdcl_list_r:
|
||||||
structdcl
|
structdcl
|
||||||
|
|
|
||||||
50
src/c/subr.c
50
src/c/subr.c
|
|
@ -542,16 +542,12 @@ opnames[] =
|
||||||
[OXCASE] = "XCASE",
|
[OXCASE] = "XCASE",
|
||||||
[OFALL] = "FALL",
|
[OFALL] = "FALL",
|
||||||
[OCONV] = "CONV",
|
[OCONV] = "CONV",
|
||||||
[OCOLAS] = "COLAS",
|
|
||||||
[OCOM] = "COM",
|
[OCOM] = "COM",
|
||||||
[OCONST] = "CONST",
|
[OCONST] = "CONST",
|
||||||
[OCONTINUE] = "CONTINUE",
|
[OCONTINUE] = "CONTINUE",
|
||||||
[ODCLARG] = "DCLARG",
|
[ODCLARG] = "DCLARG",
|
||||||
[ODCLCONST] = "DCLCONST",
|
|
||||||
[ODCLFIELD] = "DCLFIELD",
|
[ODCLFIELD] = "DCLFIELD",
|
||||||
[ODCLFUNC] = "DCLFUNC",
|
[ODCLFUNC] = "DCLFUNC",
|
||||||
[ODCLTYPE] = "DCLTYPE",
|
|
||||||
[ODCLVAR] = "DCLVAR",
|
|
||||||
[ODIV] = "DIV",
|
[ODIV] = "DIV",
|
||||||
[ODOT] = "DOT",
|
[ODOT] = "DOT",
|
||||||
[ODOTPTR] = "DOTPTR",
|
[ODOTPTR] = "DOTPTR",
|
||||||
|
|
@ -570,6 +566,7 @@ opnames[] =
|
||||||
[OINDEX] = "INDEX",
|
[OINDEX] = "INDEX",
|
||||||
[OINDEXPTR] = "INDEXPTR",
|
[OINDEXPTR] = "INDEXPTR",
|
||||||
[OINDEXSTR] = "INDEXSTR",
|
[OINDEXSTR] = "INDEXSTR",
|
||||||
|
[OINDEXPTRSTR] = "INDEXPTRSTR",
|
||||||
[OINDEXMAP] = "INDEXMAP",
|
[OINDEXMAP] = "INDEXMAP",
|
||||||
[OINDEXPTRMAP] = "INDEXPTRMAP",
|
[OINDEXPTRMAP] = "INDEXPTRMAP",
|
||||||
[OIND] = "IND",
|
[OIND] = "IND",
|
||||||
|
|
@ -597,6 +594,8 @@ opnames[] =
|
||||||
[ORETURN] = "RETURN",
|
[ORETURN] = "RETURN",
|
||||||
[ORSH] = "RSH",
|
[ORSH] = "RSH",
|
||||||
[OSLICE] = "SLICE",
|
[OSLICE] = "SLICE",
|
||||||
|
[OSLICESTR] = "SLICESTR",
|
||||||
|
[OSLICEPTRSTR] = "SLICEPTRSTR",
|
||||||
[OSUB] = "SUB",
|
[OSUB] = "SUB",
|
||||||
[OSWITCH] = "SWITCH",
|
[OSWITCH] = "SWITCH",
|
||||||
[OTYPE] = "TYPE",
|
[OTYPE] = "TYPE",
|
||||||
|
|
@ -1076,8 +1075,12 @@ eqtype(Node *t1, Node *t2, int d)
|
||||||
if(t1->nname != N && t1->nname->sym != S) {
|
if(t1->nname != N && t1->nname->sym != S) {
|
||||||
if(t2->nname == N || t2->nname->sym == S)
|
if(t2->nname == N || t2->nname->sym == S)
|
||||||
return 0;
|
return 0;
|
||||||
if(strcmp(t1->nname->sym->name, t2->nname->sym->name) != 0)
|
if(strcmp(t1->nname->sym->name, t2->nname->sym->name) != 0) {
|
||||||
return 0;
|
// assigned names dont count
|
||||||
|
if(t1->nname->sym->name[0] != '_' ||
|
||||||
|
t2->nname->sym->name[0] != '_')
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
t1 = t1->down;
|
t1 = t1->down;
|
||||||
t2 = t2->down;
|
t2 = t2->down;
|
||||||
|
|
@ -1106,6 +1109,41 @@ eqtype(Node *t1, Node *t2, int d)
|
||||||
return eqtype(t1->type, t2->type, d+1);
|
return eqtype(t1->type, t2->type, d+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* are the arg names of two
|
||||||
|
* functions the same. we know
|
||||||
|
* that eqtype has been called
|
||||||
|
* and has returned true.
|
||||||
|
*/
|
||||||
|
int
|
||||||
|
eqargs(Node *t1, Node *t2)
|
||||||
|
{
|
||||||
|
if(t1 == t2)
|
||||||
|
return 1;
|
||||||
|
if(t1 == N || t2 == N)
|
||||||
|
return 0;
|
||||||
|
if(t1->op != OTYPE || t2->op != OTYPE)
|
||||||
|
fatal("eqargs: oops %O %O", t1->op, t2->op);
|
||||||
|
|
||||||
|
if(t1->etype != t2->etype)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if(t1->etype != TFUNC)
|
||||||
|
fatal("eqargs: oops %E", t1->etype);
|
||||||
|
|
||||||
|
t1 = t1->type;
|
||||||
|
t2 = t2->type;
|
||||||
|
for(;;) {
|
||||||
|
if(t1 == t2)
|
||||||
|
break;
|
||||||
|
if(!eqtype(t1, t2, 0))
|
||||||
|
return 0;
|
||||||
|
t1 = t1->down;
|
||||||
|
t2 = t2->down;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
ulong
|
ulong
|
||||||
typehash(Node *at, int d)
|
typehash(Node *at, int d)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
31
src/c/walk.c
31
src/c/walk.c
|
|
@ -46,9 +46,6 @@ loop:
|
||||||
fatal("walktype: switch 1 unknown op %N", n);
|
fatal("walktype: switch 1 unknown op %N", n);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case ODCLTYPE:
|
|
||||||
goto ret;
|
|
||||||
|
|
||||||
case OPANIC:
|
case OPANIC:
|
||||||
case OPRINT:
|
case OPRINT:
|
||||||
walktype(n->left, 0);
|
walktype(n->left, 0);
|
||||||
|
|
@ -172,8 +169,6 @@ loop:
|
||||||
ascompatte(n->op, getinarg(t), &n->right);
|
ascompatte(n->op, getinarg(t), &n->right);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OCOLAS:
|
|
||||||
case ODCLVAR:
|
|
||||||
case OAS:
|
case OAS:
|
||||||
if(!top)
|
if(!top)
|
||||||
goto nottop;
|
goto nottop;
|
||||||
|
|
@ -364,6 +359,13 @@ loop:
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// left side is ptr to string
|
||||||
|
if(isptrto(t, TPTR) && isptrto(t->type, TSTRING)) {
|
||||||
|
n->op = OINDEXPTRSTR;
|
||||||
|
n->type = types[TUINT8];
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
|
|
||||||
// left side is array
|
// left side is array
|
||||||
if(t->etype == TPTR) {
|
if(t->etype == TPTR) {
|
||||||
t = t->type;
|
t = t->type;
|
||||||
|
|
@ -741,14 +743,23 @@ walkslice(Node *n)
|
||||||
|
|
||||||
if(n->left == N || n->right == N)
|
if(n->left == N || n->right == N)
|
||||||
return;
|
return;
|
||||||
walktype(n->left, 0);
|
|
||||||
if(!isptrto(n->left->type, TSTRING)) {
|
|
||||||
badtype(OSLICE, n->left->type, N);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if(n->right->op != OLIST)
|
if(n->right->op != OLIST)
|
||||||
fatal("slice not a list");
|
fatal("slice not a list");
|
||||||
|
|
||||||
|
walktype(n->left, 0);
|
||||||
|
if(isptrto(n->left->type, TSTRING)) {
|
||||||
|
n->op = OSLICESTR;
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
if(isptrto(n->left->type->type, TPTR) && isptrto(n->left->type->type, TSTRING)) {
|
||||||
|
n->op = OSLICEPTRSTR;
|
||||||
|
goto ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
badtype(OSLICE, n->left->type, N);
|
||||||
|
return;
|
||||||
|
|
||||||
|
ok:
|
||||||
// check for type errors
|
// check for type errors
|
||||||
walktype(n->right, 0);
|
walktype(n->right, 0);
|
||||||
l = n->right->left;
|
l = n->right->left;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue