]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typealias] cmd/compile: declare methods after resolving receiver type
authorMatthew Dempsky <mdempsky@google.com>
Mon, 23 Jan 2017 22:24:24 +0000 (14:24 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Wed, 25 Jan 2017 08:04:17 +0000 (08:04 +0000)
For #18130.
Fixes #18655.

Change-Id: I58e2f076b9d8273f128cc033bba9edcd06c81567
Reviewed-on: https://go-review.googlesource.com/35575
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/bimport.go
src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/export.go
src/cmd/compile/internal/gc/noder.go
src/cmd/compile/internal/gc/typecheck.go
test/alias2.go
test/fixedbugs/issue18655.go [new file with mode: 0644]

index 3c1f7100c306efe0833b29a2617a552e627e634f..1ee9e76737e51644514526fadfa7a35be38bc0a1 100644 (file)
@@ -466,14 +466,7 @@ func (p *importer) typ() *Type {
                        result := p.paramList()
                        nointerface := p.bool()
 
-                       base := recv[0].Type
-                       star := false
-                       if base.IsPtr() {
-                               base = base.Elem()
-                               star = true
-                       }
-
-                       n := methodname0(sym, star, base.Sym)
+                       n := newfuncname(methodname(sym, recv[0].Type))
                        n.Type = functypefield(recv[0], params, result)
                        checkwidth(n.Type)
                        addmethod(sym, n.Type, false, nointerface)
index a5c50f06dccacdacbb737a1c7ce0d85059b032de..856a7faced906ed71d7c25e1b3d83f8ec2541421 100644 (file)
@@ -519,10 +519,6 @@ func funchdr(n *Node) {
                Fatalf("funchdr: dclcontext = %d", dclcontext)
        }
 
-       if Ctxt.Flag_dynlink && importpkg == nil && n.Func.Nname != nil {
-               makefuncsym(n.Func.Nname.Sym)
-       }
-
        dclcontext = PAUTO
        funcstart(n)
 
@@ -1163,19 +1159,19 @@ bad:
        return nil
 }
 
-func methodname(s *Sym, recv *Node) *Node {
+// methodname is a misnomer because this now returns a Sym, rather
+// than an ONAME.
+// TODO(mdempsky): Reconcile with methodsym.
+func methodname(s *Sym, recv *Type) *Sym {
        star := false
-       if recv.Op == OIND {
+       if recv.IsPtr() {
                star = true
-               recv = recv.Left
+               recv = recv.Elem()
        }
 
-       return methodname0(s, star, recv.Sym)
-}
-
-func methodname0(s *Sym, star bool, tsym *Sym) *Node {
+       tsym := recv.Sym
        if tsym == nil || isblanksym(s) {
-               return newfuncname(s)
+               return s
        }
 
        var p string
@@ -1191,7 +1187,7 @@ func methodname0(s *Sym, star bool, tsym *Sym) *Node {
                s = Pkglookup(p, tsym.Pkg)
        }
 
-       return newfuncname(s)
+       return s
 }
 
 // Add a method, declared as a function.
@@ -1335,6 +1331,9 @@ func makefuncsym(s *Sym) {
                return
        }
        s1 := funcsym(s)
+       if s1.Def != nil {
+               return
+       }
        s1.Def = newfuncname(s1)
        s1.Def.Func.Shortname = s
        funcsyms = append(funcsyms, s1.Def)
index 5556984dcb6a144f3fe1706fbc75e8c3be726dbe..58b2bf8121bf73cace44cd7cf1d18099c3b27024 100644 (file)
@@ -83,7 +83,7 @@ func autoexport(n *Node, ctxt Class) {
        if (ctxt != PEXTERN && ctxt != PFUNC) || dclcontext != PEXTERN {
                return
        }
-       if n.Name.Param != nil && n.Name.Param.Ntype != nil && n.Name.Param.Ntype.Op == OTFUNC && n.Name.Param.Ntype.Left != nil { // method
+       if n.Type != nil && n.Type.IsKind(TFUNC) && n.Type.Recv() != nil { // method
                return
        }
 
index 0c5957f987c575f3367f89655fc3fdb703f11774..1d69151cc41dd2be51a70c01b9cf37820353774f 100644 (file)
@@ -247,19 +247,19 @@ func (p *noder) funcHeader(fun *syntax.FuncDecl) *Node {
                                yyerror("func main must have no arguments and no return values")
                        }
                }
-
-               f.Func.Nname = newfuncname(name)
        } else {
-               // Receiver MethodName Signature
-
                f.Func.Shortname = name
-               f.Func.Nname = methodname(f.Func.Shortname, t.Left.Right)
+               name = nblank.Sym // filled in by typecheckfunc
        }
 
+       f.Func.Nname = newfuncname(name)
        f.Func.Nname.Name.Defn = f
        f.Func.Nname.Name.Param.Ntype = t // TODO: check if nname already has an ntype
 
-       declare(f.Func.Nname, PFUNC)
+       if fun.Recv == nil {
+               declare(f.Func.Nname, PFUNC)
+       }
+
        funchdr(f)
        return f
 }
index d7516107636eaf23ad2ac317ef2ac371e867913c..1379bb56d4c5282d24fd994cb722eb326e046219 100644 (file)
@@ -3436,8 +3436,15 @@ func typecheckfunc(n *Node) {
        t.SetNname(n.Func.Nname)
        rcvr := t.Recv()
        if rcvr != nil && n.Func.Shortname != nil {
+               n.Func.Nname.Sym = methodname(n.Func.Shortname, rcvr.Type)
+               declare(n.Func.Nname, PFUNC)
+
                addmethod(n.Func.Shortname, t, true, n.Func.Pragma&Nointerface != 0)
        }
+
+       if Ctxt.Flag_dynlink && importpkg == nil && n.Func.Nname != nil {
+               makefuncsym(n.Func.Nname.Sym)
+       }
 }
 
 // The result of stringtoarraylit MUST be assigned back to n, e.g.
index 58eedf0c8cc76e4a9e7082f0a6d0b7d6d46e4b1f..32c365499590995693c045acfc4804e1b787700e 100644 (file)
@@ -37,8 +37,8 @@ type (
 // Methods can be declared on the original named type and the alias.
 func (T0) m1()  {} // GCCGO_ERROR "previous"
 func (*T0) m1() {} // ERROR "method redeclared: T0\.m1|redefinition of .m1."
-func (A0) m1()  {} // TODO(gri) this should be an error  // GCCGO_ERROR "redefinition of .m1."
-func (A0) m1()  {} // ERROR "A0\.m1 redeclared in this block|redefinition of .m1."
+func (A0) m1()  {} // ERROR "T0\.m1 redeclared in this block|redefinition of .m1."
+func (A0) m1()  {} // ERROR "T0\.m1 redeclared in this block|redefinition of .m1."
 func (A0) m2()  {}
 
 // Type aliases and the original type name can be used interchangeably.
@@ -95,10 +95,10 @@ type _ = reflect.ValueOf // ERROR "reflect.ValueOf is not a type|expected type"
 func (A1) m() {} // ERROR "cannot define new methods on non-local type int|may not define methods on non-local type"
 func (A2) m() {} // ERROR "invalid receiver type"
 func (A3) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
-func (A4) m() {} // ERROR "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
+func (A4) m() {} // ERROR "reflect.Value.m redeclared in this block" "cannot define new methods on non-local type reflect.Value|may not define methods on non-local type"
 
 type B1 = struct{}
 
-func (B1) m() {} // ERROR "invalid receiver type"
+func (B1) m() {} // ERROR "m redeclared in this block" "invalid receiver type"
 
 // TODO(gri) expand
diff --git a/test/fixedbugs/issue18655.go b/test/fixedbugs/issue18655.go
new file mode 100644 (file)
index 0000000..abc2600
--- /dev/null
@@ -0,0 +1,22 @@
+// errorcheck
+
+// Copyright 2017 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 struct{}
+type A = T
+type B = T
+
+func (T) m() {}
+func (T) m() {} // ERROR "redeclared"
+func (A) m() {} // ERROR "redeclared"
+func (A) m() {} // ERROR "redeclared"
+func (B) m() {} // ERROR "redeclared"
+func (B) m() {} // ERROR "redeclared"
+
+func (*T) m() {} // ERROR "redeclared"
+func (*A) m() {} // ERROR "redeclared"
+func (*B) m() {} // ERROR "redeclared"