public inbox for gcc@gcc.gnu.org
 help / color / mirror / Atom feed
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



  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).