return nil
}
+// getAddressableNameFromNode is like getNameFromNode but returns nil if the node is not addressable.
+func getAddressableNameFromNode(n ir.Node) *ir.Name {
+ if name := getNameFromNode(n); name != nil && ir.IsAddressable(name) {
+ return name
+ }
+ return nil
+}
+
// keepAliveAt returns a statement that is either curNode, or a
// block containing curNode followed by a call to runtime.KeepAlive for each
// node in ns. These calls ensure that nodes in ns will be live until
if n.Sym().IsBlank() {
continue
}
+ if !ir.IsAddressable(n) {
+ base.FatalfAt(n.Pos(), "keepAliveAt: node %v is not addressable", n)
+ }
arg := ir.NewConvExpr(pos, ir.OCONV, types.Types[types.TUNSAFEPTR], typecheck.NodAddr(n))
if !n.Type().IsInterface() {
srcRType0 := reflectdata.TypePtrAt(pos, n.Type())
switch n := stmt.(type) {
case *ir.AssignStmt:
// Peel down struct and slice indexing to get the names
- name := getNameFromNode(n.X)
+ name := getAddressableNameFromNode(n.X)
if name != nil {
debugName(name, n.Pos())
ret = keepAliveAt([]ir.Node{name}, n)
case *ir.AssignListStmt:
ns := []ir.Node{}
for _, lhs := range n.Lhs {
- name := getNameFromNode(lhs)
+ name := getAddressableNameFromNode(lhs)
if name != nil {
debugName(name, n.Pos())
ns = append(ns, name)
}
ret = keepAliveAt(ns, n)
case *ir.AssignOpStmt:
- name := getNameFromNode(n.X)
+ name := getAddressableNameFromNode(n.X)
if name != nil {
debugName(name, n.Pos())
ret = keepAliveAt([]ir.Node{name}, n)
argTmps := []ir.Node{}
names := []ir.Node{}
for i, a := range n.Args {
- if name := getNameFromNode(a); name != nil {
+ if name := getAddressableNameFromNode(a); name != nil {
// If they are name, keep them alive directly.
debugName(name, n.Pos())
names = append(names, name)
s := a.(*ir.CompLitExpr)
ns := []ir.Node{}
for i, elem := range s.List {
- if name := getNameFromNode(elem); name != nil {
+ if name := getAddressableNameFromNode(elem); name != nil {
debugName(name, n.Pos())
ns = append(ns, name)
} else {
something = x[0]
}
+func receiver(f func()) { // ERROR "can inline receiver" "f does not escape"
+ f()
+}
+
+func argument() {} // ERROR "can inline argument"
+
func test(b *testing.B, localsink, cond int) { // ERROR ".*"
for i := 0; i < b.N; i++ {
caninline(1) // ERROR "inlining call to caninline"
{
caninline(1) // ERROR "inlining call to caninline" "function result will be kept alive"
}
+
+ receiver(argument) // ERROR inlining call to receiver" "function arg will be kept alive"
}
}