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) {
const (
gccgov1Magic = "v1;\n"
gccgov2Magic = "v2;\n"
goimporterMagic = "\n$$ "
archiveMagic = "!<ar"
)
......@@ -91,7 +92,7 @@ func openExportFile(fpath string) (reader io.ReadSeeker, closer io.Closer, err e
var elfreader io.ReaderAt
switch string(magic[:]) {
case gccgov1Magic, goimporterMagic:
case gccgov1Magic, gccgov2Magic, goimporterMagic:
// Raw export data.
reader = f
return
......@@ -168,7 +169,7 @@ func GetImporter(searchpaths []string, initmap map[*types.Package]InitData) Impo
}
switch string(magic[:]) {
case gccgov1Magic:
case gccgov1Magic, gccgov2Magic:
var p parser
p.init(fpath, reader, imports)
pkg = p.parsePackage()
......
......@@ -95,6 +95,7 @@ var importerTests = [...]importerTest{
{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: "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
//{pkgpath: "imports", wantinits: []string{"imports..import", "fmt..import", "math..import"}},
}
......
......@@ -19,6 +19,7 @@ import (
type parser struct {
scanner scanner.Scanner
version string // format version
tok rune // current token
lit string // literal string; only valid for Ident, Int, String tokens
pkgpath string // package path of imported package
......@@ -245,9 +246,20 @@ func (p *parser) parseVar(pkg *types.Package) *types.Var {
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"] .
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 {
case scanner.String:
str := p.parseString()
......@@ -262,6 +274,9 @@ func (p *parser) parseConstValue() (val constant.Value, typ types.Type) {
case "true":
b = true
case "convert":
return p.parseConversion(pkg)
default:
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 {
typ = p.parseType(pkg)
}
p.expect('=')
val, vtyp := p.parseConstValue()
val, vtyp := p.parseConstValue(pkg)
if typ == nil {
typ = vtyp
}
......@@ -723,7 +738,7 @@ func (p *parser) maybeCreatePackage() {
}
}
// InitDataDirective = "v1" ";" |
// InitDataDirective = ( "v1" | "v2" ) ";" |
// "priority" int ";" |
// "init" { PackageInit } ";" |
// "checksum" unquotedString ";" .
......@@ -734,7 +749,8 @@ func (p *parser) parseInitDataDirective() {
}
switch p.lit {
case "v1":
case "v1", "v2":
p.version = p.lit
p.next()
p.expect(';')
......@@ -766,8 +782,9 @@ func (p *parser) parseInitDataDirective() {
}
// Directive = InitDataDirective |
// "package" unquotedString ";" |
// "package" unquotedString [ unquotedString ] [ unquotedString ] ";" |
// "pkgpath" unquotedString ";" |
// "prefix" unquotedString ";" |
// "import" unquotedString unquotedString string ";" |
// "func" Func ";" |
// "type" Type ";" |
......@@ -780,13 +797,17 @@ func (p *parser) parseDirective() {
}
switch p.lit {
case "v1", "priority", "init", "checksum":
case "v1", "v2", "priority", "init", "checksum":
p.parseInitDataDirective()
case "package":
p.next()
p.pkgname = p.parseUnquotedString()
p.maybeCreatePackage()
if p.version == "v2" && p.tok != ';' {
p.parseUnquotedString()
p.parseUnquotedString()
}
p.expect(';')
case "pkgpath":
......@@ -795,6 +816,11 @@ func (p *parser) parseDirective() {
p.maybeCreatePackage()
p.expect(';')
case "prefix":
p.next()
p.pkgpath = p.parseUnquotedString()
p.expect(';')
case "import":
p.next()
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