The order of evaluation among initializers is unspecified, which makes it UB.
We don't have to use mixed-up designated initializers to run aground. Just simply:
{ int a = 0;
int x[2] = { a++, a++ }; }
This was also new in C99 (not to mention the struct literal syntax); in C90, run-time values couldn't be used for initializing aggregate members, so the issue wouldn't arise.
Code like:
{ int a = 0;
struct foo f = { a, a }; }
was supported in the GNU C dialect of C90 before C99 and of course is also a long-time C++ feature.