From: "Alejandro Colomar (man-pages)" <alx.manpages@gmail.com>
To: Joseph Myers <joseph@codesourcery.com>
Cc: gcc@gcc.gnu.org, cfe-dev@lists.llvm.org
Subject: Re: ISO C3X proposal: nonnull qualifier
Date: Tue, 16 Nov 2021 13:34:35 +0100 [thread overview]
Message-ID: <c9b2f273-c8ae-519d-78b9-1d4f34f51c19@gmail.com> (raw)
In-Reply-To: <alpine.DEB.2.22.394.2111152241180.369620@digraph.polyomino.org.uk>
Hi Joseph,
On 11/15/21 23:47, Joseph Myers wrote:
> On Mon, 15 Nov 2021, Alejandro Colomar (man-pages) via Gcc wrote:
>
>> Hi Joseph,
>>
>> On 11/15/21 23:17, Joseph Myers wrote:
>>> On Mon, 15 Nov 2021, Alejandro Colomar (man-pages) via Gcc wrote:
>>>
>>>> How is restrict handling that problem of lvalue-to-rvalue already?
>>>
>>> restrict has tricky rules about "based on" (6.7.3.1).
>>
>> Hmm, I think I can "base on" that,
>> to define what I had in mind. :)
>
> "based on" is about optimizations; I think it's even less suited to
> anything relating to diagnostics than it is to optimization.
>
> To restrict assignment between different kinds of pointers, I'd think
> you'd want pointer type variants that differ in some way *other* than
> qualifiers, a way that's unaffected by lvalue-to-rvalue conversion, but
> that comes with its own rules on implicit conversion as if by assignment
> (6.5.16.1) (though then you also need to work out what's allowed in terms
> of mixing these pointer type variants in all the other operations allowing
> pointers, what type results of pointer arithmetic have, etc.). And there
> should surely also be some way of converting a normal pointer to this
> variant with a runtime check for NULL.
>
> Note that discussion of prior art in such a proposal should also consider
> relevant prior art (for constraining possible values of a variable through
> the type system) in C++ or other languages if possible.
>
The only other language that I know is C++, so I'll talk about it:
C++ added long ago something close to this: references.
However, IMO:
- They don't provide any enforced safety at all.
It's just as safe as using [[gnu::nonnull]].
See an example code below showing why.
- They unnecessarily changed pointer syntax to use value syntax.
This syntax has not been widely accepted by some C programmers,
which would have to adapt their minds considerably.
Clang's _Nonnull (and _Nullable) qualifiers (are they?):
- Do have the safety that C++ references should have had,
if they had been properly designed.
Again, see the example code below.
- They have an intuitive syntax for C programmers,
by just adding a qualifier to a pointer,
you mark it as either possibly being NULL or not.
It has the appearance of a qualifier,
and the documentation refers to it as a qualifier,
but how does it implement it clang internally?
Is it implemented as a completely different type
with some implicit conversion rules?
I don't know.
See
<https://clang.llvm.org/docs/AttributeReference.html#nullability-attributes>.
---
$ cat nonnull.c
[[gnu::returns_nonnull]]
int *foo(int *p)
{
return p;
}
/*
* No (nonnull-related) diagnostics from the following commands:
* $ gcc -Wall -Wextra -std=gnu2x -S nonnull.c
* $ clang -Weverything -std=gnu2x -S nonnull.c
*/
/*++++++++++++*/
/* Clang only */
int *_Nonnull bar(int *_Nullable p)
{
return p;
}
/*
* Clang provides safety here:
*
* $ clang -Weverything -std=gnu2x -S nonnull.c
* nonnull.c:17:9: warning: implicit conversion from nullable pointer
'int * _Nullable' to non-nullable pointer type 'int * _Nonnull'
[-Wnullable-to-nonnull-conversion]
* return p;
* ^
*/
/*++++++++++++*/
/* C++ only */
int *baz(int *p)
{
int &q = *p;
return &q;
}
/* No (nonnull-related) diagnostics from the following commands:
* $ gcc -Wall -Wextra -std=gnu++2b -S nonnull.cxx
* $ clang -Weverything -std=gnu++20 -S nonnull.cxx
*/
---
So we have the following list of prior art:
- [[gnu::nonnull]] (GCC)
- _Nonnull (Clang)
- & (references) (C++)
From which I completely dislike references,
for not adding any real benefits,
and being unnecessarily unintuitive (to C programmers).
I like from _Nonnull that it enforces diagnostics.
And I like from [[gnu::nonnull]] that it allows optimizations.
I'm trying to mix them in a good way.
Since Clang's _Nonnull is closer to what I have in mind,
I did further tests to _Nonnull,
to see what I like,
and what I dislike:
---
$ cat _Nonnull.c
#include <stdlib.h>
int *_Nonnull f(int *_Nullable p)
{
if (!p)
exit(1);
return p;
}
int *_Nonnull g(int *_Null_unspecified p)
{
return p;
}
int *_Nonnull h(int *p)
{
return p;
}
int *_Nullable i(int *_Nonnull p)
{
return p;
}
---
First of all,
I see unnecessary (probably over-engineered) qualifiers:
- _Null_unspecified seems to me the same as nothing.
If I didn't specify its nullability,
it's by definition unspecified. Right?
- _Nullable seems to me also the same as nothing.
The language allows for a pointer to be NULL,
so if you don't specify if it can or not be null,
you better stay on the safe side and consider it as nullable.
Then,
I see other problems:
- I don't get a warning from g(), nor from h(), which I'd want.
To get something like const-safety,
we need to design it so that it can be enforced;
either you guarantee that a pointer cannot be NULL (_Nonnull),
or you cannot guarantee it (not _Nonnull).
Otherwise,
[[gnu::nonnull]] would seem better to me.
So, I'd leave out of the design everything but _Nonnull,
and consider everything else as nullable by default.
- I get a warning from f().
Ideally,
a programmer should not need to cast
(casts are dangerous),
to convert a nullable pointer to a _nonnull pointer.
For that,
appropriate checks should be in the preceeding code.
Otherwise, a diagnostic should be issued.
To be on the safe side,
if a compiler has doubts,
it should diagnose.
There's some Clang document that talks about something similar.
I don't know its validity,
or if it was a draft before _Nonnull qualifiers.
<https://clang.llvm.org/docs/analyzer/developer-docs/nullability.html>
Thanks!
Alex
next prev parent reply other threads:[~2021-11-16 12:34 UTC|newest]
Thread overview: 22+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-11-15 16:01 Alejandro Colomar (man-pages)
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) [this message]
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=c9b2f273-c8ae-519d-78b9-1d4f34f51c19@gmail.com \
--to=alx.manpages@gmail.com \
--cc=cfe-dev@lists.llvm.org \
--cc=gcc@gcc.gnu.org \
--cc=joseph@codesourcery.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).