Hi Paul,

On Mon, Dec 15, 2025 at 12:50:14PM -0800, Paul Eggert wrote:
> On 2025-12-15 09:17, Alejandro Colomar wrote:
> > I don't see why gnulib would want to have this code:
> > 
> >     $ grepc -h -C1 VLA_ELEMS .
> >     #ifdef __STDC_NO_VLA__
> >     # define VLA_ELEMS(n)
> >     #else
> >     # define VLA_ELEMS(n) static n
> >     #endif
> > 
> > Instead of just using
> > 
> >     #ifdef __STDC_NO_VLA__
> >     # define VLA_ELEMS(n)
> >     #else
> >     # define VLA_ELEMS(n)  n
> >     #endif
> > 
> > plus using __attribute__((__nonnull__())) appropriately.
> 
> First, some compilers support [static n] but lack support for
> __attribute__((__nonnull__())), and it's useful to port well to these
> compilers. One example is Oracle Developer Studio 12.6; I'm sure there are
> others.

Hmmm, well, you could expand to [static n] for Oracle.  But it would be
nice if for the usual compilers you use bare [n].

> 
> Second, the VLA_ELEMS notation is shorter and easier to read as-is. For
> example, this:
> 
>   int
>   main (int argc, char *argv[VLA_ELEMS (argc)])
>   ...
> 
> is easier to read than what I think you're proposing:
> 
>   int ATTRIBUTE_NONNULL ((2))
>   main (int argc, char *argv[VLA_ELEMS (argc)])
>   ...

I'd say the below is easier to read, as it's more explicit about the
nonnull-ness of the parameter.  The fact that VLA_ELEMS() hides an
implicit nonnull is going to surprise programmers.  The fact that it
hides an implicit n>0 is going to surprise programmers too.

As a side note, the attribute should go before the type:

        ATTRIBUTE_NONNULL ((2))
        int
        main (int argc, char *argv[VLA_ELEMS (argc)])
        ...

(At least with C23's [[gnu::nonnull()]]; GNU C attribute syntax is more
 forgiving.)

I often use precisely that syntax, where I use one line for the
attributes, one line for the storage-class specifiers and the type,
and another one for the identifier an parameter list.

Plus, since you're already using ATTRIBUTE_NONNULL() for non-array
parameters, it would be natural to also use it with array parameters.

BTW, out of curiosity, which compilers don't support [n] in function
parameters?  


Have a lovely night!
Alex

> Here I am assuming Gnulib vla.h's definition of VLA_ELEMS (which you've
> quoted above) along with Gnulib attribute.h plus config.h's definitions,
> which are as follows (I have somewhat simplified, but it's still quite a
> portability mess, right? No wonder most C software developers run away from
> this stuff...):
> 
>  #if defined __GNUC__ && defined __GNUC_MINOR__ && !defined __clang__
>  # define _GL_GNUC_PREREQ(major, minor) \
>       ((major) < __GNUC__ + ((minor) <= __GNUC_MINOR__))
>   #elif defined __clang__
>     /* clang really only groks GNU C 4.2.  */
>   # define _GL_GNUC_PREREQ(major, minor) \
>       ((major) < 4 + ((minor) <= 2))
>   #else
>   # define _GL_GNUC_PREREQ(major, minor) 0
>   #endif
>   #if (defined __has_attribute \
>        && (!defined __clang_minor__ \
>            || (defined __apple_build_version__ \
>                ? 7000000 <= __apple_build_version__ \
>                : 5 <= __clang_major__)))
>   # define _GL_HAS_ATTRIBUTE(attr) __has_attribute (__##attr##__)
>   #else
>   # define _GL_HAS_ATTRIBUTE(attr) _GL_ATTR_##attr
>   # define _GL_ATTR_nonnull _GL_GNUC_PREREQ (3, 3)
>     /* ... */
>   #endif
>   #if _GL_HAS_ATTRIBUTE (nonnull)
>   # define _GL_ATTRIBUTE_NONNULL(args) __attribute__ ((__nonnull__ args))
>   #else
>   # define _GL_ATTRIBUTE_NONNULL(args)
>   #endif
>   #define ATTRIBUTE_NONNULL(args) _GL_ATTRIBUTE_NONNULL (args)

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

Attachment: signature.asc
Description: PGP signature

Reply via email to