// Already in the process of diagnosing an error.
return f2
}
+ orig := n.X
tt := n.X.Type()
types.CalcSize(tt)
rcvr := f2.Type.Recv().Type
}
}
- implicit, ll := n.Implicit(), n.X
- for ll != nil && (ll.Op() == ir.ODOT || ll.Op() == ir.ODOTPTR || ll.Op() == ir.ODEREF) {
- switch l := ll.(type) {
+ // Check that we haven't implicitly dereferenced any defined pointer types.
+ for x := n.X; ; {
+ var inner ir.Node
+ implicit := false
+ switch x := x.(type) {
+ case *ir.AddrExpr:
+ inner, implicit = x.X, x.Implicit()
case *ir.SelectorExpr:
- implicit, ll = l.Implicit(), l.X
+ inner, implicit = x.X, x.Implicit()
case *ir.StarExpr:
- implicit, ll = l.Implicit(), l.X
+ inner, implicit = x.X, x.Implicit()
}
- }
- if implicit && ll.Type().IsPtr() && ll.Type().Sym() != nil && ll.Type().Sym().Def != nil && ir.AsNode(ll.Type().Sym().Def).Op() == ir.OTYPE {
- // It is invalid to automatically dereference a named pointer type when selecting a method.
- // Make n.Left == ll to clarify error message.
- n.X = ll
- return nil
+ if !implicit {
+ break
+ }
+ if inner.Type().Sym() != nil && (x.Op() == ir.ODEREF || x.Op() == ir.ODOTPTR) {
+ // Found an implicit dereference of a defined pointer type.
+ // Restore n.X for better error message.
+ n.X = orig
+ return nil
+ }
+ x = inner
}
n.Selection = f2
--- /dev/null
+// errorcheck
+
+// 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
+
+type T int
+
+func (T) Mv() {}
+func (*T) Mp() {}
+
+type P1 struct{ T }
+type P2 struct{ *T }
+type P3 *struct{ T }
+type P4 *struct{ *T }
+
+func _() {
+ {
+ var p P1
+ p.Mv()
+ (&p).Mv()
+ (*&p).Mv()
+ p.Mp()
+ (&p).Mp()
+ (*&p).Mp()
+ }
+ {
+ var p P2
+ p.Mv()
+ (&p).Mv()
+ (*&p).Mv()
+ p.Mp()
+ (&p).Mp()
+ (*&p).Mp()
+ }
+ {
+ var p P3
+ p.Mv() // ERROR "undefined"
+ (&p).Mv() // ERROR "undefined"
+ (*&p).Mv() // ERROR "undefined"
+ (**&p).Mv()
+ (*p).Mv()
+ (&*p).Mv()
+ p.Mp() // ERROR "undefined"
+ (&p).Mp() // ERROR "undefined"
+ (*&p).Mp() // ERROR "undefined"
+ (**&p).Mp()
+ (*p).Mp()
+ (&*p).Mp()
+ }
+ {
+ var p P4
+ p.Mv() // ERROR "undefined"
+ (&p).Mv() // ERROR "undefined"
+ (*&p).Mv() // ERROR "undefined"
+ (**&p).Mv()
+ (*p).Mv()
+ (&*p).Mv()
+ p.Mp() // ERROR "undefined"
+ (&p).Mp() // ERROR "undefined"
+ (*&p).Mp() // ERROR "undefined"
+ (**&p).Mp()
+ (*p).Mp()
+ (&*p).Mp()
+ }
+}
+
+func _() {
+ type P5 struct{ T }
+ type P6 struct{ *T }
+ type P7 *struct{ T }
+ type P8 *struct{ *T }
+
+ {
+ var p P5
+ p.Mv()
+ (&p).Mv()
+ (*&p).Mv()
+ p.Mp()
+ (&p).Mp()
+ (*&p).Mp()
+ }
+ {
+ var p P6
+ p.Mv()
+ (&p).Mv()
+ (*&p).Mv()
+ p.Mp()
+ (&p).Mp()
+ (*&p).Mp()
+ }
+ {
+ var p P7
+ p.Mv() // ERROR "undefined"
+ (&p).Mv() // ERROR "undefined"
+ (*&p).Mv() // ERROR "undefined"
+ (**&p).Mv()
+ (*p).Mv()
+ (&*p).Mv()
+ p.Mp() // ERROR "undefined"
+ (&p).Mp() // ERROR "undefined"
+ (*&p).Mp() // ERROR "undefined"
+ (**&p).Mp()
+ (*p).Mp()
+ (&*p).Mp()
+ }
+ {
+ var p P8
+ p.Mv() // ERROR "undefined"
+ (&p).Mv() // ERROR "undefined"
+ (*&p).Mv() // ERROR "undefined"
+ (**&p).Mv()
+ (*p).Mv()
+ (&*p).Mv()
+ p.Mp() // ERROR "undefined"
+ (&p).Mp() // ERROR "undefined"
+ (*&p).Mp() // ERROR "undefined"
+ (**&p).Mp()
+ (*p).Mp()
+ (&*p).Mp()
+ }
+}