Hi Joseph,

> Date: 2026-10-07 21:31:03+0000
> From: Joseph Myers <[email protected]>
>
> On Wed, 7 Oct 2026, Alejandro Colomar wrote:
> 
> > The strict rules would be that it's a constraint to have the forward
> > declaration of a parameter contradict the declaration, and thus a
> > constraint violation.  However, implementing those diagnostics would be
> > non-trivial for me.
> 
> My suggestion would be to be strict on the new feature (e.g. disallow 
> _Countof for any parameter for which both a forward declaration and 
> another declaration of the parameter are visible) rather than adding extra 
> checks for consistency of forward parameter declarations.

That'd be unacceptable for me.  I need to be able to use _Countof() on
arrays that have been forward declared.

Here's are a couple of examples:

        char *
        vseprintf(char dst[], const char end[];
            char dst[dst?end-dst:0], const char end[0], const char *restrict 
fmt, va_list ap)
        {
                int        len;
                ptrdiff_t  size;

                if (dst == NULL)
                        return NULL;

                len = vstprintf(dst, _Countof(dst), fmt, ap);
                if (len == -1)
                        return NULL;

                return dst + len;
        }

        char *
        stpecpy(char dst[], const char end[];
            char dst[dst?end-dst:0], const char end[0], const char *restrict 
src)
        {
                ssize_t  dlen;

                if (dst == NULL)
                        return NULL;

                dlen = strtcpy(dst, src, _Countof(dst));
                if (dlen == -1)
                        return NULL;

                return dst + dlen;
        }

But we could have a different constraint which I'd find acceptable:

-  Disallow declaring any array length expressions within a forward
   declaration of a parameter.

        void f(int a[42]; int a[]);     // constraint violation
        void g(int a[42]; int a[42]);   // constraint violation
        void g(int a[]; int a[42]);     // ok

> >         int
> >         g(int n, int m, int a[][n]; int n, int m, int a[][m])
> >         {
> >                 return _Countof(a[0]);
> 
> The cases of concern to me are where the length of the parameter array 
> itself might vary between the declarations (or one declaration might be a 
> pointer and another an array), because those are the ones where the new 
> extension of _Countof on array parameters actually comes into play and 
> starts interacting with forward declarations.
> 
> This example is using _Countof on something that has array type in the 
> existing language for all purposes - not on an array parameter that's 
> adjusted to a pointer for most purposes.  So it already has undefined 
> behavior at runtime if the two declarations (adjusted to pointer-to-array 
> type) specify different lengths n and m, and that doesn't depend on the 
> use of _Countof, only on the function being called with n != m.

Consistency between arrays and array parameters is what I'm seeking.

I understand you are afraid of adding UB for something which has been
always allowed (IMO, by a historical mistake).  So, the viable
alternatives are unspecified behavior, which is like UB but more
benevolent, or a constraint that is acceptable to all of us.  The
constraint you specified is unacceptable for me, but maybe my constraint
counter-proposal is acceptable to you (and Martin)?


Have a lovely day!
Alex

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

Attachment: signature.asc
Description: PGP signature

Reply via email to