mirror of
https://github.com/golang/go
synced 2024-09-15 22:20:06 +00:00
cmd/compile: don't panic in complex division
Updates #20227 Change-Id: Idadc3137490181a5d380367660cee21e8313cf3b Reviewed-on: https://go-review.googlesource.com/42650 Run-TryBot: Alberto Donizetti <alb.donizetti@gmail.com> TryBot-Result: Gobot Gobot <gobot@golang.org> Reviewed-by: Robert Griesemer <gri@golang.org>
This commit is contained in:
parent
c7cae34b19
commit
2d1829b539
|
@ -1037,15 +1037,13 @@ func evconst(n *Node) {
|
||||||
cmplxmpy(v.U.(*Mpcplx), rv.U.(*Mpcplx))
|
cmplxmpy(v.U.(*Mpcplx), rv.U.(*Mpcplx))
|
||||||
|
|
||||||
case ODIV_ | CTCPLX_:
|
case ODIV_ | CTCPLX_:
|
||||||
if rv.U.(*Mpcplx).Real.CmpFloat64(0) == 0 && rv.U.(*Mpcplx).Imag.CmpFloat64(0) == 0 {
|
if !cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx)) {
|
||||||
yyerror("complex division by zero")
|
yyerror("complex division by zero")
|
||||||
rv.U.(*Mpcplx).Real.SetFloat64(1.0)
|
rv.U.(*Mpcplx).Real.SetFloat64(1.0)
|
||||||
rv.U.(*Mpcplx).Imag.SetFloat64(0.0)
|
rv.U.(*Mpcplx).Imag.SetFloat64(0.0)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
cmplxdiv(v.U.(*Mpcplx), rv.U.(*Mpcplx))
|
|
||||||
|
|
||||||
case OEQ_ | CTNIL_:
|
case OEQ_ | CTNIL_:
|
||||||
goto settrue
|
goto settrue
|
||||||
|
|
||||||
|
@ -1591,7 +1589,11 @@ func cmplxmpy(v *Mpcplx, rv *Mpcplx) {
|
||||||
|
|
||||||
// complex divide v /= rv
|
// complex divide v /= rv
|
||||||
// (a, b) / (c, d) = ((a*c + b*d), (b*c - a*d))/(c*c + d*d)
|
// (a, b) / (c, d) = ((a*c + b*d), (b*c - a*d))/(c*c + d*d)
|
||||||
func cmplxdiv(v *Mpcplx, rv *Mpcplx) {
|
func cmplxdiv(v *Mpcplx, rv *Mpcplx) bool {
|
||||||
|
if rv.Real.CmpFloat64(0) == 0 && rv.Imag.CmpFloat64(0) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
var ac Mpflt
|
var ac Mpflt
|
||||||
var bd Mpflt
|
var bd Mpflt
|
||||||
var bc Mpflt
|
var bc Mpflt
|
||||||
|
@ -1599,6 +1601,7 @@ func cmplxdiv(v *Mpcplx, rv *Mpcplx) {
|
||||||
var cc_plus_dd Mpflt
|
var cc_plus_dd Mpflt
|
||||||
|
|
||||||
cc_plus_dd.Set(&rv.Real)
|
cc_plus_dd.Set(&rv.Real)
|
||||||
|
|
||||||
cc_plus_dd.Mul(&rv.Real) // cc
|
cc_plus_dd.Mul(&rv.Real) // cc
|
||||||
|
|
||||||
ac.Set(&rv.Imag)
|
ac.Set(&rv.Imag)
|
||||||
|
@ -1607,6 +1610,14 @@ func cmplxdiv(v *Mpcplx, rv *Mpcplx) {
|
||||||
|
|
||||||
cc_plus_dd.Add(&ac) // cc+dd
|
cc_plus_dd.Add(&ac) // cc+dd
|
||||||
|
|
||||||
|
// We already checked that c and d are not both zero, but we can't
|
||||||
|
// assume that c²+d² != 0 follows, because for tiny values of c
|
||||||
|
// and/or d c²+d² can underflow to zero. Check that c²+d² is
|
||||||
|
// nonzero,return if it's not.
|
||||||
|
if cc_plus_dd.CmpFloat64(0) == 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
ac.Set(&v.Real)
|
ac.Set(&v.Real)
|
||||||
|
|
||||||
ac.Mul(&rv.Real) // ac
|
ac.Mul(&rv.Real) // ac
|
||||||
|
@ -1632,6 +1643,8 @@ func cmplxdiv(v *Mpcplx, rv *Mpcplx) {
|
||||||
|
|
||||||
v.Imag.Sub(&ad) // bc-ad
|
v.Imag.Sub(&ad) // bc-ad
|
||||||
v.Imag.Quo(&cc_plus_dd) // (bc+ad)/(cc+dd)
|
v.Imag.Quo(&cc_plus_dd) // (bc+ad)/(cc+dd)
|
||||||
|
|
||||||
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
// Is n a Go language constant (as opposed to a compile-time constant)?
|
// Is n a Go language constant (as opposed to a compile-time constant)?
|
||||||
|
|
|
@ -171,6 +171,7 @@ func TestStdFixed(t *testing.T) {
|
||||||
"issue18459.go", // go/types doesn't check validity of //go:xxx directives
|
"issue18459.go", // go/types doesn't check validity of //go:xxx directives
|
||||||
"issue18882.go", // go/types doesn't check validity of //go:xxx directives
|
"issue18882.go", // go/types doesn't check validity of //go:xxx directives
|
||||||
"issue20232.go", // go/types handles larger constants than gc
|
"issue20232.go", // go/types handles larger constants than gc
|
||||||
|
"issue20227.go", // go/types does not handle this yet
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
16
test/fixedbugs/issue20227.go
Normal file
16
test/fixedbugs/issue20227.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// 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 20227: panic while constructing constant "1i/1e-600000000"
|
||||||
|
|
||||||
|
package p
|
||||||
|
|
||||||
|
var _ = 1 / 1e-600000000i // ERROR "complex division by zero"
|
||||||
|
var _ = 1i / 1e-600000000 // ERROR "complex division by zero"
|
||||||
|
var _ = 1i / 1e-600000000i // ERROR "complex division by zero"
|
||||||
|
|
||||||
|
var _ = 1 / (1e-600000000 + 1e-600000000i) // ERROR "complex division by zero"
|
||||||
|
var _ = 1i / (1e-600000000 + 1e-600000000i) // ERROR "complex division by zero"
|
Loading…
Reference in a new issue