<div dir="ltr"><div dir="ltr"><br></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Wed, Dec 1, 2021 at 2:46 PM Alejandro Colomar (man-pages) via cfe-dev <<a href="mailto:cfe-dev@lists.llvm.org">cfe-dev@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi Joerg,<br>
<br>
On 12/1/21 23:24, Joerg Sonnenberger via cfe-dev wrote:<br>
> On Wed, Dec 01, 2021 at 10:57:51PM +0100, Alejandro Colomar (man-pages) via cfe-dev wrote:<br>
>> (2): I'm not sure I understand this one. I also didn't find the LKML<br>
>> thread. My idea is that if the compiler enforces nonnull-ness as it<br>
>> does currently with const, it will be possible to guarantee that sanity<br>
>> checks are unnecessary, and therefore they can be safely omitted (by the<br>
>> user, not the compiler).<br>
> <br>
> The original "bug" boils down to something like this:<br>
> <br>
> int f(int *p) {<br>
> int x = *p;<br>
> if (!p)<br>
> return -1;<br>
> return x;<br>
> }<br>
> <br>
> GCC sees the *p, and drops the if condition. Replace that with a call to<br>
> a function that has a nonnull attribute and you get the same problem.<br>
> <br>
<br>
If I add [[gnu::nonnull]], I get a warning (-Wnonnull-compare, implied<br>
by -Wall) with GCC, even with -O3:<br>
<br>
nonnull.c: In function ‘f’:<br>
nonnull.c:5:10: warning: ‘nonnull’ argument ‘p’ compared to NULL<br>
[-Wnonnull-compare]<br>
5 | if (!p)<br>
| ^<br>
<br>
This warning should be mandatory by the standard IMO (if _Nonnull is<br>
added), since there's no valid point in comparing a nonnull pointer to<br>
NULL, but could also be non-mandatory, since it's not a dangerous thing.<br>
Having it in -Wall would be fine too.<br>
<br>
--<br>
<br>
About when nonnull is _not_ specified:<br>
<br>
GCC detects some broken code, and optimizes it.<br>
What GCC should do IMO is warn about some broken code in the begining.<br>
<br>
Clang produces the exact same code that GCC produces;<br>
both optimize the (!p) branch entirely.<br>
This is something to be reported to both of the compilers as bugs.<br>
Broken code should be warned, not optimized, and that code is broken.<br></blockquote><div><br>The issue is this code comes up in many non-broken cases, like the case Joerg mentions once you indirect through a function call:<br><br> bool other_func(int *p) {<br> if (!p)<br> return true;<br> /* probably do some other stuff */<br> }<br> int f(int *p) {</div> int x = *p;<br> if (other_func(p))<br> return -1;<br> return x;<br> }<br><br>Now it's not clear this code isn't working as intended - it's probably possible to say that for every case Clang can warn about (ones that don't require a lot of non-local reasoning) it could also suppress any optimization of such a null check (but would that be especially useful? I find it doubtful - the user could address the warning instead), but for all the more complicated non-local reasoning (due to inlining or other optimizations) it's unlikely Clang would suppress such optimizations - because in the above code, for instance, the optimization may be exactly what the user wants - in this /particular/ call site of other_func, the pointer is always non-null so the compiler can optimize away the null test from some generic code when specializing it for this particular call site.<br><br>- Dave</div></div>