cmd/internal/gc: method selector should not auto-deref named pointer type
Fixes #9017.
Change-Id: I26cb1e7d6e137ff145773169cfe2d8bd4e1b339c
Reviewed-on: https://go-review.googlesource.com/1252
Reviewed-by: Russ Cox <rsc@golang.org>
Run-TryBot: Chris Manghane <cmang@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
diff --git a/src/cmd/internal/gc/subr.go b/src/cmd/internal/gc/subr.go
index f7c07584..9dc573e 100644
--- a/src/cmd/internal/gc/subr.go
+++ b/src/cmd/internal/gc/subr.go
@@ -2172,6 +2172,9 @@
// rebuild elided dots
for c := d - 1; c >= 0; c-- {
+ if n.Left.Type != nil && Isptr[n.Left.Type.Etype] != 0 {
+ n.Left.Implicit = 1
+ }
n.Left = Nod(ODOT, n.Left, newname(dotlist[c].field.Sym))
}
diff --git a/src/cmd/internal/gc/typecheck.go b/src/cmd/internal/gc/typecheck.go
index 9fa1930..1468d5f 100644
--- a/src/cmd/internal/gc/typecheck.go
+++ b/src/cmd/internal/gc/typecheck.go
@@ -2433,6 +2433,19 @@
}
}
+ ll := n.Left
+ for ll.Left != nil {
+ ll = ll.Left
+ }
+ if ll.Implicit != 0 {
+ if Isptr[ll.Type.Etype] != 0 && ll.Type.Sym != nil && ll.Type.Sym.Def != nil && ll.Type.Sym.Def.Op == OTYPE {
+ // It is invalid to automatically dereference a named pointer type when selecting a method.
+ // Make n->left == ll to clarify error message.
+ n.Left = ll
+ return false
+ }
+ }
+
n.Right = methodname(n.Right, n.Left.Type)
n.Xoffset = f2.Width
n.Type = f2.Type
diff --git a/test/fixedbugs/issue9017.go b/test/fixedbugs/issue9017.go
new file mode 100644
index 0000000..e19bac2b
--- /dev/null
+++ b/test/fixedbugs/issue9017.go
@@ -0,0 +1,57 @@
+// errorcheck
+
+// Copyright 2014 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.
+
+// Issue 9017: Method selector shouldn't automatically dereference a named pointer type.
+
+package main
+
+type T struct{ x int }
+
+func (T) mT() {}
+
+type S struct {
+ T
+}
+
+func (S) mS() {}
+
+type P *S
+
+type I interface {
+ mT()
+}
+
+func main() {
+ var s S
+ s.T.mT()
+ s.mT() // == s.T.mT()
+
+ var i I
+ _ = i
+ i = s.T
+ i = s
+
+ var ps = &s
+ ps.mS()
+ ps.T.mT()
+ ps.mT() // == ps.T.mT()
+
+ i = ps.T
+ i = ps
+
+ var p P = ps
+ (*p).mS()
+ p.mS() // ERROR "undefined"
+
+ i = *p
+ i = p // ERROR "cannot use|incompatible types"
+
+ p.T.mT()
+ p.mT() // ERROR "undefined"
+
+ i = p.T
+ i = p // ERROR "cannot use|incompatible types"
+}