mirror of https://github.com/golang/go.git
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:
parent
ff15e5c00f
commit
14b0af4272
|
|
@ -3171,11 +3171,8 @@ walkcompare(Node **np, NodeList **init)
|
||||||
}
|
}
|
||||||
if(expr == N)
|
if(expr == N)
|
||||||
expr = nodbool(n->op == OEQ);
|
expr = nodbool(n->op == OEQ);
|
||||||
typecheck(&expr, Erv);
|
r = expr;
|
||||||
walkexpr(&expr, init);
|
goto ret;
|
||||||
expr->type = n->type;
|
|
||||||
*np = expr;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(t->etype == TSTRUCT && countfield(t) <= 4) {
|
if(t->etype == TSTRUCT && countfield(t) <= 4) {
|
||||||
|
|
@ -3194,11 +3191,8 @@ walkcompare(Node **np, NodeList **init)
|
||||||
}
|
}
|
||||||
if(expr == N)
|
if(expr == N)
|
||||||
expr = nodbool(n->op == OEQ);
|
expr = nodbool(n->op == OEQ);
|
||||||
typecheck(&expr, Erv);
|
r = expr;
|
||||||
walkexpr(&expr, init);
|
goto ret;
|
||||||
expr->type = n->type;
|
|
||||||
*np = expr;
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Chose not to inline, but still have addresses.
|
// Chose not to inline, but still have addresses.
|
||||||
|
|
@ -3233,10 +3227,7 @@ walkcompare(Node **np, NodeList **init)
|
||||||
|
|
||||||
if(n->op != OEQ)
|
if(n->op != OEQ)
|
||||||
r = nod(ONOT, r, N);
|
r = nod(ONOT, r, N);
|
||||||
typecheck(&r, Erv);
|
goto ret;
|
||||||
walkexpr(&r, init);
|
|
||||||
*np = r;
|
|
||||||
return;
|
|
||||||
|
|
||||||
hard:
|
hard:
|
||||||
// Cannot take address of one or both of the operands.
|
// 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);
|
r = mkcall1(fn, n->type, init, typename(n->left->type), l, r);
|
||||||
if(n->op == ONE) {
|
if(n->op == ONE) {
|
||||||
r = nod(ONOT, r, N);
|
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;
|
*np = r;
|
||||||
return;
|
return;
|
||||||
|
|
|
||||||
17
test/cmp.go
17
test/cmp.go
|
|
@ -387,6 +387,23 @@ func main() {
|
||||||
isfalse(iz != x)
|
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(p1)
|
||||||
shouldPanic(p2)
|
shouldPanic(p2)
|
||||||
shouldPanic(p3)
|
shouldPanic(p3)
|
||||||
|
|
|
||||||
|
|
@ -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 {
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue