1
0
mirror of https://github.com/golang/go synced 2024-11-11 19:31:37 -07:00

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
This commit is contained in:
Rémy Oudompheng 2014-02-24 19:51:59 +01:00
parent ff15e5c00f
commit 14b0af4272
3 changed files with 55 additions and 17 deletions

View File

@ -3171,13 +3171,10 @@ walkcompare(Node **np, NodeList **init)
}
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 @@ walkcompare(Node **np, NodeList **init)
}
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 @@ walkcompare(Node **np, NodeList **init)
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 @@ hard:
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;

View File

@ -387,6 +387,23 @@ func main() {
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)

View File

@ -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 {
}
}