Skip to content

Commit 5b0ec1a

Browse files
committed
cmd/compile: fix panic in field tracking logic
Within the frontend, we generally don't guarantee uniqueness of anonymous types. For example, each struct type literal gets represented by its own types.Type instance. However, the field tracking code was using the struct type as a map key. This broke in golang.org/cl/256457, because that CL started changing the inlined parameter variables from using the types.Type of the declared parameter to that of the call site argument. These are always identical types (e.g., types.Identical would report true), but they can be different pointer values, causing the map lookup to fail. The easiest fix is to simply get rid of the map and instead use Node.Opt for tracking the types.Field. To mitigate against more latent field tracking failures (e.g., if any other code were to start trying to use Opt on ODOT/ODOTPTR fields), we store this field unconditionally. I also expect having the types.Field will be useful to other frontend code in the future. Finally, to make it easier to test field tracking without having to run make.bash with GOEXPERIMENT=fieldtrack, this commit adds a -d=fieldtrack flag as an alternative way to enable field tracking within the compiler. See also #42681. Fixes #42686. Change-Id: I6923d206d5e2cab1e6798cba36cae96c1eeaea55 Reviewed-on: https://go-review.googlesource.com/c/go/+/271217 Run-TryBot: Matthew Dempsky <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Cherry Zhang <[email protected]> Trust: Matthew Dempsky <[email protected]>
1 parent b4f3d52 commit 5b0ec1a

File tree

4 files changed

+18
-14
lines changed

4 files changed

+18
-14
lines changed

src/cmd/compile/internal/gc/main.go

+1
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ var debugtab = []struct {
8989
{"dwarfinl", "print information about DWARF inlined function creation", &Debug_gendwarfinl},
9090
{"softfloat", "force compiler to emit soft-float code", &Debug_softfloat},
9191
{"defer", "print information about defer compilation", &Debug_defer},
92+
{"fieldtrack", "enable fieldtracking", &objabi.Fieldtrack_enabled},
9293
}
9394

9495
const debugHelpHeader = `usage: -d arg[,arg]* and arg is <key>[=<value>]

src/cmd/compile/internal/gc/typecheck.go

+2-13
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ package gc
66

77
import (
88
"cmd/compile/internal/types"
9-
"cmd/internal/objabi"
109
"fmt"
1110
"strings"
1211
)
@@ -2442,15 +2441,6 @@ func derefall(t *types.Type) *types.Type {
24422441
return t
24432442
}
24442443

2445-
type typeSymKey struct {
2446-
t *types.Type
2447-
s *types.Sym
2448-
}
2449-
2450-
// dotField maps (*types.Type, *types.Sym) pairs to the corresponding struct field (*types.Type with Etype==TFIELD).
2451-
// It is a cache for use during usefield in walk.go, only enabled when field tracking.
2452-
var dotField = map[typeSymKey]*types.Field{}
2453-
24542444
func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field {
24552445
s := n.Sym
24562446

@@ -2481,9 +2471,6 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field {
24812471
}
24822472
n.Xoffset = f1.Offset
24832473
n.Type = f1.Type
2484-
if objabi.Fieldtrack_enabled > 0 {
2485-
dotField[typeSymKey{t.Orig, s}] = f1
2486-
}
24872474
if t.IsInterface() {
24882475
if n.Left.Type.IsPtr() {
24892476
n.Left = nod(ODEREF, n.Left, nil) // implicitstar
@@ -2492,6 +2479,8 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field {
24922479
}
24932480

24942481
n.Op = ODOTINTER
2482+
} else {
2483+
n.SetOpt(f1)
24952484
}
24962485

24972486
return f1

src/cmd/compile/internal/gc/walk.go

+4-1
Original file line numberDiff line numberDiff line change
@@ -3734,10 +3734,13 @@ func usefield(n *Node) {
37343734
if t.IsPtr() {
37353735
t = t.Elem()
37363736
}
3737-
field := dotField[typeSymKey{t.Orig, n.Sym}]
3737+
field := n.Opt().(*types.Field)
37383738
if field == nil {
37393739
Fatalf("usefield %v %v without paramfld", n.Left.Type, n.Sym)
37403740
}
3741+
if field.Sym != n.Sym || field.Offset != n.Xoffset {
3742+
Fatalf("field inconsistency: %v,%v != %v,%v", field.Sym, field.Offset, n.Sym, n.Xoffset)
3743+
}
37413744
if !strings.Contains(field.Note, "go:\"track\"") {
37423745
return
37433746
}

test/fixedbugs/issue42686.go

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// compile -d=fieldtrack
2+
3+
// Copyright 2020 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
package p
8+
9+
func a(x struct{ f int }) { _ = x.f }
10+
11+
func b() { a(struct{ f int }{}) }

0 commit comments

Comments
 (0)