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:
Alan Donovan 2013-08-27 11:18:31 -04:00
parent 7ce958b4a5
commit de47ebac4b
3 changed files with 14 additions and 4 deletions

View File

@ -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() {

View File

@ -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)

View File

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