Re: Mangled function prototypes (phantom arguments)

Alejandro Colomar <[email protected]> Wed, 27 May 2026 15:47:01 +0200
Newsgroups org.kernel.vger.linux-man
Message-ID <ahbxJGIK8Qf4AqVl@devuan>
Hi Michael,

On 2026-05-27T14:14:39+0200, Michael Kerrisk (man7.org) wrote:
> Hello Alex,
> 
> It looks like some scripted changes have mangled the call signatures
> in multiple SYSNOPIS sections in section 2. (In some cases, multiple
> call signatures in the same SYNOPSIS have the problem.)

It wasn't scripted changes; they were hand-written.  Here are the
relevant commits:

	d2c2db8830f8 (2025-03-14; "man/: SYNOPSIS: Use GNU forward-declarations of parameters for sizes of array parameters")
	24b307093047 (2025-03-20; "man/man2/get_mempolicy.2: SYNOPSIS: Use GNU fwd declaration of parameters for sizes of array parameters")
	8eea66b827a1 (2025-06-28; "man/: SYNOPSIS: Don't highlight forward declarations of function parameters")
	3d066f79ac04 (2025-08-20; "man/man2/: SYNOPSIS: Use GNU forward-declarations of parameters for sizes of array parameters")
	f376c5ad0fa9 (2025-10-29; "bin/grepc: -tfp, -tfd: Add support for forward-declarations of parameters")

> The problems have all resulted in prototypes adding a phantom first
> argument. See for example this prototype from read.2:
> 
>        ssize_t read(size_t count;
>                     int fd, void buf[count], size_t count);

This is valid C (except for the array of void, but that's a separate
topic).

Here's for example the prototype shown in the SYNOPSIS of confstr(3):

     size_t confstr(size_t size;
                    int name, char buf[size], size_t size);

I've chosen this one because it doesn't use void.  If you try compiling
it, it will work:

	alx@devuan:~/tmp$ cat test.c 
	typedef long  size_t;

	size_t
	confstr(size_t size;
		int name, char buf[size], size_t size);
	alx@devuan:~/tmp$ gcc -Wall -Wextra -S test.c 
	alx@devuan:~/tmp$ 

And it does the right thing.  The function has 3 parameters.
It's documented in GCC's documentation here:

<https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html>

It's a forward declaration of function parameters.  It allows using
parameters that come later, to be used in array length expressions.  See
at the bottom of the link above.  I'll paste the GCC documentation here
for completeness, anyway:

	If you want to pass the array first and the length afterward,
	you can use a forward declaration in the parameter list—another
	GNU extension.

		struct entry
		tester (int len; char data[len][len], int len)
		{
		  /* … */
		}

	The ‘int len’ before the semicolon is a parameter forward
	declaration, and it serves the purpose of making the name len
	known when the declaration of data is parsed.

	Lists of parameter forward declarations are terminated by
	semicolons, and parameter forward declarations are separated
	within such lists by commas, 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.  ISO C99 does not
	support parameter forward declarations. 

> As far as I can see, at least the following pages are affected:

All functions that have an array parameter whose length is specified by
a parameter that goes after the array parameter are affected (unless I
missed some accidentally).  This is intentional.

> 
> add_key
[...]
> write
> 
> I did a quick scripted check of section 3 pages, but spotted no problems there.

There are quite some, actually.  In fact, more than in man2.

	$ find man2/ -type f \
		| xargs mansectf SYNOPSIS \
		| grep '^[^(]*([^)]*;' \
		| sed 's/(.*//' \
		| sed 's/.* //' \
		| tr -d '*' \
		| wc -l;
	65
	$ find man3/ -type f \
		| xargs mansectf SYNOPSIS \
		| grep '^[^(]*([^)]*;' \
		| sed 's/(.*//' \
		| sed 's/.* //' \
		| tr -d '*' \
		| wc -l;
	156

> 
> Thanks,
> 
> Michael

Have a lovely day!
Alex

-- 
<https://www.alejandro-colomar.es>
signature.asc (application/pgp-signature, 833 B)
-----BEGIN PGP SIGNATURE-----

iQIzBAABCgAdFiEES7Jt9u9GbmlWADAi64mZXMKQwqkFAmoW9c8ACgkQ64mZXMKQ
wql/OA//dJWLFusVTfe+Z3GjUaZhjL6RXiMhojC3cLXw+K7Cvxx8nSqNeIPUHOab
yrrY67zp3dHJy9YcyGJrd8etY/ZJ0XkdnBQv0i423fw/969/RzitTLAvB3pqI9ZB
jD86pbWvBq10Ztk1Cxd8XMHw8jr3C/6EVG4FPB1SlRi4Pu1/xXFovufsfFmJtzHe
G29SPWjfUWZKakyUE1ugZnQkoOg4qxKunzM21lSPNSXb0UoF53LJAsQGAG2UJBb8
x8MjyTn+rX1ns0bXFqdhYyrdflvhjiN+Et+57nAsMiw9P5B1Uy9wghs/b+Zv7upU
z0GAPQQkJ78WhV8L71wOA1/8LMpuH0x+Qj+bgNWHA+jfHSepO33/Q5MpbC+VJVjC
4Np0QL3BZCn8ZX38B6Qx7UrSLoZ2JZeBejGyyNg2bQm1aYn/VkUjVy/bHK+QK0Gq
xEH0QhHD2pOdux6OCxZGTyQIu1EQt+YBP2GVnNx4TqRKrxxcRxPuGgiVPDSfpWxC
S2iimyu6VX1BraJaFINEbaE4PjkHTq37hV+/niGzoUipI3DwVIjc7XDKNaDoJzQC
VARSwG0B/O3UXpNHiczdhedo7snuGPtv9YbBf9GC0hECzykFpblhvAwcMBURPP5N
6o3yJE9UwrYdX3MjQw743X5wB5bDzO55N2xNnW9+LznLQZQR298=
=VFmQ
-----END PGP SIGNATURE-----