From fcfba28e23c7bbd8474b355ca7d6a9d88afcca00 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 17 Jan 2017 15:39:01 -0800 Subject: [PATCH] go/internal/gccgoimporter: support for type aliases This is essentially a copy of the changes in https://golang.org/cl/35268/ but with Go1.9 specific tests factored out into a separate file with build tag. For golang/go#18130. Change-Id: I235693e1bc6145bb53bfd3b343647704c8e82e61 Reviewed-on: https://go-review.googlesource.com/35269 Run-TryBot: Robert Griesemer TryBot-Result: Gobot Gobot Reviewed-by: Alan Donovan --- go/internal/gccgoimporter/importer19_test.go | 15 ++++++ go/internal/gccgoimporter/importer_test.go | 6 ++- go/internal/gccgoimporter/parser.go | 52 +++++++++++++------- 3 files changed, 52 insertions(+), 21 deletions(-) create mode 100644 go/internal/gccgoimporter/importer19_test.go diff --git a/go/internal/gccgoimporter/importer19_test.go b/go/internal/gccgoimporter/importer19_test.go new file mode 100644 index 00000000..0caa2256 --- /dev/null +++ b/go/internal/gccgoimporter/importer19_test.go @@ -0,0 +1,15 @@ +// Copyright 2017 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. + +// +build go1.9 + +package gccgoimporter + +var aliasTests = []importerTest{ + {pkgpath: "alias", name: "IntAlias2", want: "type IntAlias2 = Int"}, +} + +func init() { + importerTests = append(importerTests, aliasTests...) +} diff --git a/go/internal/gccgoimporter/importer_test.go b/go/internal/gccgoimporter/importer_test.go index 2749409c..87b5ff2a 100644 --- a/go/internal/gccgoimporter/importer_test.go +++ b/go/internal/gccgoimporter/importer_test.go @@ -4,7 +4,9 @@ package gccgoimporter -// This is a verbatim copy of $GOROOT/src/go/internal/gccgoimporter/importer_test.go. +// This is a verbatim copy of $GOROOT/src/go/internal/gccgoimporter/importer_test.go +// except for the importerTests variable which does not contain Go1.9-specific tests. +// Those are added via importer19_test.go. import ( "go/types" @@ -90,7 +92,7 @@ func runImporterTest(t *testing.T, imp Importer, initmap map[*types.Package]Init } } -var importerTests = [...]importerTest{ +var importerTests = []importerTest{ {pkgpath: "pointer", name: "Int8Ptr", want: "type Int8Ptr *int8"}, {pkgpath: "complexnums", name: "NN", want: "const NN untyped complex", wantval: "(-1 + -1i)"}, {pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1 + 1i)"}, diff --git a/go/internal/gccgoimporter/parser.go b/go/internal/gccgoimporter/parser.go index ef59b298..7d0e39ce 100644 --- a/go/internal/gccgoimporter/parser.go +++ b/go/internal/gccgoimporter/parser.go @@ -372,27 +372,41 @@ func (p *parser) parseConst(pkg *types.Package) *types.Const { return types.NewConst(token.NoPos, pkg, name, typ, val) } -// TypeName = ExportedName . -func (p *parser) parseTypeName() *types.TypeName { - pkg, name := p.parseExportedName() - scope := pkg.Scope() - if obj := scope.Lookup(name); obj != nil { - return obj.(*types.TypeName) - } - obj := types.NewTypeName(token.NoPos, pkg, name, nil) - // a named type may be referred to before the underlying type - // is known - set it up - types.NewNamed(obj, nil, nil) - scope.Insert(obj) - return obj -} - -// NamedType = TypeName Type { Method } . +// NamedType = TypeName [ "=" ] Type { Method } . +// TypeName = ExportedName . // Method = "func" "(" Param ")" Name ParamList ResultList ";" . func (p *parser) parseNamedType(n int) types.Type { - obj := p.parseTypeName() + pkg, name := p.parseExportedName() + scope := pkg.Scope() + + if p.tok == '=' { + // type alias + p.next() + typ := p.parseType(pkg) + if obj := scope.Lookup(name); obj != nil { + typ = obj.Type() // use previously imported type + if typ == nil { + p.errorf("%v (type alias) used in cycle", obj) + } + } else { + obj = types.NewTypeName(token.NoPos, pkg, name, typ) + scope.Insert(obj) + } + p.typeMap[n] = typ + return typ + } + + // named type + obj := scope.Lookup(name) + if obj == nil { + // a named type may be referred to before the underlying type + // is known - set it up + tname := types.NewTypeName(token.NoPos, pkg, name, nil) + types.NewNamed(tname, nil, nil) + scope.Insert(tname) + obj = tname + } - pkg := obj.Pkg() typ := obj.Type() p.typeMap[n] = typ @@ -411,8 +425,8 @@ func (p *parser) parseNamedType(n int) types.Type { nt.SetUnderlying(underlying.Underlying()) } + // collect associated methods for p.tok == scanner.Ident { - // collect associated methods p.expectKeyword("func") p.expect('(') receiver, _ := p.parseParam(pkg)