Commit 88a21ebb authored by Matthew Dempsky's avatar Matthew Dempsky

cmd/compile: rework checkdupfields

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/20552Reviewed-by: default avatarBrad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Matthew Dempsky <mdempsky@google.com>
parent 6b3d4a53
...@@ -795,19 +795,23 @@ func structfield(n *Node) *Type { ...@@ -795,19 +795,23 @@ func structfield(n *Node) *Type {
return f return f
} }
var uniqgen uint32 // checkdupfields emits errors for duplicately named fields or methods in
// a list of struct or interface types.
func checkdupfields(t *Type, what string) { func checkdupfields(what string, ts ...*Type) {
lno := lineno lno := lineno
for ; t != nil; t = t.Down { seen := make(map[*Sym]bool)
if t.Sym != nil && t.Nname != nil && !isblank(t.Nname) { for _, t := range ts {
if t.Sym.Uniqgen == uniqgen { for f, it := IterFields(t); f != nil; f = it.Next() {
lineno = t.Nname.Lineno if f.Sym == nil || f.Nname == nil || isblank(f.Nname) {
Yyerror("duplicate %s %s", what, t.Sym.Name) continue
} else { }
t.Sym.Uniqgen = uniqgen 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) { ...@@ -839,8 +843,7 @@ func tostruct0(t *Type, l []*Node) {
} }
} }
uniqgen++ checkdupfields("field", t)
checkdupfields(t.Type, "field")
if !t.Broke { if !t.Broke {
checkwidth(t) checkwidth(t)
...@@ -980,8 +983,7 @@ func tointerface0(t *Type, l []*Node) *Type { ...@@ -980,8 +983,7 @@ func tointerface0(t *Type, l []*Node) *Type {
} }
} }
uniqgen++ checkdupfields("method", t)
checkdupfields(t.Type, "method")
t = sortinter(t) t = sortinter(t)
checkwidth(t) checkwidth(t)
...@@ -1156,10 +1158,7 @@ func functype0(t *Type, this *Node, in, out []*Node) { ...@@ -1156,10 +1158,7 @@ func functype0(t *Type, this *Node, in, out []*Node) {
*t.ResultsP() = tofunargs(out) *t.ResultsP() = tofunargs(out)
*t.ParamsP() = tofunargs(in) *t.ParamsP() = tofunargs(in)
uniqgen++ checkdupfields("argument", t.Recvs(), t.Results(), t.Params())
checkdupfields(t.Recvs().Type, "argument")
checkdupfields(t.Results().Type, "argument")
checkdupfields(t.Params().Type, "argument")
if t.Recvs().Broke || t.Results().Broke || t.Params().Broke { if t.Recvs().Broke || t.Results().Broke || t.Params().Broke {
t.Broke = true t.Broke = true
......
...@@ -68,7 +68,6 @@ type Pkg struct { ...@@ -68,7 +68,6 @@ type Pkg struct {
type Sym struct { type Sym struct {
Flags SymFlags Flags SymFlags
Uniqgen uint32
Link *Sym Link *Sym
Importdef *Pkg // where imported definition was found Importdef *Pkg // where imported definition was found
Linkname string // link name Linkname string // link name
......
...@@ -26,7 +26,7 @@ func TestSizeof(t *testing.T) { ...@@ -26,7 +26,7 @@ func TestSizeof(t *testing.T) {
{Func{}, 104, 184}, {Func{}, 104, 184},
{Name{}, 52, 80}, {Name{}, 52, 80},
{Node{}, 92, 144}, {Node{}, 92, 144},
{Sym{}, 64, 112}, {Sym{}, 60, 112},
{Type{}, 144, 240}, {Type{}, 144, 240},
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment