[cfe-dev] ISO C3X proposal: nonnull qualifier

David Blaikie via cfe-dev cfe-dev at lists.llvm.org
Wed Dec 1 14:55:13 PST 2021


On Wed, Dec 1, 2021 at 2:46 PM Alejandro Colomar (man-pages) via cfe-dev <
cfe-dev at lists.llvm.org> wrote:

> Hi Joerg,
>
> On 12/1/21 23:24, Joerg Sonnenberger via cfe-dev wrote:
> > On Wed, Dec 01, 2021 at 10:57:51PM +0100, Alejandro Colomar (man-pages)
> via cfe-dev wrote:
> >> (2):  I'm not sure I understand this one.  I also didn't find the LKML
> >> thread.  My idea is that if the compiler enforces nonnull-ness as it
> >> does currently with const, it will be possible to guarantee that sanity
> >> checks are unnecessary, and therefore they can be safely omitted (by the
> >> user, not the compiler).
> >
> > The original "bug" boils down to something like this:
> >
> >    int f(int *p) {
> >       int x = *p;
> >       if (!p)
> >         return -1;
> >       return x;
> >    }
> >
> > GCC sees the *p, and drops the if condition. Replace that with a call to
> > a function that has a nonnull attribute and you get the same problem.
> >
>
> If I add [[gnu::nonnull]], I get a warning (-Wnonnull-compare, implied
> by -Wall) with GCC, even with -O3:
>
> nonnull.c: In function ‘f’:
> nonnull.c:5:10: warning: ‘nonnull’ argument ‘p’ compared to NULL
> [-Wnonnull-compare]
>     5 |       if (!p)
>       |          ^
>
> This warning should be mandatory by the standard IMO (if _Nonnull is
> added), since there's no valid point in comparing a nonnull pointer to
> NULL, but could also be non-mandatory, since it's not a dangerous thing.
>  Having it in -Wall would be fine too.
>
> --
>
> About when nonnull is _not_ specified:
>
> GCC detects some broken code, and optimizes it.
> What GCC should do IMO is warn about some broken code in the begining.
>
> Clang produces the exact same code that GCC produces;
> both optimize the (!p) branch entirely.
> This is something to be reported to both of the compilers as bugs.
> Broken code should be warned, not optimized, and that code is broken.
>

The issue is this code comes up in many non-broken cases, like the case
Joerg mentions once you indirect through a function call:

  bool other_func(int *p) {
    if (!p)
      return true;
    /* probably do some other stuff */
  }
  int f(int *p) {
      int x = *p;
      if (other_func(p))
        return -1;
      return x;
  }

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.

- Dave
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20211201/3ba4f520/attachment.html>


More information about the cfe-dev mailing list