Commit a1fc3891 by Ian Lance Taylor

go/internal/gccgoimporter: support embedded field in pointer loop

    
    Backport of https://golang.org/cl/194440.  Original description:
    
        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.
    
    Updates golang/go#34182
    
    Reviewed-on: https://go-review.googlesource.com/c/gofrontend/+/194562

From-SVN: r275606
parent d7fb4c31
68038b4fdf1456482af986cb05dcf3121bd43ffc 556451586b10584e4778694c84b03d0ecbbab150
The first line of this file holds the git revision number of the last The first line of this file holds the git revision number of the last
merge done from the gofrontend repository. merge done from the gofrontend repository.
...@@ -96,6 +96,7 @@ var importerTests = [...]importerTest{ ...@@ -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: "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: "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: "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) { func TestGoxImporter(t *testing.T) {
......
...@@ -254,7 +254,7 @@ func (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) { ...@@ -254,7 +254,7 @@ func (p *parser) parseField(pkg *types.Package) (field *types.Var, tag string) {
case *types.Named: case *types.Named:
name = typ.Obj().Name() name = typ.Obj().Name()
default: default:
p.error("anonymous field expected") p.error("embedded field expected")
} }
} }
} }
...@@ -469,8 +469,12 @@ func (p *parser) reserve(n int) { ...@@ -469,8 +469,12 @@ func (p *parser) reserve(n int) {
} }
} }
// update sets the type map entries for the given type numbers nlist to t. // update sets the type map entries for the entries in nlist to t.
func (p *parser) update(t types.Type, nlist []int) { // 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 len(nlist) != 0 {
if t == reserved { if t == reserved {
p.errorf("internal error: update(%v) invoked on reserved", nlist) p.errorf("internal error: update(%v) invoked on reserved", nlist)
...@@ -480,20 +484,34 @@ func (p *parser) update(t types.Type, nlist []int) { ...@@ -480,20 +484,34 @@ func (p *parser) update(t types.Type, nlist []int) {
} }
} }
for _, n := range nlist { for _, n := range nlist {
if p.typeList[n] == t { switch n := n.(type) {
continue case int:
} if p.typeList[n] == t {
if p.typeList[n] != reserved { continue
p.errorf("internal error: update(%v): %d not reserved", nlist, n) }
if p.typeList[n] != reserved {
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)
} }
p.typeList[n] = t
} }
} }
// NamedType = TypeName [ "=" ] Type { Method } . // NamedType = TypeName [ "=" ] Type { Method } .
// TypeName = ExportedName . // TypeName = ExportedName .
// Method = "func" "(" Param ")" Name ParamList ResultList [InlineBody] ";" . // 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() pkg, name := p.parseExportedName()
scope := pkg.Scope() scope := pkg.Scope()
obj := scope.Lookup(name) obj := scope.Lookup(name)
...@@ -504,7 +522,7 @@ func (p *parser) parseNamedType(nlist []int) types.Type { ...@@ -504,7 +522,7 @@ func (p *parser) parseNamedType(nlist []int) types.Type {
// type alias // type alias
if p.tok == '=' { if p.tok == '=' {
p.next() p.next()
p.aliases[nlist[len(nlist)-1]] = name p.aliases[nlist[len(nlist)-1].(int)] = name
if obj != nil { if obj != nil {
// use the previously imported (canonical) type // use the previously imported (canonical) type
t := obj.Type() t := obj.Type()
...@@ -603,7 +621,7 @@ func (p *parser) parseInt() int { ...@@ -603,7 +621,7 @@ func (p *parser) parseInt() int {
} }
// ArrayOrSliceType = "[" [ int ] "]" Type . // 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('[') p.expect('[')
if p.tok == ']' { if p.tok == ']' {
p.next() p.next()
...@@ -626,7 +644,7 @@ func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []int) types.Ty ...@@ -626,7 +644,7 @@ func (p *parser) parseArrayOrSliceType(pkg *types.Package, nlist []int) types.Ty
} }
// MapType = "map" "[" Type "]" Type . // 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") p.expectKeyword("map")
t := new(types.Map) t := new(types.Map)
...@@ -642,7 +660,7 @@ func (p *parser) parseMapType(pkg *types.Package, nlist []int) types.Type { ...@@ -642,7 +660,7 @@ func (p *parser) parseMapType(pkg *types.Package, nlist []int) types.Type {
} }
// ChanType = "chan" ["<-" | "-<"] 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") p.expectKeyword("chan")
t := new(types.Chan) t := new(types.Chan)
...@@ -669,7 +687,7 @@ func (p *parser) parseChanType(pkg *types.Package, nlist []int) types.Type { ...@@ -669,7 +687,7 @@ func (p *parser) parseChanType(pkg *types.Package, nlist []int) types.Type {
} }
// StructType = "struct" "{" { Field } "}" . // 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") p.expectKeyword("struct")
t := new(types.Struct) t := new(types.Struct)
...@@ -736,7 +754,7 @@ func (p *parser) parseResultList(pkg *types.Package) *types.Tuple { ...@@ -736,7 +754,7 @@ func (p *parser) parseResultList(pkg *types.Package) *types.Tuple {
} }
// FunctionType = ParamList ResultList . // 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) t := new(types.Signature)
p.update(t, nlist) p.update(t, nlist)
...@@ -776,7 +794,7 @@ func (p *parser) parseFunc(pkg *types.Package) *types.Func { ...@@ -776,7 +794,7 @@ func (p *parser) parseFunc(pkg *types.Package) *types.Func {
} }
// InterfaceType = "interface" "{" { ("?" Type | 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") p.expectKeyword("interface")
t := new(types.Interface) t := new(types.Interface)
...@@ -805,7 +823,7 @@ func (p *parser) parseInterfaceType(pkg *types.Package, nlist []int) types.Type ...@@ -805,7 +823,7 @@ func (p *parser) parseInterfaceType(pkg *types.Package, nlist []int) types.Type
} }
// PointerType = "*" ("any" | 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('*') p.expect('*')
if p.tok == scanner.Ident { if p.tok == scanner.Ident {
p.expectKeyword("any") p.expectKeyword("any")
...@@ -817,13 +835,13 @@ func (p *parser) parsePointerType(pkg *types.Package, nlist []int) types.Type { ...@@ -817,13 +835,13 @@ func (p *parser) parsePointerType(pkg *types.Package, nlist []int) types.Type {
t := new(types.Pointer) t := new(types.Pointer)
p.update(t, nlist) p.update(t, nlist)
*t = *types.NewPointer(p.parseType(pkg)) *t = *types.NewPointer(p.parseType(pkg, t))
return t return t
} }
// TypeSpec = NamedType | MapType | ChanType | StructType | InterfaceType | PointerType | ArrayOrSliceType | FunctionType . // 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 { switch p.tok {
case scanner.String: case scanner.String:
return p.parseNamedType(nlist) return p.parseNamedType(nlist)
...@@ -912,14 +930,14 @@ func lookupBuiltinType(typ int) types.Type { ...@@ -912,14 +930,14 @@ func lookupBuiltinType(typ int) types.Type {
// //
// parseType updates the type map to t for all type numbers n. // 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('<') p.expect('<')
t, _ := p.parseTypeAfterAngle(pkg, n...) t, _ := p.parseTypeAfterAngle(pkg, n...)
return t return t
} }
// (*parser).Type after reading the "<". // (*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") p.expectKeyword("type")
n1 = 0 n1 = 0
...@@ -962,7 +980,7 @@ func (p *parser) parseTypeAfterAngle(pkg *types.Package, n ...int) (t types.Type ...@@ -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 // parseTypeExtended is identical to parseType, but if the type in
// question is a saved type, returns the index as well as the type // question is a saved type, returns the index as well as the type
// pointer (index returned is zero if we parsed a builtin). // 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('<') p.expect('<')
t, n1 = p.parseTypeAfterAngle(pkg, n...) t, n1 = p.parseTypeAfterAngle(pkg, n...)
return return
...@@ -1044,12 +1062,12 @@ func (p *parser) parseTypes(pkg *types.Package) { ...@@ -1044,12 +1062,12 @@ func (p *parser) parseTypes(pkg *types.Package) {
} }
for i := 1; i < int(exportedp1); i++ { for i := 1; i < int(exportedp1); i++ {
p.parseSavedType(pkg, i, []int{}) p.parseSavedType(pkg, i, nil)
} }
} }
// parseSavedType parses one saved type definition. // 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) { defer func(s *scanner.Scanner, tok rune, lit string) {
p.scanner = s p.scanner = s
p.tok = tok p.tok = tok
......
// 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
}
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
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