This is an archive of the discontinued LLVM Phabricator instance.

Correct warning on Float->Integer conversions.
ClosedPublic

Authored by erichkeane on May 7 2018, 9:59 AM.

Details

Summary

As identified and briefly discussed here:
https://bugs.llvm.org/show_bug.cgi?id=37305

Converting a floating point number to an integer type when
the integral part is out of the range of the integer type is
undefined behavior in C. Additionally, CodeGen emits an undef
in this situation.

HOWEVER, we've been giving a warning that says that the value is
changed. This patch corrects the warning to list that it is actually
undefined behavior.

Diff Detail

Repository
rC Clang

Event Timeline

erichkeane created this revision.May 7 2018, 9:59 AM
aaron.ballman added inline comments.May 7 2018, 1:26 PM
lib/Sema/SemaChecking.cpp
9432

floating point -> floating-point

9440–9441

I think you can combine all of the predicates into:

if (!IsBool && ((IntegerValue.isSigned() && (...) || (IntegerValue.isUnsigned() && (...))))
  return DiagnoseImpCast(S, E, T, CContext, diag::warn_impcast_literal_float_to_integer_out_of_range);
erichkeane marked 2 inline comments as done.May 7 2018, 1:30 PM
erichkeane added inline comments.
lib/Sema/SemaChecking.cpp
9440–9441

I'd waffled on whether to combine those ore not, since I was 50/50 and you have an opinion, combining it :)

erichkeane updated this revision to Diff 145536.May 7 2018, 1:38 PM
erichkeane marked an inline comment as done.

Aaron's comments :)

This revision is now accepted and ready to land.May 7 2018, 1:41 PM
This revision was automatically updated to reflect the committed changes.

The check for whether an input is "out of range" doesn't handle fractions correctly. Testcase:

int a() { return 2147483647.5; }
unsigned b() { return -.5; }

The check for whether an input is "out of range" doesn't handle fractions correctly. Testcase:

int a() { return 2147483647.5; }
unsigned b() { return -.5; }

Hrm... For some reaosn I had it in my head that both of those were UB... Interestingly, EDG/ICC thinks the second one is. I'll look into this more to see if I can refine the warning.

Hello, @erichkeane

I am working on int to float checker but I haven't found yet a way how to check if integer fits to float's significant bits. Maybe you can recommend me something? I already tried some LLVM APIs but no success. (cc @spatel as you will probably know the right function to do it)

Hello, @erichkeane

I am working on int to float checker but I haven't found yet a way how to check if integer fits to float's significant bits. Maybe you can recommend me something? I already tried some LLVM APIs but no success. (cc @spatel as you will probably know the right function to do it)

I'm not sure what you mean by that... Every Integer is representable (lossy of course) as a float as far as I know. You'll obviously lose the LSDs, but it'll be representable. Are you trying to check whether it is round-trip-able? If thats the case, I think you'll need to make sure it entirely fits in the mantissa. You can get the amount of mantissa bits by checking the APFloat's fltSemantics. There are a couple of builtin ones that I think end up being useful, but the 'precision' field seems like what you want.

Yeah, I want to check if it fits into mantissa.

Every Integer is representable (lossy of course) as a float as far as I know.

Casting a uint128_t to float can overflow. And overflowing a _Float16 is easy. (Of course, both uint128_t and _Float16 are rare in normal C/C++ code.)