Commit 75dd8fdb authored by Russ Cox's avatar Russ Cox

gc: ... changes

R=ken2, ken3
CC=golang-dev
https://golang.org/cl/2208047
parent 6cf1a344
...@@ -68,7 +68,7 @@ static void fixlbrace(int); ...@@ -68,7 +68,7 @@ static void fixlbrace(int);
%type <list> xdcl fnbody fnres switch_body loop_body dcl_name_list %type <list> xdcl fnbody fnres switch_body loop_body dcl_name_list
%type <list> new_name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list %type <list> new_name_list expr_list keyval_list braced_keyval_list expr_or_type_list xdcl_list
%type <list> oexpr_list oexpr_or_type_list_ocomma caseblock_list stmt_list oarg_type_list_ocomma arg_type_list %type <list> oexpr_list caseblock_list stmt_list oarg_type_list_ocomma arg_type_list
%type <list> interfacedcl_list vardcl vardcl_list structdcl structdcl_list %type <list> interfacedcl_list vardcl vardcl_list structdcl structdcl_list
%type <list> common_dcl constdcl constdcl1 constdcl_list typedcl_list %type <list> common_dcl constdcl constdcl1 constdcl_list typedcl_list
...@@ -808,10 +808,20 @@ uexpr: ...@@ -808,10 +808,20 @@ uexpr:
* can be preceded by 'defer' and 'go' * can be preceded by 'defer' and 'go'
*/ */
pseudocall: pseudocall:
pexpr '(' oexpr_or_type_list_ocomma ')' pexpr '(' ')'
{
$$ = nod(OCALL, $1, N);
}
| pexpr '(' expr_or_type_list ocomma ')'
{
$$ = nod(OCALL, $1, N);
$$->list = $3;
}
| pexpr '(' expr_or_type_list LDDD ocomma ')'
{ {
$$ = nod(OCALL, $1, N); $$ = nod(OCALL, $1, N);
$$->list = $3; $$->list = $3;
$$->isddd = 1;
} }
pexpr_no_paren: pexpr_no_paren:
...@@ -1583,12 +1593,6 @@ oexpr_list: ...@@ -1583,12 +1593,6 @@ oexpr_list:
} }
| expr_list | expr_list
oexpr_or_type_list_ocomma:
{
$$ = nil;
}
| expr_or_type_list ocomma
osimple_stmt: osimple_stmt:
{ {
$$ = N; $$ = N;
......
...@@ -271,7 +271,6 @@ setlineno(Node *n) ...@@ -271,7 +271,6 @@ setlineno(Node *n)
case OTYPE: case OTYPE:
case OPACK: case OPACK:
case OLITERAL: case OLITERAL:
case ONONAME:
break; break;
default: default:
lineno = n->lineno; lineno = n->lineno;
...@@ -3033,11 +3032,14 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) ...@@ -3033,11 +3032,14 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
Node *this, *fn, *call, *n, *t, *pad; Node *this, *fn, *call, *n, *t, *pad;
NodeList *l, *args, *in, *out; NodeList *l, *args, *in, *out;
Type *tpad; Type *tpad;
int isddd;
if(debug['r']) if(debug['r'])
print("genwrapper rcvrtype=%T method=%T newnam=%S\n", print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
rcvr, method, newnam); rcvr, method, newnam);
lineno = 1; // less confusing than end of input
dclcontext = PEXTERN; dclcontext = PEXTERN;
markdcl(); markdcl();
...@@ -3069,12 +3071,16 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface) ...@@ -3069,12 +3071,16 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
// arg list // arg list
args = nil; args = nil;
for(l=in; l; l=l->next) isddd = 0;
for(l=in; l; l=l->next) {
args = list(args, l->n->left); args = list(args, l->n->left);
isddd = l->n->left->isddd;
}
// generate call // generate call
call = nod(OCALL, adddot(nod(OXDOT, this->left, newname(method->sym))), N); call = nod(OCALL, adddot(nod(OXDOT, this->left, newname(method->sym))), N);
call->list = args; call->list = args;
call->isddd = isddd;
fn->nbody = list1(call); fn->nbody = list1(call);
if(method->type->outtuple > 0) { if(method->type->outtuple > 0) {
n = nod(ORETURN, N, N); n = nod(ORETURN, N, N);
......
...@@ -17,7 +17,7 @@ static void implicitstar(Node**); ...@@ -17,7 +17,7 @@ static void implicitstar(Node**);
static int onearg(Node*, char*, ...); static int onearg(Node*, char*, ...);
static int twoarg(Node*); static int twoarg(Node*);
static int lookdot(Node*, Type*, int); static int lookdot(Node*, Type*, int);
static void typecheckaste(int, Type*, NodeList*, char*); static void typecheckaste(int, int, Type*, NodeList*, char*);
static Type* lookdot1(Sym *s, Type *t, Type *f, int); static Type* lookdot1(Sym *s, Type *t, Type *f, int);
static int nokeys(NodeList*); static int nokeys(NodeList*);
static void typecheckcomplit(Node**); static void typecheckcomplit(Node**);
...@@ -716,12 +716,16 @@ reswitch: ...@@ -716,12 +716,16 @@ reswitch:
case OCALL: case OCALL:
l = n->left; l = n->left;
if(l->op == ONAME && (r = unsafenmagic(n)) != N) { if(l->op == ONAME && (r = unsafenmagic(n)) != N) {
if(n->isddd)
yyerror("invalid use of ... with builtin %#N", l);
n = r; n = r;
goto reswitch; goto reswitch;
} }
typecheck(&n->left, Erv | Etype | Ecall); typecheck(&n->left, Erv | Etype | Ecall);
l = n->left; l = n->left;
if(l->op == ONAME && l->etype != 0) { if(l->op == ONAME && l->etype != 0) {
if(n->isddd)
yyerror("invalid use of ... with builtin %#N", l);
// builtin: OLEN, OCAP, etc. // builtin: OLEN, OCAP, etc.
n->op = l->etype; n->op = l->etype;
n->left = n->right; n->left = n->right;
...@@ -731,6 +735,8 @@ reswitch: ...@@ -731,6 +735,8 @@ reswitch:
defaultlit(&n->left, T); defaultlit(&n->left, T);
l = n->left; l = n->left;
if(l->op == OTYPE) { if(l->op == OTYPE) {
if(n->isddd)
yyerror("invalid use of ... in type conversion", l);
// pick off before type-checking arguments // pick off before type-checking arguments
ok |= Erv; ok |= Erv;
// turn CALL(type, arg) into CONV(arg) w/ type // turn CALL(type, arg) into CONV(arg) w/ type
...@@ -757,7 +763,7 @@ reswitch: ...@@ -757,7 +763,7 @@ reswitch:
case ODOTMETH: case ODOTMETH:
n->op = OCALLMETH; n->op = OCALLMETH;
typecheckaste(OCALL, getthisx(t), list1(l->left), "method receiver"); typecheckaste(OCALL, 0, getthisx(t), list1(l->left), "method receiver");
break; break;
default: default:
...@@ -768,7 +774,7 @@ reswitch: ...@@ -768,7 +774,7 @@ reswitch:
} }
break; break;
} }
typecheckaste(OCALL, getinargx(t), n->list, "function argument"); typecheckaste(OCALL, n->isddd, getinargx(t), n->list, "function argument");
ok |= Etop; ok |= Etop;
if(t->outtuple == 0) if(t->outtuple == 0)
goto ret; goto ret;
...@@ -1160,7 +1166,7 @@ reswitch: ...@@ -1160,7 +1166,7 @@ reswitch:
} }
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, "return argument"); typecheckaste(ORETURN, 0, getoutargx(curfn->type), n->list, "return argument");
goto ret; goto ret;
case OSELECT: case OSELECT:
...@@ -1451,7 +1457,7 @@ nokeys(NodeList *l) ...@@ -1451,7 +1457,7 @@ nokeys(NodeList *l)
* typecheck assignment: type list = expression list * typecheck assignment: type list = expression list
*/ */
static void static void
typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc) typecheckaste(int op, int isddd, Type *tstruct, NodeList *nl, char *desc)
{ {
Type *t, *tl, *tn; Type *t, *tl, *tn;
Node *n; Node *n;
...@@ -1465,7 +1471,6 @@ typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc) ...@@ -1465,7 +1471,6 @@ typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc)
if(nl != nil && nl->next == nil && (n = nl->n)->type != T) if(nl != nil && nl->next == nil && (n = nl->n)->type != T)
if(n->type->etype == TSTRUCT && n->type->funarg) { if(n->type->etype == TSTRUCT && n->type->funarg) {
setlineno(n);
tn = n->type->type; tn = n->type->type;
for(tl=tstruct->type; tl; tl=tl->down) { for(tl=tstruct->type; tl; tl=tl->down) {
if(tl->isddd) { if(tl->isddd) {
...@@ -1474,29 +1479,34 @@ typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc) ...@@ -1474,29 +1479,34 @@ typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc)
yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type->type, desc, why); yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type->type, desc, why);
goto out; goto out;
} }
if(tn == T) { if(tn == T)
yyerror("not enough arguments to %#O", op); goto notenough;
goto out;
}
if(assignop(tn->type, tl->type, &why) == 0) if(assignop(tn->type, tl->type, &why) == 0)
yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type, desc, why); yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type, desc, why);
tn = tn->down; tn = tn->down;
} }
if(tn != T) if(tn != T)
yyerror("too many arguments to %#O", op); goto toomany;
goto out; goto out;
} }
for(tl=tstruct->type; tl; tl=tl->down) { for(tl=tstruct->type; tl; tl=tl->down) {
t = tl->type; t = tl->type;
if(tl->isddd) { if(tl->isddd) {
if(nl != nil && nl->n->isddd && !eqtype(nl->n->type, t)) { if(nl != nil && nl->n->isddd && !isddd) {
// TODO(rsc): This is not actually illegal but will // TODO(rsc): This is not actually illegal, but it will help catch bugs.
// help catch bugs. yyerror("to pass '%#N' as ...%T, use '%#N...'", nl->n, t->type, nl->n);
yyerror("cannot pass %+N as %T (... mismatch)", nl->n, tl); isddd = 1;
} }
if(nl != nil && nl->next == nil && nl->n->isddd && eqtype(nl->n->type, t)) if(isddd) {
if(nl == nil)
goto notenough;
if(nl->next != nil)
goto toomany;
if(assignop(nl->n->type, t, &why) == 0)
yyerror("ddd cannot use %+N as type %T in %s%s", nl->n, t, desc, why);
goto out; goto out;
}
for(; nl; nl=nl->next) { for(; nl; nl=nl->next) {
setlineno(nl->n); setlineno(nl->n);
defaultlit(&nl->n, t->type); defaultlit(&nl->n, t->type);
...@@ -1505,23 +1515,30 @@ typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc) ...@@ -1505,23 +1515,30 @@ typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc)
} }
goto out; goto out;
} }
if(nl == nil) { if(nl == nil)
yyerror("not enough arguments to %#O", op); goto notenough;
goto out;
}
n = nl->n; n = nl->n;
setlineno(nl->n); setlineno(n);
if(n->type != T) if(n->type != T)
nl->n = assignconv(n, t, desc); nl->n = assignconv(n, t, desc);
nl = nl->next; nl = nl->next;
} }
if(nl != nil) { if(nl != nil)
yyerror("too many arguments to %#O", op); goto toomany;
goto out; if(isddd)
} yyerror("invalid use of ... in %#O", op);
out: out:
lineno = lno; lineno = lno;
return;
notenough:
yyerror("not enough arguments to %#O", op);
goto out;
toomany:
yyerror("too many arguments to %#O", op);
goto out;
} }
/* /*
...@@ -1695,11 +1712,13 @@ typecheckcomplit(Node **np) ...@@ -1695,11 +1712,13 @@ typecheckcomplit(Node **np)
NodeList *ll; NodeList *ll;
Type *t, *f; Type *t, *f;
Sym *s; Sym *s;
int32 lno;
n = *np; n = *np;
lno = lineno;
memset(hash, 0, sizeof hash); memset(hash, 0, sizeof hash);
setlineno(n->right);
l = typecheck(&n->right /* sic */, Etype); l = typecheck(&n->right /* sic */, Etype);
if((t = l->type) == T) if((t = l->type) == T)
goto error; goto error;
...@@ -1715,6 +1734,7 @@ typecheckcomplit(Node **np) ...@@ -1715,6 +1734,7 @@ typecheckcomplit(Node **np)
i = 0; i = 0;
for(ll=n->list; ll; ll=ll->next) { for(ll=n->list; ll; ll=ll->next) {
l = ll->n; l = ll->n;
setlineno(l);
if(l->op == OKEY) { if(l->op == OKEY) {
typecheck(&l->left, Erv); typecheck(&l->left, Erv);
evconst(l->left); evconst(l->left);
...@@ -1756,6 +1776,7 @@ typecheckcomplit(Node **np) ...@@ -1756,6 +1776,7 @@ typecheckcomplit(Node **np)
case TMAP: case TMAP:
for(ll=n->list; ll; ll=ll->next) { for(ll=n->list; ll; ll=ll->next) {
l = ll->n; l = ll->n;
setlineno(l);
if(l->op != OKEY) { if(l->op != OKEY) {
typecheck(&ll->n, Erv); typecheck(&ll->n, Erv);
yyerror("missing key in map literal"); yyerror("missing key in map literal");
...@@ -1778,6 +1799,7 @@ typecheckcomplit(Node **np) ...@@ -1778,6 +1799,7 @@ typecheckcomplit(Node **np)
// simple list of variables // simple list of variables
f = t->type; f = t->type;
for(ll=n->list; ll; ll=ll->next) { for(ll=n->list; ll; ll=ll->next) {
setlineno(ll->n);
typecheck(&ll->n, Erv); typecheck(&ll->n, Erv);
if(f == nil) { if(f == nil) {
if(!bad++) if(!bad++)
...@@ -1798,6 +1820,7 @@ typecheckcomplit(Node **np) ...@@ -1798,6 +1820,7 @@ typecheckcomplit(Node **np)
// keyed list // keyed list
for(ll=n->list; ll; ll=ll->next) { for(ll=n->list; ll; ll=ll->next) {
l = ll->n; l = ll->n;
setlineno(l);
if(l->op != OKEY) { if(l->op != OKEY) {
if(!bad++) if(!bad++)
yyerror("mixture of field:value and value initializers"); yyerror("mixture of field:value and value initializers");
...@@ -1836,11 +1859,13 @@ typecheckcomplit(Node **np) ...@@ -1836,11 +1859,13 @@ typecheckcomplit(Node **np)
n->type = t; n->type = t;
*np = n; *np = n;
lineno = lno;
return; return;
error: error:
n->type = T; n->type = T;
*np = n; *np = n;
lineno = lno;
} }
/* /*
......
...@@ -6,6 +6,8 @@ ...@@ -6,6 +6,8 @@
package main package main
import "unsafe"
func sum(args ...int) int { return 0 } func sum(args ...int) int { return 0 }
var ( var (
...@@ -26,3 +28,20 @@ var ( ...@@ -26,3 +28,20 @@ var (
_ = funny(nil, nil) _ = funny(nil, nil)
_ = funny([]T{}) // ok because []T{} is a T; passes []T{[]T{}} _ = funny([]T{}) // ok because []T{} is a T; passes []T{[]T{}}
) )
func bad(args ...int) {
print(1, 2, args...) // ERROR "[.][.][.]"
println(args...) // ERROR "[.][.][.]"
ch := make(chan int)
close(ch...) // ERROR "[.][.][.]"
_ = len(args...) // ERROR "[.][.][.]"
_ = closed(ch...) // ERROR "[.][.][.]"
_ = new(int...) // ERROR "[.][.][.]"
n := 10
_ = make([]byte, n...) // ERROR "[.][.][.]"
// TODO(rsc): enable after gofmt bug is fixed
// _ = make([]byte, 10 ...) // error "[.][.][.]"
var x int
_ = unsafe.Pointer(&x...) // ERROR "[.][.][.]"
_ = unsafe.Sizeof(x...) // ERROR "[.][.][.]"
}
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