aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCuong Manh Le <cuong.manhle.vn@gmail.com>2022-05-30 21:34:01 +0700
committerHeschi Kreinick <heschi@google.com>2022-07-06 19:31:10 +0000
commit3da88c0bdc94f8cacc5cef3026a7e256109e616d (patch)
treef904550973079686da32c6b5b25a4f1235f4d39f
parentf0eca661ea69b107143c9619ec0d0df4829b5b7e (diff)
downloadgo-3da88c0bdc94f8cacc5cef3026a7e256109e616d.tar.gz
go-3da88c0bdc94f8cacc5cef3026a7e256109e616d.zip
[release-branch.go1.18] cmd/compile: fix wrong unsafe.Offsetof evaluation inside generic function
For instantiated generic functions, all implicit dot operations are resolved. Thus unsafe.Offsetof may calculating the offset against the wrong base selector. To fix it, we must remove any implicit dot operations to find the first non-implicit one, which is the right base selector for calculating the offset. Fixes #53159 Change-Id: I38504067ce0f274615b306edc8f7d7933bdb631a Reviewed-on: https://go-review.googlesource.com/c/go/+/409355 Run-TryBot: Cuong Manh Le <cuong.manhle.vn@gmail.com> Reviewed-by: Dmitri Shuralyov <dmitshur@google.com> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> Reviewed-on: https://go-review.googlesource.com/c/go/+/409494
-rw-r--r--src/cmd/compile/internal/typecheck/const.go12
-rw-r--r--test/fixedbugs/issue53137.dir/main.go30
-rw-r--r--test/fixedbugs/issue53137.go7
3 files changed, 49 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/typecheck/const.go b/src/cmd/compile/internal/typecheck/const.go
index fbe7c02c49..24058fae58 100644
--- a/src/cmd/compile/internal/typecheck/const.go
+++ b/src/cmd/compile/internal/typecheck/const.go
@@ -895,6 +895,18 @@ func evalunsafe(n ir.Node) int64 {
sel.X = Expr(sel.X)
sbase := sel.X
+ // Implicit dot may already be resolved for instantiating generic function. So we
+ // need to remove any implicit dot until we reach the first non-implicit one, it's
+ // the right base selector. See issue #53137.
+ var clobberBase func(n ir.Node) ir.Node
+ clobberBase = func(n ir.Node) ir.Node {
+ if sel, ok := n.(*ir.SelectorExpr); ok && sel.Implicit() {
+ return clobberBase(sel.X)
+ }
+ return n
+ }
+ sbase = clobberBase(sbase)
+
tsel := Expr(sel)
n.X = tsel
if tsel.Type() == nil {
diff --git a/test/fixedbugs/issue53137.dir/main.go b/test/fixedbugs/issue53137.dir/main.go
new file mode 100644
index 0000000000..88632bf0cb
--- /dev/null
+++ b/test/fixedbugs/issue53137.dir/main.go
@@ -0,0 +1,30 @@
+// Copyright 2022 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 main
+
+import (
+ "unsafe"
+)
+
+type Embedded struct {
+ B int
+}
+
+type S[K any] struct {
+ A K
+ Embedded
+}
+
+func showOffsets[K any](d *S[K]) {
+ o1 := unsafe.Offsetof(d.B)
+ o2 := unsafe.Offsetof(d.Embedded)
+ if o1 != o2 {
+ panic("offset mismatch")
+ }
+}
+
+func main() {
+ showOffsets(new(S[int]))
+}
diff --git a/test/fixedbugs/issue53137.go b/test/fixedbugs/issue53137.go
new file mode 100644
index 0000000000..aefbe67310
--- /dev/null
+++ b/test/fixedbugs/issue53137.go
@@ -0,0 +1,7 @@
+// rundir
+
+// Copyright 2022 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