Hi Joseph,

On Mon, Jan 19, 2026 at 04:53:00PM +0000, Joseph Myers wrote:
> On Sun, 18 Jan 2026, Alejandro Colomar wrote:
> 
> > diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
> > index b4879b3d82ff..48166d44546e 100644
> > --- a/gcc/doc/extend.texi
> > +++ b/gcc/doc/extend.texi
> > @@ -711,8 +711,15 @@ just like in the regular list of parameter 
> > declarations.
> >  You can write any number of lists of parameter forward declaration,
> >  but using more than one is unnecessary.
> >  The last semicolon is followed by the list of parameter declarations.
> > -Each parameter forward declaration must match
> > -a parameter declaration in parameter name and data type.
> > +
> > +Each parameter forward declaration must
> > +match a parameter declaration in parameter name
> > +and must be compatible with its type.
> 
> Compatible with only the final parameter declaration, or do they also need 
> to be compatible with each other?  As written, the three types
> 
>   int (*)[2]
>   int (*)[3]
>   int (*)[]
> 
> for the same parameter would be valid because the two forward declarations 
> are compatible with the final declaration.  But at present such a 
> combination isn't accepted (and I think it shouldn't be accepted, i.e. the 
> compiler is right to reject it).

Yup.  I'll split the paragraph in two:

        Each parameter forward declaration must
        match a parameter declaration in parameter name.

        A parameter declaration
        and any preceding parameter forward declarations of the same name
        must be have a compatible type.

> Whatever is documented should also come with thorough testcases (which 
> might mean adjusting the compiler to behave in whatever way we agree is 
> desired).

The compiler already behaves in the desired way, AFAICS.  The only
thing we need is more diagnostics, of course, but the current behavior
matches what we're talking.

> Furthermore, _Countof for array parameters *does* introduce new issues 
> because compatibility above can only refer to the types *after* 
> adjustment, but with _Countof the question of matching lengths *before* 
> adjustment comes into play

IMO, GCC already requires type compatibility on array parameters taking
into account their length, as an extension.  This is implemented as part
of -Warray-parameter=.

        alx@devuan:~/tmp$ cat f.c 
        int f(int a[2]);
        int f(int a[3]);
        alx@devuan:~/tmp$ gcc -Wall -S f.c
        f.c:2:11: warning: argument 1 of type ‘int[3]’ with mismatched bound 
[-Warray-parameter=]
            2 | int f(int a[3]);
              |       ~~~~^~~~
        f.c:1:11: note: previously declared as ‘int[2]’
            1 | int f(int a[2]);
              |       ~~~~^~~~

I think we should document this as an extension to type compatibility
rules, independent of forward parameter declarations.

Since this isn't necessarily about arrays of variable length, I think it
would deserve a new node on the GCC manual, under 6.2 ("Array, Union,
and Struct Extensions").
<https://gcc.gnu.org/onlinedocs/gcc/Aggregate-Types.html#Array_002c-Union_002c-and-Struct-Extensions>

I'd add something like this:

        6.2.0+1  Array parameters to functions

        Array parameters are adjusted to pointers.
        ISO C ignores the length of array parameters.
        However,
        GCC extends the language so that
        the length of array parameters is meaningful.

        For a function declared as

                void f(int n, int a[n]);

        A caller must provide a pointer to at least n elements.
        and the function must not access more than n elements.

        Type compatibility rules are extended
        to take this length into account.
        For this purpose,
        pointers and arrays of unspecified length
        are considered equivalent.

        For example, the following pairs of declarations are compatible:

                void f(int n, int a[n]);
                void f(int n, int a[*]);

                void g(int a[2]);
                void g(int a[*]);

                void h(int a[2]);
                void h(int *a);

        But the following pairs are incompatible:

                void i(int n, int a[n]);
                void i(int n, int a[2]);

                void j(int n, int m, int a[n]);
                void j(int n, int m, int a[m]);

        Violations of these extended rules are diagnosed as part of
        -Warray-parameter=.

Then within parameter forward declarations we only need to invoke
compatibility rules.

> (and with it, the concern about whether adding 
> new UB relating to something that doesn't affect types at all is 
> desirable).  So it needs to come with appropriate documentation of the 
> semantic model involved.

Does the above sound reasonable?

> In all cases, if the forward declarations appear in a function definition, 
> there is also the question of whether the array length expressions in 
> forward declarations (including lengths of arrays adjusted to pointers) 
> get evaluated for their side effects on entry to the function.

Yes, they must get evaluated.

> I believe 
> they should be; this ought to be documented and tested.

I agree; however, I find this to be orthogonal to _Countof().

I'll try to prepare a patch, anyway.


Cheers,
Alex

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

Attachment: signature.asc
Description: PGP signature

Reply via email to