On Tue, Mar 19, 2013 at 5:42 PM, Sean McBride <span dir="ltr"><<a href="mailto:sean@rogue-research.com" target="_blank">sean@rogue-research.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi all,<br>
<br>
I'm not a language lawyer, but...<br>
<br>
----------------<br>
float f = sqrtf(-1.0f);<br>
double d = (double)f;<br>
<br>
printf("%a -- %a\n", d, f);<br>
----------------<br>
<br>
$ clang++ -fsanitize=undefined Test.cxx<br>
<br>
runtime error: value nan is outside the range of representable values of type 'double'<br>
<br>
My quick googling of the C++ standard finds:<br>
<br>
"4.6 Floating point promotion: A prvalue of type float can be converted to a prvalue of type double. The value is unchanged."<br>
<br>
That suggests to me ubsan is wrong to complain.<br>
<br>
ubsan warns about the opposite conversion too, that is:<br>
<br>
----------------<br>
double d = sqrt(-1.0);<br>
float f = (float)d;<br>
----------------<br>
<br>
"4.8 Floating point conversions: A prvalue of floating point type can be converted to a prvalue of another floating point type. If the source value can be exactly represented in the destination type, the result of the conversion is that exact representation. If the source value is between two adjacent destination values, the result of the conversion is an implementation-defined choice of either of those values. Otherwise, the behavior is undefined."<br>
<br>
This is less clear (to me anyway). Is double-NaN exactly representable by float-NaN? (I'd like to hope so, because otherwise -fsanitize=float-cast-overflow is going to be very noisy with various math/science codebases.)</blockquote>
<div><br></div><div>This is a rather tricky area; the C++ standard's core wording doesn't really address the possibility that floating-point values might be NaN or infinite, and it's not clear whether these values are, or should be, in the range of values that can be represented in the floating-point type. Also, are FLT_MAX and float infinity "adjacent destination values"? (If so, any double larger than FLT_MAX must convert to either FLT_MAX or float infinity, and thus *no* floating-point conversions have undefined behavior).</div>
<div><br></div><div>C's annex F gives some answers to these questions: it says that '+-inf' is in the range of representable values, which removes all undefined behavior from floating-point conversions other than perhaps double NaN to float NaN. However, that approach loses the (valuable) check for overflow due to data loss in double -> float conversion.</div>
<div><br></div><div>(Even C's annex F doesn't cover NaNs very well. Converting a double-NaN to a float-NaN is lossy (it discards the payload), so it's not exactly clear what it means for a particular double NaN to be exactly represented as a float. And vice versa: there is no way to convert a float NaN to a double NaN without changing the value, if NaN is in the set of values of the type.)</div>
<div><br></div><div>So I suggest we split float-cast-overflow into two checks, one for floating-integral conversions and one for floating point conversions, and we suggest that people who want to use IEEE 754 floating-point semantics turn the latter check off. Would that work for you?</div>
</div>