mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
cmd/compile: diagnose constant division by complex zero
When casting an ideal to complex{64,128}, for example during the
evaluation of
var a = complex64(0) / 1e-50
we want the compiler to report a division-by-zero error if a divisor
would be zero after the cast.
We already do this for floats; for example
var b = float32(0) / 1e-50
generates a 'division by zero' error at compile time (because
float32(1e-50) is zero, and the cast is done before performing the
division).
There's no such check in the path for complex{64,128} expressions, and
no cast is performed before the division in the evaluation of
var a = complex64(0) / 1e-50
which compiles just fine.
This patch changes the convlit1 function so that complex ideals
components (real and imag) are correctly truncated to float{32,64}
when doing an ideal -> complex{64, 128} cast.
Fixes #11674
Change-Id: Ic5f8ee3c8cfe4c3bb0621481792c96511723d151
Reviewed-on: https://go-review.googlesource.com/37891
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
49f4b5a4f5
commit
10a200e560
4 changed files with 149 additions and 4 deletions
|
|
@ -160,6 +160,37 @@ func truncfltlit(oldv *Mpflt, t *types.Type) *Mpflt {
|
|||
return fv
|
||||
}
|
||||
|
||||
// truncate Real and Imag parts of Mpcplx to 32-bit or 64-bit
|
||||
// precision, according to type; return truncated value. In case of
|
||||
// overflow, calls yyerror but does not truncate the input value.
|
||||
func trunccmplxlit(oldv *Mpcplx, t *types.Type) *Mpcplx {
|
||||
if t == nil {
|
||||
return oldv
|
||||
}
|
||||
|
||||
if overflow(Val{oldv}, t) {
|
||||
// Avoid setting to Inf if there was an overflow. It's never
|
||||
// useful, and it'll cause spourious and confusing 'constant Inf
|
||||
// overflows float32' errors down the road.
|
||||
return oldv
|
||||
}
|
||||
|
||||
cv := newMpcmplx()
|
||||
|
||||
switch t.Etype {
|
||||
case TCOMPLEX64:
|
||||
cv.Real.SetFloat64(oldv.Real.Float32())
|
||||
cv.Imag.SetFloat64(oldv.Imag.Float32())
|
||||
case TCOMPLEX128:
|
||||
cv.Real.SetFloat64(oldv.Real.Float64())
|
||||
cv.Imag.SetFloat64(oldv.Imag.Float64())
|
||||
default:
|
||||
Fatalf("trunccplxlit: unexpected Etype %v", t.Etype)
|
||||
}
|
||||
|
||||
return cv
|
||||
}
|
||||
|
||||
// canReuseNode indicates whether it is known to be safe
|
||||
// to reuse a Node.
|
||||
type canReuseNode bool
|
||||
|
|
@ -361,7 +392,7 @@ func convlit1(n *Node, t *types.Type, explicit bool, reuse canReuseNode) *Node {
|
|||
fallthrough
|
||||
|
||||
case CTCPLX:
|
||||
overflow(n.Val(), t)
|
||||
n.SetVal(Val{trunccmplxlit(n.Val().U.(*Mpcplx), t)})
|
||||
}
|
||||
} else if et == types.TSTRING && (ct == CTINT || ct == CTRUNE) && explicit {
|
||||
n.SetVal(tostr(n.Val()))
|
||||
|
|
@ -519,21 +550,25 @@ func doesoverflow(v Val, t *types.Type) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
func overflow(v Val, t *types.Type) {
|
||||
func overflow(v Val, t *types.Type) bool {
|
||||
// v has already been converted
|
||||
// to appropriate form for t.
|
||||
if t == nil || t.Etype == TIDEAL {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
// Only uintptrs may be converted to unsafe.Pointer, which cannot overflow.
|
||||
if t.Etype == TUNSAFEPTR {
|
||||
return
|
||||
return false
|
||||
}
|
||||
|
||||
if doesoverflow(v, t) {
|
||||
yyerror("constant %v overflows %v", v, t)
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
|
||||
}
|
||||
|
||||
func tostr(v Val) Val {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue