cmd/compile: does not diagnose constant division by zero
dvyukov opened this issue · 4 comments
gc produces an error for c and d, but not for a and b:
package a
var a = complex64(0)/1e-1000
var b = complex64(0)/1e-47
var c = float32(0)/1e-1000
var d = float32(0)/1e-47
go.go:4: division by zero
go.go:5: division by zero
gotype produces errors for all 4 variables.
go version devel +9b04852 Sat Jul 11 00:08:50 2015 +0000 linux/amd64
The spec is not super-clear, but this appears to be a compiler bug: The untyped constants (1e-47, 1e-1000) are converted to float32/complex64 values before the operation, and the conversion results in silent underflow to 0, hence the div-by-zero error.
For comparison, in
package main
const _ = int8(-128) + 128
( http://play.golang.org/p/YrUx9sSX3w ) the compiler does exactly that: it converts the untyped 128 into an int8 which is not possible and thus returns an error.
Analysis: in convlit1
function inside const.go
. What happens for a float
constant is that the node is converted to float
using
n.SetVal(Val{truncfltlit(n.Val().U.(*Mpflt), t)})
Note the call to truncfltlit
, that truncates a float literal to float32
or float64
precision. For the above snippet, both the denominators get truncated to 0
. After that we enter the evconst
function, and the following check fails
mpcmpfltc(rv.U.(*Mpflt), 0) == 0
here, because rv
is 0
, and the compiler calls Yyerror("division by zero")
.
For complex
values, the compiler executes
n.SetVal(tocplx(n.Val()))
unfortunately, the tocplx
function does not truncate float
values. It just does
mpmovefltflt(&c.Real, v.U.(*Mpflt))
i.e. it moves the value of the real part to c
. For that reason evconst
actually gets 1e-1000
, so the following check
mpcmpfltc(&rv.U.(*Mpcplx).Real, 0) == 0 && mpcmpfltc(&rv.U.(*Mpcplx).Imag, 0) == 0
here passes, because rv (the real part) in not zero, and the
Yyerror("complex division by zero")
lines is not called.
I have a simple patch for this (we just need to call truncfltlit
after the tocplx
call in convlit1
) that passes all.bash
. I will email it if nobody else already have a CL for this.
CL https://golang.org/cl/37891 mentions this issue.