Fangrui Song <i...@maskray.me> writes: > The warning will be enabled by default in clang 10. It is not available for > clang <= 9. > > qemu/migration/migration.c:2038:24: error: implicit conversion from 'long' to > 'double' changes value from 9223372036854775807 to 9223372036854775808 > [-Werror,-Wimplicit-int-float-conversion] > ... > qemu/util/cutils.c:245:23: error: implicit conversion from 'unsigned long' to > 'double' changes value from 18446744073709550592 to 18446744073709551616 > [-Werror,-Wimplicit-int-float-conversion] > > Signed-off-by: Fangrui Song <i...@maskray.me> > --- > migration/migration.c | 4 ++-- > util/cutils.c | 4 ++-- > 2 files changed, 4 insertions(+), 4 deletions(-) > > diff --git a/migration/migration.c b/migration/migration.c > index 354ad072fa..ac3ea2934a 100644 > --- a/migration/migration.c > +++ b/migration/migration.c > @@ -53,6 +53,7 @@ > #include "monitor/monitor.h" > #include "net/announce.h" > #include "qemu/queue.h" > +#include <math.h> > > #define MAX_THROTTLE (32 << 20) /* Migration transfer speed > throttling */ > > @@ -2035,11 +2036,10 @@ void qmp_migrate_set_downtime(double value, Error > **errp) if (value < 0 || value > MAX_MIGRATE_DOWNTIME_SECONDS) { error_setg(errp, "Parameter 'downtime_limit' expects an integer in " "the range of 0 to %d seconds", MAX_MIGRATE_DOWNTIME_SECONDS); return; > }
@value is now in [0,2000]. > > value *= 1000; /* Convert to milliseconds */ @value is in [0,2000000] > - value = MAX(0, MIN(INT64_MAX, value)); This does nothing. > > MigrateSetParameters p = { > .has_downtime_limit = true, > - .downtime_limit = value, > + .downtime_limit = (int64_t)fmin(value, nextafter(0x1p63, 0)), This does nothing and is hard to read :) Can we simply drop the offending line statement instead? > }; > > qmp_migrate_set_parameters(&p, errp); > diff --git a/util/cutils.c b/util/cutils.c > index fd591cadf0..2b4484c015 100644 > --- a/util/cutils.c > +++ b/util/cutils.c > @@ -239,10 +239,10 @@ static int do_strtosz(const char *nptr, const char > **end, > goto out; > } > /* > - * Values >= 0xfffffffffffffc00 overflow uint64_t after their trip > + * Values > nextafter(0x1p64, 0) overflow uint64_t after their trip > * through double (53 bits of precision). > */ > - if ((val * mul >= 0xfffffffffffffc00) || val < 0) { > + if ((val * mul > nextafter(0x1p64, 0)) || val < 0) { > retval = -ERANGE; > goto out; > } *result = val * mul; I figure this one is correct and hard to read. 0xfffffffffffffc00 is not representable exactly as double. It's half-way between the representable values 0xfffffffffffff800 and 0x10000000000000000. Which one we get is implementation-defined. Bad. nextafter(0x1p64, 0) is a clever way to write 0xfffffffffffff800, the largest uint64_t exactly representable as double. With your patch, val * mul in [0,0xfffffffffffff800] will be accepted. The first val * mul above this range is 0x1p64. Rejecting it is correct, because it overflows yint64_t.