From 685fecacd0a02bd01f374ad779b72456e0cd9f8b Mon Sep 17 00:00:00 2001 From: Than McIntosh Date: Fri, 19 Apr 2019 16:05:25 -0400 Subject: [PATCH] go/internal/gccgoimporter: update package to match std lib version Import changes from std lib version, specifically https://golang.org/cl/172603 https://golang.org/cl/165739 which contain to a fix for reading of import data as well as a couple of new test cases. Updates golang/go#31540. Change-Id: Iecb1a5a5a7bf100b2ebb871196868e96b1a50611 Reviewed-on: https://go-review.googlesource.com/c/tools/+/173037 Run-TryBot: Than McIntosh TryBot-Result: Gobot Gobot Reviewed-by: Ian Lance Taylor --- go/internal/gccgoimporter/importer_test.go | 3 +- go/internal/gccgoimporter/parser.go | 46 +++++++++++++------ .../gccgoimporter/testdata/issue30628.go | 18 ++++++++ .../gccgoimporter/testdata/issue30628.gox | 28 +++++++++++ .../gccgoimporter/testdata/issue31540.go | 26 +++++++++++ .../gccgoimporter/testdata/issue31540.gox | 16 +++++++ 6 files changed, 123 insertions(+), 14 deletions(-) create mode 100644 go/internal/gccgoimporter/testdata/issue30628.go create mode 100644 go/internal/gccgoimporter/testdata/issue30628.gox create mode 100644 go/internal/gccgoimporter/testdata/issue31540.go create mode 100644 go/internal/gccgoimporter/testdata/issue31540.gox diff --git a/go/internal/gccgoimporter/importer_test.go b/go/internal/gccgoimporter/importer_test.go index 73aa9d15..aa03879c 100644 --- a/go/internal/gccgoimporter/importer_test.go +++ b/go/internal/gccgoimporter/importer_test.go @@ -94,7 +94,8 @@ var importerTests = [...]importerTest{ {pkgpath: "v1reflect", name: "Type", want: "type Type interface{Align() int; AssignableTo(u Type) bool; Bits() int; ChanDir() ChanDir; Elem() Type; Field(i int) StructField; FieldAlign() int; FieldByIndex(index []int) StructField; FieldByName(name string) (StructField, bool); FieldByNameFunc(match func(string) bool) (StructField, bool); Implements(u Type) bool; In(i int) Type; IsVariadic() bool; Key() Type; Kind() Kind; Len() int; Method(int) Method; MethodByName(string) (Method, bool); Name() string; NumField() int; NumIn() int; NumMethod() int; NumOut() int; Out(i int) Type; PkgPath() string; Size() uintptr; String() string; common() *commonType; rawString() string; runtimeType() *runtimeType; uncommon() *uncommonType}"}, {pkgpath: "nointerface", name: "I", want: "type I int"}, {pkgpath: "issue29198", name: "FooServer", want: "type FooServer struct{FooServer *FooServer; user string; ctx context.Context}"}, -} + {pkgpath: "issue30628", name: "Apple", want: "type Apple struct{hey sync.RWMutex; x int; RQ [517]struct{Count uintptr; NumBytes uintptr; Last uintptr}}"}, + {pkgpath: "issue31540", name: "S", want: "type S struct{b int; map[Y]Z}"}} func TestGoxImporter(t *testing.T) { testenv.MustHaveExec(t) // this is to skip nacl, js diff --git a/go/internal/gccgoimporter/parser.go b/go/internal/gccgoimporter/parser.go index 179c9878..ca63b342 100644 --- a/go/internal/gccgoimporter/parser.go +++ b/go/internal/gccgoimporter/parser.go @@ -35,6 +35,7 @@ type parser struct { typeData []string // unparsed type data (v3 and later) fixups []fixupRecord // fixups to apply at end of parsing initdata InitData // package init priority data + aliases map[int]string // maps saved type number to alias name } // When reading export data it's possible to encounter a defined type @@ -61,6 +62,7 @@ func (p *parser) init(filename string, src io.Reader, imports map[string]*types. p.scanner = new(scanner.Scanner) p.initScanner(filename, src) p.imports = imports + p.aliases = make(map[int]string) p.typeList = make([]types.Type, 1 /* type numbers start at 1 */, 16) } @@ -242,17 +244,22 @@ func deref(typ types.Type) types.Type { // Field = Name Type [string] . func (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) { name := p.parseName() - typ := p.parseType(pkg) + typ, n := p.parseTypeExtended(pkg) anon := false if name == "" { anon = true - switch typ := deref(typ).(type) { - case *types.Basic: - name = typ.Name() - case *types.Named: - name = typ.Obj().Name() - default: - p.error("anonymous field expected") + // Alias? + if aname, ok := p.aliases[n]; ok { + name = aname + } else { + switch typ := deref(typ).(type) { + case *types.Basic: + name = typ.Name() + case *types.Named: + name = typ.Obj().Name() + default: + p.error("anonymous field expected") + } } } field = types.NewField(token.NoPos, pkg, name, typ, anon) @@ -499,6 +506,7 @@ func (p *parser) parseNamedType(nlist []int) types.Type { } t := p.parseType(pkg, nlist...) obj = types.NewTypeName(token.NoPos, pkg, name, t) + p.aliases[nlist[len(nlist)-1]] = name scope.Insert(obj) return t } @@ -706,7 +714,8 @@ func (p *parser) parseResultList(pkg *types.Package) *types.Tuple { if p.tok == scanner.Ident && p.lit == "inl" { return nil } - return types.NewTuple(types.NewParam(token.NoPos, pkg, "", p.parseTypeAfterAngle(pkg))) + taa, _ := p.parseTypeAfterAngle(pkg) + return types.NewTuple(types.NewParam(token.NoPos, pkg, "", taa)) case '(': params, _ := p.parseParamList(pkg) @@ -880,16 +889,18 @@ func lookupBuiltinType(typ int) types.Type { // func (p *parser) parseType(pkg *types.Package, n ...int) types.Type { p.expect('<') - return p.parseTypeAfterAngle(pkg, n...) + t, _ := p.parseTypeAfterAngle(pkg, n...) + return t } // (*parser).Type after reading the "<". -func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...int) (t types.Type) { +func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...int) (t types.Type, n1 int) { p.expectKeyword("type") + n1 = 0 switch p.tok { case scanner.Int: - n1 := p.parseInt() + n1 = p.parseInt() if p.tok == '>' { if len(p.typeData) > 0 && p.typeList[n1] == nil { p.parseSavedType(pkg, n1, n) @@ -912,7 +923,7 @@ func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...int) (t types.Type default: p.errorf("expected type number, got %s (%q)", scanner.TokenString(p.tok), p.lit) - return nil + return nil, 0 } if t == nil || t == reserved { @@ -923,6 +934,15 @@ func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...int) (t types.Type return } +// parseTypeExtended is identical to parseType, but if the type in +// question is a saved type, returns the index as well as the type +// pointer (index returned is zero if we parsed a builtin). +func (p *parser) parseTypeExtended(pkg *types.Package, n ...int) (t types.Type, n1 int) { + p.expect('<') + t, n1 = p.parseTypeAfterAngle(pkg, n...) + return +} + // InlineBody = "" .{NN} // Reports whether a body was skipped. func (p *parser) skipInlineBody() { diff --git a/go/internal/gccgoimporter/testdata/issue30628.go b/go/internal/gccgoimporter/testdata/issue30628.go new file mode 100644 index 00000000..8fd7c13d --- /dev/null +++ b/go/internal/gccgoimporter/testdata/issue30628.go @@ -0,0 +1,18 @@ +package issue30628 + +import ( + "os" + "sync" +) + +const numR = int32(os.O_TRUNC + 5) + +type Apple struct { + hey sync.RWMutex + x int + RQ [numR]struct { + Count uintptr + NumBytes uintptr + Last uintptr + } +} diff --git a/go/internal/gccgoimporter/testdata/issue30628.gox b/go/internal/gccgoimporter/testdata/issue30628.gox new file mode 100644 index 00000000..0ff6259d --- /dev/null +++ b/go/internal/gccgoimporter/testdata/issue30628.gox @@ -0,0 +1,28 @@ +v3; +package issue30628 +pkgpath issue30628 +import os os "os" +import sync sync "sync" +init cpu internal..z2fcpu..import poll internal..z2fpoll..import testlog internal..z2ftestlog..import io io..import os os..import runtime runtime..import sys runtime..z2finternal..z2fsys..import sync sync..import syscall syscall..import time time..import +init_graph 1 0 1 3 1 5 1 6 1 7 1 8 1 9 3 0 3 5 3 6 3 7 4 0 4 1 4 2 4 3 4 5 4 6 4 7 4 8 4 9 5 0 5 6 7 0 7 5 7 6 8 0 8 5 8 6 8 7 9 0 9 5 9 6 9 7 9 8 +types 13 2 24 84 208 17 30 41 147 86 17 64 25 75 +type 1 "Apple" +type 2 struct { .issue30628.hey ; .issue30628.x ; RQ ; } +type 3 "sync.RWMutex" + func (rw ) Lock () + func (rw ) RLocker () ($ret8 ) + func (rw ) RUnlock () + func (rw ) Unlock () + func (rw ) RLock () +type 4 * +type 5 "sync.Locker" +type 6 interface { Lock (); Unlock (); } +type 7 struct { .sync.w ; .sync.writerSem ; .sync.readerSem ; .sync.readerCount ; .sync.readerWait ; } +type 8 "sync.Mutex" + func (m ) Unlock () + func (m ) Lock () +type 9 * +type 10 struct { .sync.state ; .sync.sema ; } +type 11 [517 ] +type 12 struct { Count ; NumBytes ; Last ; } +checksum 199DCF6D3EE2FCF39F715B4E42B5F87F5B15D3AF diff --git a/go/internal/gccgoimporter/testdata/issue31540.go b/go/internal/gccgoimporter/testdata/issue31540.go new file mode 100644 index 00000000..2c6799ec --- /dev/null +++ b/go/internal/gccgoimporter/testdata/issue31540.go @@ -0,0 +1,26 @@ +// Copyright 2019 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 issue31540 + +type Y struct { + q int +} + +type Z map[int]int + +type X = map[Y]Z + +type A1 = X + +type A2 = A1 + +type S struct { + b int + A2 +} + +func Hallo() S { + return S{} +} diff --git a/go/internal/gccgoimporter/testdata/issue31540.gox b/go/internal/gccgoimporter/testdata/issue31540.gox new file mode 100644 index 00000000..abdc696c --- /dev/null +++ b/go/internal/gccgoimporter/testdata/issue31540.gox @@ -0,0 +1,16 @@ +v3; +package issue31540 +pkgpath issue31540 +types 11 7 23 23 20 22 20 21 57 31 45 36 +type 1 "A1" = +type 2 "A2" = +type 3 "S" +type 4 "X" = +type 5 "Y" +type 6 "Z" +type 7 struct { .go.mapalias.b ; ? ; } +type 8 map [] +type 9 struct { .go.mapalias.q ; } +type 10 map [] +func Hallo () +checksum C3FAF2524A90BC11225EE65D059BF27DFB69134B