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"
+}