]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: fix panic in field tracking logic
authorMatthew Dempsky <mdempsky@google.com>
Wed, 18 Nov 2020 20:08:59 +0000 (12:08 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 18 Nov 2020 22:12:57 +0000 (22:12 +0000)
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 <mdempsky@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Reviewed-by: Cherry Zhang <cherryyz@google.com>
Trust: Matthew Dempsky <mdempsky@google.com>

src/cmd/compile/internal/gc/main.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/gc/walk.go
test/fixedbugs/issue42686.go [new file with mode: 0644]

index d1097e8236d3f770745876f0728ca90865e78da5..f0a913275a0b8adc016e0c4302aeb3a9037ddb1e 100644 (file)
@@ -89,6 +89,7 @@ var debugtab = []struct {
        {"dwarfinl", "print information about DWARF inlined function creation", &Debug_gendwarfinl},
        {"softfloat", "force compiler to emit soft-float code", &Debug_softfloat},
        {"defer", "print information about defer compilation", &Debug_defer},
+       {"fieldtrack", "enable fieldtracking", &objabi.Fieldtrack_enabled},
 }
 
 const debugHelpHeader = `usage: -d arg[,arg]* and arg is <key>[=<value>]
index cbba5ff79ccaff9162aac8fbf364db102d0f78c1..c0b05035f033c1f1b6b6a54868ab2e2476471522 100644 (file)
@@ -6,7 +6,6 @@ package gc
 
 import (
        "cmd/compile/internal/types"
-       "cmd/internal/objabi"
        "fmt"
        "strings"
 )
@@ -2442,15 +2441,6 @@ func derefall(t *types.Type) *types.Type {
        return t
 }
 
-type typeSymKey struct {
-       t *types.Type
-       s *types.Sym
-}
-
-// dotField maps (*types.Type, *types.Sym) pairs to the corresponding struct field (*types.Type with Etype==TFIELD).
-// It is a cache for use during usefield in walk.go, only enabled when field tracking.
-var dotField = map[typeSymKey]*types.Field{}
-
 func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field {
        s := n.Sym
 
@@ -2481,9 +2471,6 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field {
                }
                n.Xoffset = f1.Offset
                n.Type = f1.Type
-               if objabi.Fieldtrack_enabled > 0 {
-                       dotField[typeSymKey{t.Orig, s}] = f1
-               }
                if t.IsInterface() {
                        if n.Left.Type.IsPtr() {
                                n.Left = nod(ODEREF, n.Left, nil) // implicitstar
@@ -2492,6 +2479,8 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field {
                        }
 
                        n.Op = ODOTINTER
+               } else {
+                       n.SetOpt(f1)
                }
 
                return f1
index 82898c81672bc0a69aeeb8d9f4fd3b2557d93f2f..a7b6e7fcb3c7657ed7574cc267c63fe2ea42bca9 100644 (file)
@@ -3734,10 +3734,13 @@ func usefield(n *Node) {
        if t.IsPtr() {
                t = t.Elem()
        }
-       field := dotField[typeSymKey{t.Orig, n.Sym}]
+       field := n.Opt().(*types.Field)
        if field == nil {
                Fatalf("usefield %v %v without paramfld", n.Left.Type, n.Sym)
        }
+       if field.Sym != n.Sym || field.Offset != n.Xoffset {
+               Fatalf("field inconsistency: %v,%v != %v,%v", field.Sym, field.Offset, n.Sym, n.Xoffset)
+       }
        if !strings.Contains(field.Note, "go:\"track\"") {
                return
        }
diff --git a/test/fixedbugs/issue42686.go b/test/fixedbugs/issue42686.go
new file mode 100644 (file)
index 0000000..962bdd3
--- /dev/null
@@ -0,0 +1,11 @@
+// compile -d=fieldtrack
+
+// Copyright 2020 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 p
+
+func a(x struct{ f int }) { _ = x.f }
+
+func b() { a(struct{ f int }{}) }