Why does gcc allow extern declarations of type void? Is this an extension or standard C? Are there acceptable uses for this?
I am guessing it is an extension, but
Strangely enough (or perhaps not so strangely...) it looks to me like gcc is correct to accept this.
If this was declared static instead of extern, then it would have internal linkage, and §6.9.2/3 would apply:
If the declaration of an identifier for an object is a tentative definition and has internal linkage, the declared type shall not be an incomplete type.
If it didn't specify any storage class (extern, in this case), then §6.7/7 would apply:
If an identifier for an object is declared with no linkage, the type for the object shall be complete by the end of its declarator, or by the end of its init-declarator if it has an initializer; in the case of function arguments (including in prototypes), it is the adjusted type (see 6.7.5.3) that is required to be complete.
I either of these cases, void would not work, because (§6.2.5/19):
The void type [...] is an incomplete type that cannot be completed.
None of those applies, however. That seems to leave only the requirements of §6.7.2/2, which seems to allow a declaration of a name with type void:
At least one type specifier shall be given in the declaration specifiers in each declaration, and in the specifier-qualifier list in each struct declaration and type name. Each list of type specifiers shall be one of the following sets (delimited by commas, when there is more than one set on a line); the type specifiers may occur in any order, possibly intermixed with the other declaration specifiers.
- void
- char
- signed char
[ ... more types elided]
I'm not sure that's really intentional -- I suspect the void is really intended for things like derived types (e.g., pointer to void) or the return type from a function, but I can't find anything that directly specifies that restriction.