go/internal/gccgoimporter: handle conversions in exported const values

Same as https://go-review.googlesource.com/c/33412/ in the standard library.

Fixes #17981.

Change-Id: Iaf47872840a4456d824ed5d7b3eda205c043e4cf
Reviewed-on: https://go-review.googlesource.com/34110
Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
Alan Donovan 2016-12-07 10:57:27 -05:00
parent 99be5a0b85
commit 3d92dd6003
5 changed files with 48 additions and 9 deletions

View File

@ -65,6 +65,7 @@ func findExportFile(searchpaths []string, pkgpath string) (string, error) {
const ( const (
gccgov1Magic = "v1;\n" gccgov1Magic = "v1;\n"
gccgov2Magic = "v2;\n"
goimporterMagic = "\n$$ " goimporterMagic = "\n$$ "
archiveMagic = "!<ar" archiveMagic = "!<ar"
) )
@ -93,7 +94,7 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
var elfreader io.ReaderAt var elfreader io.ReaderAt
switch string(magic[:]) { switch string(magic[:]) {
case gccgov1Magic, goimporterMagic: case gccgov1Magic, gccgov2Magic, goimporterMagic:
// Raw export data. // Raw export data.
reader = f reader = f
return return
@ -170,7 +171,7 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo
} }
switch string(magic[:]) { switch string(magic[:]) {
case gccgov1Magic: case gccgov1Magic, gccgov2Magic:
var p parser var p parser
p.init(fpath, reader, imports) p.init(fpath, reader, imports)
pkg = p.parsePackage() pkg = p.parsePackage()

View File

@ -96,6 +96,7 @@ var importerTests = [...]importerTest{
{pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1 + 1i)"}, {pkgpath: "complexnums", name: "NP", want: "const NP untyped complex", wantval: "(-1 + 1i)"},
{pkgpath: "complexnums", name: "PN", want: "const PN untyped complex", wantval: "(1 + -1i)"}, {pkgpath: "complexnums", name: "PN", want: "const PN untyped complex", wantval: "(1 + -1i)"},
{pkgpath: "complexnums", name: "PP", want: "const PP untyped complex", wantval: "(1 + 1i)"}, {pkgpath: "complexnums", name: "PP", want: "const PP untyped complex", wantval: "(1 + 1i)"},
{pkgpath: "conversions", name: "Bits", want: "const Bits Units", wantval: `"bits"`},
// TODO: enable this entry once bug has been tracked down // TODO: enable this entry once bug has been tracked down
//{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}}, //{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}},
} }

View File

@ -21,6 +21,7 @@ import (
type parser struct { type parser struct {
scanner scanner.Scanner scanner scanner.Scanner
version string // format version
tok rune // current token tok rune // current token
lit string // literal string; only valid for Ident, Int, String tokens lit string // literal string; only valid for Ident, Int, String tokens
pkgpath string // package path of imported package pkgpath string // package path of imported package
@ -247,9 +248,20 @@ func (p *parser) parseVar(pkg *types.Package) *types.Var {
return types.NewVar(token.NoPos, pkg, name, p.parseType(pkg)) return types.NewVar(token.NoPos, pkg, name, p.parseType(pkg))
} }
// ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) . // Conversion = "convert" "(" Type "," ConstValue ")" .
func (p *parser) parseConversion(pkg *types.Package) (val constant.Value, typ types.Type) {
p.expectKeyword("convert")
p.expect('(')
typ = p.parseType(pkg)
p.expect(',')
val, _ = p.parseConstValue(pkg)
p.expect(')')
return
}
// ConstValue = string | "false" | "true" | ["-"] (int ["'"] | FloatOrComplex) | Conversion .
// FloatOrComplex = float ["i" | ("+"|"-") float "i"] . // FloatOrComplex = float ["i" | ("+"|"-") float "i"] .
func (p *parser) parseConstValue() (val constant.Value, typ types.Type) { func (p *parser) parseConstValue(pkg *types.Package) (val constant.Value, typ types.Type) {
switch p.tok { switch p.tok {
case scanner.String: case scanner.String:
str := p.parseString() str := p.parseString()
@ -264,6 +276,9 @@ func (p *parser) parseConstValue() (val constant.Value, typ types.Type) {
case "true": case "true":
b = true b = true
case "convert":
return p.parseConversion(pkg)
default: default:
p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit) p.errorf("expected const value, got %s (%q)", scanner.TokenString(p.tok), p.lit)
} }
@ -350,7 +365,7 @@ func (p *parser) parseConst(pkg *types.Package) *types.Const {
typ = p.parseType(pkg) typ = p.parseType(pkg)
} }
p.expect('=') p.expect('=')
val, vtyp := p.parseConstValue() val, vtyp := p.parseConstValue(pkg)
if typ == nil { if typ == nil {
typ = vtyp typ = vtyp
} }
@ -725,7 +740,7 @@ func (p *parser) maybeCreatePackage() {
} }
} }
// InitDataDirective = "v1" ";" | // InitDataDirective = ( "v1" | "v2" ) ";" |
// "priority" int ";" | // "priority" int ";" |
// "init" { PackageInit } ";" | // "init" { PackageInit } ";" |
// "checksum" unquotedString ";" . // "checksum" unquotedString ";" .
@ -736,7 +751,8 @@ func (p *parser) parseInitDataDirective() {
} }
switch p.lit { switch p.lit {
case "v1": case "v1", "v2":
p.version = p.lit
p.next() p.next()
p.expect(';') p.expect(';')
@ -768,8 +784,9 @@ func (p *parser) parseInitDataDirective() {
} }
// Directive = InitDataDirective | // Directive = InitDataDirective |
// "package" unquotedString ";" | // "package" unquotedString [ unquotedString ] [ unquotedString ] ";" |
// "pkgpath" unquotedString ";" | // "pkgpath" unquotedString ";" |
// "prefix" unquotedString ";" |
// "import" unquotedString unquotedString string ";" | // "import" unquotedString unquotedString string ";" |
// "func" Func ";" | // "func" Func ";" |
// "type" Type ";" | // "type" Type ";" |
@ -782,13 +799,17 @@ func (p *parser) parseDirective() {
} }
switch p.lit { switch p.lit {
case "v1", "priority", "init", "checksum": case "v1", "v2", "priority", "init", "checksum":
p.parseInitDataDirective() p.parseInitDataDirective()
case "package": case "package":
p.next() p.next()
p.pkgname = p.parseUnquotedString() p.pkgname = p.parseUnquotedString()
p.maybeCreatePackage() p.maybeCreatePackage()
if p.version == "v2" && p.tok != ';' {
p.parseUnquotedString()
p.parseUnquotedString()
}
p.expect(';') p.expect(';')
case "pkgpath": case "pkgpath":
@ -797,6 +818,11 @@ func (p *parser) parseDirective() {
p.maybeCreatePackage() p.maybeCreatePackage()
p.expect(';') p.expect(';')
case "prefix":
p.next()
p.pkgpath = p.parseUnquotedString()
p.expect(';')
case "import": case "import":
p.next() p.next()
pkgname := p.parseUnquotedString() pkgname := p.parseUnquotedString()

View File

@ -0,0 +1,5 @@
package conversions
type Units string
const Bits = Units("bits")

View File

@ -0,0 +1,6 @@
v2;
package conversions;
prefix go;
package conversions go.conversions go.conversions;
const Bits <type 1 "Units" <type -16>> = convert(<type 1>, "bits");
type <type 1>;