{
Type *l, *ll;
Node *r, *a;
- NodeList *nn, *lr0;
+ NodeList *nn, *lr0, *alist;
Iter savel, peekl;
lr0 = lr;
// 1 to many
peekl = savel;
- if(l != T && r != N
- && structnext(&peekl) != T
- && lr->next == nil
- && eqtypenoname(r->type, *nl)) {
- // clumsy check for differently aligned structs.
- // now that output structs are aligned separately
- // from the input structs, should never happen.
- if(r->type->width != (*nl)->width)
- fatal("misaligned multiple return\n\t%T\n\t%T", r->type, *nl);
- a = nodarg(*nl, fp);
- a->type = r->type;
- nn = list1(convas(nod(OAS, a, r), init));
- goto ret;
+ if(l != T && r != N && structnext(&peekl) != T && lr->next == nil
+ && r->type->etype == TSTRUCT && r->type->funarg) {
+ // optimization - can do block copy
+ if(eqtypenoname(r->type, *nl)) {
+ a = nodarg(*nl, fp);
+ a->type = r->type;
+ nn = list1(convas(nod(OAS, a, r), init));
+ goto ret;
+ }
+ // conversions involved.
+ // copy into temporaries.
+ alist = nil;
+ for(l=structfirst(&savel, &r->type); l; l=structnext(&savel)) {
+ a = nod(OXXX, N, N);
+ tempname(a, l->type);
+ alist = list(alist, a);
+ }
+ a = nod(OAS2, N, N);
+ a->list = alist;
+ a->rlist = lr;
+ typecheck(&a, Etop);
+ walkstmt(&a);
+ *init = list(*init, a);
+ lr = alist;
+ r = lr->n;
+ l = structfirst(&savel, nl);
}
loop:
if(l == T || r == N) {
if(l != T || r != N) {
if(l != T)
- yyerror("not enough arguments to %O", op);
+ yyerror("xxx not enough arguments to %O", op);
else
- yyerror("too many arguments to %O", op);
+ yyerror("xxx too many arguments to %O", op);
dumptypes(nl, "expected");
dumpnodetypes(lr0, "given");
}
--- /dev/null
+// $G $D/$F.go && $L $F.$A && ./$A.out
+
+// Copyright 2009 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.
+
+package main
+
+import "fmt"
+
+type Buffer int
+func (*Buffer) Read() {
+}
+
+type Reader interface { Read() }
+
+func f() *Buffer {
+ return nil
+}
+
+func g() Reader {
+ // implicit interface conversion in assignment during return
+ return f()
+}
+
+func h() (b *Buffer, ok bool) {
+ return
+}
+
+func i() (r Reader, ok bool) {
+ // implicit interface conversion in multi-assignment during return
+ return h();
+}
+
+func fmter() (s string, i int, t string) {
+ return "%#x %q", 100, "hello"
+}
+
+func main() {
+ b := g();
+ bb, ok := b.(*Buffer);
+
+ b, ok = i();
+ bb, ok = b.(*Buffer);
+
+ s := fmt.Sprintf(fmter());
+ if s != "0x64 \"hello\"" {
+ panicln(s);
+ }
+}
+