]> Cypherpunks repositories - gostls13.git/commitdiff
go/internal/gccgoimporter: handle conversions in exported const values
authorRobert Griesemer <gri@golang.org>
Fri, 18 Nov 2016 22:47:51 +0000 (14:47 -0800)
committerRobert Griesemer <gri@golang.org>
Fri, 18 Nov 2016 23:43:02 +0000 (23:43 +0000)
Also: handle version "v2" of export data format.

Fixes #17981.

Change-Id: I8042ce18c4a27c70cc1ede675daca019b047bcf3
Reviewed-on: https://go-review.googlesource.com/33412
Reviewed-by: Ian Lance Taylor <iant@golang.org>
src/go/internal/gccgoimporter/importer.go
src/go/internal/gccgoimporter/importer_test.go
src/go/internal/gccgoimporter/parser.go
src/go/internal/gccgoimporter/testdata/conversions.go [new file with mode: 0644]
src/go/internal/gccgoimporter/testdata/conversions.gox [new file with mode: 0644]

index 19b9c73568605f3e6e75707996b2450c3c196c6f..a22d8fed90eac4f5c6986e06ad98ea30bb37b23e 100644 (file)
@@ -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()
index c10fa484e391854350732a78149497b82598bc63..58abbba94ef15edcf2720c8ca43a3ae65a6e1df7 100644 (file)
@@ -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"}},
 }
index c06cce435b168a7be50ceda03a4510170b13b144..7312cb487921a4ea83ce9f4245fef59930583457 100644 (file)
@@ -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()
diff --git a/src/go/internal/gccgoimporter/testdata/conversions.go b/src/go/internal/gccgoimporter/testdata/conversions.go
new file mode 100644 (file)
index 0000000..653927a
--- /dev/null
@@ -0,0 +1,5 @@
+package conversions
+
+type Units string
+
+const Bits = Units("bits")
diff --git a/src/go/internal/gccgoimporter/testdata/conversions.gox b/src/go/internal/gccgoimporter/testdata/conversions.gox
new file mode 100644 (file)
index 0000000..7de6cda
--- /dev/null
@@ -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>;