Skip to content

Commit 6731659

Browse files
committed
go/ssa: adds position info to implicit field selection instructions
Fixes golang/go#51986 Change-Id: I1fa5868d70ae53f57b6c2bc0c4dbe4ac524b89e6 Reviewed-on: https://go-review.googlesource.com/c/tools/+/396495 gopls-CI: kokoro <[email protected]> Run-TryBot: Zvonimir Pavlinovic <[email protected]> Reviewed-by: Robert Findley <[email protected]> Reviewed-by: Tim King <[email protected]> Trust: Zvonimir Pavlinovic <[email protected]>
1 parent 74cea6e commit 6731659

File tree

5 files changed

+26
-6
lines changed

5 files changed

+26
-6
lines changed

go/analysis/passes/nilness/testdata/src/a/a.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,3 +181,16 @@ func f11(a interface{}) {
181181
return
182182
}
183183
}
184+
185+
type Y struct {
186+
innerY
187+
}
188+
189+
type innerY struct {
190+
value int
191+
}
192+
193+
func f12() {
194+
var d *Y
195+
print(d.value) // want "nil dereference in field selection"
196+
}

go/ssa/builder.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -741,7 +741,7 @@ func (b *builder) expr0(fn *Function, e ast.Expr, tv types.TypeAndValue) Value {
741741
indices := sel.Index()
742742
last := len(indices) - 1
743743
v := b.expr(fn, e.X)
744-
v = emitImplicitSelections(fn, v, indices[:last])
744+
v = emitImplicitSelections(fn, v, indices[:last], e.Pos())
745745
v = emitFieldSelection(fn, v, indices[last], false, e.Sel)
746746
return v
747747
}
@@ -832,7 +832,8 @@ func (b *builder) receiver(fn *Function, e ast.Expr, wantAddr, escaping bool, se
832832
}
833833

834834
last := len(sel.Index()) - 1
835-
v = emitImplicitSelections(fn, v, sel.Index()[:last])
835+
// The position of implicit selection is the position of the inducing receiver expression.
836+
v = emitImplicitSelections(fn, v, sel.Index()[:last], e.Pos())
836837
if !wantAddr && isPointer(v.Type()) {
837838
v = emitLoad(fn, v)
838839
}

go/ssa/emit.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -373,7 +373,7 @@ func emitTailCall(f *Function, call *Call) {
373373
// a field; if it is the value of a struct, the result will be the
374374
// value of a field.
375375
//
376-
func emitImplicitSelections(f *Function, v Value, indices []int) Value {
376+
func emitImplicitSelections(f *Function, v Value, indices []int, pos token.Pos) Value {
377377
for _, index := range indices {
378378
fld := deref(v.Type()).Underlying().(*types.Struct).Field(index)
379379

@@ -382,6 +382,7 @@ func emitImplicitSelections(f *Function, v Value, indices []int) Value {
382382
X: v,
383383
Field: index,
384384
}
385+
instr.setPos(pos)
385386
instr.setType(types.NewPointer(fld.Type()))
386387
v = f.emit(instr)
387388
// Load the field's value iff indirectly embedded.
@@ -393,6 +394,7 @@ func emitImplicitSelections(f *Function, v Value, indices []int) Value {
393394
X: v,
394395
Field: index,
395396
}
397+
instr.setPos(pos)
396398
instr.setType(fld.Type())
397399
v = f.emit(instr)
398400
}

go/ssa/ssa.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -795,7 +795,8 @@ type Slice struct {
795795
// Type() returns a (possibly named) *types.Pointer.
796796
//
797797
// Pos() returns the position of the ast.SelectorExpr.Sel for the
798-
// field, if explicit in the source.
798+
// field, if explicit in the source. For implicit selections, returns
799+
// the position of the inducing explicit selection.
799800
//
800801
// Example printed form:
801802
// t1 = &t0.name [#1]
@@ -813,7 +814,9 @@ type FieldAddr struct {
813814
// package-local identifiers and permit compact representations.
814815
//
815816
// Pos() returns the position of the ast.SelectorExpr.Sel for the
816-
// field, if explicit in the source.
817+
// field, if explicit in the source. For implicit selections, returns
818+
// the position of the inducing explicit selection.
819+
817820
//
818821
// Example printed form:
819822
// t1 = t0.name [#1]

go/ssa/wrappers.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ package ssa
2222
import (
2323
"fmt"
2424

25+
"go/token"
2526
"go/types"
2627
)
2728

@@ -112,7 +113,7 @@ func makeWrapper(prog *Program, sel *types.Selection) *Function {
112113
// Load) in preference to value extraction (Field possibly
113114
// preceded by Load).
114115

115-
v = emitImplicitSelections(fn, v, indices[:len(indices)-1])
116+
v = emitImplicitSelections(fn, v, indices[:len(indices)-1], token.NoPos)
116117

117118
// Invariant: v is a pointer, either
118119
// value of implicit *C field, or

0 commit comments

Comments
 (0)