Change History (26)

FYI, exactly zero of the cases this sanitizer flagged as undefined behaviour in #29527 are actually undefined behaviour. Of the ~50 reports, only two of them are potentially evidence of problems, but since the tests pass with no floating-point invalid-operation exceptions I suspect they might not be problems either.

Strictly speaking, Annex F is optional. Strictly speaking, there may be bugs in the IEEE 754 conformance of clang or gcc. Strictly speaking, not everything is up to the compiler, so if you used clang or gcc but linked against a broken libm that didn't provide IEEE 754 semantics, it might be technically wrong for clang or gcc to advertise IEEE 754 semantics (a.k.a. Annex F support, indicated by the definition of the __STDC_IEC_559__ macro).

Nobody except a disingenuous language lawyer trolling for a point would seriously choose to wittingly make clang or gcc deviate in any substantial way from IEEE 754 semantics.
Essentially the entire body of numerical software on the planet of the past quarter century, outside now-obscure platforms like legacy IBM mainframes or VAXen, has been designed under the premise of IEEE 754 semantics.

Even clang UB optimization attorneys, who might delete null pointer checks if they can be proven to follow undefined behaviour in the absence of -fno-delete-null-pointer-checks, don't seem to be inclined to take advantage of the potential room for disagreement between C99 6.5.5 and Annex F. Where clang deviates from IEEE 754 semantics, it's because of a lack of devpower to go through IEEE 754 and clang with a fine-toothed comb to catch all the corner cases (e.g., optimization bugs in nondefault rounding modes), not because they intend to exploit it.

For an illustrative example of the value of IEEE 754 semantics, see the dozens of cases in #29527 that could have gone wrong if we didn't have IEEE 754 divide-by-zero semantics, but that do exactly the right thing even though I wasn't thinking about those cases when I wrote the code (until I wrote the test cases, and again later when I reviewed all the false positives). Failure to support IEEE 754 semantics, particularly extremely basic parts like consistently giving infinities for division by zero, would likely be blamed for ​billion-dollar mistakes.

So the UBSan runtime reports divisions by zero, but the UBSan trap does not? That's also really weird.

Clang has very poor documentation, but a lot of features come from GCC, and Clang's devs recommend to use GCC docs :( plus "read the source" :(
So, here's where it comes from (GCC):
"Unlike other similar options, -fsanitize=float-divide-by-zero is not enabled by -fsanitize=undefined, since floating-point division by zero can be a legitimate way of obtaining infinities and NaNs."
And trap one has the same default behavior:
"The -fsanitize-undefined-trap-on-error option instructs the compiler to report undefined behavior using __builtin_trap rather than a libubsan library routine. The advantage of this is that the libubsan library is not needed and is not linked in, so this is usable even in freestanding environments."