cmd/gc: fix walkcompare bugs.

Revision c0e0467635ec (cmd/gc: return canonical Node* from temp)
exposed original nodes of temporaries, allowing callers to mutate
their types.

In walkcompare a temporary could be typed as ideal because of
this. Additionnally, assignment of a comparison result to
a custom boolean type was broken.

Fixes #7366.

LGTM=rsc
R=rsc, iant, khr
CC=golang-codereviews
https://golang.org/cl/66930044
diff --git a/src/cmd/gc/walk.c b/src/cmd/gc/walk.c
index 97473de..068e38c 100644
--- a/src/cmd/gc/walk.c
+++ b/src/cmd/gc/walk.c
@@ -3171,13 +3171,10 @@
 		}
 		if(expr == N)
 			expr = nodbool(n->op == OEQ);
-		typecheck(&expr, Erv);
-		walkexpr(&expr, init);
-		expr->type = n->type;
-		*np = expr;
-		return;
+		r = expr;
+		goto ret;
 	}
-	
+
 	if(t->etype == TSTRUCT && countfield(t) <= 4) {
 		// Struct of four or fewer fields.
 		// Inline comparisons.
@@ -3194,13 +3191,10 @@
 		}
 		if(expr == N)
 			expr = nodbool(n->op == OEQ);
-		typecheck(&expr, Erv);
-		walkexpr(&expr, init);
-		expr->type = n->type;
-		*np = expr;
-		return;
+		r = expr;
+		goto ret;
 	}
-	
+
 	// Chose not to inline, but still have addresses.
 	// Call equality function directly.
 	// The equality function requires a bool pointer for
@@ -3233,10 +3227,7 @@
 
 	if(n->op != OEQ)
 		r = nod(ONOT, r, N);
-	typecheck(&r, Erv);
-	walkexpr(&r, init);
-	*np = r;
-	return;
+	goto ret;
 
 hard:
 	// Cannot take address of one or both of the operands.
@@ -3252,7 +3243,16 @@
 	r = mkcall1(fn, n->type, init, typename(n->left->type), l, r);
 	if(n->op == ONE) {
 		r = nod(ONOT, r, N);
-		typecheck(&r, Erv);
+	}
+	goto ret;
+
+ret:
+	typecheck(&r, Erv);
+	walkexpr(&r, init);
+	if(r->type != n->type) {
+		r = nod(OCONVNOP, r, N);
+		r->type = n->type;
+		r->typecheck = 1;
 	}
 	*np = r;
 	return;
diff --git a/test/cmp.go b/test/cmp.go
index 73de502..9ac0ebe 100644
--- a/test/cmp.go
+++ b/test/cmp.go
@@ -387,6 +387,23 @@
 		isfalse(iz != x)
 	}
 
+	// named booleans
+	{
+		type mybool bool
+		var b mybool
+
+		type T struct{ data [20]byte }
+		var x, y T
+		b = x == y
+		istrue(x == y)
+		istrue(bool(b))
+
+		m := make(map[string][10]interface{})
+		b = m["x"] == m["y"]
+		istrue(m["x"] == m["y"])
+		istrue(bool(b))
+	}
+
 	shouldPanic(p1)
 	shouldPanic(p2)
 	shouldPanic(p3)
diff --git a/test/fixedbugs/issue7366.go b/test/fixedbugs/issue7366.go
new file mode 100644
index 0000000..754da6f
--- /dev/null
+++ b/test/fixedbugs/issue7366.go
@@ -0,0 +1,21 @@
+// compile
+
+// Copyright 2014 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 7366: generates a temporary with ideal type
+// during comparison of small structs.
+
+package main
+
+type T struct {
+	data [10]byte
+}
+
+func main() {
+	var a T
+	var b T
+	if a == b {
+	}
+}