Function prototype
void foo(int n, int a[][]);
gives error about incomplete type while
void foo(int n, int (*a)[]);
EDIT
Having read through all the relevant parts of the standard, C11 6.7.6.2 and 6.7.6.3, I believe this is a compiler bug/non-conformance. it apparently boils down to the text that the committee sneaked into the middle of a paragraph concerning array delimiters. 6.7.6.2/1 emphasis mine:
In addition to optional type qualifiers and the keyword static, the [ and ] may delimit an expression or *. If they delimit an expression (which specifies the size of an array), the expression shall have an integer type. If the expression is a constant expression, it shall have a value greater than zero. The element type shall not be an incomplete or function type. The optional type qualifiers and the keyword static shall appear only in a declaration of a function parameter with an array type, and then only in the outermost array type derivation.
Now this is of course very poorly written, basically it says
"peripheral feature of little interest, peripheral feature of little interest, peripheral feature of little interest, OUT OF THE BLUE HERE COMES SOME ARRAY ELEMENT TYPE SPECIFICATION NOT RELATED TO THE REST OF THIS PARAGRAPH, peripheral feature of little interest, peripheral feature of little interest,...."
So it is easy to misunderstand, fooled me.
Meaning that int a[][]
is always incorrect no matter where it is declared, since an array cannot be an array of incomplete type.
However, my original answer below raises some valid concerns regarding whether array decay should be done before or after the compiler decides if the type is incomplete or not.
Given the specific case void foo(int n, int a[][]);
only, this is a function declaration. It is not a definition.
C11 6.7.6.3/12
If the function declarator is not part of a definition of that function, parameters may have incomplete type
So first of all, parameters are allowed to have incomplete type in the function declaration. The standard is clear. Which is why code like this compiles just fine:
struct s; // incomplete type
void foo(int n, struct s a); // just fine, incomplete type is allowed in the declaration
Furthermore:
C11 6.7.6.3/4
After adjustment, the parameters in a parameter type list in a function declarator that is part of a definition of that function shall not have incomplete type.
After adjustment is very important here.
Meaning that after adjusting int a[][]
to int (*a)[]
, the parameter shall not have incomplete type. It does not, it is a pointer to incomplete type, which is always allowed and perfectly fine.
The compiler is not allowed to first evaluate int a[][]
as an incomplete array of incomplete arrays, and then later adjust it (if it found that the type was not incomplete). This would directly violate 6.7.6.3/4.