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:
parent
99be5a0b85
commit
3d92dd6003
|
@ -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()
|
||||||
|
|
|
@ -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"}},
|
||||||
}
|
}
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package conversions
|
||||||
|
|
||||||
|
type Units string
|
||||||
|
|
||||||
|
const Bits = Units("bits")
|
|
@ -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>;
|
Loading…
Reference in New Issue