Skip to content

Commit 7628521

Browse files
committed
cmd/compile/internal/gc: there are no -0 floating-point constants
Fixes #12577. Change-Id: Id469cd92f5f9436b0ef948ee1a252ed1842bc7aa Reviewed-on: https://go-review.googlesource.com/16133 Run-TryBot: Robert Griesemer <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Keith Randall <[email protected]>
1 parent ff85f86 commit 7628521

File tree

2 files changed

+84
-6
lines changed

2 files changed

+84
-6
lines changed

src/cmd/compile/internal/gc/mparith3.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func mpgetflt(a *Mpflt) float64 {
113113
Yyerror("mpgetflt ovf")
114114
}
115115

116-
return x
116+
return x + 0 // avoid -0 (should not be needed, but be conservative)
117117
}
118118

119119
func mpgetflt32(a *Mpflt) float64 {
@@ -125,14 +125,18 @@ func mpgetflt32(a *Mpflt) float64 {
125125
Yyerror("mpgetflt32 ovf")
126126
}
127127

128-
return x
128+
return x + 0 // avoid -0 (should not be needed, but be conservative)
129129
}
130130

131131
func Mpmovecflt(a *Mpflt, c float64) {
132132
if Mpdebug {
133133
fmt.Printf("\nconst %g", c)
134134
}
135135

136+
// convert -0 to 0
137+
if c == 0 {
138+
c = 0
139+
}
136140
a.Val.SetFloat64(c)
137141

138142
if Mpdebug {
@@ -141,7 +145,10 @@ func Mpmovecflt(a *Mpflt, c float64) {
141145
}
142146

143147
func mpnegflt(a *Mpflt) {
144-
a.Val.Neg(&a.Val)
148+
// avoid -0
149+
if a.Val.Sign() != 0 {
150+
a.Val.Neg(&a.Val)
151+
}
145152
}
146153

147154
//
@@ -163,15 +170,20 @@ func mpatoflt(a *Mpflt, as string) {
163170
// - decimal point and binary point in constant
164171
// TODO(gri) use different conversion function or check separately
165172
Yyerror("malformed constant: %s", as)
166-
a.Val.SetUint64(0)
173+
a.Val.SetFloat64(0)
167174
return
168175
}
169176

170177
if f.IsInf() {
171178
Yyerror("constant too large: %s", as)
172-
a.Val.SetUint64(0)
179+
a.Val.SetFloat64(0)
173180
return
174181
}
182+
183+
// -0 becomes 0
184+
if f.Sign() == 0 && f.Signbit() {
185+
a.Val.SetFloat64(0)
186+
}
175187
}
176188

177189
func (f *Mpflt) String() string {
@@ -188,7 +200,7 @@ func Fconv(fvp *Mpflt, flag int) string {
188200
// determine sign
189201
f := &fvp.Val
190202
var sign string
191-
if fvp.Val.Signbit() {
203+
if f.Sign() < 0 {
192204
sign = "-"
193205
f = new(big.Float).Abs(f)
194206
} else if flag&obj.FmtSign != 0 {

test/fixedbugs/issue12577.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
// run
2+
3+
// Copyright 2015 The Go Authors. All rights reserved.
4+
// Use of this source code is governed by a BSD-style
5+
// license that can be found in the LICENSE file.
6+
7+
// Issue 12577: Test that there are no -0 floating-point constants.
8+
9+
package main
10+
11+
import "math"
12+
13+
const (
14+
z0 = 0.0
15+
z1 = -0.0
16+
z2 = -z0
17+
z3 = -z2
18+
)
19+
20+
var (
21+
x0 float32 = z0
22+
x1 float32 = z1
23+
x2 float32 = z2
24+
x3 float32 = z3
25+
26+
y0 float64 = z0
27+
y1 float64 = z1
28+
y2 float64 = z2
29+
y3 float64 = z3
30+
)
31+
32+
func test32(f float32) {
33+
if f != 0 || math.Signbit(float64(f)) {
34+
println("BUG: got", f, "want 0.0")
35+
return
36+
}
37+
}
38+
39+
func test64(f float64) {
40+
if f != 0 || math.Signbit(f) {
41+
println("BUG: got", f, "want 0.0")
42+
return
43+
}
44+
}
45+
46+
func main() {
47+
if f := -x0; f != 0 || !math.Signbit(float64(f)) {
48+
println("BUG: got", f, "want -0.0")
49+
}
50+
51+
test32(-0.0)
52+
test32(x0)
53+
test32(x1)
54+
test32(x2)
55+
test32(x3)
56+
57+
if f := -y0; f != 0 || !math.Signbit(f) {
58+
println("BUG: got", f, "want -0.0")
59+
}
60+
61+
test64(-0.0)
62+
test64(y0)
63+
test64(y1)
64+
test64(y2)
65+
test64(y3)
66+
}

0 commit comments

Comments
 (0)