cmd/compile: don't run ComputeAddrTaken on imported generic functions

It causes a crash because of the unexpected XDOT operation. It's not
needed, since we will run ComputeAddrTaken() on function instantiations
after stenciling. And it's not always correct, since we may not be able
to distinguish between a array and a slice, if a type is dependent on a
type param.

However, we do need to call ComputeAddrTaken on instantiations created
during inlining, since that is after the main ComputeAddrTaken pass.

Fixes #49659

Change-Id: I0bb610cf11f14e4aa9068f6ca2a012337b069c79
Reviewed-on: https://go-review.googlesource.com/c/go/+/365214
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>
This commit is contained in:
Dan Scales 2021-11-18 10:52:35 -08:00
parent 2375b6edf3
commit e8cda0a6c9
7 changed files with 77 additions and 2 deletions

View file

@ -584,7 +584,7 @@ func OuterValue(n Node) Node {
for {
switch nn := n; nn.Op() {
case OXDOT:
base.FatalfAt(n.Pos(), "OXDOT in walk: %v", n)
base.FatalfAt(n.Pos(), "OXDOT in OuterValue: %v", n)
case ODOT:
nn := nn.(*SelectorExpr)
n = nn.X

View file

@ -109,6 +109,13 @@ func (g *genInst) buildInstantiations(preinliningMainScan bool) {
// main round of inlining)
for _, fun := range g.newInsts {
inline.InlineCalls(fun.(*ir.Func))
// New instantiations created during inlining should run
// ComputeAddrTaken directly, since we are past the main pass
// that did ComputeAddrTaken(). We could instead do this
// incrementally during stenciling (for all instantiations,
// including main ones before inlining), since we have the
// type information.
typecheck.ComputeAddrtaken(fun.(*ir.Func).Body)
}
}
assert(l == len(g.newInsts))

View file

@ -160,7 +160,12 @@ func ImportedBody(fn *ir.Func) {
IncrementalAddrtaken = false
defer func() {
if DirtyAddrtaken {
ComputeAddrtaken(fn.Inl.Body) // compute addrtaken marks once types are available
// We do ComputeAddrTaken on function instantiations, but not
// generic functions (since we may not yet know if x in &x[i]
// is an array or a slice).
if !fn.Type().HasTParam() {
ComputeAddrtaken(fn.Inl.Body) // compute addrtaken marks once types are available
}
DirtyAddrtaken = false
}
IncrementalAddrtaken = true

View file

@ -0,0 +1,13 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package a
type A[T any] struct {
a int
}
func (a A[T]) F() {
_ = &a.a
}

View file

@ -0,0 +1,15 @@
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package b
import "a"
type B[T any] struct {
v a.A[T]
}
func (b B[T]) F() {
b.v.F()
}

View file

@ -0,0 +1,7 @@
// compiledir -G=3
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package ignored

View file

@ -0,0 +1,28 @@
// run -gcflags=-G=3
// Copyright 2021 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
// Testing that AddrTaken logic doesn't cause problems for function instantiations
package main
type A[T interface{ []int | [5]int }] struct {
val T
}
//go:noinline
func (a A[T]) F() {
_ = &a.val[2]
}
func main() {
var x A[[]int]
x.val = make([]int, 4)
_ = &x.val[3]
x.F()
var y A[[5]int]
_ = &y.val[3]
y.F()
}