]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix position info for implicit nodes due to generics
authorDan Scales <danscales@google.com>
Sun, 14 Nov 2021 00:17:52 +0000 (16:17 -0800)
committerDan Scales <danscales@google.com>
Mon, 15 Nov 2021 18:02:28 +0000 (18:02 +0000)
The main fix is that we should call ir.SetPos() at the beginning of
(*subster).node.edit function, since that is analogous to the
ir.SetPos() at the beginning of typecheck.typecheck(). It ensures that
transform functions can use base.Pos() with appropriate results, just
like their corresponding tc*() functions do.

A small fix is to make sure that the new nodes creates for dictionary
references have the correct position based on the location of the
function call.

Another small fix is to the use of base.Pos when creating a new selector
expression (including implicit XDOTs) for a method expression in
buildClosure().

Also, I converted the final use of base.Pos in stencil.go to src.NoXPos,
since the nodes created by AddImplicitDots will be checked for their
type, but won't actually be used.

I also needed to add an ir.SetPos() at the beginning of transformCall(),
since transformCall() is called in the modify and dict passes, when we
base.Pos is not being set for each node.

This change fixes all the line numbering problems printed out from
Alessandro's program, except for auto-generated functions (which I think
are fine).

Fixes #49523

Change-Id: I9836a497b7beba25ecafdde653a6c2036a3020d3
Reviewed-on: https://go-review.googlesource.com/c/go/+/363835
Trust: Dan Scales <danscales@google.com>
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/noder/stencil.go
src/cmd/compile/internal/noder/transform.go

index 4f9f8107bc2d214ba802ba67bd790fa3cb0a8e31..174006ab5ed416f51dafd9a25bec27e0af0e3ce8 100644 (file)
@@ -500,7 +500,7 @@ func (g *genInst) buildClosure(outer *ir.Func, x ir.Node) ir.Node {
                        // explicitly traverse any embedded fields in the receiver
                        // argument in order to call the method instantiation.
                        arg0 := formalParams[0].Nname.(ir.Node)
-                       arg0 = typecheck.AddImplicitDots(ir.NewSelectorExpr(base.Pos, ir.OXDOT, arg0, x.(*ir.SelectorExpr).Sel)).X
+                       arg0 = typecheck.AddImplicitDots(ir.NewSelectorExpr(x.Pos(), ir.OXDOT, arg0, x.(*ir.SelectorExpr).Sel)).X
                        if valueMethod && arg0.Type().IsPtr() {
                                // For handling the (*T).M case: if we have a pointer
                                // receiver after following all the embedded fields,
@@ -616,7 +616,7 @@ func (g *genInst) getDictOrSubdict(declInfo *instInfo, n ir.Node, nameNode *ir.N
                }
        }
        if !usingSubdict {
-               dict = g.getDictionaryValue(nameNode, targs, isMeth)
+               dict = g.getDictionaryValue(n.Pos(), nameNode, targs, isMeth)
        }
        return dict, usingSubdict
 }
@@ -905,6 +905,10 @@ func (subst *subster) node(n ir.Node) ir.Node {
        // Use closure to capture all state needed by the ir.EditChildren argument.
        var edit func(ir.Node) ir.Node
        edit = func(x ir.Node) ir.Node {
+               // Analogous to ir.SetPos() at beginning of typecheck.typecheck() -
+               // allows using base.Pos during the transform functions, just like
+               // the tc*() functions.
+               ir.SetPos(x)
                switch x.Op() {
                case ir.OTYPE:
                        return ir.TypeNode(subst.ts.Typ(x.Type()))
@@ -1555,9 +1559,9 @@ func (g *genInst) getDictionarySym(gf *ir.Name, targs []*types.Type, isMeth bool
                                if se.X.Type().IsShape() {
                                        // This is a method call enabled by a type bound.
 
-                                       // We need this extra check for type expressions, which
-                                       // don't add in the implicit XDOTs.
-                                       tmpse := ir.NewSelectorExpr(base.Pos, ir.OXDOT, se.X, se.Sel)
+                                       // We need this extra check for method expressions,
+                                       // which don't add in the implicit XDOTs.
+                                       tmpse := ir.NewSelectorExpr(src.NoXPos, ir.OXDOT, se.X, se.Sel)
                                        tmpse = typecheck.AddImplicitDots(tmpse)
                                        tparam := tmpse.X.Type()
                                        if !tparam.IsShape() {
@@ -1725,7 +1729,7 @@ func (g *genInst) finalizeSyms() {
        g.dictSymsToFinalize = nil
 }
 
-func (g *genInst) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node {
+func (g *genInst) getDictionaryValue(pos src.XPos, gf *ir.Name, targs []*types.Type, isMeth bool) ir.Node {
        sym := g.getDictionarySym(gf, targs, isMeth)
 
        // Make (or reuse) a node referencing the dictionary symbol.
@@ -1733,15 +1737,18 @@ func (g *genInst) getDictionaryValue(gf *ir.Name, targs []*types.Type, isMeth bo
        if sym.Def != nil {
                n = sym.Def.(*ir.Name)
        } else {
-               n = typecheck.NewName(sym)
+               // We set the position of a static dictionary to be the position of
+               // one of its uses.
+               n = ir.NewNameAt(pos, sym)
+               n.Curfn = ir.CurFunc
                n.SetType(types.Types[types.TUINTPTR]) // should probably be [...]uintptr, but doesn't really matter
                n.SetTypecheck(1)
                n.Class = ir.PEXTERN
                sym.Def = n
        }
 
-       // Return the address of the dictionary.
-       np := typecheck.NodAddr(n)
+       // Return the address of the dictionary.  Addr node gets position that was passed in.
+       np := typecheck.NodAddrAt(pos, n)
        // Note: treat dictionary pointers as uintptrs, so they aren't pointers
        // with respect to GC. That saves on stack scanning work, write barriers, etc.
        // We can get away with it because dictionaries are global variables.
index 47e6397206d27d3e2d7966409962b2c0dd616c8e..a673484821b0c2161f2e5eb7e2a13136c5b8c12d 100644 (file)
@@ -133,6 +133,9 @@ func transformConvCall(n *ir.CallExpr) ir.Node {
 // (non-conversion, non-builtin part) of typecheck.tcCall. This code should work even
 // in the case of OCALL/OFUNCINST.
 func transformCall(n *ir.CallExpr) {
+       // Set base.Pos, since transformArgs below may need it, but transformCall
+       // is called in some passes that don't set base.Pos.
+       ir.SetPos(n)
        // n.Type() can be nil for calls with no return value
        assert(n.Typecheck() == 1)
        transformArgs(n)