An incomplete type may only by used when the size of an object of that type is not needed. It is not
needed, for example, when a typedef name is declared to be a specifier for a structure or union, or
when a pointer to or a function returning a structure or union is being declared. (See incomplete types
in 6.2.5.) The specification has to be complete before such a function is called or defined.
6.2.5.22 goes on to say:
An array type of unknown size is an incomplete type. It is completed, for an identifier of
that type, by specifying the size in a later declaration (with internal or external linkage).
What does that mean?
It means that for:
void mat(int param[]);
the size is not needed. It can be treated as an array of int of unspecified size where the size isn't needed. Incrementing a pointer to the next element of the array means adding sizeof(int) to the pointer.
For:
void mat(int param[][]);
a 2D array (an array of int[]) is specified, but we don't know the size of int[]. In this case, the size is needed. We don't know how to increment the pointer to an int[].
For:
void mat(int param[][1]);
a 2D array (an array of int[1]) is specified. We know how to increment the pointer to the next element, it's sizeof(int) * 1.
Why all this? The background link I posted earlier talks about the history of the treatment of arrays.