mirror of
https://github.com/golang/go
synced 2024-11-18 16:14:46 -07:00
go.tools/ssa: preserve type of &&/|| operands in result.
+ test. With this change, the Go Oracle is now self-aware. :) R=gri, rsc CC=golang-dev https://golang.org/cl/12381043
This commit is contained in:
parent
41a15a3013
commit
3b53279d8f
@ -146,14 +146,19 @@ func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value {
|
||||
rhs := fn.newBasicBlock("binop.rhs")
|
||||
done := fn.newBasicBlock("binop.done")
|
||||
|
||||
// T(e) = T(e.X) = T(e.Y) after untyped constants have been
|
||||
// eliminated.
|
||||
t := fn.Pkg.typeOf(e)
|
||||
|
||||
var short Value // value of the short-circuit path
|
||||
switch e.Op {
|
||||
case token.LAND:
|
||||
b.cond(fn, e.X, rhs, done)
|
||||
short = vFalse
|
||||
short = NewConst(exact.MakeBool(false), t)
|
||||
|
||||
case token.LOR:
|
||||
b.cond(fn, e.X, done, rhs)
|
||||
short = vTrue
|
||||
short = NewConst(exact.MakeBool(true), t)
|
||||
}
|
||||
|
||||
// Is rhs unreachable?
|
||||
@ -184,7 +189,7 @@ func (b *builder) logicalBinop(fn *Function, e *ast.BinaryExpr) Value {
|
||||
|
||||
phi := &Phi{Edges: edges, Comment: e.Op.String()}
|
||||
phi.pos = e.OpPos
|
||||
phi.typ = phi.Edges[0].Type()
|
||||
phi.typ = t
|
||||
return done.emit(phi)
|
||||
}
|
||||
|
||||
@ -433,6 +438,8 @@ func (b *builder) addr(fn *Function, e ast.Expr, escaping bool) lvalue {
|
||||
return &address{addr: fn.emit(v), expr: e}
|
||||
|
||||
case *ast.StarExpr:
|
||||
// TODO(adonovan): fix: implement nil-check if e.X
|
||||
// evaluates to nil, per http://golang.org/s/go12nil.
|
||||
return &address{addr: b.expr(fn, e.X), starPos: e.Star, expr: e}
|
||||
}
|
||||
|
||||
@ -580,7 +587,9 @@ func (b *builder) expr(fn *Function, e ast.Expr) (result Value) {
|
||||
return emitArith(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), fn.Pkg.typeOf(e), e.OpPos)
|
||||
|
||||
case token.EQL, token.NEQ, token.GTR, token.LSS, token.LEQ, token.GEQ:
|
||||
return emitCompare(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), e.OpPos)
|
||||
// TODO(gri): we shouldn't need DefaultType here.
|
||||
cmp := emitCompare(fn, e.Op, b.expr(fn, e.X), b.expr(fn, e.Y), e.OpPos)
|
||||
return emitConv(fn, cmp, DefaultType(fn.Pkg.typeOf(e)))
|
||||
default:
|
||||
panic("illegal op in BinaryExpr: " + e.Op.String())
|
||||
}
|
||||
|
17
ssa/interp/testdata/coverage.go
vendored
17
ssa/interp/testdata/coverage.go
vendored
@ -188,6 +188,8 @@ func main() {
|
||||
case anint = <-ch:
|
||||
default:
|
||||
}
|
||||
_ = anint
|
||||
_ = ok
|
||||
|
||||
// Anon structs with methods.
|
||||
anon := struct{ T }{T: T{z: 1}}
|
||||
@ -275,6 +277,19 @@ type mybool bool
|
||||
|
||||
func (mybool) f() {}
|
||||
|
||||
func init() {
|
||||
type mybool bool
|
||||
var b mybool
|
||||
var i interface{} = b || b // result preserves types of operands
|
||||
_ = i.(mybool)
|
||||
|
||||
i = false && b // result preserves type of "typed" operand
|
||||
_ = i.(mybool)
|
||||
|
||||
i = b || true // result preserves type of "typed" operand
|
||||
_ = i.(mybool)
|
||||
}
|
||||
|
||||
func init() {
|
||||
var x, y int
|
||||
var b mybool = x == y // x==y is an untyped bool
|
||||
@ -359,7 +374,7 @@ func init() {
|
||||
// An I->I type-assert fails iff the value is nil.
|
||||
func init() {
|
||||
defer func() {
|
||||
r := recover()
|
||||
r := fmt.Sprint(recover())
|
||||
if r != "interface conversion: interface is nil, not main.I" {
|
||||
panic("I->I type assertion succeeed for nil value")
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ import (
|
||||
var buildFlag = flag.String("build", "", `Options controlling the SSA builder.
|
||||
The value is a sequence of zero or more of these letters:
|
||||
C perform sanity [C]hecking of the SSA form.
|
||||
D include debug info for every function.
|
||||
D include [D]ebug info for every function.
|
||||
P log [P]ackage inventory.
|
||||
F log [F]unction SSA code.
|
||||
S log [S]ource locations as SSA builder progresses.
|
||||
@ -120,6 +120,8 @@ func main() {
|
||||
}
|
||||
prog.BuildAll()
|
||||
|
||||
prog.Package(info.Pkg).CreateTestMainFunction() // FIXME
|
||||
|
||||
// Run the interpreter.
|
||||
if *runFlag {
|
||||
interp.Interpret(prog.Package(info.Pkg), interpMode, info.Pkg.Path(), args)
|
||||
|
Loading…
Reference in New Issue
Block a user