Commit 671cc6ef authored by Chris Manghane's avatar Chris Manghane Committed by Russ Cox

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
parent 202e6153
......@@ -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;
......
// 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)
}
}
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