mirror of
https://github.com/golang/go
synced 2024-11-25 07:47:56 -07:00
delay := processing
R=ken OCL=32772 CL=32772
This commit is contained in:
parent
ebdbbe0f49
commit
54b403723b
@ -4,7 +4,7 @@
|
|||||||
|
|
||||||
CC=quietgcc
|
CC=quietgcc
|
||||||
LD=quietgcc
|
LD=quietgcc
|
||||||
CFLAGS=-ggdb -I$(GOROOT)/include -O1
|
CFLAGS=-ggdb -I$(GOROOT)/include -O1 -fno-inline
|
||||||
O=o
|
O=o
|
||||||
YFLAGS=-d
|
YFLAGS=-d
|
||||||
# GNU Make syntax:
|
# GNU Make syntax:
|
||||||
|
@ -574,6 +574,83 @@ dclchecks(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* := declarations
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int
|
||||||
|
colasname(Node *n)
|
||||||
|
{
|
||||||
|
// TODO(rsc): can probably simplify
|
||||||
|
// once late-binding of names goes in
|
||||||
|
switch(n->op) {
|
||||||
|
case ONAME:
|
||||||
|
case ONONAME:
|
||||||
|
case OPACK:
|
||||||
|
case OTYPE:
|
||||||
|
case OLITERAL:
|
||||||
|
return n->sym != S;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node*
|
||||||
|
old2new(Node *n, Type *t, NodeList **init)
|
||||||
|
{
|
||||||
|
Node *l;
|
||||||
|
|
||||||
|
if(!colasname(n)) {
|
||||||
|
yyerror("left side of := must be a name");
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
if(t != T && t->funarg) {
|
||||||
|
yyerror("use of multi func value as single value in :=");
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
l = newname(n->sym);
|
||||||
|
dodclvar(l, t, init);
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
Node*
|
||||||
|
colas(NodeList *left, NodeList *right)
|
||||||
|
{
|
||||||
|
int nnew;
|
||||||
|
Node *n, *as;
|
||||||
|
NodeList *l;
|
||||||
|
|
||||||
|
if(count(left) == 1 && count(right) == 1)
|
||||||
|
as = nod(OAS, left->n, right->n);
|
||||||
|
else {
|
||||||
|
as = nod(OAS2, N, N);
|
||||||
|
as->list = left;
|
||||||
|
as->rlist = right;
|
||||||
|
}
|
||||||
|
as->colas = 1;
|
||||||
|
|
||||||
|
nnew = 0;
|
||||||
|
for(l=left; l; l=l->next) {
|
||||||
|
n = l->n;
|
||||||
|
if(!colasname(n)) {
|
||||||
|
yyerror("non-name %#N on left side of :=", n);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if(n->sym->block == block)
|
||||||
|
continue;
|
||||||
|
nnew++;
|
||||||
|
n = newname(n->sym);
|
||||||
|
declare(n, dclcontext);
|
||||||
|
if(as->op == OAS)
|
||||||
|
as->left = n;
|
||||||
|
n->defn = as;
|
||||||
|
as->ninit = list(as->ninit, nod(ODCL, n, N));
|
||||||
|
l->n = n;
|
||||||
|
}
|
||||||
|
if(nnew == 0)
|
||||||
|
yyerror("no new variables on left side of :=");
|
||||||
|
return as;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* structs, functions, and methods.
|
* structs, functions, and methods.
|
||||||
|
@ -35,7 +35,9 @@ allocparams(void)
|
|||||||
n = l->n;
|
n = l->n;
|
||||||
if(n->op != ONAME || n->class != PAUTO)
|
if(n->op != ONAME || n->class != PAUTO)
|
||||||
continue;
|
continue;
|
||||||
typecheck(&n, Erv);
|
typecheck(&n, Erv); // only needed for unused variables
|
||||||
|
if(n->type == T)
|
||||||
|
continue;
|
||||||
dowidth(n->type);
|
dowidth(n->type);
|
||||||
w = n->type->width;
|
w = n->type->width;
|
||||||
if(n->class & PHEAP)
|
if(n->class & PHEAP)
|
||||||
|
@ -465,7 +465,8 @@ enum
|
|||||||
Etop = 1<<1, // evaluated at statement level
|
Etop = 1<<1, // evaluated at statement level
|
||||||
Erv = 1<<2, // evaluated in value context
|
Erv = 1<<2, // evaluated in value context
|
||||||
Etype = 1<<3,
|
Etype = 1<<3,
|
||||||
Ecall = 1<<4,
|
Ecall = 1<<4, // call-only expressions are ok
|
||||||
|
Efnstruct = 1<<5, // multivalue function returns are ok
|
||||||
};
|
};
|
||||||
|
|
||||||
#define BITS 5
|
#define BITS 5
|
||||||
|
@ -519,8 +519,8 @@ case:
|
|||||||
// done in casebody()
|
// done in casebody()
|
||||||
poptodcl();
|
poptodcl();
|
||||||
$$ = nod(OXCASE, N, N);
|
$$ = nod(OXCASE, N, N);
|
||||||
typecheck(&$4, Erv);
|
// $$->list = list1(nod(OAS, selectas($2, $4, &$$->ninit), $4));
|
||||||
$$->list = list1(nod(OAS, selectas($2, $4, &$$->ninit), $4));
|
$$->list = list1(colas(list1($2), list1($4)));
|
||||||
}
|
}
|
||||||
| LDEFAULT ':'
|
| LDEFAULT ':'
|
||||||
{
|
{
|
||||||
|
@ -66,6 +66,10 @@ typecheckselect(Node *sel)
|
|||||||
ncase->list = nil;
|
ncase->list = nil;
|
||||||
setlineno(n);
|
setlineno(n);
|
||||||
switch(n->op) {
|
switch(n->op) {
|
||||||
|
default:
|
||||||
|
yyerror("select case must be receive, send or assign recv");;
|
||||||
|
break;
|
||||||
|
|
||||||
case OAS:
|
case OAS:
|
||||||
// convert x = <-c into OSELRECV(x, c)
|
// convert x = <-c into OSELRECV(x, c)
|
||||||
if(n->right->op != ORECV) {
|
if(n->right->op != ORECV) {
|
||||||
@ -123,6 +127,10 @@ walkselect(Node *sel)
|
|||||||
r = nod(OIF, N, N);
|
r = nod(OIF, N, N);
|
||||||
r->nbody = ncase->ninit;
|
r->nbody = ncase->ninit;
|
||||||
ncase->ninit = nil;
|
ncase->ninit = nil;
|
||||||
|
if(n != nil) {
|
||||||
|
r->nbody = concat(r->nbody, n->ninit);
|
||||||
|
n->ninit = nil;
|
||||||
|
}
|
||||||
if(n == nil) {
|
if(n == nil) {
|
||||||
// selectdefault(sel *byte);
|
// selectdefault(sel *byte);
|
||||||
r->ntest = mkcall("selectdefault", types[TBOOL], &init, var);
|
r->ntest = mkcall("selectdefault", types[TBOOL], &init, var);
|
||||||
|
@ -582,7 +582,7 @@ dodump(Node *n, int dep)
|
|||||||
print("%O-ntype\n", n->op);
|
print("%O-ntype\n", n->op);
|
||||||
dodump(n->ntype, dep+1);
|
dodump(n->ntype, dep+1);
|
||||||
}
|
}
|
||||||
if(n->defn != nil) {
|
if(n->defn != nil && n->defn->op != OAS && n->defn->op != OAS2) {
|
||||||
indent(dep);
|
indent(dep);
|
||||||
print("%O-defn\n", n->op);
|
print("%O-defn\n", n->op);
|
||||||
dodump(n->defn, dep+1);
|
dodump(n->defn, dep+1);
|
||||||
|
@ -27,6 +27,7 @@ static int nokeys(NodeList*);
|
|||||||
static void typecheckcomplit(Node**);
|
static void typecheckcomplit(Node**);
|
||||||
static void addrescapes(Node*);
|
static void addrescapes(Node*);
|
||||||
static void typecheckas2(Node*);
|
static void typecheckas2(Node*);
|
||||||
|
static void typecheckas(Node*);
|
||||||
static void checklvalue(Node*, char*);
|
static void checklvalue(Node*, char*);
|
||||||
static void checkassign(Node*);
|
static void checkassign(Node*);
|
||||||
static void checkassignlist(NodeList*);
|
static void checkassignlist(NodeList*);
|
||||||
@ -88,8 +89,8 @@ reswitch:
|
|||||||
|
|
||||||
case ONAME:
|
case ONAME:
|
||||||
if(n->etype != 0) {
|
if(n->etype != 0) {
|
||||||
yyerror("must call builtin %S", n->sym);
|
ok |= Ecall;
|
||||||
goto error;
|
goto ret;
|
||||||
}
|
}
|
||||||
ok |= Erv;
|
ok |= Erv;
|
||||||
goto ret;
|
goto ret;
|
||||||
@ -348,6 +349,7 @@ reswitch:
|
|||||||
* exprs
|
* exprs
|
||||||
*/
|
*/
|
||||||
case OADDR:
|
case OADDR:
|
||||||
|
ok |= Erv;
|
||||||
typecheck(&n->left, Erv);
|
typecheck(&n->left, Erv);
|
||||||
if(n->left->type == T)
|
if(n->left->type == T)
|
||||||
goto error;
|
goto error;
|
||||||
@ -368,6 +370,7 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OCOMPLIT:
|
case OCOMPLIT:
|
||||||
|
ok |= Erv;
|
||||||
typecheckcomplit(&n);
|
typecheckcomplit(&n);
|
||||||
if(n->type == T)
|
if(n->type == T)
|
||||||
goto error;
|
goto error;
|
||||||
@ -403,6 +406,7 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case ODOTTYPE:
|
case ODOTTYPE:
|
||||||
|
ok |= Erv;
|
||||||
typecheck(&n->left, Erv);
|
typecheck(&n->left, Erv);
|
||||||
defaultlit(&n->left, T);
|
defaultlit(&n->left, T);
|
||||||
l = n->left;
|
l = n->left;
|
||||||
@ -422,6 +426,7 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OINDEX:
|
case OINDEX:
|
||||||
|
ok |= Erv;
|
||||||
typecheck(&n->left, Erv);
|
typecheck(&n->left, Erv);
|
||||||
defaultlit(&n->left, T);
|
defaultlit(&n->left, T);
|
||||||
implicitstar(&n->left);
|
implicitstar(&n->left);
|
||||||
@ -436,21 +441,18 @@ reswitch:
|
|||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
case TARRAY:
|
case TARRAY:
|
||||||
ok |= Erv;
|
|
||||||
defaultlit(&n->right, types[TUINT]);
|
defaultlit(&n->right, types[TUINT]);
|
||||||
n->type = t->type;
|
n->type = t->type;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TMAP:
|
case TMAP:
|
||||||
n->etype = 0;
|
n->etype = 0;
|
||||||
ok |= Erv;
|
|
||||||
defaultlit(&n->right, t->down);
|
defaultlit(&n->right, t->down);
|
||||||
n->type = t->type;
|
n->type = t->type;
|
||||||
n->op = OINDEXMAP;
|
n->op = OINDEXMAP;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TSTRING:
|
case TSTRING:
|
||||||
ok |= Erv;
|
|
||||||
defaultlit(&n->right, types[TUINT]);
|
defaultlit(&n->right, types[TUINT]);
|
||||||
n->type = types[TUINT8];
|
n->type = types[TUINT8];
|
||||||
n->op = OINDEXSTR;
|
n->op = OINDEXSTR;
|
||||||
@ -459,6 +461,7 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case ORECV:
|
case ORECV:
|
||||||
|
ok |= Etop | Erv;
|
||||||
typecheck(&n->left, Erv);
|
typecheck(&n->left, Erv);
|
||||||
defaultlit(&n->left, T);
|
defaultlit(&n->left, T);
|
||||||
l = n->left;
|
l = n->left;
|
||||||
@ -473,10 +476,10 @@ reswitch:
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
n->type = t->type;
|
n->type = t->type;
|
||||||
ok |= Erv;
|
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OSEND:
|
case OSEND:
|
||||||
|
ok |= Etop | Erv;
|
||||||
l = typecheck(&n->left, Erv);
|
l = typecheck(&n->left, Erv);
|
||||||
typecheck(&n->right, Erv);
|
typecheck(&n->right, Erv);
|
||||||
defaultlit(&n->left, T);
|
defaultlit(&n->left, T);
|
||||||
@ -495,7 +498,6 @@ reswitch:
|
|||||||
n->etype = 0;
|
n->etype = 0;
|
||||||
if(top & Erv)
|
if(top & Erv)
|
||||||
n->op = OSENDNB;
|
n->op = OSENDNB;
|
||||||
ok |= Etop | Erv;
|
|
||||||
n->type = types[TBOOL];
|
n->type = types[TBOOL];
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
@ -564,6 +566,9 @@ reswitch:
|
|||||||
typecheck(&n->left, Erv | Etype | Ecall);
|
typecheck(&n->left, Erv | Etype | Ecall);
|
||||||
defaultlit(&n->left, T);
|
defaultlit(&n->left, T);
|
||||||
l = n->left;
|
l = n->left;
|
||||||
|
if(count(n->list) == 1)
|
||||||
|
typecheck(&n->list->n, Erv | Efnstruct);
|
||||||
|
else
|
||||||
typechecklist(n->list, Erv);
|
typechecklist(n->list, Erv);
|
||||||
if((t = l->type) == T)
|
if((t = l->type) == T)
|
||||||
goto error;
|
goto error;
|
||||||
@ -598,12 +603,11 @@ reswitch:
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
typecheckaste(OCALL, getinargx(t), n->list);
|
typecheckaste(OCALL, getinargx(t), n->list);
|
||||||
if(t->outtuple == 0) {
|
|
||||||
ok |= Etop;
|
ok |= Etop;
|
||||||
|
if(t->outtuple == 0)
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
|
||||||
if(t->outtuple == 1) {
|
|
||||||
ok |= Erv;
|
ok |= Erv;
|
||||||
|
if(t->outtuple == 1) {
|
||||||
t = getoutargx(l->type)->type;
|
t = getoutargx(l->type)->type;
|
||||||
if(t->etype == TFIELD)
|
if(t->etype == TFIELD)
|
||||||
t = t->type;
|
t = t->type;
|
||||||
@ -611,12 +615,16 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
// multiple return
|
// multiple return
|
||||||
// ok |= Emulti;
|
if(!(top & (Efnstruct | Etop))) {
|
||||||
|
yyerror("multiple-value %#N() in single-value context", l);
|
||||||
|
goto ret;
|
||||||
|
}
|
||||||
n->type = getoutargx(l->type);
|
n->type = getoutargx(l->type);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OCAP:
|
case OCAP:
|
||||||
case OLEN:
|
case OLEN:
|
||||||
|
ok |= Erv;
|
||||||
if(onearg(n) < 0)
|
if(onearg(n) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
typecheck(&n->left, Erv);
|
typecheck(&n->left, Erv);
|
||||||
@ -671,6 +679,7 @@ reswitch:
|
|||||||
|
|
||||||
case OCONV:
|
case OCONV:
|
||||||
doconv:
|
doconv:
|
||||||
|
ok |= Erv;
|
||||||
typecheck(&n->left, Erv);
|
typecheck(&n->left, Erv);
|
||||||
defaultlit(&n->left, n->type);
|
defaultlit(&n->left, n->type);
|
||||||
if((t = n->left->type) == T || n->type == T)
|
if((t = n->left->type) == T || n->type == T)
|
||||||
@ -681,6 +690,7 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OMAKE:
|
case OMAKE:
|
||||||
|
ok |= Erv;
|
||||||
args = n->list;
|
args = n->list;
|
||||||
if(args == nil) {
|
if(args == nil) {
|
||||||
yyerror("missing argument to make");
|
yyerror("missing argument to make");
|
||||||
@ -779,6 +789,7 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case ONEW:
|
case ONEW:
|
||||||
|
ok |= Erv;
|
||||||
args = n->list;
|
args = n->list;
|
||||||
if(args == nil) {
|
if(args == nil) {
|
||||||
yyerror("missing argument to new");
|
yyerror("missing argument to new");
|
||||||
@ -800,6 +811,7 @@ reswitch:
|
|||||||
case OPANICN:
|
case OPANICN:
|
||||||
case OPRINT:
|
case OPRINT:
|
||||||
case OPRINTN:
|
case OPRINTN:
|
||||||
|
ok |= Etop;
|
||||||
typechecklist(n->list, Erv);
|
typechecklist(n->list, Erv);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
@ -807,14 +819,12 @@ reswitch:
|
|||||||
* statements
|
* statements
|
||||||
*/
|
*/
|
||||||
case OAS:
|
case OAS:
|
||||||
typecheck(&n->left, Erv);
|
ok |= Etop;
|
||||||
checkassign(n->left);
|
typecheckas(n);
|
||||||
typecheck(&n->right, Erv);
|
|
||||||
if(n->left->type != T && n->right && n->right->type != T)
|
|
||||||
n->right = typecheckconv(nil, n->right, n->left->type, 0);
|
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OAS2:
|
case OAS2:
|
||||||
|
ok |= Etop;
|
||||||
typecheckas2(n);
|
typecheckas2(n);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
@ -825,14 +835,17 @@ reswitch:
|
|||||||
case OGOTO:
|
case OGOTO:
|
||||||
case OLABEL:
|
case OLABEL:
|
||||||
case OXFALL:
|
case OXFALL:
|
||||||
|
ok |= Etop;
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case ODEFER:
|
case ODEFER:
|
||||||
case OPROC:
|
case OPROC:
|
||||||
|
ok |= Etop;
|
||||||
typecheck(&n->left, Etop);
|
typecheck(&n->left, Etop);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OFOR:
|
case OFOR:
|
||||||
|
ok |= Etop;
|
||||||
typechecklist(n->ninit, Etop);
|
typechecklist(n->ninit, Etop);
|
||||||
typecheck(&n->ntest, Erv);
|
typecheck(&n->ntest, Erv);
|
||||||
if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
|
if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
|
||||||
@ -842,6 +855,7 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OIF:
|
case OIF:
|
||||||
|
ok |= Etop;
|
||||||
typechecklist(n->ninit, Etop);
|
typechecklist(n->ninit, Etop);
|
||||||
typecheck(&n->ntest, Erv);
|
typecheck(&n->ntest, Erv);
|
||||||
if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
|
if(n->ntest != N && (t = n->ntest->type) != T && t->etype != TBOOL)
|
||||||
@ -851,30 +865,35 @@ reswitch:
|
|||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case ORETURN:
|
case ORETURN:
|
||||||
typechecklist(n->list, Erv);
|
ok |= Etop;
|
||||||
|
typechecklist(n->list, Erv | Efnstruct);
|
||||||
if(curfn->type->outnamed && n->list == nil)
|
if(curfn->type->outnamed && n->list == nil)
|
||||||
goto ret;
|
goto ret;
|
||||||
typecheckaste(ORETURN, getoutargx(curfn->type), n->list);
|
typecheckaste(ORETURN, getoutargx(curfn->type), n->list);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OSELECT:
|
case OSELECT:
|
||||||
|
ok |= Etop;
|
||||||
typecheckselect(n);
|
typecheckselect(n);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OSWITCH:
|
case OSWITCH:
|
||||||
|
ok |= Etop;
|
||||||
typecheckswitch(n);
|
typecheckswitch(n);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OTYPECASE:
|
case OTYPECASE:
|
||||||
|
ok |= Etop | Erv;
|
||||||
typecheck(&n->left, Erv);
|
typecheck(&n->left, Erv);
|
||||||
ok |= Erv;
|
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OTYPESW:
|
case OTYPESW:
|
||||||
|
ok |= Etop;
|
||||||
typecheck(&n->right, Erv);
|
typecheck(&n->right, Erv);
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
case OXCASE:
|
case OXCASE:
|
||||||
|
ok |= Etop;
|
||||||
typechecklist(n->list, Erv);
|
typechecklist(n->list, Erv);
|
||||||
typechecklist(n->nbody, Etop);
|
typechecklist(n->nbody, Etop);
|
||||||
goto ret;
|
goto ret;
|
||||||
@ -891,7 +910,15 @@ ret:
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
if((ok & Ecall) && !(top & Ecall)) {
|
if((ok & Ecall) && !(top & Ecall)) {
|
||||||
yyerror("must call method %#N", n);
|
yyerror("must call %#N", n);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if((top & (Ecall|Erv|Etype)) && !(ok & (Erv|Etype|Ecall))) {
|
||||||
|
yyerror("%#N used as value", n);
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
if((top & Etop) && !(ok & Etop)) {
|
||||||
|
yyerror("%#N not used", n);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1662,8 +1689,41 @@ checkassignlist(NodeList *l)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* multiple assignment
|
* type check assignment.
|
||||||
|
* if this assignment is the definition of a var on the left side,
|
||||||
|
* fill in the var's type.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
static void
|
||||||
|
typecheckas(Node *n)
|
||||||
|
{
|
||||||
|
// delicate little dance.
|
||||||
|
// the definition of n may refer to this assignment
|
||||||
|
// as its definition, in which case it will call typecheckas.
|
||||||
|
// in that case, do not call typecheck back, or it will cycle.
|
||||||
|
// if the variable has a type (ntype) then typechecking
|
||||||
|
// will not look at defn, so it is okay (and desirable,
|
||||||
|
// so that the conversion below happens).
|
||||||
|
if(n->left->defn != n || n->left->ntype)
|
||||||
|
typecheck(&n->left, Erv);
|
||||||
|
|
||||||
|
checkassign(n->left);
|
||||||
|
typecheck(&n->right, Erv);
|
||||||
|
if(n->left->type != T && n->right && n->right->type != T)
|
||||||
|
n->right = typecheckconv(nil, n->right, n->left->type, 0);
|
||||||
|
if(n->left->defn == n && n->left->ntype == N) {
|
||||||
|
defaultlit(&n->right, T);
|
||||||
|
n->left->type = n->right->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
// second half of dance.
|
||||||
|
// now that right is done, typecheck the left
|
||||||
|
// just to get it over with. see dance above.
|
||||||
|
n->typecheck = 1;
|
||||||
|
if(n->left->typecheck == 0)
|
||||||
|
typecheck(&n->left, Erv);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
typecheckas2(Node *n)
|
typecheckas2(Node *n)
|
||||||
{
|
{
|
||||||
@ -1673,19 +1733,30 @@ typecheckas2(Node *n)
|
|||||||
Iter s;
|
Iter s;
|
||||||
Type *t;
|
Type *t;
|
||||||
|
|
||||||
typechecklist(n->list, Erv);
|
for(ll=n->list; ll; ll=ll->next) {
|
||||||
checkassignlist(n->list);
|
// delicate little dance.
|
||||||
typechecklist(n->rlist, Erv);
|
if(ll->n->defn != n || ll->n->ntype)
|
||||||
|
typecheck(&ll->n, Erv);
|
||||||
|
}
|
||||||
cl = count(n->list);
|
cl = count(n->list);
|
||||||
cr = count(n->rlist);
|
cr = count(n->rlist);
|
||||||
|
checkassignlist(n->list);
|
||||||
|
if(cl > 1 && cr == 1)
|
||||||
|
typecheck(&n->rlist->n, Erv | Efnstruct);
|
||||||
|
else
|
||||||
|
typechecklist(n->rlist, Erv);
|
||||||
|
|
||||||
if(cl == cr) {
|
if(cl == cr) {
|
||||||
// easy
|
// easy
|
||||||
for(ll=n->list, lr=n->rlist; ll; ll=ll->next, lr=lr->next)
|
for(ll=n->list, lr=n->rlist; ll; ll=ll->next, lr=lr->next) {
|
||||||
if(ll->n->type != T && lr->n->type != T)
|
if(ll->n->type != T && lr->n->type != T)
|
||||||
lr->n = typecheckconv(nil, lr->n, ll->n->type, 0);
|
lr->n = typecheckconv(nil, lr->n, ll->n->type, 0);
|
||||||
return;
|
if(ll->n->defn == n && ll->n->ntype == N) {
|
||||||
|
defaultlit(&lr->n, T);
|
||||||
|
ll->n->type = lr->n->type;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1695,18 +1766,18 @@ typecheckas2(Node *n)
|
|||||||
// m[i] = x, ok
|
// m[i] = x, ok
|
||||||
if(cl == 1 && cr == 2 && l->op == OINDEXMAP) {
|
if(cl == 1 && cr == 2 && l->op == OINDEXMAP) {
|
||||||
if(l->type == T)
|
if(l->type == T)
|
||||||
return;
|
goto out;
|
||||||
n->op = OAS2MAPW;
|
n->op = OAS2MAPW;
|
||||||
n->rlist->n = typecheckconv(nil, r, l->type->down, 0);
|
n->rlist->n = typecheckconv(nil, r, l->type->down, 0);
|
||||||
r = n->rlist->next->n;
|
r = n->rlist->next->n;
|
||||||
n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 0);
|
n->rlist->next->n = typecheckconv(nil, r, types[TBOOL], 0);
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
// x,y,z = f()
|
// x,y,z = f()
|
||||||
if(cr == 1) {
|
if(cr == 1) {
|
||||||
if(r->type == T)
|
if(r->type == T)
|
||||||
return;
|
goto out;
|
||||||
switch(r->op) {
|
switch(r->op) {
|
||||||
case OCALLMETH:
|
case OCALLMETH:
|
||||||
case OCALLINTER:
|
case OCALLINTER:
|
||||||
@ -1722,16 +1793,18 @@ typecheckas2(Node *n)
|
|||||||
if(ll->n->type != T)
|
if(ll->n->type != T)
|
||||||
if(checkconv(t->type, ll->n->type, 0, &op, &et) < 0)
|
if(checkconv(t->type, ll->n->type, 0, &op, &et) < 0)
|
||||||
yyerror("cannot assign type %T to %+N", t->type, ll->n);
|
yyerror("cannot assign type %T to %+N", t->type, ll->n);
|
||||||
|
if(ll->n->defn == n && ll->n->ntype == N)
|
||||||
|
ll->n->type = t->type;
|
||||||
t = structnext(&s);
|
t = structnext(&s);
|
||||||
}
|
}
|
||||||
return;
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// x, ok = y
|
// x, ok = y
|
||||||
if(cl == 2 && cr == 1) {
|
if(cl == 2 && cr == 1) {
|
||||||
if(r->type == T)
|
if(r->type == T)
|
||||||
return;
|
goto out;
|
||||||
switch(r->op) {
|
switch(r->op) {
|
||||||
case OINDEXMAP:
|
case OINDEXMAP:
|
||||||
n->op = OAS2MAPR;
|
n->op = OAS2MAPR;
|
||||||
@ -1744,13 +1817,24 @@ typecheckas2(Node *n)
|
|||||||
common:
|
common:
|
||||||
if(l->type != T && checkconv(r->type, l->type, 0, &op, &et) < 0)
|
if(l->type != T && checkconv(r->type, l->type, 0, &op, &et) < 0)
|
||||||
yyerror("cannot assign %+N to %+N", r, l);
|
yyerror("cannot assign %+N to %+N", r, l);
|
||||||
|
if(l->defn == n)
|
||||||
|
l->type = r->type;
|
||||||
l = n->list->next->n;
|
l = n->list->next->n;
|
||||||
if(l->type != T && checkconv(types[TBOOL], l->type, 0, &op, &et) < 0)
|
if(l->type != T && checkconv(types[TBOOL], l->type, 0, &op, &et) < 0)
|
||||||
yyerror("cannot assign bool value to %+N", l);
|
yyerror("cannot assign bool value to %+N", l);
|
||||||
return;
|
if(l->defn == n && l->ntype == N)
|
||||||
|
l->type = types[TBOOL];
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mismatch:
|
mismatch:
|
||||||
yyerror("assignment count mismatch: %d = %d", cl, cr);
|
yyerror("assignment count mismatch: %d = %d", cl, cr);
|
||||||
|
|
||||||
|
out:
|
||||||
|
// second half of dance
|
||||||
|
n->typecheck = 1;
|
||||||
|
for(ll=n->list; ll; ll=ll->next)
|
||||||
|
if(ll->n->typecheck == 0)
|
||||||
|
typecheck(&ll->n, Erv);
|
||||||
}
|
}
|
||||||
|
@ -145,7 +145,6 @@ walkdef(Node *n)
|
|||||||
if(n->type != T || n->sym == S) // builtin or no name
|
if(n->type != T || n->sym == S) // builtin or no name
|
||||||
goto ret;
|
goto ret;
|
||||||
|
|
||||||
|
|
||||||
init = nil;
|
init = nil;
|
||||||
switch(n->op) {
|
switch(n->op) {
|
||||||
case OLITERAL:
|
case OLITERAL:
|
||||||
@ -185,25 +184,12 @@ walkdef(Node *n)
|
|||||||
n->diag = 1;
|
n->diag = 1;
|
||||||
goto ret;
|
goto ret;
|
||||||
}
|
}
|
||||||
n->ntype = N;
|
|
||||||
}
|
}
|
||||||
if(n->type != T)
|
if(n->type != T)
|
||||||
break;
|
break;
|
||||||
if(n->defn == N)
|
if(n->defn == N)
|
||||||
fatal("var without type, init: %S", n->sym);
|
fatal("var without type, init: %S", n->sym);
|
||||||
switch(n->defn->op) {
|
typecheck(&n->defn, Etop); // fills in n->type
|
||||||
default:
|
|
||||||
fatal("walkdef name defn");
|
|
||||||
case OAS:
|
|
||||||
typecheck(&n->defn->right, Erv);
|
|
||||||
defaultlit(&n->defn->right, T);
|
|
||||||
if((t = n->defn->right->type) == T) {
|
|
||||||
n->diag = 1;
|
|
||||||
goto ret;
|
|
||||||
}
|
|
||||||
n->type = t;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1667,7 +1653,7 @@ ifacecvt(Type *tl, Node *n, int et, NodeList **init)
|
|||||||
|
|
||||||
r = nod(OCALL, on, N);
|
r = nod(OCALL, on, N);
|
||||||
r->list = args;
|
r->list = args;
|
||||||
typecheck(&r, Erv);
|
typecheck(&r, Erv | Efnstruct);
|
||||||
walkexpr(&r, init);
|
walkexpr(&r, init);
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
@ -1716,276 +1702,6 @@ out:
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
colasname(Node *n)
|
|
||||||
{
|
|
||||||
// TODO(rsc): can probably simplify
|
|
||||||
// once late-binding of names goes in
|
|
||||||
switch(n->op) {
|
|
||||||
case ONAME:
|
|
||||||
case ONONAME:
|
|
||||||
case OPACK:
|
|
||||||
break;
|
|
||||||
case OTYPE:
|
|
||||||
case OLITERAL:
|
|
||||||
if(n->sym != S)
|
|
||||||
break;
|
|
||||||
// fallthrough
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node*
|
|
||||||
old2new(Node *n, Type *t, NodeList **init)
|
|
||||||
{
|
|
||||||
Node *l;
|
|
||||||
|
|
||||||
if(!colasname(n)) {
|
|
||||||
yyerror("left side of := must be a name");
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
if(t != T && t->funarg) {
|
|
||||||
yyerror("use of multi func value as single value in :=");
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
l = newname(n->sym);
|
|
||||||
dodclvar(l, t, init);
|
|
||||||
return l;
|
|
||||||
}
|
|
||||||
|
|
||||||
static Node*
|
|
||||||
mixedoldnew(Node *n, Type *t)
|
|
||||||
{
|
|
||||||
n = nod(OXXX, n, N);
|
|
||||||
n->type = t;
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
static NodeList*
|
|
||||||
checkmixed(NodeList *nl, NodeList **init)
|
|
||||||
{
|
|
||||||
Node *a, *l;
|
|
||||||
NodeList *ll, *n;
|
|
||||||
Type *t;
|
|
||||||
int ntot, nred;
|
|
||||||
|
|
||||||
// first pass, check if it is a special
|
|
||||||
// case of new and old declarations
|
|
||||||
|
|
||||||
ntot = 0; // number assignments
|
|
||||||
nred = 0; // number redeclarations
|
|
||||||
for(ll=nl; ll; ll=ll->next) {
|
|
||||||
l = ll->n;
|
|
||||||
t = l->type;
|
|
||||||
l = l->left;
|
|
||||||
|
|
||||||
if(!colasname(l))
|
|
||||||
goto allnew;
|
|
||||||
if(l->sym->block == block)
|
|
||||||
nred++;
|
|
||||||
ntot++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// test for special case
|
|
||||||
// a) multi-assignment (ntot>1)
|
|
||||||
// b) at least one redeclaration (red>0)
|
|
||||||
// c) not all redeclarations (nred!=ntot)
|
|
||||||
if(nred == 0 || ntot <= 1 || nred == ntot)
|
|
||||||
goto allnew;
|
|
||||||
|
|
||||||
n = nil;
|
|
||||||
for(ll=nl; ll; ll=ll->next) {
|
|
||||||
l = ll->n;
|
|
||||||
t = l->type;
|
|
||||||
l = l->left;
|
|
||||||
|
|
||||||
a = l;
|
|
||||||
if(l->sym->block != block)
|
|
||||||
a = old2new(l, t, init);
|
|
||||||
|
|
||||||
n = list(n, a);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
|
|
||||||
allnew:
|
|
||||||
// same as original
|
|
||||||
n = nil;
|
|
||||||
for(ll=nl; ll; ll=ll->next) {
|
|
||||||
l = ll->n;
|
|
||||||
t = l->type;
|
|
||||||
l = l->left;
|
|
||||||
|
|
||||||
a = old2new(l, t, init);
|
|
||||||
n = list(n, a);
|
|
||||||
}
|
|
||||||
return n;
|
|
||||||
}
|
|
||||||
|
|
||||||
Node*
|
|
||||||
colas(NodeList *ll, NodeList *lr)
|
|
||||||
{
|
|
||||||
Node *l, *r, *a, *nl, *nr;
|
|
||||||
Iter savet;
|
|
||||||
NodeList *init, *savel, *saver, *n;
|
|
||||||
Type *t;
|
|
||||||
int cl, cr;
|
|
||||||
|
|
||||||
/* nl is an expression list.
|
|
||||||
* nr is an expression list.
|
|
||||||
* return a newname-list from
|
|
||||||
* types derived from the rhs.
|
|
||||||
*/
|
|
||||||
cr = count(lr);
|
|
||||||
cl = count(ll);
|
|
||||||
init = nil;
|
|
||||||
n = nil;
|
|
||||||
|
|
||||||
/* check calls early, to give better message for a := f() */
|
|
||||||
if(cr == 1) {
|
|
||||||
nr = lr->n;
|
|
||||||
switch(nr->op) {
|
|
||||||
case OCALL:
|
|
||||||
case OCALLFUNC:
|
|
||||||
if(nr->left->op == ONAME && nr->left->etype != 0)
|
|
||||||
break;
|
|
||||||
typecheck(&nr->left, Erv | Etype | Ecall);
|
|
||||||
walkexpr(&nr->left, &init);
|
|
||||||
if(nr->left->op == OTYPE)
|
|
||||||
break;
|
|
||||||
goto call;
|
|
||||||
case OCALLMETH:
|
|
||||||
case OCALLINTER:
|
|
||||||
typecheck(&nr->left, Erv);
|
|
||||||
walkexpr(&nr->left, &init);
|
|
||||||
call:
|
|
||||||
convlit(&nr->left, types[TFUNC]);
|
|
||||||
t = nr->left->type;
|
|
||||||
if(t == T)
|
|
||||||
goto outl; // error already printed
|
|
||||||
if(t->etype == tptr)
|
|
||||||
t = t->type;
|
|
||||||
if(t == T || t->etype != TFUNC) {
|
|
||||||
yyerror("cannot call %T", t);
|
|
||||||
goto outl;
|
|
||||||
}
|
|
||||||
if(t->outtuple != cl) {
|
|
||||||
cr = t->outtuple;
|
|
||||||
goto badt;
|
|
||||||
}
|
|
||||||
// finish call - first half above
|
|
||||||
t = structfirst(&savet, getoutarg(t));
|
|
||||||
if(t == T)
|
|
||||||
goto outl;
|
|
||||||
for(savel=ll; savel; savel=savel->next) {
|
|
||||||
l = savel->n;
|
|
||||||
a = mixedoldnew(l, t->type);
|
|
||||||
n = list(n, a);
|
|
||||||
t = structnext(&savet);
|
|
||||||
}
|
|
||||||
n = checkmixed(n, &init);
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(cl != cr) {
|
|
||||||
if(cr == 1) {
|
|
||||||
nr = lr->n;
|
|
||||||
goto multi;
|
|
||||||
}
|
|
||||||
goto badt;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(savel=ll, saver=lr; savel != nil; savel=savel->next, saver=saver->next) {
|
|
||||||
l = savel->n;
|
|
||||||
r = saver->n;
|
|
||||||
|
|
||||||
typecheck(&r, Erv);
|
|
||||||
defaultlit(&r, T);
|
|
||||||
saver->n = r;
|
|
||||||
a = mixedoldnew(l, r->type);
|
|
||||||
n = list(n, a);
|
|
||||||
}
|
|
||||||
n = checkmixed(n, &init);
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
multi:
|
|
||||||
typecheck(&nr, Erv);
|
|
||||||
lr->n = nr;
|
|
||||||
|
|
||||||
/*
|
|
||||||
* there is a list on the left
|
|
||||||
* and a mono on the right.
|
|
||||||
* go into the right to get
|
|
||||||
* individual types for the left.
|
|
||||||
*/
|
|
||||||
switch(nr->op) {
|
|
||||||
default:
|
|
||||||
goto badt;
|
|
||||||
|
|
||||||
case OINDEXMAP:
|
|
||||||
// check if rhs is a map index.
|
|
||||||
// if so, types are valuetype,bool
|
|
||||||
if(cl != 2)
|
|
||||||
goto badt;
|
|
||||||
walkexpr(&nr->left, &init);
|
|
||||||
t = nr->left->type;
|
|
||||||
a = mixedoldnew(ll->n, t->type);
|
|
||||||
n = list1(a);
|
|
||||||
a = mixedoldnew(ll->next->n, types[TBOOL]);
|
|
||||||
n = list(n, a);
|
|
||||||
n = checkmixed(n, &init);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ODOTTYPE:
|
|
||||||
// a,b := i.(T)
|
|
||||||
walkdottype(nr, &init);
|
|
||||||
if(cl != 2)
|
|
||||||
goto badt;
|
|
||||||
// a,b = iface
|
|
||||||
a = mixedoldnew(ll->n, nr->type);
|
|
||||||
n = list1(a);
|
|
||||||
a = mixedoldnew(ll->next->n, types[TBOOL]);
|
|
||||||
n = list(n, a);
|
|
||||||
n = checkmixed(n, &init);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ORECV:
|
|
||||||
if(cl != 2)
|
|
||||||
goto badt;
|
|
||||||
walkexpr(&nr->left, &init);
|
|
||||||
t = nr->left->type;
|
|
||||||
if(!istype(t, TCHAN))
|
|
||||||
goto badt;
|
|
||||||
a = mixedoldnew(ll->n, t->type);
|
|
||||||
n = list1(a);
|
|
||||||
a = mixedoldnew(ll->next->n, types[TBOOL]);
|
|
||||||
n = list(n, a);
|
|
||||||
n = checkmixed(n, &init);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
goto out;
|
|
||||||
|
|
||||||
badt:
|
|
||||||
nl = ll->n;
|
|
||||||
if(nl->diag == 0) {
|
|
||||||
nl->diag = 1;
|
|
||||||
yyerror("assignment count mismatch: %d = %d %#N", cl, cr, lr->n);
|
|
||||||
}
|
|
||||||
outl:
|
|
||||||
n = ll;
|
|
||||||
|
|
||||||
out:
|
|
||||||
// n is the lhs of the assignment.
|
|
||||||
// init holds the list of declarations.
|
|
||||||
a = nod(OAS2, N, N);
|
|
||||||
a->list = n;
|
|
||||||
a->rlist = lr;
|
|
||||||
a->ninit = init;
|
|
||||||
a->colas = 1;
|
|
||||||
return a;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* rewrite a range statement
|
* rewrite a range statement
|
||||||
* k and v are names/new_names
|
* k and v are names/new_names
|
||||||
@ -2596,7 +2312,7 @@ vmkcall(Node *fn, Type *t, NodeList **init, va_list va)
|
|||||||
r = nod(OCALL, fn, N);
|
r = nod(OCALL, fn, N);
|
||||||
r->list = args;
|
r->list = args;
|
||||||
if(fn->type->outtuple > 0)
|
if(fn->type->outtuple > 0)
|
||||||
typecheck(&r, Erv);
|
typecheck(&r, Erv | Efnstruct);
|
||||||
else
|
else
|
||||||
typecheck(&r, Etop);
|
typecheck(&r, Etop);
|
||||||
walkexpr(&r, init);
|
walkexpr(&r, init);
|
||||||
|
@ -16,8 +16,9 @@ maketest() {
|
|||||||
do
|
do
|
||||||
(
|
(
|
||||||
xcd $i
|
xcd $i
|
||||||
make clean
|
# make clean
|
||||||
time make
|
# time make
|
||||||
|
make install
|
||||||
make test
|
make test
|
||||||
) || exit $?
|
) || exit $?
|
||||||
done
|
done
|
||||||
|
@ -16,7 +16,7 @@ func main() {
|
|||||||
{
|
{
|
||||||
// simple redeclaration
|
// simple redeclaration
|
||||||
i := f1();
|
i := f1();
|
||||||
i := f1(); // ERROR "redeclared|redefinition"
|
i := f1(); // ERROR "redeclared|redefinition|no new"
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// change of type for f
|
// change of type for f
|
||||||
@ -31,21 +31,21 @@ func main() {
|
|||||||
{
|
{
|
||||||
// no new variables
|
// no new variables
|
||||||
i, f, s := f3();
|
i, f, s := f3();
|
||||||
i, f := f2(); // ERROR "redeclared|redefinition"
|
i, f := f2(); // ERROR "redeclared|redefinition|no new"
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// single redeclaration
|
// single redeclaration
|
||||||
i, f, s := f3(); // GCCGO_ERROR "previous"
|
i, f, s := f3(); // GCCGO_ERROR "previous"
|
||||||
i := f1(); // ERROR "redeclared|redefinition"
|
i := f1(); // ERROR "redeclared|redefinition|no new"
|
||||||
}
|
}
|
||||||
// double redeclaration
|
// double redeclaration
|
||||||
{
|
{
|
||||||
i, f, s := f3();
|
i, f, s := f3();
|
||||||
i, f := f2(); // ERROR "redeclared|redefinition"
|
i, f := f2(); // ERROR "redeclared|redefinition|no new"
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// triple redeclaration
|
// triple redeclaration
|
||||||
i, f, s := f3();
|
i, f, s := f3();
|
||||||
i, f, s := f3(); // ERROR "redeclared|redefinition"
|
i, f, s := f3(); // ERROR "redeclared|redefinition|no new"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,5 +8,5 @@ package main
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
var x int;
|
var x int;
|
||||||
x := 0; // BUG: redeclaration - should not compile
|
x := 0; // ERROR "declar|:="
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
func f9(a int) (i int, f float) {
|
func f9(a int) (i int, f float) {
|
||||||
i := 9; // ERROR "redecl"
|
i := 9; // ERROR "redecl|no new"
|
||||||
f := float(9); // ERROR "redecl"
|
f := float(9); // ERROR "redecl|no new"
|
||||||
return i, f;
|
return i, f;
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,6 @@ package main
|
|||||||
func f() /* no return type */ {}
|
func f() /* no return type */ {}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
x := f(); // ERROR "mismatch"
|
x := f(); // ERROR "mismatch|as value"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user