]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: rework checkdupfields
authorMatthew Dempsky <mdempsky@google.com>
Thu, 10 Mar 2016 23:50:49 +0000 (15:50 -0800)
committerMatthew Dempsky <mdempsky@google.com>
Fri, 11 Mar 2016 01:52:42 +0000 (01:52 +0000)
Use a map to detect duplicate symbols. Allows eliminating an otherwise
unneeded field from Sym and gets rid of a global variable.

Change-Id: Ic004bca7e9130a1261a1cddbc17244529a2a1df4
Reviewed-on: https://go-review.googlesource.com/20552
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>

src/cmd/compile/internal/gc/dcl.go
src/cmd/compile/internal/gc/go.go
src/cmd/compile/internal/gc/sizeof_test.go

index 8c9906cc162753e413411a8ff965b43f4b2728f3..e1209ff8ecb3de6f24989e2a8aee948029773510 100644 (file)
@@ -795,19 +795,23 @@ func structfield(n *Node) *Type {
        return f
 }
 
-var uniqgen uint32
-
-func checkdupfields(t *Type, what string) {
+// checkdupfields emits errors for duplicately named fields or methods in
+// a list of struct or interface types.
+func checkdupfields(what string, ts ...*Type) {
        lno := lineno
 
-       for ; t != nil; t = t.Down {
-               if t.Sym != nil && t.Nname != nil && !isblank(t.Nname) {
-                       if t.Sym.Uniqgen == uniqgen {
-                               lineno = t.Nname.Lineno
-                               Yyerror("duplicate %s %s", what, t.Sym.Name)
-                       } else {
-                               t.Sym.Uniqgen = uniqgen
+       seen := make(map[*Sym]bool)
+       for _, t := range ts {
+               for f, it := IterFields(t); f != nil; f = it.Next() {
+                       if f.Sym == nil || f.Nname == nil || isblank(f.Nname) {
+                               continue
+                       }
+                       if seen[f.Sym] {
+                               lineno = f.Nname.Lineno
+                               Yyerror("duplicate %s %s", what, f.Sym.Name)
+                               continue
                        }
+                       seen[f.Sym] = true
                }
        }
 
@@ -839,8 +843,7 @@ func tostruct0(t *Type, l []*Node) {
                }
        }
 
-       uniqgen++
-       checkdupfields(t.Type, "field")
+       checkdupfields("field", t)
 
        if !t.Broke {
                checkwidth(t)
@@ -980,8 +983,7 @@ func tointerface0(t *Type, l []*Node) *Type {
                }
        }
 
-       uniqgen++
-       checkdupfields(t.Type, "method")
+       checkdupfields("method", t)
        t = sortinter(t)
        checkwidth(t)
 
@@ -1156,10 +1158,7 @@ func functype0(t *Type, this *Node, in, out []*Node) {
        *t.ResultsP() = tofunargs(out)
        *t.ParamsP() = tofunargs(in)
 
-       uniqgen++
-       checkdupfields(t.Recvs().Type, "argument")
-       checkdupfields(t.Results().Type, "argument")
-       checkdupfields(t.Params().Type, "argument")
+       checkdupfields("argument", t.Recvs(), t.Results(), t.Params())
 
        if t.Recvs().Broke || t.Results().Broke || t.Params().Broke {
                t.Broke = true
index 29b4b5471a01034cac936b086b612f4c5d628b69..3d221e60493124a43cef14fdd8fdc9283cd07055 100644 (file)
@@ -68,7 +68,6 @@ type Pkg struct {
 
 type Sym struct {
        Flags     SymFlags
-       Uniqgen   uint32
        Link      *Sym
        Importdef *Pkg   // where imported definition was found
        Linkname  string // link name
index 199b5ce3c69e54d474e7799a1f460fe3c91ef9f8..489dfaa6f8444de5dc2261da6abf436bfa634a14 100644 (file)
@@ -26,7 +26,7 @@ func TestSizeof(t *testing.T) {
                {Func{}, 104, 184},
                {Name{}, 52, 80},
                {Node{}, 92, 144},
-               {Sym{}, 64, 112},
+               {Sym{}, 60, 112},
                {Type{}, 144, 240},
        }