It is because of this term (emphasize mine) in the C standard:
"For an identifier declared with the storage-class specifier extern in a scope in which a prior declaration of that identifier is visible,31) if the prior declaration specifies internal or external linkage, the linkage of the identifier at the later declaration is the same as the linkage specified at the prior declaration. If no prior declaration is visible, or if the prior declaration specifies no linkage, then the identifier has external linkage."
- As specified in 6.2.1, the later declaration might hide the prior declaration.
Source: C18, §6.2.2/4
That means that the first example is valid. The linkage of the function foo
is determined by the prior declaration of it, which is internal / static
.
The reason for this is probably because of compatibility to function definitions which omit the static
qualifier, which are declared as extern
by default:
"If the declaration of an identifier for a function has no storage-class specifier, its linkage is determined exactly as if it were declared with the storage-class specifier extern
."
Source: C18, §6.2.2/5
which is also considered in Peter's answer to Rationale of static declaration followed by non-static declaration allowed but not vice versa.
Example:
static int foo (void);
....
int foo (void) // extern by default.
{
return 0;
}
Since foo
is defined at global scope, its linkage is external by default and with that equivalent to as it have been qualified with extern
.
In the second example, you attempt to redeclare a extern
/ having external linkage (global scope) as static
(file scope) function, which is not permissible.
So, it is not a GCC specific kind of thing, as you thought it would be.