[cfe-dev] ISO C3X proposal: nonnull qualifier

Alejandro Colomar (man-pages) via cfe-dev cfe-dev at lists.llvm.org
Mon Nov 15 08:30:24 PST 2021


Hi,

On 11/15/21 5:01 PM, Alejandro Colomar (man-pages) wrote:
> Hi all,
> 
> I'd like to propose the following feature for ISO C (and also ISO C++).
> It is based on a mix of GCC's [[gnu::nonnull]] and Clang's _Nonnull,
> with a pinch of salt of mine.
> 
> I'd like to get some feedback from GCC and Clang,
> before sending it as an official proposal.
> 
> BTW, since the working group is probably very busy with C2X,
> I may delay sending it more than a year.
> Or I may propose it first to ISO C++,
> and then to ISO C.
> 
> I wrote the initial draft in the form of a manual page,
> whose source code can be found here:
> <https://github.com/alejandro-colomar/nonnull>
> 
> It has a Makefile to easily transform it into a PDF.
> I also rendered it with cat to inline it in this email.

I just came up with some addition to the initial draft:

$ git diff
diff --git a/nonnull.7 b/nonnull.7
index 1390b2d..75370e1 100644
--- a/nonnull.7
+++ b/nonnull.7
@@ -44,7 +44,10 @@ through the use of
 an lvalue with
 .BR \%nonnull -qualified
 type,
-the behavior is undefined.
+the behavior is undefined,
+except if preceeding code
+can prove at compile time that the pointer will not possibly be
+.BR NULL .
 .PP
 The intended use of the
 .B \%nonnull
@@ -212,6 +215,32 @@ since the user isn't properly informed that
 may cause undefined behavior in the implementation of the function
 .RI ( dest
 is dereferenced).
+.SS non-nonnull-qualified to nonnull-qualified valid assignment
+.EX
+int *nonnull foo(int *p)
+{
+       if (!p)
+               exit(EXIT_FAILURE);
+
+       return p;
+}
+.EE
+.PP
+The code above is guaranteed to behave correctly,
+since the check against
+.B NULL
+guarantees that the
+(otherwise causing undefined behaviour)
+assignment is only done if
+.I p
+is not
+.BR NULL .
+Forcing the user to add casts would be dangerous,
+since casts usually disable most compiler diagnostics.
+Since this qualifier pretends to improve programs' correctness,
+that would be disastrous.
+Casts also unnecessarily make code less readable.
+Letting the compiler decide if some assignment is valid is safer.
 .SH AUTHORS
 Alejandro Colomar
 .UR alx.manpages at gmail.com


The affected paragraphs now render as:

[
       If an attempt is made to assign NULL to a pointer defined
       with  the  nonnull  qualifier, the behavior is undefined.
       If an attempt is made to refer to a pointer with a  non‐‐
       nonnull‐qualified  type through the use of an lvalue with
       nonnull‐qualified type, the behavior is undefined, except
       if  preceeding  code  can  prove at compile time that the
       pointer will not possibly be NULL.
]

[
   non‐nonnull‐qualified to nonnull‐qualified valid assignment
       int *nonnull foo(int *p)
       {
            if (!p)
                 exit(EXIT_FAILURE);

            return p;
       }

       The code above is guaranteed to behave  correctly,  since
       the  check  against  NULL  guarantees that the (otherwise
       causing undefined behaviour) assignment is only done if p
       is not NULL.  Forcing the user to add casts would be dan‐
       gerous, since casts usually disable most  compiler  diag‐
       nostics.   Since  this qualifier pretends to improve pro‐
       grams' correctness, that would be disastrous.  Casts also
       unnecessarily  make code less readable.  Letting the com‐
       piler decide if some assignment is valid is safer.
]

However,
I'm not sure if this imposes too much complexity for compilers,
and maybe it's better to say that it's implementation-defined.


Thanks,
Alex


-- 
Alejandro Colomar
Linux man-pages comaintainer; https://www.kernel.org/doc/man-pages/
http://www.alejandro-colomar.es/


More information about the cfe-dev mailing list