go.tools/ssa: fix bad type info in 'for _ = range channel'.
Previously, if the result was not wanted, the received (value, ok) tuple had no type for 'value'. Now it is always set to the channel's element type. Also: set the position on such receive instructions to that of the = or := token, and document it. + (indirect) test via pointer analysis. R=crawshaw, gri CC=golang-dev https://golang.org/cl/12956052
This commit is contained in:
parent
7ce958b4a5
commit
de47ebac4b
|
|
@ -81,6 +81,13 @@ func chan4() {
|
||||||
print(chA) // @pointsto makechan@c4makeA:13
|
print(chA) // @pointsto makechan@c4makeA:13
|
||||||
print(chB) // @pointsto makechan@c4makeB:13
|
print(chB) // @pointsto makechan@c4makeB:13
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for k := range chA {
|
||||||
|
print(k) // @pointsto main.incr
|
||||||
|
}
|
||||||
|
// Exercise constraint generation (regtest for a crash).
|
||||||
|
for _ = range chA {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
|
|
||||||
|
|
@ -1868,8 +1868,9 @@ func (b *builder) rangeIter(fn *Function, x Value, tk, tv types.Type, pos token.
|
||||||
// channel x until it fails.
|
// channel x until it fails.
|
||||||
// tk is the channel's element type, or nil if the k result is
|
// tk is the channel's element type, or nil if the k result is
|
||||||
// not wanted
|
// not wanted
|
||||||
|
// pos is the position of the '=' or ':=' token.
|
||||||
//
|
//
|
||||||
func (b *builder) rangeChan(fn *Function, x Value, tk types.Type) (k Value, loop, done *BasicBlock) {
|
func (b *builder) rangeChan(fn *Function, x Value, tk types.Type, pos token.Pos) (k Value, loop, done *BasicBlock) {
|
||||||
//
|
//
|
||||||
// loop: (target of continue)
|
// loop: (target of continue)
|
||||||
// ko = <-x (key, ok)
|
// ko = <-x (key, ok)
|
||||||
|
|
@ -1889,8 +1890,9 @@ func (b *builder) rangeChan(fn *Function, x Value, tk types.Type) (k Value, loop
|
||||||
X: x,
|
X: x,
|
||||||
CommaOk: true,
|
CommaOk: true,
|
||||||
}
|
}
|
||||||
|
recv.setPos(pos)
|
||||||
recv.setType(types.NewTuple(
|
recv.setType(types.NewTuple(
|
||||||
types.NewVar(token.NoPos, nil, "k", tk),
|
types.NewVar(token.NoPos, nil, "k", x.Type().Underlying().(*types.Chan).Elem()),
|
||||||
varOk,
|
varOk,
|
||||||
))
|
))
|
||||||
ko := fn.emit(recv)
|
ko := fn.emit(recv)
|
||||||
|
|
@ -1940,7 +1942,7 @@ func (b *builder) rangeStmt(fn *Function, s *ast.RangeStmt, label *lblock) {
|
||||||
k, v, loop, done = b.rangeIndexed(fn, x, tv)
|
k, v, loop, done = b.rangeIndexed(fn, x, tv)
|
||||||
|
|
||||||
case *types.Chan:
|
case *types.Chan:
|
||||||
k, loop, done = b.rangeChan(fn, x, tk)
|
k, loop, done = b.rangeChan(fn, x, tk, s.TokPos)
|
||||||
|
|
||||||
case *types.Map, *types.Basic: // string
|
case *types.Map, *types.Basic: // string
|
||||||
k, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For)
|
k, v, loop, done = b.rangeIter(fn, x, tk, tv, s.For)
|
||||||
|
|
|
||||||
|
|
@ -508,7 +508,8 @@ type BinOp struct {
|
||||||
// and a boolean indicating the success of the receive. The
|
// and a boolean indicating the success of the receive. The
|
||||||
// components of the tuple are accessed using Extract.
|
// components of the tuple are accessed using Extract.
|
||||||
//
|
//
|
||||||
// Pos() returns the ast.UnaryExpr.OpPos, if explicit in the source,
|
// Pos() returns the ast.UnaryExpr.OpPos or ast.RangeStmt.TokPos (for
|
||||||
|
// ranging over a channel), if explicit in the source.
|
||||||
//
|
//
|
||||||
// Example printed form:
|
// Example printed form:
|
||||||
// t0 = *x
|
// t0 = *x
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue