Undefined Behaviour in C99 related to adjusted parameters

The first quote from the C Standard is incorrect. It sounds like

— An adjusted parameter type in a function definition is not a complete object type (6.9.1)

That is you omitted the word complete.

For example in a function declaration that is not at the same type its definition you may specify an incomplete object type like

void f( size_t, size_t, int [][*] );

In this function declaration the declaration of the third parameter is not a complete object type because the size of the array elements is unknown.

Here is a demonstrative program

#include <stdio.h>

void f( size_t, size_t, int [][*] );

void f( size_t m, size_t n, int a[][n] )
{
    for ( size_t i = 0; i < m; i++ )
    {
        for ( size_t j = 0; j < n; j++ )
        {
            a[i][j] = n * i + j;
        }
    }
}

void g( size_t, size_t, int [][*] );

void g( size_t m, size_t n, int a[][n] )
{
    for ( size_t i = 0; i < m; i++ )
    {
        for ( size_t j = 0; j < n; j++ )
        {
            printf( "%d ", a[i][j] );
        }
        putchar( '\n' );
    }
}

int main(void) 
{
    size_t m = 2, n = 3;
    int a[m][n];
    
    f( m, n, a );
    g( m, n, a );
    
    return 0;
}

Its output is

0 1 2 
3 4 5 

Here in the program these two function declarations

void f( size_t, size_t, int [][*] );

and

void g( size_t, size_t, int [][*] );

have a parameter declaration with an incomplete object type.

You may not use such a declaration that at the same type is its definition like for example

void f( size_t m, size_t n, int a[][*] )
{
    // ...
}

Because the compiler is unable to determine the pointer type after adjusting the third parameter to pointer. That is the pointer will have an incomplete object type int ( * )[].


As pointed out in the comments, the text in the standard was corrected in C11. It now reads (C11 J.2):

— An adjusted parameter type in a function definition is not a complete object type (6.9.1).

That makes more sense.

However, I cannot think of an example of the use of an incomplete object type in the parameter of a function definition that would compile without an error. All I can think of is that perhaps some compilers allow unused parameters to have incomplete object types.

As pointed out by @Lundin in the comments, Appendix J is informative, not a normative part of the standard. The correction was also made in the text of the referenced section 6.9.1 in the normative part of the standard. The final clause of the final sentence of 6.9.1/7 was changed from "the resulting type shall be an object type" to "the resulting type shall be a complete object type".

@Lundin also points out that in a function definition, an adjusted parameter type that is an incomplete type is a constraint violation by C11 6.7.6.3/4 (C99 6.7.5.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.

That is listed under "constraints" and so requires translation of the program to produce at least one diagnostic.