Hi Joseph,

On Tue, Jan 20, 2026 at 10:11:28PM +0000, Joseph Myers wrote:
> On Tue, 20 Jan 2026, Alejandro Colomar wrote:
> 
> > +For a function declared as
> > +
> > +@smallexample
> > +void f (int n, int a[n]);
> > +@end smallexample
> > +
> > +A caller must provide a pointer to at least @code{n} elements,
> > +and the function must not access more than @code{n} elements.
> 
> That's misleading.  "must provide" suggests UB for violation, which is not 
> the case; this is just about warnings.

I am indeed suggesting a constraint violation and subsequent UB if the
diagnostic is ignored.

Of course, the non-written contract is that old code will keep working,
but it is declared UB by this text, and programmers should make sure to
not violate the contract.  Anyway, I'm pretty sure virtually no code is
violating this.

> > +Type compatibility rules are also extended
> > +to take this length into account.
> 
> That's also misleading, when it's about warnings rather than errors.

Same here.  This patch is paving a future where this might be a default
error, and not just a warning.

> > +void j (int n, int a[n]);
> > +void j (int n, int a[n + 1]);
> 
> Given that ISO C defines both of those to mean [*] as the array dimension, 
> this is also misleading (and suggests much trickier questions about what 
> happens with [(n)+(1)] or [1 + n] or [n - -1] or similar - which is why 
> it's hard to define any kind of constraints here).

This patch is making these have the same compatibility rules as for
pointers to arrays.

In the case of pointers to arrays:

        void k (int n, int (*p)[n]);
        void k (int n, int (*p)[n + 1]);

The relevant text is n3685::6.7.7.3p6:

        If the two array types are used
        in a context which requires them to be compatible,
        the behavior is undefined
        if the lengths of both are specified
        and the corresponding array length expressions
        evaluate to unequal values.

And by this documentation, I'm bringing array parameters to parity with
them.  In that case above, the two declarations of j() use unequal array
length expressions (n != n+1; regardless of n), and thus the behavior is
undefined.

> *In the specific case of _Countof and parameter forward declarations*, 
> what needs to be defined is more constrained.  In the case of function 
> prototype scope, it just needs to be clear whether _Countof gets a 
> constant length or a non-constant one that is treated as [*], and, in the 
> case of a constant length, which constant length if there's more than one 
> (and it would be possible to add a constraint when multiple constant 
> lengths are present for the same array parameter but disagree, since that 
> doesn't have the issues with comparisons that there are for non-constant 
> expressions).  In the case of function definitions, if all the lengths get 
> evaluated on function entry, either you have UB for non-constant lengths 
> disagreeing or you avoid UB by defining exactly which of those lengths 
> applies at each point for the purposes of _Countof (given that those 
> lengths are of no significance except for _Countof).

I really want to turn this into a CV and subsequent UB on violation,
with the non-written contract that we won't break user code unless
necessary.  We have the diagnostics in place, and this text would be
a reason for turning them into default errors in the future.

_Countof() and forward parameter declarations have just pushed me to do
this earlier than I was planning to do it, but I certainly planned to do
it anyway.


Have a lovely night!
Alex

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

Attachment: signature.asc
Description: PGP signature

Reply via email to