From: "Alejandro Colomar (man-pages)" <alx.manpages@gmail.com>
To: JeanHeyd Meneide <phdofthehouse@gmail.com>,
gcc@gcc.gnu.org, cfe-dev@lists.llvm.org
Subject: ISO C3X proposal: nonnull qualifier
Date: Mon, 15 Nov 2021 17:01:49 +0100 [thread overview]
Message-ID: <a0e33e64-460a-6830-69ac-a67b52734bd5@gmail.com> (raw)
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.
Cheers,
Alex
---
nonnull(3) Nxxxx nonnull(3)
NAME
nonnull - non‐null pointer
SYNOPSIS
type‐qualifier:
const
nonnull
restrict
volatile
_Atomic
DESCRIPTION
Constraints
Types other than pointer types shall not be
nonnull‐qualified.
Semantics
The properties associated with qualified types are mean‐
ingfull only for expressions that are lvalues.
If the same qualifier appears more than once in the same
specifier‐qualifier list or as declaration specifiers,
either directly or via one or more typedefs, the behavior
is the same as if it appeared only once. If other quali‐
fiers appear along with the _Atomic qualifier, the re‐
sulting type is the so‐qualified atomic type.
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.
The intended use of the nonnull and restrict qualifiers
(like the register storage class) is to promote optimiza‐
tion, and deleting all instances of the qualifier from
all preprocessing translation units composing a conform‐
ing program does not change its meaning (i.e., observable
behavior).
NOTES
These rules for nonnull are somewhat of the reverse of
const: Instead of forbidding the discarding of the quali‐
fier, we forbid the addition of the qualifier. The rea‐
son is that constant variables are a subset of variables,
and the danger is in treating a const as a variable.
Similarly, nonnull pointers are a subset of (possibly‐
NULL) pointers, but the danger is in treating possibly‐
NULL pointers as nonnull pointers.
Prior art
GCC has [[gnu::nonnull]]. Why is this better?
It can be applied more specifically in the case of point‐
ers to pointers. And, like with const, the nonnull‐ness
can be better enforced by passing the qualifier around.
However, we recognize the optimizations allowed by
[[gnu::nonnull]], and also allow them, by specifying the
behavior as undefined when the qualifier is misused, as
GCC does.
Clang has _Nonnull. Why is this better?
Clang found that using a qualifier was better than an at‐
tribute, since it allowed to more specifically apply it
to pointers to pointers. We recognize that, and also use
a qualifier.
Clang doesn't specify the behavior as being undefined.
That forbids optimizations, that would otherwise be pos‐
sible. We prefer to allow for those optimizations.
Clang considers this qualifier to be useful only as a di‐
agnostics generator. We not only allow for diagnostics
to be issued, but we have stricter rules that make it
more difficult to produce incorrect code.
Even though the language has reserved identifiers start‐
ing with underscore + uppercase for this kind of key‐
words, Clang has already used _Nonnull, and since we are
changing the meaning, it might cause problems to existing
code. So nonnull seems a better name, which hopefully is
not used by existing code, or at least it is less used.
EXAMPLES
Correct
strcpy(3) may be implemented in the following way, to
signify that it cannot accept NULL as input to any of its
arguments, and that it cannot ever return NULL either.
char *nonnull strcpy(char *nonnull restrict dest,
const char *nonnull restrict src)
{
char *d;
d = dest;
while ((*d++ = *src++) != '\0');
return dest;
}
Note that d need not be nonnull‐qualified, since possibly
being NULL is a superset of not possibly being NULL.
The following variations of the above are incorrect, for
the reasons that follow the code examples.
Incorrect
char *strcpy(char *nonnull restrict dest,
const char *nonnull restrict src)
{
char *d;
d = dest;
while ((*d++ = *src++) != '\0');
return dest;
}
Although this would be valid by itself (wouldn't have un‐
defined behavior), it forbids callers of the function
from assigning the return value to a nonnull‐qualified
pointer.
Undefined behavior
char *nonnull strcpy(char *restrict dest,
const char *nonnull restrict src)
{
char *d;
d = dest;
while ((*d++ = *src++) != '\0');
return dest;
}
This causes undefined behavior, since it assigns a non‐‐
nonnull‐qualified pointer (dest) to a qualified one (the
return value). It's also dangerous, since the user isn't
properly informed that NULL may cause undefined behavior
in the implementation of the function (dest is derefer‐
enced).
AUTHORS
Alejandro Colomar
I must thank the GCC and Clang programmers for having
provided a solid base on which I based this proposal.
SEE ALSO
N2731 ‐ 6.7.3
⟨https://gcc.gnu.org/onlinedocs/gcc/Common‐Function‐
Attributes.html#Common‐Function‐Attributes⟩
⟨https://clang.llvm.org/docs/AttributeReference.html
#nullability‐attributes⟩
C3X 2021‐11‐15 nonnull(3)
--
Alejandro Colomar
Linux man-pages comaintainer; https://www.kernel.org/doc/man-pages/
http://www.alejandro-colomar.es/
next reply other threads:[~2021-11-15 16:01 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-15 16:01 Alejandro Colomar (man-pages) [this message]
2021-11-15 16:30 ` Alejandro Colomar (man-pages)
2021-11-15 20:18 ` Joseph Myers
2021-11-15 21:09 ` Alejandro Colomar (man-pages)
2021-11-15 22:17 ` Joseph Myers
2021-11-15 22:35 ` Alejandro Colomar (man-pages)
2021-11-15 22:47 ` Joseph Myers
2021-11-16 12:34 ` Alejandro Colomar (man-pages)
2021-11-17 0:06 ` Alejandro Colomar (man-pages)
2021-11-20 16:47 ` Ping: " Alejandro Colomar (man-pages)
2021-11-23 11:32 ` [cfe-dev] " Dmitri Gribenko
2021-11-23 11:17 ` Dmitri Gribenko
2021-11-23 11:45 ` Alejandro Colomar (man-pages)
2021-11-23 12:45 ` Dmitri Gribenko
2021-12-01 22:24 ` Alejandro Colomar (man-pages)
2021-12-02 0:39 ` Dmitri Gribenko
2021-12-02 1:00 ` Alejandro Colomar (man-pages)
2021-12-02 20:24 ` Alejandro Colomar (man-pages)
2021-12-02 20:31 ` Alejandro Colomar (man-pages)
2021-12-02 20:36 ` Joseph Myers
2021-11-16 9:30 ` Jonathan Wakely
2021-11-16 17:13 ` [cfe-dev] " Arthur O'Dwyer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=a0e33e64-460a-6830-69ac-a67b52734bd5@gmail.com \
--to=alx.manpages@gmail.com \
--cc=cfe-dev@lists.llvm.org \
--cc=gcc@gcc.gnu.org \
--cc=phdofthehouse@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).