mirror of
https://github.com/golang/go
synced 2024-11-21 20:14:52 -07:00
gc: ... changes
R=ken2, ken3 CC=golang-dev https://golang.org/cl/2208047
This commit is contained in:
parent
6cf1a34402
commit
75dd8fdb34
@ -68,7 +68,7 @@ static void fixlbrace(int);
|
||||
|
||||
%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> 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> common_dcl constdcl constdcl1 constdcl_list typedcl_list
|
||||
|
||||
@ -808,11 +808,21 @@ uexpr:
|
||||
* can be preceded by 'defer' and 'go'
|
||||
*/
|
||||
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);
|
||||
$$->list = $3;
|
||||
$$->isddd = 1;
|
||||
}
|
||||
|
||||
pexpr_no_paren:
|
||||
LLITERAL
|
||||
@ -1583,12 +1593,6 @@ oexpr_list:
|
||||
}
|
||||
| expr_list
|
||||
|
||||
oexpr_or_type_list_ocomma:
|
||||
{
|
||||
$$ = nil;
|
||||
}
|
||||
| expr_or_type_list ocomma
|
||||
|
||||
osimple_stmt:
|
||||
{
|
||||
$$ = N;
|
||||
|
@ -271,7 +271,6 @@ setlineno(Node *n)
|
||||
case OTYPE:
|
||||
case OPACK:
|
||||
case OLITERAL:
|
||||
case ONONAME:
|
||||
break;
|
||||
default:
|
||||
lineno = n->lineno;
|
||||
@ -3033,11 +3032,14 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
|
||||
Node *this, *fn, *call, *n, *t, *pad;
|
||||
NodeList *l, *args, *in, *out;
|
||||
Type *tpad;
|
||||
int isddd;
|
||||
|
||||
if(debug['r'])
|
||||
print("genwrapper rcvrtype=%T method=%T newnam=%S\n",
|
||||
rcvr, method, newnam);
|
||||
|
||||
lineno = 1; // less confusing than end of input
|
||||
|
||||
dclcontext = PEXTERN;
|
||||
markdcl();
|
||||
|
||||
@ -3069,12 +3071,16 @@ genwrapper(Type *rcvr, Type *method, Sym *newnam, int iface)
|
||||
|
||||
// arg list
|
||||
args = nil;
|
||||
for(l=in; l; l=l->next)
|
||||
isddd = 0;
|
||||
for(l=in; l; l=l->next) {
|
||||
args = list(args, l->n->left);
|
||||
isddd = l->n->left->isddd;
|
||||
}
|
||||
|
||||
// generate call
|
||||
call = nod(OCALL, adddot(nod(OXDOT, this->left, newname(method->sym))), N);
|
||||
call->list = args;
|
||||
call->isddd = isddd;
|
||||
fn->nbody = list1(call);
|
||||
if(method->type->outtuple > 0) {
|
||||
n = nod(ORETURN, N, N);
|
||||
|
@ -17,7 +17,7 @@ static void implicitstar(Node**);
|
||||
static int onearg(Node*, char*, ...);
|
||||
static int twoarg(Node*);
|
||||
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 int nokeys(NodeList*);
|
||||
static void typecheckcomplit(Node**);
|
||||
@ -716,12 +716,16 @@ reswitch:
|
||||
case OCALL:
|
||||
l = n->left;
|
||||
if(l->op == ONAME && (r = unsafenmagic(n)) != N) {
|
||||
if(n->isddd)
|
||||
yyerror("invalid use of ... with builtin %#N", l);
|
||||
n = r;
|
||||
goto reswitch;
|
||||
}
|
||||
typecheck(&n->left, Erv | Etype | Ecall);
|
||||
l = n->left;
|
||||
if(l->op == ONAME && l->etype != 0) {
|
||||
if(n->isddd)
|
||||
yyerror("invalid use of ... with builtin %#N", l);
|
||||
// builtin: OLEN, OCAP, etc.
|
||||
n->op = l->etype;
|
||||
n->left = n->right;
|
||||
@ -731,6 +735,8 @@ reswitch:
|
||||
defaultlit(&n->left, T);
|
||||
l = n->left;
|
||||
if(l->op == OTYPE) {
|
||||
if(n->isddd)
|
||||
yyerror("invalid use of ... in type conversion", l);
|
||||
// pick off before type-checking arguments
|
||||
ok |= Erv;
|
||||
// turn CALL(type, arg) into CONV(arg) w/ type
|
||||
@ -757,7 +763,7 @@ reswitch:
|
||||
|
||||
case ODOTMETH:
|
||||
n->op = OCALLMETH;
|
||||
typecheckaste(OCALL, getthisx(t), list1(l->left), "method receiver");
|
||||
typecheckaste(OCALL, 0, getthisx(t), list1(l->left), "method receiver");
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -768,7 +774,7 @@ reswitch:
|
||||
}
|
||||
break;
|
||||
}
|
||||
typecheckaste(OCALL, getinargx(t), n->list, "function argument");
|
||||
typecheckaste(OCALL, n->isddd, getinargx(t), n->list, "function argument");
|
||||
ok |= Etop;
|
||||
if(t->outtuple == 0)
|
||||
goto ret;
|
||||
@ -1160,7 +1166,7 @@ reswitch:
|
||||
}
|
||||
if(curfn->type->outnamed && n->list == nil)
|
||||
goto ret;
|
||||
typecheckaste(ORETURN, getoutargx(curfn->type), n->list, "return argument");
|
||||
typecheckaste(ORETURN, 0, getoutargx(curfn->type), n->list, "return argument");
|
||||
goto ret;
|
||||
|
||||
case OSELECT:
|
||||
@ -1451,7 +1457,7 @@ nokeys(NodeList *l)
|
||||
* typecheck assignment: type list = expression list
|
||||
*/
|
||||
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;
|
||||
Node *n;
|
||||
@ -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(n->type->etype == TSTRUCT && n->type->funarg) {
|
||||
setlineno(n);
|
||||
tn = n->type->type;
|
||||
for(tl=tstruct->type; tl; tl=tl->down) {
|
||||
if(tl->isddd) {
|
||||
@ -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);
|
||||
goto out;
|
||||
}
|
||||
if(tn == T) {
|
||||
yyerror("not enough arguments to %#O", op);
|
||||
goto out;
|
||||
}
|
||||
if(tn == T)
|
||||
goto notenough;
|
||||
if(assignop(tn->type, tl->type, &why) == 0)
|
||||
yyerror("cannot use %T as type %T in %s%s", tn->type, tl->type, desc, why);
|
||||
tn = tn->down;
|
||||
}
|
||||
if(tn != T)
|
||||
yyerror("too many arguments to %#O", op);
|
||||
goto toomany;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for(tl=tstruct->type; tl; tl=tl->down) {
|
||||
t = tl->type;
|
||||
if(tl->isddd) {
|
||||
if(nl != nil && nl->n->isddd && !eqtype(nl->n->type, t)) {
|
||||
// TODO(rsc): This is not actually illegal but will
|
||||
// help catch bugs.
|
||||
yyerror("cannot pass %+N as %T (... mismatch)", nl->n, tl);
|
||||
if(nl != nil && nl->n->isddd && !isddd) {
|
||||
// TODO(rsc): This is not actually illegal, but it will help catch bugs.
|
||||
yyerror("to pass '%#N' as ...%T, use '%#N...'", nl->n, t->type, nl->n);
|
||||
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;
|
||||
}
|
||||
for(; nl; nl=nl->next) {
|
||||
setlineno(nl->n);
|
||||
defaultlit(&nl->n, t->type);
|
||||
@ -1505,23 +1515,30 @@ typecheckaste(int op, Type *tstruct, NodeList *nl, char *desc)
|
||||
}
|
||||
goto out;
|
||||
}
|
||||
if(nl == nil) {
|
||||
yyerror("not enough arguments to %#O", op);
|
||||
goto out;
|
||||
}
|
||||
if(nl == nil)
|
||||
goto notenough;
|
||||
n = nl->n;
|
||||
setlineno(nl->n);
|
||||
setlineno(n);
|
||||
if(n->type != T)
|
||||
nl->n = assignconv(n, t, desc);
|
||||
nl = nl->next;
|
||||
}
|
||||
if(nl != nil) {
|
||||
yyerror("too many arguments to %#O", op);
|
||||
goto out;
|
||||
}
|
||||
if(nl != nil)
|
||||
goto toomany;
|
||||
if(isddd)
|
||||
yyerror("invalid use of ... in %#O", op);
|
||||
|
||||
out:
|
||||
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)
|
||||
NodeList *ll;
|
||||
Type *t, *f;
|
||||
Sym *s;
|
||||
int32 lno;
|
||||
|
||||
n = *np;
|
||||
lno = lineno;
|
||||
|
||||
memset(hash, 0, sizeof hash);
|
||||
|
||||
setlineno(n->right);
|
||||
l = typecheck(&n->right /* sic */, Etype);
|
||||
if((t = l->type) == T)
|
||||
goto error;
|
||||
@ -1715,6 +1734,7 @@ typecheckcomplit(Node **np)
|
||||
i = 0;
|
||||
for(ll=n->list; ll; ll=ll->next) {
|
||||
l = ll->n;
|
||||
setlineno(l);
|
||||
if(l->op == OKEY) {
|
||||
typecheck(&l->left, Erv);
|
||||
evconst(l->left);
|
||||
@ -1756,6 +1776,7 @@ typecheckcomplit(Node **np)
|
||||
case TMAP:
|
||||
for(ll=n->list; ll; ll=ll->next) {
|
||||
l = ll->n;
|
||||
setlineno(l);
|
||||
if(l->op != OKEY) {
|
||||
typecheck(&ll->n, Erv);
|
||||
yyerror("missing key in map literal");
|
||||
@ -1778,6 +1799,7 @@ typecheckcomplit(Node **np)
|
||||
// simple list of variables
|
||||
f = t->type;
|
||||
for(ll=n->list; ll; ll=ll->next) {
|
||||
setlineno(ll->n);
|
||||
typecheck(&ll->n, Erv);
|
||||
if(f == nil) {
|
||||
if(!bad++)
|
||||
@ -1798,6 +1820,7 @@ typecheckcomplit(Node **np)
|
||||
// keyed list
|
||||
for(ll=n->list; ll; ll=ll->next) {
|
||||
l = ll->n;
|
||||
setlineno(l);
|
||||
if(l->op != OKEY) {
|
||||
if(!bad++)
|
||||
yyerror("mixture of field:value and value initializers");
|
||||
@ -1836,11 +1859,13 @@ typecheckcomplit(Node **np)
|
||||
n->type = t;
|
||||
|
||||
*np = n;
|
||||
lineno = lno;
|
||||
return;
|
||||
|
||||
error:
|
||||
n->type = T;
|
||||
*np = n;
|
||||
lineno = lno;
|
||||
}
|
||||
|
||||
/*
|
||||
|
19
test/ddd1.go
19
test/ddd1.go
@ -6,6 +6,8 @@
|
||||
|
||||
package main
|
||||
|
||||
import "unsafe"
|
||||
|
||||
func sum(args ...int) int { return 0 }
|
||||
|
||||
var (
|
||||
@ -26,3 +28,20 @@ var (
|
||||
_ = funny(nil, nil)
|
||||
_ = 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 "[.][.][.]"
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user