A pointer-to-a-VLA-typed controlling expression in a _Generic expression

Solution 1:

They are in fact compatible.

First, section 6.7.6.2p6 of the C standard says the following about the compatibility of array types:

For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value. If the two array types are used in a context which requires them to be compatible, it is undefined behavior if the two size specifiers evaluate to unequal values.

From this, there is a requirement that if both array sizes are integer constant expressions (i.e. neither is a VLA) then they must be the same. This however does not apply if one is a VLA, so that makes them compatible.

In addition, section 6.2.7p3 says the following regarding composite types:

A composite type can be constructed from two types that are compatible; it is a type that is compatible with both of the two types and satisfies the following conditions:

  • If both types are array types, the following rules are applied:
    • If one type is an array of known constant size, the composite type is an array of that size.
    • Otherwise, if one type is a variable length array whose size is specified by an expression that is not evaluated, the behavior is undefined.
    • Otherwise, if one type is a variable length array whose size is specified, the composite type is a variable length array of that size.
    • Otherwise, if one type is a variable length array of unspecified size, the composite type is a variable length array of unspecified size.
    • Otherwise, both types are arrays of unknown size and the composite type is an array of unknown size. The element type of the composite type is the composite type of the two element types.

This means that when comparing the types char(*)[x] and char(*)[1], their composite type is char(*)[1]. What this also means is that char(*)[x] is compatible with any pointer to a fixed size array of char. So if your function looked like this:

void test(int x){
    _Static_assert(_Generic( (char(*)[x])0, 
      char (*)[2]: 2, 
      char (*)[1]: 1, 
      default: 0),"");
}

You would get a compilation error because the controlling expression is compatible with multiple options, even though the options are not compatible with each other.

Solution 2:

They are compatible. C 2018 6.7.6.2 6 says “For two array types to be compatible, both shall have compatible element types, and if both size specifiers are present, and are integer constant expressions, then both size specifiers shall have the same constant value…” Since it is not true that both size specifiers are integer constant expressions, the requirement to have the same value does not apply.

The pointer compatibility inherits from the pointed-to types.