From 39b12e2dcb47d25828e3272649294b0ad32d6e6e Mon Sep 17 00:00:00 2001
From: Russ Cox <rsc@golang.org>
Date: Fri, 7 Aug 2009 14:38:31 -0700
Subject: [PATCH] bug185 - return b,a from func() (a,b int)

R=ken
OCL=32900
CL=32900
---
 src/cmd/gc/walk.c        | 38 ++++++++++++++++++++++++++++++++++----
 test/fixedbugs/bug185.go | 33 +++++++++++++++++++++++++++++++++
 2 files changed, 67 insertions(+), 4 deletions(-)
 create mode 100644 test/fixedbugs/bug185.go

diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 90196ad7d6..0d9f7f520e 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -247,12 +247,22 @@ walkstmtlist(NodeList *l)
 		walkstmt(&l->n);
 }
 
+static int
+samelist(NodeList *a, NodeList *b)
+{
+	for(; a && b; a=a->next, b=b->next)
+		if(a->n != b->n)
+			return 0;
+	return a == b;
+}
+
+
 void
 walkstmt(Node **np)
 {
 	NodeList *init;
-	NodeList *ll;
-	int lno;
+	NodeList *ll, *rl;
+	int cl, lno;
 	Node *n;
 
 	n = *np;
@@ -350,8 +360,28 @@ walkstmt(Node **np)
 
 	case ORETURN:
 		walkexprlist(n->list, &n->ninit);
-		if(curfn->type->outnamed && n->list == nil) {
-			// print("special return\n");
+		if(curfn->type->outnamed && count(n->list) != 1) {
+			if(n->list == nil) {
+				// print("special return\n");
+				break;
+			}
+			// assign to the function out parameters,
+			// so that reorder3 can fix up conflicts
+			rl = nil;
+			for(ll=curfn->dcl; ll != nil; ll=ll->next) {
+				cl = ll->n->class & ~PHEAP;
+				if(cl == PAUTO)
+					break;
+				if(cl == PPARAMOUT)
+					rl = list(rl, ll->n);
+			}
+			if(samelist(rl, n->list)) {
+				// special return in disguise
+				n->list = nil;
+				break;
+			}
+			ll = ascompatee(n->op, rl, n->list, &n->ninit);
+			n->list = reorder3(ll);
 			break;
 		}
 		ll = ascompatte(n->op, getoutarg(curfn->type), n->list, 1, &n->ninit);
diff --git a/test/fixedbugs/bug185.go b/test/fixedbugs/bug185.go
new file mode 100644
index 0000000000..7f4bcb2c79
--- /dev/null
+++ b/test/fixedbugs/bug185.go
@@ -0,0 +1,33 @@
+// $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
+
+func g() { }
+
+func f1() (a, b int) {
+	a, b = 2, 1;
+	g();	// defeat optimizer
+	return a, b;
+}
+
+func f2() (a, b int) {
+	a, b = 1, 2;
+	g();	// defeat optimizer
+	return b, a;
+}
+
+func main() {
+	x, y := f1();
+	if x != 2 || y != 1 {
+		panicln("f1", x, y);
+	}
+
+	x, y = f2();
+	if x != 2 || y != 1 {
+		panicln("f2", x, y);
+	}
+}
-- 
2.30.9