Issue 1087: Reentering variably modified declaration

Authors: Jay Ghiron
Date: 2026-06-24
Submitted against: C23
Status: Open

Considering the following program:

#include<stddef.h>
char(**foo(size_t x))[]{
static char(*p)[x];
return&p;
}
int main(){
char(**a)[1]=foo(1);
*a;/* lengths match, valid */
char(**b)[2]=foo(2);
*b;/* ? */
*a;/* ? */
}

The first time the declaration of p is reached, x has value one so it creates a pointer to an array of one char. The first *a should therefore be valid, since the length expressions have the same value. The second time the declaration of p is reached, x has a value two which is different than the previous time the declaration of p was reached. The result of that is unclear, the following are some possible results:

The first interpretation could be justified by:

All declarations that refer to the same object or function shall have compatible type; otherwise, the behavior is undefined.

(C23 6.2.7 "Compatible type and composite type" paragraph 2.)

Though this text was present in initial standardization before variable length arrays existed, and presumably is intended to apply to identifiers with linkage rather than this scenario. It would also make being able to use variably modified types with static storage duration or thread storage duration almost entirely useless. What is the intended result of this program? This is also observable with automatic storage duration when using goto:

int main(){
char(**c)[1],(**d)[2];
l:;
char(*q)[++(static int){}];
if(sizeof(*q)==1){
c=&q;
*c;/* lengths match, valid */
goto l;
}else{
d=&q;
*d;/* ? */
*c;/* ? */
}
}

Note that the object must have variably modified but not variable length array type for this scenario, an object with variable length array type does not exist for the entire block that contains it.