Commit 5d6eba80 authored by Ken Thompson's avatar Ken Thompson

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
parent 87278c26
...@@ -283,6 +283,15 @@ funchdr(Node *n) ...@@ -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
......
...@@ -87,9 +87,6 @@ loop: ...@@ -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: ...@@ -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) ...@@ -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) ...@@ -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) ...@@ -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: ...@@ -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);
......
...@@ -171,12 +171,11 @@ enum ...@@ -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 ...@@ -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); ...@@ -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);
......
...@@ -39,8 +39,6 @@ ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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: ...@@ -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
......
...@@ -542,16 +542,12 @@ opnames[] = ...@@ -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[] = ...@@ -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[] = ...@@ -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) ...@@ -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) ...@@ -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)
{ {
......
...@@ -46,9 +46,6 @@ loop: ...@@ -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: ...@@ -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: ...@@ -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) ...@@ -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;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment