mirror of
https://github.com/golang/go.git
synced 2026-01-29 23:22:06 +03:00
Compare commits
8 Commits
dev.unifie
...
go1.10
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bf86aec259 | ||
|
|
0b3f04d5f9 | ||
|
|
d1fbe07092 | ||
|
|
c622ec556b | ||
|
|
07a153e0a4 | ||
|
|
65b209897f | ||
|
|
a68e93791d | ||
|
|
419e6f0835 |
@@ -15,12 +15,7 @@ Do not send CLs removing the interior tags from such phrases.
|
||||
ul li { margin: 0.5em 0; }
|
||||
</style>
|
||||
|
||||
<h2 id="introduction">DRAFT RELEASE NOTES - Introduction to Go 1.10</h2>
|
||||
|
||||
<p><strong>
|
||||
Go 1.10 is not yet released. These are work-in-progress
|
||||
release notes. Go 1.10 is expected to be released in February 2018.
|
||||
</strong></p>
|
||||
<h2 id="introduction">Introduction to Go 1.10</h2>
|
||||
|
||||
<p>
|
||||
The latest Go release, version 1.10, arrives six months after <a href="go1.9">Go 1.9</a>.
|
||||
@@ -35,6 +30,10 @@ adds <a href="#test">caching of successful test results</a>,
|
||||
runs <a href="#test-vet">vet automatically during tests</a>,
|
||||
and
|
||||
permits <a href="#cgo">passing string values directly between Go and C using cgo</a>.
|
||||
A new <a href="#cgo">compiler option whitelist</a> may cause
|
||||
unexpected <a href="https://golang.org/s/invalidflag"><code>invalid
|
||||
flag</code></a> errors in code that built successfully with older
|
||||
releases.
|
||||
</p>
|
||||
|
||||
<h2 id="language">Changes to the language</h2>
|
||||
@@ -266,6 +265,18 @@ and the <a href="/cmd/test2json/">test2json documentation</a>.
|
||||
|
||||
<h3 id="cgo">Cgo</h3>
|
||||
|
||||
<p>
|
||||
Options specified by cgo using <code>#cgo CFLAGS</code> and the like
|
||||
are now checked against a whitelist of permitted options.
|
||||
This closes a security hole in which a downloaded package uses
|
||||
compiler options like
|
||||
<span style="white-space: nowrap"><code>-fplugin</code></span>
|
||||
to run arbitrary code on the machine where it is being built.
|
||||
This can cause a build error such as <code>invalid flag in #cgo CFLAGS</code>.
|
||||
For more background, and how to handle this error, see
|
||||
<a href="https://golang.org/s/invalidflag">https://golang.org/s/invalidflag</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Cgo now implements a C typedef like “<code>typedef</code> <code>X</code> <code>Y</code>” using a Go type alias,
|
||||
so that Go code may use the types <code>C.X</code> and <code>C.Y</code> interchangeably.
|
||||
@@ -1214,6 +1225,10 @@ The content-serving handlers also now omit the <code>Content-Type</code> header
|
||||
if passed an invalid (non-3-digit) status code.
|
||||
</p>
|
||||
<p>
|
||||
<!-- CL 46631 -->
|
||||
The <code>Server</code> will no longer add an implicit Content-Type when a <code>Handler</code> does not write any output.
|
||||
</p>
|
||||
<p>
|
||||
<a href="/pkg/net/http/#Redirect"><code>Redirect</code></a> now sets the <code>Content-Type</code> header before writing its HTTP response.
|
||||
</p>
|
||||
</dl>
|
||||
|
||||
@@ -1346,8 +1346,22 @@ func (p *noder) pragma(pos src.Pos, text string) syntax.Pragma {
|
||||
}
|
||||
p.linknames = append(p.linknames, linkname{pos, f[1], f[2]})
|
||||
|
||||
case strings.HasPrefix(text, "go:cgo_import_dynamic "):
|
||||
// This is permitted for general use because Solaris
|
||||
// code relies on it in golang.org/x/sys/unix and others.
|
||||
fields := pragmaFields(text)
|
||||
if len(fields) >= 4 {
|
||||
lib := strings.Trim(fields[3], `"`)
|
||||
if lib != "" && !safeArg(lib) && !isCgoGeneratedFile(pos) {
|
||||
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("invalid library name %q in cgo_import_dynamic directive", lib)})
|
||||
}
|
||||
p.pragcgobuf += p.pragcgo(pos, text)
|
||||
return pragmaValue("go:cgo_import_dynamic")
|
||||
}
|
||||
fallthrough
|
||||
case strings.HasPrefix(text, "go:cgo_"):
|
||||
// For security, we disallow //go:cgo_* directives outside cgo-generated files.
|
||||
// For security, we disallow //go:cgo_* directives other
|
||||
// than cgo_import_dynamic outside cgo-generated files.
|
||||
// Exception: they are allowed in the standard library, for runtime and syscall.
|
||||
if !isCgoGeneratedFile(pos) && !compiling_std {
|
||||
p.error(syntax.Error{Pos: pos, Msg: fmt.Sprintf("//%s only allowed in cgo-generated code", text)})
|
||||
@@ -1383,6 +1397,18 @@ func isCgoGeneratedFile(pos src.Pos) bool {
|
||||
return strings.HasPrefix(filepath.Base(filepath.Clean(pos.AbsFilename())), "_cgo_")
|
||||
}
|
||||
|
||||
// safeArg reports whether arg is a "safe" command-line argument,
|
||||
// meaning that when it appears in a command-line, it probably
|
||||
// doesn't have some special meaning other than its own name.
|
||||
// This is copied from SafeArg in cmd/go/internal/load/pkg.go.
|
||||
func safeArg(name string) bool {
|
||||
if name == "" {
|
||||
return false
|
||||
}
|
||||
c := name[0]
|
||||
return '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' || c == '.' || c == '_' || c == '/' || c >= utf8.RuneSelf
|
||||
}
|
||||
|
||||
func mkname(sym *types.Sym) *Node {
|
||||
n := oldname(sym)
|
||||
if n.Name != nil && n.Name.Pack != nil {
|
||||
|
||||
@@ -1647,9 +1647,9 @@
|
||||
(SUBQconst (MOVQconst [d]) [c]) -> (MOVQconst [d-c])
|
||||
(SUBQconst (SUBQconst x [d]) [c]) && is32Bit(-c-d) -> (ADDQconst [-c-d] x)
|
||||
(SARQconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
|
||||
(SARLconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
|
||||
(SARWconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
|
||||
(SARBconst [c] (MOVQconst [d])) -> (MOVQconst [d>>uint64(c)])
|
||||
(SARLconst [c] (MOVQconst [d])) -> (MOVQconst [int64(int32(d))>>uint64(c)])
|
||||
(SARWconst [c] (MOVQconst [d])) -> (MOVQconst [int64(int16(d))>>uint64(c)])
|
||||
(SARBconst [c] (MOVQconst [d])) -> (MOVQconst [int64(int8(d))>>uint64(c)])
|
||||
(NEGQ (MOVQconst [c])) -> (MOVQconst [-c])
|
||||
(NEGL (MOVLconst [c])) -> (MOVLconst [int64(int32(-c))])
|
||||
(MULQconst [c] (MOVQconst [d])) -> (MOVQconst [c*d])
|
||||
|
||||
@@ -270,22 +270,22 @@ func init() {
|
||||
// Note: x86 is weird, the 16 and 8 byte shifts still use all 5 bits of shift amount!
|
||||
|
||||
{name: "SHRQ", argLength: 2, reg: gp21shift, asm: "SHRQ", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> arg1, shift amount is mod 64
|
||||
{name: "SHRL", argLength: 2, reg: gp21shift, asm: "SHRL", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> arg1, shift amount is mod 32
|
||||
{name: "SHRW", argLength: 2, reg: gp21shift, asm: "SHRW", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> arg1, shift amount is mod 32
|
||||
{name: "SHRB", argLength: 2, reg: gp21shift, asm: "SHRB", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> arg1, shift amount is mod 32
|
||||
{name: "SHRL", argLength: 2, reg: gp21shift, asm: "SHRL", resultInArg0: true, clobberFlags: true}, // unsigned uint32(arg0) >> arg1, shift amount is mod 32
|
||||
{name: "SHRW", argLength: 2, reg: gp21shift, asm: "SHRW", resultInArg0: true, clobberFlags: true}, // unsigned uint16(arg0) >> arg1, shift amount is mod 32
|
||||
{name: "SHRB", argLength: 2, reg: gp21shift, asm: "SHRB", resultInArg0: true, clobberFlags: true}, // unsigned uint8(arg0) >> arg1, shift amount is mod 32
|
||||
{name: "SHRQconst", argLength: 1, reg: gp11, asm: "SHRQ", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-63
|
||||
{name: "SHRLconst", argLength: 1, reg: gp11, asm: "SHRL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-31
|
||||
{name: "SHRWconst", argLength: 1, reg: gp11, asm: "SHRW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-15
|
||||
{name: "SHRBconst", argLength: 1, reg: gp11, asm: "SHRB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned arg0 >> auxint, shift amount 0-7
|
||||
{name: "SHRLconst", argLength: 1, reg: gp11, asm: "SHRL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned uint32(arg0) >> auxint, shift amount 0-31
|
||||
{name: "SHRWconst", argLength: 1, reg: gp11, asm: "SHRW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned uint16(arg0) >> auxint, shift amount 0-15
|
||||
{name: "SHRBconst", argLength: 1, reg: gp11, asm: "SHRB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // unsigned uint8(arg0) >> auxint, shift amount 0-7
|
||||
|
||||
{name: "SARQ", argLength: 2, reg: gp21shift, asm: "SARQ", resultInArg0: true, clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 64
|
||||
{name: "SARL", argLength: 2, reg: gp21shift, asm: "SARL", resultInArg0: true, clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 32
|
||||
{name: "SARW", argLength: 2, reg: gp21shift, asm: "SARW", resultInArg0: true, clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 32
|
||||
{name: "SARB", argLength: 2, reg: gp21shift, asm: "SARB", resultInArg0: true, clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 32
|
||||
{name: "SARL", argLength: 2, reg: gp21shift, asm: "SARL", resultInArg0: true, clobberFlags: true}, // signed int32(arg0) >> arg1, shift amount is mod 32
|
||||
{name: "SARW", argLength: 2, reg: gp21shift, asm: "SARW", resultInArg0: true, clobberFlags: true}, // signed int16(arg0) >> arg1, shift amount is mod 32
|
||||
{name: "SARB", argLength: 2, reg: gp21shift, asm: "SARB", resultInArg0: true, clobberFlags: true}, // signed int8(arg0) >> arg1, shift amount is mod 32
|
||||
{name: "SARQconst", argLength: 1, reg: gp11, asm: "SARQ", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-63
|
||||
{name: "SARLconst", argLength: 1, reg: gp11, asm: "SARL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-31
|
||||
{name: "SARWconst", argLength: 1, reg: gp11, asm: "SARW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-15
|
||||
{name: "SARBconst", argLength: 1, reg: gp11, asm: "SARB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-7
|
||||
{name: "SARLconst", argLength: 1, reg: gp11, asm: "SARL", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed int32(arg0) >> auxint, shift amount 0-31
|
||||
{name: "SARWconst", argLength: 1, reg: gp11, asm: "SARW", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed int16(arg0) >> auxint, shift amount 0-15
|
||||
{name: "SARBconst", argLength: 1, reg: gp11, asm: "SARB", aux: "Int8", resultInArg0: true, clobberFlags: true}, // signed int8(arg0) >> auxint, shift amount 0-7
|
||||
|
||||
{name: "ROLQ", argLength: 2, reg: gp21shift, asm: "ROLQ", resultInArg0: true, clobberFlags: true}, // arg0 rotate left arg1 bits.
|
||||
{name: "ROLL", argLength: 2, reg: gp21shift, asm: "ROLL", resultInArg0: true, clobberFlags: true}, // arg0 rotate left arg1 bits.
|
||||
|
||||
@@ -1088,7 +1088,7 @@
|
||||
(SUBconst (MOVDconst [d]) [c]) -> (MOVDconst [d-c])
|
||||
(SUBconst (SUBconst x [d]) [c]) && is32Bit(-c-d) -> (ADDconst [-c-d] x)
|
||||
(SRADconst [c] (MOVDconst [d])) -> (MOVDconst [d>>uint64(c)])
|
||||
(SRAWconst [c] (MOVDconst [d])) -> (MOVDconst [d>>uint64(c)])
|
||||
(SRAWconst [c] (MOVDconst [d])) -> (MOVDconst [int64(int32(d))>>uint64(c)])
|
||||
(NEG (MOVDconst [c])) -> (MOVDconst [-c])
|
||||
(NEGW (MOVDconst [c])) -> (MOVDconst [int64(int32(-c))])
|
||||
(MULLDconst [c] (MOVDconst [d])) -> (MOVDconst [c*d])
|
||||
|
||||
@@ -309,15 +309,15 @@ func init() {
|
||||
{name: "SLWconst", argLength: 1, reg: gp11, asm: "SLW", aux: "Int8"}, // arg0 << auxint, shift amount 0-31
|
||||
|
||||
{name: "SRD", argLength: 2, reg: sh21, asm: "SRD"}, // unsigned arg0 >> arg1, shift amount is mod 64
|
||||
{name: "SRW", argLength: 2, reg: sh21, asm: "SRW"}, // unsigned arg0 >> arg1, shift amount is mod 32
|
||||
{name: "SRW", argLength: 2, reg: sh21, asm: "SRW"}, // unsigned uint32(arg0) >> arg1, shift amount is mod 32
|
||||
{name: "SRDconst", argLength: 1, reg: gp11, asm: "SRD", aux: "Int8"}, // unsigned arg0 >> auxint, shift amount 0-63
|
||||
{name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "Int8"}, // unsigned arg0 >> auxint, shift amount 0-31
|
||||
{name: "SRWconst", argLength: 1, reg: gp11, asm: "SRW", aux: "Int8"}, // unsigned uint32(arg0) >> auxint, shift amount 0-31
|
||||
|
||||
// Arithmetic shifts clobber flags.
|
||||
{name: "SRAD", argLength: 2, reg: sh21, asm: "SRAD", clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 64
|
||||
{name: "SRAW", argLength: 2, reg: sh21, asm: "SRAW", clobberFlags: true}, // signed arg0 >> arg1, shift amount is mod 32
|
||||
{name: "SRAW", argLength: 2, reg: sh21, asm: "SRAW", clobberFlags: true}, // signed int32(arg0) >> arg1, shift amount is mod 32
|
||||
{name: "SRADconst", argLength: 1, reg: gp11, asm: "SRAD", aux: "Int8", clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-63
|
||||
{name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "Int8", clobberFlags: true}, // signed arg0 >> auxint, shift amount 0-31
|
||||
{name: "SRAWconst", argLength: 1, reg: gp11, asm: "SRAW", aux: "Int8", clobberFlags: true}, // signed int32(arg0) >> auxint, shift amount 0-31
|
||||
|
||||
{name: "RLLGconst", argLength: 1, reg: gp11, asm: "RLLG", aux: "Int8"}, // arg0 rotate left auxint, rotate amount 0-63
|
||||
{name: "RLLconst", argLength: 1, reg: gp11, asm: "RLL", aux: "Int8"}, // arg0 rotate left auxint, rotate amount 0-31
|
||||
|
||||
@@ -34892,7 +34892,7 @@ func rewriteValueAMD64_OpAMD64SARBconst_0(v *Value) bool {
|
||||
}
|
||||
// match: (SARBconst [c] (MOVQconst [d]))
|
||||
// cond:
|
||||
// result: (MOVQconst [d>>uint64(c)])
|
||||
// result: (MOVQconst [int64(int8(d))>>uint64(c)])
|
||||
for {
|
||||
c := v.AuxInt
|
||||
v_0 := v.Args[0]
|
||||
@@ -34901,7 +34901,7 @@ func rewriteValueAMD64_OpAMD64SARBconst_0(v *Value) bool {
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v.reset(OpAMD64MOVQconst)
|
||||
v.AuxInt = d >> uint64(c)
|
||||
v.AuxInt = int64(int8(d)) >> uint64(c)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -35147,7 +35147,7 @@ func rewriteValueAMD64_OpAMD64SARLconst_0(v *Value) bool {
|
||||
}
|
||||
// match: (SARLconst [c] (MOVQconst [d]))
|
||||
// cond:
|
||||
// result: (MOVQconst [d>>uint64(c)])
|
||||
// result: (MOVQconst [int64(int32(d))>>uint64(c)])
|
||||
for {
|
||||
c := v.AuxInt
|
||||
v_0 := v.Args[0]
|
||||
@@ -35156,7 +35156,7 @@ func rewriteValueAMD64_OpAMD64SARLconst_0(v *Value) bool {
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v.reset(OpAMD64MOVQconst)
|
||||
v.AuxInt = d >> uint64(c)
|
||||
v.AuxInt = int64(int32(d)) >> uint64(c)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
@@ -35467,7 +35467,7 @@ func rewriteValueAMD64_OpAMD64SARWconst_0(v *Value) bool {
|
||||
}
|
||||
// match: (SARWconst [c] (MOVQconst [d]))
|
||||
// cond:
|
||||
// result: (MOVQconst [d>>uint64(c)])
|
||||
// result: (MOVQconst [int64(int16(d))>>uint64(c)])
|
||||
for {
|
||||
c := v.AuxInt
|
||||
v_0 := v.Args[0]
|
||||
@@ -35476,7 +35476,7 @@ func rewriteValueAMD64_OpAMD64SARWconst_0(v *Value) bool {
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v.reset(OpAMD64MOVQconst)
|
||||
v.AuxInt = d >> uint64(c)
|
||||
v.AuxInt = int64(int16(d)) >> uint64(c)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -37197,7 +37197,7 @@ func rewriteValueS390X_OpS390XSRAW_0(v *Value) bool {
|
||||
func rewriteValueS390X_OpS390XSRAWconst_0(v *Value) bool {
|
||||
// match: (SRAWconst [c] (MOVDconst [d]))
|
||||
// cond:
|
||||
// result: (MOVDconst [d>>uint64(c)])
|
||||
// result: (MOVDconst [int64(int32(d))>>uint64(c)])
|
||||
for {
|
||||
c := v.AuxInt
|
||||
v_0 := v.Args[0]
|
||||
@@ -37206,7 +37206,7 @@ func rewriteValueS390X_OpS390XSRAWconst_0(v *Value) bool {
|
||||
}
|
||||
d := v_0.AuxInt
|
||||
v.reset(OpS390XMOVDconst)
|
||||
v.AuxInt = d >> uint64(c)
|
||||
v.AuxInt = int64(int32(d)) >> uint64(c)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
|
||||
@@ -1206,6 +1206,7 @@ func (p *Package) load(stk *ImportStack, bp *build.Package, err error) {
|
||||
// GNU binutils flagfile specifiers, sometimes called "response files").
|
||||
// To be conservative, we reject almost any arg beginning with non-alphanumeric ASCII.
|
||||
// We accept leading . _ and / as likely in file system paths.
|
||||
// There is a copy of this function in cmd/compile/internal/gc/noder.go.
|
||||
func SafeArg(name string) bool {
|
||||
if name == "" {
|
||||
return false
|
||||
|
||||
@@ -935,15 +935,20 @@ func splitPkgConfigOutput(out []byte) []string {
|
||||
// Calls pkg-config if needed and returns the cflags/ldflags needed to build the package.
|
||||
func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string, err error) {
|
||||
if pkgs := p.CgoPkgConfig; len(pkgs) > 0 {
|
||||
var pcflags []string
|
||||
for len(pkgs) > 0 && strings.HasPrefix(pkgs[0], "--") {
|
||||
pcflags = append(pcflags, pkgs[0])
|
||||
pkgs = pkgs[1:]
|
||||
}
|
||||
for _, pkg := range pkgs {
|
||||
if !load.SafeArg(pkg) {
|
||||
return nil, nil, fmt.Errorf("invalid pkg-config package name: %s", pkg)
|
||||
}
|
||||
}
|
||||
var out []byte
|
||||
out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", "--", pkgs)
|
||||
out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--cflags", pcflags, "--", pkgs)
|
||||
if err != nil {
|
||||
b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pkgs, " "), string(out))
|
||||
b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --cflags "+strings.Join(pcflags, " ")+strings.Join(pkgs, " "), string(out))
|
||||
b.Print(err.Error() + "\n")
|
||||
return nil, nil, errPrintedOutput
|
||||
}
|
||||
@@ -953,15 +958,15 @@ func (b *Builder) getPkgConfigFlags(p *load.Package) (cflags, ldflags []string,
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", "--", pkgs)
|
||||
out, err = b.runOut(p.Dir, p.ImportPath, nil, b.PkgconfigCmd(), "--libs", pcflags, "--", pkgs)
|
||||
if err != nil {
|
||||
b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pkgs, " "), string(out))
|
||||
b.showOutput(nil, p.Dir, b.PkgconfigCmd()+" --libs "+strings.Join(pcflags, " ")+strings.Join(pkgs, " "), string(out))
|
||||
b.Print(err.Error() + "\n")
|
||||
return nil, nil, errPrintedOutput
|
||||
}
|
||||
if len(out) > 0 {
|
||||
ldflags = strings.Fields(string(out))
|
||||
if err := checkLinkerFlags("CFLAGS", "pkg-config --cflags", ldflags); err != nil {
|
||||
if err := checkLinkerFlags("LDFLAGS", "pkg-config --libs", ldflags); err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
var re = regexp.MustCompile
|
||||
@@ -45,26 +46,42 @@ var validCompilerFlags = []*regexp.Regexp{
|
||||
re(`-O([^@\-].*)`),
|
||||
re(`-W`),
|
||||
re(`-W([^@,]+)`), // -Wall but not -Wa,-foo.
|
||||
re(`-f(no-)?blocks`),
|
||||
re(`-f(no-)?common`),
|
||||
re(`-f(no-)?constant-cfstrings`),
|
||||
re(`-f(no-)?exceptions`),
|
||||
re(`-finput-charset=([^@\-].*)`),
|
||||
re(`-f(no-)?lto`),
|
||||
re(`-f(no-)?modules`),
|
||||
re(`-f(no-)?objc-arc`),
|
||||
re(`-f(no-)?omit-frame-pointer`),
|
||||
re(`-f(no-)?openmp(-simd)?`),
|
||||
re(`-f(no-)?permissive`),
|
||||
re(`-f(no-)?(pic|PIC|pie|PIE)`),
|
||||
re(`-f(no-)?rtti`),
|
||||
re(`-f(no-)?split-stack`),
|
||||
re(`-f(no-)?stack-(.+)`),
|
||||
re(`-f(no-)?strict-aliasing`),
|
||||
re(`-fsanitize=(.+)`),
|
||||
re(`-g([^@\-].*)?`),
|
||||
re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`),
|
||||
re(`-m(no-)?avx[0-9a-z.]*`),
|
||||
re(`-m(no-)?ms-bitfields`),
|
||||
re(`-m(no-)?stack-(.+)`),
|
||||
re(`-mmacosx-(.+)`),
|
||||
re(`-mnop-fun-dllimport`),
|
||||
re(`-m(no-)?sse[0-9.]*`),
|
||||
re(`-pedantic(-errors)?`),
|
||||
re(`-pipe`),
|
||||
re(`-pthread`),
|
||||
re(`-std=([^@\-].*)`),
|
||||
re(`-?-std=([^@\-].*)`),
|
||||
re(`-x([^@\-].*)`),
|
||||
}
|
||||
|
||||
var validCompilerFlagsWithNextArg = []string{
|
||||
"-D",
|
||||
"-I",
|
||||
"-isystem",
|
||||
"-framework",
|
||||
"-x",
|
||||
}
|
||||
@@ -79,16 +96,29 @@ var validLinkerFlags = []*regexp.Regexp{
|
||||
re(`-m(arch|cpu|fpu|tune)=([^@\-].*)`),
|
||||
re(`-(pic|PIC|pie|PIE)`),
|
||||
re(`-pthread`),
|
||||
re(`-?-static([-a-z0-9+]*)`),
|
||||
|
||||
// Note that any wildcards in -Wl need to exclude comma,
|
||||
// since -Wl splits its argument at commas and passes
|
||||
// them all to the linker uninterpreted. Allowing comma
|
||||
// in a wildcard would allow tunnelling arbitrary additional
|
||||
// linker arguments through one of these.
|
||||
re(`-Wl,--(no-)?as-needed`),
|
||||
re(`-Wl,-Bdynamic`),
|
||||
re(`-Wl,-Bstatic`),
|
||||
re(`-Wl,--disable-new-dtags`),
|
||||
re(`-Wl,--enable-new-dtags`),
|
||||
re(`-Wl,--end-group`),
|
||||
re(`-Wl,-framework,[^,@\-][^,]+`),
|
||||
re(`-Wl,-headerpad_max_install_names`),
|
||||
re(`-Wl,--no-undefined`),
|
||||
re(`-Wl,-rpath,([^,@\-][^,]+)`),
|
||||
re(`-Wl,-search_paths_first`),
|
||||
re(`-Wl,--start-group`),
|
||||
re(`-Wl,-?-unresolved-symbols=[^,]+`),
|
||||
re(`-Wl,--(no-)?warn-([^,]+)`),
|
||||
|
||||
re(`[a-zA-Z0-9_].*\.(o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)
|
||||
re(`[a-zA-Z0-9_/].*\.(a|o|obj|dll|dylib|so)`), // direct linker inputs: x.o or libfoo.so (but not -foo.o or @foo.o)
|
||||
}
|
||||
|
||||
var validLinkerFlagsWithNextArg = []string{
|
||||
@@ -96,6 +126,7 @@ var validLinkerFlagsWithNextArg = []string{
|
||||
"-l",
|
||||
"-L",
|
||||
"-framework",
|
||||
"-Wl,-framework",
|
||||
}
|
||||
|
||||
func checkCompilerFlags(name, source string, list []string) error {
|
||||
@@ -147,10 +178,21 @@ Args:
|
||||
i++
|
||||
continue Args
|
||||
}
|
||||
if i+1 < len(list) {
|
||||
return fmt.Errorf("invalid flag in %s: %s %s", source, arg, list[i+1])
|
||||
|
||||
// Permit -Wl,-framework -Wl,name.
|
||||
if i+1 < len(list) &&
|
||||
strings.HasPrefix(arg, "-Wl,") &&
|
||||
strings.HasPrefix(list[i+1], "-Wl,") &&
|
||||
load.SafeArg(list[i+1][4:]) &&
|
||||
!strings.Contains(list[i+1][4:], ",") {
|
||||
i++
|
||||
continue Args
|
||||
}
|
||||
return fmt.Errorf("invalid flag in %s: %s without argument", source, arg)
|
||||
|
||||
if i+1 < len(list) {
|
||||
return fmt.Errorf("invalid flag in %s: %s %s (see https://golang.org/s/invalidflag)", source, arg, list[i+1])
|
||||
}
|
||||
return fmt.Errorf("invalid flag in %s: %s without argument (see https://golang.org/s/invalidflag)", source, arg)
|
||||
}
|
||||
}
|
||||
Bad:
|
||||
|
||||
@@ -132,6 +132,9 @@ var goodLinkerFlags = [][]string{
|
||||
{"-l", "世界"},
|
||||
{"-L", "framework"},
|
||||
{"-framework", "Chocolate"},
|
||||
{"-Wl,-framework", "-Wl,Chocolate"},
|
||||
{"-Wl,-framework,Chocolate"},
|
||||
{"-Wl,-unresolved-symbols=ignore-all"},
|
||||
}
|
||||
|
||||
var badLinkerFlags = [][]string{
|
||||
@@ -185,6 +188,10 @@ var badLinkerFlags = [][]string{
|
||||
{"-l", "-foo"},
|
||||
{"-framework", "-Caffeine"},
|
||||
{"-framework", "@Home"},
|
||||
{"-Wl,-framework,-Caffeine"},
|
||||
{"-Wl,-framework", "-Wl,@Home"},
|
||||
{"-Wl,-framework", "@Home"},
|
||||
{"-Wl,-framework,Chocolate,@Home"},
|
||||
{"-x", "--c"},
|
||||
{"-x", "@obj"},
|
||||
{"-Wl,-rpath,@foo"},
|
||||
|
||||
34
test/fixedbugs/issue23812.go
Normal file
34
test/fixedbugs/issue23812.go
Normal file
@@ -0,0 +1,34 @@
|
||||
// run
|
||||
|
||||
// Copyright 2018 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
want := int32(0x3edae8)
|
||||
got := foo(1)
|
||||
if want != got {
|
||||
panic(fmt.Sprintf("want %x, got %x", want, got))
|
||||
}
|
||||
}
|
||||
|
||||
func foo(a int32) int32 {
|
||||
return shr1(int32(shr2(int64(0x14ff6e2207db5d1f), int(a))), 4)
|
||||
}
|
||||
|
||||
func shr1(n int32, m int) int32 { return n >> uint(m) }
|
||||
|
||||
func shr2(n int64, m int) int64 {
|
||||
if m < 0 {
|
||||
m = -m
|
||||
}
|
||||
if m >= 64 {
|
||||
return n
|
||||
}
|
||||
|
||||
return n >> uint(m)
|
||||
}
|
||||
Reference in New Issue
Block a user