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
GCC (also, LLVM C frontend) is definitely buggy. Both Comeau and MS seems to report errors though.
The OP's snippet has at least two definite UBs and one red-herring:
From N1570
[UB #1] Missing main
in hosted environment:
J2. Undefined Behavior
[...] A program in a hosted environment does not define a function named main using one of the specified forms (5.1.2.2.1).
[UB #2] Even if we ignore the above there still remains the issue of taking the address of a void
expression which is explicitly forbidden:
6.3.2.1 Lvalues, arrays, and function designators
1 An lvalue is an expression (with an object type other than void) that potentially designates an object;64)
and:
6.5.3.2 Address and indirection operators
Constraints
1T he operand of the unary & operator shall be either a function designator, the result of a [] or unary * operator, or an lvalue that designates an object that is not a bit-field and is not declared with the register storage-class specifier.
[Note: emphasis on lvalue mine]
Also, there is a section in the standard specifically on void
:
6.3.2.2 void
1 The (nonexistent) value of a void expression (an expression that has type void) shall not be used in any way, and implicit or explicit conversions (except to void) shall not be applied to such an expression.
A file-scope definition is a primary-expression (6.5). So, is taking the address of the object denoted by foo
. BTW, the latter invokes UB. This is thus explicitly ruled out.
What remains to be figured out is if removing the extern
qualifier makes the above valid or not:
In our case the, for foo
as per §6.2.2/5:
5 [...] If the declaration of an identifier for an object has file scope and no storage-class specifier, its linkage is external.
i.e. even if we left out the extern
we'd still land in the same problem.