diff options
| author | Robert Griesemer <gri@golang.org> | 2015-07-28 15:44:19 -0700 |
|---|---|---|
| committer | Robert Griesemer <gri@golang.org> | 2015-08-21 04:42:02 +0000 |
| commit | 80eca3a98b960bd612d0251137b93dfddbbb64de (patch) | |
| tree | 0e8118b4a10d017316d4d89e049456129fabc2b2 /src | |
| parent | f1b5bb95887685afa85d6a58ee8054101ce2d24c (diff) | |
| download | go-80eca3a98b960bd612d0251137b93dfddbbb64de.tar.xz | |
go/types: don't crash for erroneous program involving a shift in a declaration cycle
R=1.6
Fixes #11347.
Change-Id: Ic6b09f38682500ffcc8d1f96e58f7237a7528806
Reviewed-on: https://go-review.googlesource.com/12812
Reviewed-by: Alan Donovan <adonovan@google.com>
Diffstat (limited to 'src')
| -rw-r--r-- | src/go/types/expr.go | 25 | ||||
| -rw-r--r-- | src/go/types/testdata/issues.src | 6 |
2 files changed, 24 insertions, 7 deletions
diff --git a/src/go/types/expr.go b/src/go/types/expr.go index 542ce76497..dd78756845 100644 --- a/src/go/types/expr.go +++ b/src/go/types/expr.go @@ -681,13 +681,24 @@ func (check *Checker) shift(x, y *operand, op token.Token) { // constant is what it would be if the shift expression // were replaced by its left operand alone.". // - // Delay operand checking until we know the final type: - // The lhs expression must be in the untyped map, mark - // the entry as lhs shift operand. - info, found := check.untyped[x.expr] - assert(found) - info.isLhs = true - check.untyped[x.expr] = info + // Delay operand checking until we know the final type + // by marking the lhs expression as lhs shift operand. + // + // Usually (in correct programs), the lhs expression + // is in the untyped map. However, it is possible to + // create incorrect programs where the same expression + // is evaluated twice (via a declaration cycle) such + // that the lhs expression type is determined in the + // first round and thus deleted from the map, and then + // not found in the second round (double insertion of + // the same expr node still just leads to one entry for + // that node, and it can only be deleted once). + // Be cautious and check for presence of entry. + // Example: var e, f = int(1<<""[f]) // issue 11347 + if info, found := check.untyped[x.expr]; found { + info.isLhs = true + check.untyped[x.expr] = info + } // keep x's type x.mode = value return diff --git a/src/go/types/testdata/issues.src b/src/go/types/testdata/issues.src index 595a6342b7..9e2c901a28 100644 --- a/src/go/types/testdata/issues.src +++ b/src/go/types/testdata/issues.src @@ -95,3 +95,9 @@ func issue10979() { m() } } + +// issue11347 +// These should not crash. +var a1, b1 /* ERROR cycle */ , c1 /* ERROR cycle */ b1 = 0 > 0<<""[""[c1]]>c1 +var a2, b2 /* ERROR cycle */ = 0 /* ERROR mismatch */ /* ERROR mismatch */ > 0<<""[b2] +var a3, b3 /* ERROR cycle */ = int /* ERROR mismatch */ /* ERROR mismatch */ (1<<""[b3]) |
