mirror of
https://github.com/golang/go
synced 2024-11-23 05:40:04 -07:00
cmd/gc: allow append and complex builtins to accept 2-result call expression as first argument.
Fixes #5793. LGTM=rsc R=rsc, adonovan, dave CC=golang-codereviews https://golang.org/cl/13367051
This commit is contained in:
parent
202e6153f5
commit
671cc6efba
@ -392,6 +392,8 @@ inlnode(Node **np)
|
||||
case OCALLFUNC:
|
||||
case OCALLMETH:
|
||||
case OCALLINTER:
|
||||
case OAPPEND:
|
||||
case OCOMPLEX:
|
||||
// if we just replaced arg in f(arg()) or return arg with an inlined call
|
||||
// and arg returns multiple values, glue as list
|
||||
if(count(n->list) == 1 && n->list->n->op == OINLCALL && count(n->list->n->rlist) > 1) {
|
||||
|
@ -344,6 +344,8 @@ orderexpr(Node **np, NodeList **out)
|
||||
case OCALLFUNC:
|
||||
case OCALLMETH:
|
||||
case OCALLINTER:
|
||||
case OAPPEND:
|
||||
case OCOMPLEX:
|
||||
ordercall(n, out);
|
||||
n = copyexpr(n, n->type, out);
|
||||
break;
|
||||
|
@ -1212,17 +1212,29 @@ reswitch:
|
||||
|
||||
case OCOMPLEX:
|
||||
ok |= Erv;
|
||||
if(twoarg(n) < 0)
|
||||
goto error;
|
||||
l = typecheck(&n->left, Erv | (top & Eiota));
|
||||
r = typecheck(&n->right, Erv | (top & Eiota));
|
||||
if(l->type == T || r->type == T)
|
||||
goto error;
|
||||
defaultlit2(&l, &r, 0);
|
||||
if(l->type == T || r->type == T)
|
||||
goto error;
|
||||
n->left = l;
|
||||
n->right = r;
|
||||
if(count(n->list) == 1) {
|
||||
typechecklist(n->list, Efnstruct);
|
||||
t = n->list->n->left->type;
|
||||
if(t->outtuple != 2) {
|
||||
yyerror("invalid operation: complex expects two arguments, %N returns %d results", n->list->n, t->outtuple);
|
||||
goto error;
|
||||
}
|
||||
t = n->list->n->type->type;
|
||||
l = t->nname;
|
||||
r = t->down->nname;
|
||||
} else {
|
||||
if(twoarg(n) < 0)
|
||||
goto error;
|
||||
l = typecheck(&n->left, Erv | (top & Eiota));
|
||||
r = typecheck(&n->right, Erv | (top & Eiota));
|
||||
if(l->type == T || r->type == T)
|
||||
goto error;
|
||||
defaultlit2(&l, &r, 0);
|
||||
if(l->type == T || r->type == T)
|
||||
goto error;
|
||||
n->left = l;
|
||||
n->right = r;
|
||||
}
|
||||
if(!eqtype(l->type, r->type)) {
|
||||
yyerror("invalid operation: %N (mismatched types %T and %T)", n, l->type, r->type);
|
||||
goto error;
|
||||
@ -1301,9 +1313,22 @@ reswitch:
|
||||
yyerror("missing arguments to append");
|
||||
goto error;
|
||||
}
|
||||
typechecklist(args, Erv);
|
||||
|
||||
if(count(args) == 1 && !n->isddd)
|
||||
typecheck(&args->n, Erv | Efnstruct);
|
||||
else
|
||||
typechecklist(args, Erv);
|
||||
|
||||
if((t = args->n->type) == T)
|
||||
goto error;
|
||||
|
||||
// Unpack multiple-return result before type-checking.
|
||||
if(istype(t, TSTRUCT)) {
|
||||
t = t->type;
|
||||
if(istype(t, TFIELD))
|
||||
t = t->type;
|
||||
}
|
||||
|
||||
n->type = t;
|
||||
if(!isslice(t)) {
|
||||
if(isconst(args->n, CTNIL)) {
|
||||
|
@ -493,6 +493,11 @@ walkexpr(Node **np, NodeList **init)
|
||||
case OADD:
|
||||
case OCOMPLEX:
|
||||
case OLROT:
|
||||
// Use results from call expression as arguments for complex.
|
||||
if(n->op == OCOMPLEX && n->left == N && n->right == N) {
|
||||
n->left = n->list->n;
|
||||
n->right = n->list->next->n;
|
||||
}
|
||||
walkexpr(&n->left, init);
|
||||
walkexpr(&n->right, init);
|
||||
goto ret;
|
||||
@ -2772,6 +2777,10 @@ append(Node *n, NodeList **init)
|
||||
l->n = cheapexpr(l->n, init);
|
||||
|
||||
nsrc = n->list->n;
|
||||
|
||||
// Resolve slice type of multi-valued return.
|
||||
if(istype(nsrc->type, TSTRUCT))
|
||||
nsrc->type = nsrc->type->type->type;
|
||||
argc = count(n->list) - 1;
|
||||
if (argc < 1) {
|
||||
return nsrc;
|
||||
|
36
test/fixedbugs/issue5793.go
Normal file
36
test/fixedbugs/issue5793.go
Normal file
@ -0,0 +1,36 @@
|
||||
// run
|
||||
|
||||
// Copyright 2013 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Issue 5793: calling 2-arg builtin with multiple-result f() call expression gives
|
||||
// spurious error.
|
||||
|
||||
package main
|
||||
|
||||
func complexArgs() (float64, float64) {
|
||||
return 5, 7
|
||||
}
|
||||
|
||||
func appendArgs() ([]string, string) {
|
||||
return []string{"foo"}, "bar"
|
||||
}
|
||||
|
||||
func appendMultiArgs() ([]byte, byte, byte) {
|
||||
return []byte{'a', 'b'}, '1', '2'
|
||||
}
|
||||
|
||||
func main() {
|
||||
if c := complex(complexArgs()); c != 5+7i {
|
||||
panic(c)
|
||||
}
|
||||
|
||||
if s := append(appendArgs()); len(s) != 2 || s[0] != "foo" || s[1] != "bar" {
|
||||
panic(s)
|
||||
}
|
||||
|
||||
if b := append(appendMultiArgs()); len(b) != 4 || b[0] != 'a' || b[1] != 'b' || b[2] != '1' || b[3] != '2' {
|
||||
panic(b)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user