Why does C's BNF grammar allow declarations with an empty sequence of init-declarators?

declaration-specifier includes type-specifier, which includes enum-specifier. A construct like

enum stuff {x, y};

is a valid declaration with no init-declarator.

Constructs like int; are ruled out by constraints beyond the grammar:

A declaration other than a static_assert declaration shall declare at least a declarator (other than the parameters of a function or the members of a structure or union), a tag, or the members of an enumeration.

I would guess that there are backward compatibility reasons behind your compiler only issuing a warning.


A declaration without an init declarator:

<declaration> ::=  {<declaration-specifier>}+ {<init-declarator>}* ;

is harmless for declaration specifier lists that aren't a single enum/struct/union specifier and it usefully matches those that are.

In any case, the presented grammar will also erroneously match declarations like int struct foo x; or double _Bool y; (it allows multiple specifiers in order to match things like long long int), but all these can be detected later, in a semantic check.

The BNF grammar itself won't weed out all illegal constructs.