diff --git a/src/cmd/compile/internal/gc/const.go b/src/cmd/compile/internal/gc/const.go index bd307116e8..24c0fba523 100644 --- a/src/cmd/compile/internal/gc/const.go +++ b/src/cmd/compile/internal/gc/const.go @@ -6,6 +6,7 @@ package gc import ( "cmd/internal/src" + "math/big" "strings" ) @@ -455,19 +456,33 @@ func toint(v Val) Val { case *Mpflt: i := new(Mpint) - if i.SetFloat(u) < 0 { - msg := "constant %v truncated to integer" - // provide better error message if SetFloat failed because f was too large - if u.Val.IsInt() { - msg = "constant %v overflows integer" + if !i.SetFloat(u) { + if i.Ovf { + yyerror("integer too large") + } else { + // The value of u cannot be represented as an integer; + // so we need to print an error message. + // Unfortunately some float values cannot be + // reasonably formatted for inclusion in an error + // message (example: 1 + 1e-100), so first we try to + // format the float; if the truncation resulted in + // something that looks like an integer we omit the + // value from the error message. + // (See issue #11371). + var t big.Float + t.Parse(fconv(u, FmtSharp), 10) + if t.IsInt() { + yyerror("constant truncated to integer") + } else { + yyerror("constant %v truncated to integer", fconv(u, FmtSharp)) + } } - yyerror(msg, fconv(u, FmtSharp)) } v.U = i case *Mpcplx: i := new(Mpint) - if i.SetFloat(&u.Real) < 0 || u.Imag.CmpFloat64(0) != 0 { + if !i.SetFloat(&u.Real) || u.Imag.CmpFloat64(0) != 0 { yyerror("constant %v%vi truncated to integer", fconv(&u.Real, FmtSharp), fconv(&u.Imag, FmtSharp|FmtSign)) } diff --git a/src/cmd/compile/internal/gc/mpint.go b/src/cmd/compile/internal/gc/mpint.go index fba82607b5..f4efde3751 100644 --- a/src/cmd/compile/internal/gc/mpint.go +++ b/src/cmd/compile/internal/gc/mpint.go @@ -36,15 +36,16 @@ func (a *Mpint) Set(b *Mpint) { a.Val.Set(&b.Val) } -func (a *Mpint) SetFloat(b *Mpflt) int { +func (a *Mpint) SetFloat(b *Mpflt) bool { // avoid converting huge floating-point numbers to integers // (2*Mpprec is large enough to permit all tests to pass) if b.Val.MantExp(nil) > 2*Mpprec { - return -1 + a.SetOverflow() + return false } if _, acc := b.Val.Int(&a.Val); acc == big.Exact { - return 0 + return true } const delta = 16 // a reasonably small number of bits > 0 @@ -55,17 +56,18 @@ func (a *Mpint) SetFloat(b *Mpflt) int { t.SetMode(big.ToZero) t.Set(&b.Val) if _, acc := t.Int(&a.Val); acc == big.Exact { - return 0 + return true } // try rounding up a little t.SetMode(big.AwayFromZero) t.Set(&b.Val) if _, acc := t.Int(&a.Val); acc == big.Exact { - return 0 + return true } - return -1 + a.Ovf = false + return false } func (a *Mpint) Add(b *Mpint) { diff --git a/test/fixedbugs/issue11371.go b/test/fixedbugs/issue11371.go new file mode 100644 index 0000000000..b2d966fac8 --- /dev/null +++ b/test/fixedbugs/issue11371.go @@ -0,0 +1,17 @@ +// errorcheck + +// Copyright 2017 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. + +// Issue 11371 (cmd/compile: meaningless error message "truncated to +// integer") + +package issue11371 + +const a int = 1.1 // ERROR "constant 1.1 truncated to integer" +const b int = 1e20 // ERROR "overflows int" +const c int = 1 + 1e-100 // ERROR "constant truncated to integer" +const d int = 1 - 1e-100 // ERROR "constant truncated to integer" +const e int = 1.00000001 // ERROR "constant truncated to integer" +const f int = 0.00000001 // ERROR "constant 1e-08 truncated to integer" diff --git a/test/fixedbugs/issue13471.go b/test/fixedbugs/issue13471.go index 81f034ba79..0bfed42616 100644 --- a/test/fixedbugs/issue13471.go +++ b/test/fixedbugs/issue13471.go @@ -9,17 +9,17 @@ package main func main() { - const _ int64 = 1e646456992 // ERROR "1e\+646456992 overflows integer" - const _ int32 = 1e64645699 // ERROR "1e\+64645699 overflows integer" - const _ int16 = 1e6464569 // ERROR "1e\+6464569 overflows integer" - const _ int8 = 1e646456 // ERROR "1e\+646456 overflows integer" - const _ int = 1e64645 // ERROR "1e\+64645 overflows integer" + const _ int64 = 1e646456992 // ERROR "integer too large" + const _ int32 = 1e64645699 // ERROR "integer too large" + const _ int16 = 1e6464569 // ERROR "integer too large" + const _ int8 = 1e646456 // ERROR "integer too large" + const _ int = 1e64645 // ERROR "integer too large" - const _ uint64 = 1e646456992 // ERROR "1e\+646456992 overflows integer" - const _ uint32 = 1e64645699 // ERROR "1e\+64645699 overflows integer" - const _ uint16 = 1e6464569 // ERROR "1e\+6464569 overflows integer" - const _ uint8 = 1e646456 // ERROR "1e\+646456 overflows integer" - const _ uint = 1e64645 // ERROR "1e\+64645 overflows integer" + const _ uint64 = 1e646456992 // ERROR "integer too large" + const _ uint32 = 1e64645699 // ERROR "integer too large" + const _ uint16 = 1e6464569 // ERROR "integer too large" + const _ uint8 = 1e646456 // ERROR "integer too large" + const _ uint = 1e64645 // ERROR "integer too large" - const _ rune = 1e64645 // ERROR "1e\+64645 overflows integer" + const _ rune = 1e64645 // ERROR "integer too large" } diff --git a/test/fixedbugs/issue13559.go b/test/fixedbugs/issue13559.go index 4783c62f68..16de2a2e31 100644 --- a/test/fixedbugs/issue13559.go +++ b/test/fixedbugs/issue13559.go @@ -13,11 +13,11 @@ package p const _ int64 = 1e-10000 // ERROR "1e\-10000 truncated" const ( - _ int64 = 1e10000000 // ERROR "1e\+10000000 overflows" - _ int64 = 1e1000000 // ERROR "1e\+1000000 overflows" - _ int64 = 1e100000 // ERROR "1e\+100000 overflows" - _ int64 = 1e10000 // ERROR "1e\+10000 overflows" - _ int64 = 1e1000 // ERROR "1e\+1000 overflows" + _ int64 = 1e10000000 // ERROR "integer too large" + _ int64 = 1e1000000 // ERROR "integer too large" + _ int64 = 1e100000 // ERROR "integer too large" + _ int64 = 1e10000 // ERROR "integer too large" + _ int64 = 1e1000 // ERROR "integer too large" _ int64 = 1e100 // ERROR "10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows" _ int64 = 1e10 _ int64 = 1e1 @@ -32,11 +32,11 @@ const ( ) const ( - _ int64 = -1e10000000 // ERROR "\-1e\+10000000 overflows" - _ int64 = -1e1000000 // ERROR "\-1e\+1000000 overflows" - _ int64 = -1e100000 // ERROR "\-1e\+100000 overflows" - _ int64 = -1e10000 // ERROR "\-1e\+10000 overflows" - _ int64 = -1e1000 // ERROR "\-1e\+1000 overflows" + _ int64 = -1e10000000 // ERROR "integer too large" + _ int64 = -1e1000000 // ERROR "integer too large" + _ int64 = -1e100000 // ERROR "integer too large" + _ int64 = -1e10000 // ERROR "integer too large" + _ int64 = -1e1000 // ERROR "integer too large" _ int64 = -1e100 // ERROR "\-10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows" _ int64 = -1e10 _ int64 = -1e1 @@ -51,11 +51,11 @@ const ( ) const ( - _ int64 = 1.23456789e10000000 // ERROR "1\.23457e\+10000000 overflows" - _ int64 = 1.23456789e1000000 // ERROR "1\.23457e\+1000000 overflows" - _ int64 = 1.23456789e100000 // ERROR "1\.23457e\+100000 overflows" - _ int64 = 1.23456789e10000 // ERROR "1\.23457e\+10000 overflows" - _ int64 = 1.23456789e1000 // ERROR "1\.23457e\+1000 overflows" + _ int64 = 1.23456789e10000000 // ERROR "integer too large" + _ int64 = 1.23456789e1000000 // ERROR "integer too large" + _ int64 = 1.23456789e100000 // ERROR "integer too large" + _ int64 = 1.23456789e10000 // ERROR "integer too large" + _ int64 = 1.23456789e1000 // ERROR "integer too large" _ int64 = 1.23456789e100 // ERROR "12345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows" _ int64 = 1.23456789e10 _ int64 = 1.23456789e1 // ERROR "12\.3457 truncated" @@ -70,11 +70,11 @@ const ( ) const ( - _ int64 = -1.23456789e10000000 // ERROR "\-1\.23457e\+10000000 overflows" - _ int64 = -1.23456789e1000000 // ERROR "\-1\.23457e\+1000000 overflows" - _ int64 = -1.23456789e100000 // ERROR "\-1\.23457e\+100000 overflows" - _ int64 = -1.23456789e10000 // ERROR "\-1\.23457e\+10000 overflows" - _ int64 = -1.23456789e1000 // ERROR "\-1\.23457e\+1000 overflows" + _ int64 = -1.23456789e10000000 // ERROR "integer too large" + _ int64 = -1.23456789e1000000 // ERROR "integer too large" + _ int64 = -1.23456789e100000 // ERROR "integer too large" + _ int64 = -1.23456789e10000 // ERROR "integer too large" + _ int64 = -1.23456789e1000 // ERROR "integer too large" _ int64 = -1.23456789e100 // ERROR "\-12345678900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 overflows" _ int64 = -1.23456789e10 _ int64 = -1.23456789e1 // ERROR "\-12\.3457 truncated"