Thank you, Alex.

I agree this was a mistake.

>From experience, there is only one robust interface design when it comes to 
>null pointer arguments: either a function handles them, or it doesn't. Whether 
>or not it handles them should have nothing to do with the value of other 
>parameters. This is also how Python's type system works.

I have no objection to the long-established (if it ain't broken, don't fix it) 
memcpy interface being upgraded to handle null pointers. The cost in CPU cycles 
and code size is probably negligible.

What I *do* object to is a halfway house solution where memcpy only handles 
null pointers contingent on the value of some other parameter. This is hard to 
document, hard to teach static analysis tools, and hard to verify when reading 
calling code.

I do not think it serves anyone.

Best regards,
Chris
________________________________________
From: Alejandro Colomar
Sent: Sunday, December 01, 2024 17:24
To: qing.z...@oracle.com
Cc: f...@deneb.enyo.de; gcc@gcc.gnu.org; ja...@redhat.com; josmy...@redhat.com; 
libc-al...@sourceware.org; uec...@tugraz.at; Chris Bazley
Subject: Re: Handling C2Y zero-length operations on null pointers


Hi,

I had a discussion about this with another WG14 member when this was
voted in.  We both voted against, because this is nefarious for static
analysis.

However, I think this can be though to resemble how 'const' works in the
standard:

        const char cbuf[10];

        memcpy((char *)cbuf, "", 0);

The code above is legal even if it is passing a const pointer where a
non-const one is expected.  This is because memcpy(3) will not write to
it.

Nevertheless, if one does

        memcpy(NULL, "", 0);

without a cast, the compiler will still diagnose.  This is important,
because if we would remove the diagnostics, it would be a footgun.

Similarly, we should allow null pointers (just like const pointers), in
the sense that there's no Undefined Behavior.  BUT there should be a
diagnostic.  Passing NULL is bad, and if one project wants to pass it,
it should do so with whatever compiler shenanigans to disable the
diagnostic (a cast, or a pragma, or whatever, not my problem).  In my
code, I want to see a diagnostic if I pass NULL to it, because in my
dialect (and in every C language before C2y), a null pointer is an
invalid pointer, and that distinction makes the code more robust.

I would either transform [[gnu::nonnull]] to be only about diagnostics
and not optimizations, or maybe add a _Optional qualifier that would
be used for this.

TL;DR:  Removing UB is nice, but removing diagnostics is NOT nice.

Have a lovely day!
Alex

P.S.:  I think it was a big mistake to vote this into C2y, and I voted
against.

-- 
<https://www.alejandro-colomar.es/>


Reply via email to