mirror of
https://github.com/golang/go
synced 2024-11-18 18:14:43 -07:00
go/internal/gccgoimporter: support embedded field in pointer loop
If an embedded field refers to a type via a pointer, the parser needs to know the name of the embedded field. It is possible that the pointer type is not yet resolved. This CL fixes the parser to handle that case by setting the pointer element type to the unresolved named type while the pointer is being resolved. Fixes #34182 Change-Id: I48435e0404362a85effd7463685c502290fa3c57 Reviewed-on: https://go-review.googlesource.com/c/go/+/194440 Run-TryBot: Ian Lance Taylor <iant@golang.org> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org> Reviewed-by: Than McIntosh <thanm@google.com>
This commit is contained in:
parent
23bf6af996
commit
0a3b65c492
@ -96,6 +96,7 @@ var importerTests = [...]importerTest{
|
||||
{pkgpath: "issue29198", name: "FooServer", gccgoVersion: 7, 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", gccgoVersion: 7, want: "type S struct{b int; map[Y]Z}"},
|
||||
{pkgpath: "issue34182", name: "T1", want: "type T1 struct{f *T2}"},
|
||||
}
|
||||
|
||||
func TestGoxImporter(t *testing.T) {
|
||||
|
@ -254,7 +254,7 @@ func (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) {
|
||||
case *types.Named:
|
||||
name = typ.Obj().Name()
|
||||
default:
|
||||
p.error("anonymous field expected")
|
||||
p.error("embedded field expected")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -469,8 +469,12 @@ func (p *parser) reserve(n int) {
|
||||
}
|
||||
}
|
||||
|
||||
// update sets the type map entries for the given type numbers nlist to t.
|
||||
func (p *parser) update(t types.Type, nlist []int) {
|
||||
// update sets the type map entries for the entries in nlist to t.
|
||||
// An entry in nlist can be a type number in p.typeList,
|
||||
// used to resolve named types, or it can be a *types.Pointer,
|
||||
// used to resolve pointers to named types in case they are referenced
|
||||
// by embedded fields.
|
||||
func (p *parser) update(t types.Type, nlist []interface{}) {
|
||||
if len(nlist) != 0 {
|
||||
if t == reserved {
|
||||
p.errorf("internal error: update(%v) invoked on reserved", nlist)
|
||||
@ -480,6 +484,8 @@ func (p *parser) update(t types.Type, nlist []int) {
|
||||
}
|
||||
}
|
||||
for _, n := range nlist {
|
||||
switch n := n.(type) {
|
||||
case int:
|
||||
if p.typeList[n] == t {
|
||||
continue
|
||||
}
|
||||
@ -487,13 +493,25 @@ func (p *parser) update(t types.Type, nlist []int) {
|
||||
p.errorf("internal error: update(%v): %d not reserved", nlist, n)
|
||||
}
|
||||
p.typeList[n] = t
|
||||
case *types.Pointer:
|
||||
if *n != (types.Pointer{}) {
|
||||
elem := n.Elem()
|
||||
if elem == t {
|
||||
continue
|
||||
}
|
||||
p.errorf("internal error: update: pointer already set to %v, expected %v", elem, t)
|
||||
}
|
||||
*n = *types.NewPointer(t)
|
||||
default:
|
||||
p.errorf("internal error: %T on nlist", n)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// NamedType = TypeName [ "=" ] Type { Method } .
|
||||
// TypeName = ExportedName .
|
||||
// Method = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" .
|
||||
func (p *parser) parseNamedType(nlist []int) types.Type {
|
||||
func (p *parser) parseNamedType(nlist []interface{}) types.Type {
|
||||
pkg, name := p.parseExportedName()
|
||||
scope := pkg.Scope()
|
||||
obj := scope.Lookup(name)
|
||||
@ -504,7 +522,7 @@ func (p *parser) parseNamedType(nlist []int) types.Type {
|
||||
// type alias
|
||||
if p.tok == '=' {
|
||||
p.next()
|
||||
p.aliases[nlist[len(nlist)-1]] = name
|
||||
p.aliases[nlist[len(nlist)-1].(int)] = name
|
||||
if obj != nil {
|
||||
// use the previously imported (canonical) type
|
||||
t := obj.Type()
|
||||
@ -603,7 +621,7 @@ func (p *parser) parseInt() int {
|
||||
}
|
||||
|
||||
// ArrayOrSliceType = "[" [ int ] "]" Type .
|
||||
func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []int) types.Type {
|
||||
func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []interface{}) types.Type {
|
||||
p.expect('[')
|
||||
if p.tok == ']' {
|
||||
p.next()
|
||||
@ -626,7 +644,7 @@ func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []int) types.Ty
|
||||
}
|
||||
|
||||
// MapType = "map" "[" Type "]" Type .
|
||||
func (p *parser) parseMapType(pkg *types.Package, nlist []int) types.Type {
|
||||
func (p *parser) parseMapType(pkg *types.Package, nlist []interface{}) types.Type {
|
||||
p.expectKeyword("map")
|
||||
|
||||
t := new(types.Map)
|
||||
@ -642,7 +660,7 @@ func (p *parser) parseMapType(pkg *types.Package, nlist []int) types.Type {
|
||||
}
|
||||
|
||||
// ChanType = "chan" ["<-" | "-<"] Type .
|
||||
func (p *parser) parseChanType(pkg *types.Package, nlist []int) types.Type {
|
||||
func (p *parser) parseChanType(pkg *types.Package, nlist []interface{}) types.Type {
|
||||
p.expectKeyword("chan")
|
||||
|
||||
t := new(types.Chan)
|
||||
@ -669,7 +687,7 @@ func (p *parser) parseChanType(pkg *types.Package, nlist []int) types.Type {
|
||||
}
|
||||
|
||||
// StructType = "struct" "{" { Field } "}" .
|
||||
func (p *parser) parseStructType(pkg *types.Package, nlist []int) types.Type {
|
||||
func (p *parser) parseStructType(pkg *types.Package, nlist []interface{}) types.Type {
|
||||
p.expectKeyword("struct")
|
||||
|
||||
t := new(types.Struct)
|
||||
@ -736,7 +754,7 @@ func (p *parser) parseResultList(pkg *types.Package) *types.Tuple {
|
||||
}
|
||||
|
||||
// FunctionType = ParamList ResultList .
|
||||
func (p *parser) parseFunctionType(pkg *types.Package, nlist []int) *types.Signature {
|
||||
func (p *parser) parseFunctionType(pkg *types.Package, nlist []interface{}) *types.Signature {
|
||||
t := new(types.Signature)
|
||||
p.update(t, nlist)
|
||||
|
||||
@ -776,7 +794,7 @@ func (p *parser) parseFunc(pkg *types.Package) *types.Func {
|
||||
}
|
||||
|
||||
// InterfaceType = "interface" "{" { ("?" Type | Func) ";" } "}" .
|
||||
func (p *parser) parseInterfaceType(pkg *types.Package, nlist []int) types.Type {
|
||||
func (p *parser) parseInterfaceType(pkg *types.Package, nlist []interface{}) types.Type {
|
||||
p.expectKeyword("interface")
|
||||
|
||||
t := new(types.Interface)
|
||||
@ -805,7 +823,7 @@ func (p *parser) parseInterfaceType(pkg *types.Package, nlist []int) types.Type
|
||||
}
|
||||
|
||||
// PointerType = "*" ("any" | Type) .
|
||||
func (p *parser) parsePointerType(pkg *types.Package, nlist []int) types.Type {
|
||||
func (p *parser) parsePointerType(pkg *types.Package, nlist []interface{}) types.Type {
|
||||
p.expect('*')
|
||||
if p.tok == scanner.Ident {
|
||||
p.expectKeyword("any")
|
||||
@ -817,13 +835,13 @@ func (p *parser) parsePointerType(pkg *types.Package, nlist []int) types.Type {
|
||||
t := new(types.Pointer)
|
||||
p.update(t, nlist)
|
||||
|
||||
*t = *types.NewPointer(p.parseType(pkg))
|
||||
*t = *types.NewPointer(p.parseType(pkg, t))
|
||||
|
||||
return t
|
||||
}
|
||||
|
||||
// TypeSpec = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType .
|
||||
func (p *parser) parseTypeSpec(pkg *types.Package, nlist []int) types.Type {
|
||||
func (p *parser) parseTypeSpec(pkg *types.Package, nlist []interface{}) types.Type {
|
||||
switch p.tok {
|
||||
case scanner.String:
|
||||
return p.parseNamedType(nlist)
|
||||
@ -912,14 +930,14 @@ func lookupBuiltinType(typ int) types.Type {
|
||||
//
|
||||
// parseType updates the type map to t for all type numbers n.
|
||||
//
|
||||
func (p *parser) parseType(pkg *types.Package, n ...int) types.Type {
|
||||
func (p *parser) parseType(pkg *types.Package, n ...interface{}) types.Type {
|
||||
p.expect('<')
|
||||
t, _ := p.parseTypeAfterAngle(pkg, n...)
|
||||
return t
|
||||
}
|
||||
|
||||
// (*parser).Type after reading the "<".
|
||||
func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...int) (t types.Type, n1 int) {
|
||||
func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...interface{}) (t types.Type, n1 int) {
|
||||
p.expectKeyword("type")
|
||||
|
||||
n1 = 0
|
||||
@ -962,7 +980,7 @@ func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...int) (t types.Type
|
||||
// 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) {
|
||||
func (p *parser) parseTypeExtended(pkg *types.Package, n ...interface{}) (t types.Type, n1 int) {
|
||||
p.expect('<')
|
||||
t, n1 = p.parseTypeAfterAngle(pkg, n...)
|
||||
return
|
||||
@ -1044,12 +1062,12 @@ func (p *parser) parseTypes(pkg *types.Package) {
|
||||
}
|
||||
|
||||
for i := 1; i < int(exportedp1); i++ {
|
||||
p.parseSavedType(pkg, i, []int{})
|
||||
p.parseSavedType(pkg, i, nil)
|
||||
}
|
||||
}
|
||||
|
||||
// parseSavedType parses one saved type definition.
|
||||
func (p *parser) parseSavedType(pkg *types.Package, i int, nlist []int) {
|
||||
func (p *parser) parseSavedType(pkg *types.Package, i int, nlist []interface{}) {
|
||||
defer func(s *scanner.Scanner, tok rune, lit string) {
|
||||
p.scanner = s
|
||||
p.tok = tok
|
||||
|
17
src/go/internal/gccgoimporter/testdata/issue34182.go
vendored
Normal file
17
src/go/internal/gccgoimporter/testdata/issue34182.go
vendored
Normal file
@ -0,0 +1,17 @@
|
||||
// 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 issue34182
|
||||
|
||||
type T1 struct {
|
||||
f *T2
|
||||
}
|
||||
|
||||
type T2 struct {
|
||||
f T3
|
||||
}
|
||||
|
||||
type T3 struct {
|
||||
*T2
|
||||
}
|
13
src/go/internal/gccgoimporter/testdata/issue34182.gox
vendored
Normal file
13
src/go/internal/gccgoimporter/testdata/issue34182.gox
vendored
Normal file
@ -0,0 +1,13 @@
|
||||
v3;
|
||||
package issue34182
|
||||
pkgpath issue34182
|
||||
init issue34182 ~go.issue34182
|
||||
types 8 4 21 21 21 17 30 45 45
|
||||
type 1 "T1" <type 6>
|
||||
type 2 "T2" <type 7>
|
||||
type 3 "T3" <type 5>
|
||||
type 4 *<type 2>
|
||||
type 5 struct { ? <type 4>; }
|
||||
type 6 struct { .go.issue34182.f <type 4>; }
|
||||
type 7 struct { .go.issue34182.f <type 3>; }
|
||||
checksum FF02C49BAF44B06C087ED4E573F7CC880C79C208
|
Loading…
Reference in New Issue
Block a user