Commit f42929ce authored by Robert Griesemer's avatar Robert Griesemer

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

Also: handle version "v2" of export data format.

Fixes #17981.

Change-Id: I8042ce18c4a27c70cc1ede675daca019b047bcf3
Reviewed-on: https://go-review.googlesource.com/33412Reviewed-by: 's avatarIan Lance Taylor <iant@golang.org>
parent f39050c8
...@@ -63,6 +63,7 @@ func findExportFile(searchpaths []string, pkgpath string) (string, error) { ...@@ -63,6 +63,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"
) )
...@@ -91,7 +92,7 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e ...@@ -91,7 +92,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
...@@ -168,7 +169,7 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo ...@@ -168,7 +169,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()
......
...@@ -95,6 +95,7 @@ var importerTests = [...]importerTest{ ...@@ -95,6 +95,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"}},
} }
......
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,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
...@@ -245,9 +246,20 @@ func (p *parser) parseVar(pkg *types.Package) *types.Var { ...@@ -245,9 +246,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()
...@@ -262,6 +274,9 @@ func (p *parser) parseConstValue() (val constant.Value, typ types.Type) { ...@@ -262,6 +274,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)
} }
...@@ -348,7 +363,7 @@ func (p *parser) parseConst(pkg *types.Package) *types.Const { ...@@ -348,7 +363,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
} }
...@@ -723,7 +738,7 @@ func (p *parser) maybeCreatePackage() { ...@@ -723,7 +738,7 @@ func (p *parser) maybeCreatePackage() {
} }
} }
// InitDataDirective = "v1" ";" | // InitDataDirective = ( "v1" | "v2" ) ";" |
// "priority" int ";" | // "priority" int ";" |
// "init" { PackageInit } ";" | // "init" { PackageInit } ";" |
// "checksum" unquotedString ";" . // "checksum" unquotedString ";" .
...@@ -734,7 +749,8 @@ func (p *parser) parseInitDataDirective() { ...@@ -734,7 +749,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(';')
...@@ -766,8 +782,9 @@ func (p *parser) parseInitDataDirective() { ...@@ -766,8 +782,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 ";" |
...@@ -780,13 +797,17 @@ func (p *parser) parseDirective() { ...@@ -780,13 +797,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":
...@@ -795,6 +816,11 @@ func (p *parser) parseDirective() { ...@@ -795,6 +816,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()
......
package conversions
type Units string
const Bits = Units("bits")
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>;
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