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(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() {
|
||||
|
|
|
|||
|
|
@ -1868,8 +1868,9 @@ func (b *builder) rangeIter(fn *Function, x Value, tk, tv types.Type, pos token.
|
|||
// channel x until it fails.
|
||||
// tk is the channel's element type, or nil if the k result is
|
||||
// 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)
|
||||
// ko = <-x (key, ok)
|
||||
|
|
@ -1889,8 +1890,9 @@ func (b *builder) rangeChan(fn *Function, x Value, tk types.Type) (k Value, loop
|
|||
X: x,
|
||||
CommaOk: true,
|
||||
}
|
||||
recv.setPos(pos)
|
||||
recv.setType(types.NewTuple(
|
||||
types.NewVar(token.NoPos, nil, "k", tk),
|
||||
types.NewVar(token.NoPos, nil, "k", x.Type().Underlying().(*types.Chan).Elem()),
|
||||
varOk,
|
||||
))
|
||||
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)
|
||||
|
||||
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
|
||||
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
|
||||
// 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:
|
||||
// t0 = *x
|
||||
|
|
|
|||
Loading…
Reference in New Issue