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 (
|
||||
gccgov1Magic = "v1;\n"
|
||||
gccgov2Magic = "v2;\n"
|
||||
goimporterMagic = "\n$$ "
|
||||
archiveMagic = "!<ar"
|
||||
)
|
||||
|
@ -93,7 +94,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
|
||||
|
@ -170,7 +171,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()
|
||||
|
|
|
@ -96,6 +96,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"}},
|
||||
}
|
||||
|
|
|
@ -21,6 +21,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
|
||||
|
@ -247,9 +248,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()
|
||||
|
@ -264,6 +276,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)
|
||||
}
|
||||
|
@ -350,7 +365,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
|
||||
}
|
||||
|
@ -725,7 +740,7 @@ func (p *parser) maybeCreatePackage() {
|
|||
}
|
||||
}
|
||||
|
||||
// InitDataDirective = "v1" ";" |
|
||||
// InitDataDirective = ( "v1" | "v2" ) ";" |
|
||||
// "priority" int ";" |
|
||||
// "init" { PackageInit } ";" |
|
||||
// "checksum" unquotedString ";" .
|
||||
|
@ -736,7 +751,8 @@ func (p *parser) parseInitDataDirective() {
|
|||
}
|
||||
|
||||
switch p.lit {
|
||||
case "v1":
|
||||
case "v1", "v2":
|
||||
p.version = p.lit
|
||||
p.next()
|
||||
p.expect(';')
|
||||
|
||||
|
@ -768,8 +784,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 ";" |
|
||||
|
@ -782,13 +799,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":
|
||||
|
@ -797,6 +818,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()
|
||||
|
|
|
@ -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