From a832fa65c4efd1bdba1ff334fa4d2daa9a3cc44d Mon Sep 17 00:00:00 2001 From: Bung Date: Fri, 13 Nov 2020 20:44:48 +0800 Subject: [PATCH] Fix #8404 JS backend doesn't handle float->int type conversion (#15950) [backport] * Fix #8404 JS backend doesn't handle float->int type conversion * handle conv to uint as cast, discard other cases * limit to int32, times use int64 * toInt including tyInt64 break times timezones lib, ignore for now * also affect to vm * move to tests/misc/t8404.nim (cherry picked from commit 797cb2e67b084f28474cc5d4251e57275c1e8f5f) --- compiler/jsgen.nim | 12 +++++++++--- tests/misc/t8404.nim | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 42 insertions(+), 3 deletions(-) create mode 100644 tests/misc/t8404.nim diff --git a/compiler/jsgen.nim b/compiler/jsgen.nim index 9340b7dd89..e5b60f0ae1 100644 --- a/compiler/jsgen.nim +++ b/compiler/jsgen.nim @@ -2124,11 +2124,17 @@ proc genConv(p: PProc, n: PNode, r: var TCompRes) = if dest.kind == src.kind: # no-op conversion return - case dest.kind: - of tyBool: + let toInt = (dest.kind in tyInt..tyInt32) + let fromInt = (src.kind in tyInt..tyInt32) + let toUint = (dest.kind in tyUInt..tyUInt32) + let fromUint = (src.kind in tyUInt..tyUInt32) + if toUint and (fromInt or fromUint): + let trimmer = unsignedTrimmer(dest.size) + r.res = "($1 $2)" % [r.res, trimmer] + elif dest.kind == tyBool: r.res = "(!!($1))" % [r.res] r.kind = resExpr - of tyInt: + elif toInt: r.res = "(($1)|0)" % [r.res] else: # TODO: What types must we handle here? diff --git a/tests/misc/t8404.nim b/tests/misc/t8404.nim new file mode 100644 index 0000000000..87991071c5 --- /dev/null +++ b/tests/misc/t8404.nim @@ -0,0 +1,33 @@ +discard """ + targets: "c cpp js" +""" +template main() = + block: # bug #8404 + # can conv + template float2int(T) = + var a = -1.0 + let b = T(a) + doAssert b < 0 + let c = b + 1 + doAssert c is T + doAssert c == 0 + + float2int(int8) + float2int(int16) + float2int(int32) + float2int(int64) + + block: + # can handle middle conv + # `/` can trigger int to float + template float2int(T) = + let n = T(1 / 256) + doAssert n == 0 + + float2int(int8) + float2int(int16) + float2int(int32) + # float2int(int64) +main() +static: + main()