An even better solution for the "for" example is enforcing the curly braces around every block. Simple rule, no heuristics to catch such bugs.
if (x);
etc. are also rejected. If you actually want an empty statement, { } does the job. Doing it with the grammar is not hackish and it works out quite nicely.In the olden days (1989) people were more willing to accept change in C, such as value-preserving rather than sign-preserving integer promotion rules, and some improvements to the C preprocessor.
if (x) foo(); // accepted
if (x) ; // rejected
if (x) { } // accepted