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 <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Alan Donovan <adonovan@google.com>
diff --git a/go/internal/gccgoimporter/importer19_test.go b/go/internal/gccgoimporter/importer19_test.go
new file mode 100644
index 0000000..0caa225
--- /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 2749409..87b5ff2 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 @@
 	}
 }
 
-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 ef59b29..7d0e39c 100644
--- a/go/internal/gccgoimporter/parser.go
+++ b/go/internal/gccgoimporter/parser.go
@@ -372,27 +372,41 @@
 	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()
 
-	pkg := obj.Pkg()
+	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
+	}
+
 	typ := obj.Type()
 	p.typeMap[n] = typ
 
@@ -411,8 +425,8 @@
 		nt.SetUnderlying(underlying.Underlying())
 	}
 
+	// collect associated methods
 	for p.tok == scanner.Ident {
-		// collect associated methods
 		p.expectKeyword("func")
 		p.expect('(')
 		receiver, _ := p.parseParam(pkg)