C99 is different from C11
The rules change between C99 and C11 (and the C11 rules match the C++ rules, as I understand it). Note that in both standards, ?3 is in the Constraints section and ?5 is in the Semantics section. That is important for error messages — constraint violations require a diagnostic.
ISO/IEC 9899:1999 §6.7 Declarations
?3 If an identifier has no linkage, there shall be no more than one declaration of the identifier
(in a declarator or type specifier) with the same scope and in the same name space, except
for tags as specified in 6.7.2.3.
5 A declaration specifies the interpretation and attributes of a set of identifiers. A definition
of an identifier is a declaration for that identifier that:
- for an object, causes storage to be reserved for that object;
- for a function, includes the function body;98)
- for an enumeration constant or typedef name, is the (only) declaration of the
identifier.
ISO/IEC 9899:2011 §6.7 Declarations
?3 If an identifier has no linkage, there shall be no more than one declaration of the identifier
(in a declarator or type specifier) with the same scope and in the same name space, except
that:
- a typedef name may be redefined to denote the same type as it currently does,
provided that type is not a variably modified type;
- tags may be redeclared as specified in 6.7.2.3.
?5 A declaration specifies the interpretation and attributes of a set of identifiers. A definition
of an identifier is a declaration for that identifier that:
- for an object, causes storage to be reserved for that object;
- for a function, includes the function body;119)
- for an enumeration constant, is the (only) declaration of the identifier;
- for a typedef name, is the first (or only) declaration of the identifier.
Lundin noted that the Standard C Committee's web site contains n1360, a one page document detailing why this change was made. Basically: C++ does it; some compilers already do it; it is neither hard to do nor subverting anything to permit (require) it.
GCC doesn't always enforce the standard
If your code is compiling, then it is being compiled under the C11 rules, or C++ rules. It is not being compiled under (strict) C99 rules.
Note that sufficiently recent versions of GCC allow the redefinition unless you insist otherwise, but also note the report by John Bollinger that GCC 4.4.7 (on an unidentified platform) does not allow the redefinition at all in C99 mode.
Consider the file retypedef.c
:
int main(void)
{
typedef int x;
typedef int x;
x y = 0;
return y;
}
Compiling on Mac OS X 10.9.5 with GCC 4.9.1, I get:
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -c retypedef.c
$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -pedantic -c retypedef.c
$ gcc -O3 -g -std=c99 -Wall -Wextra -Werror -c retypedef.c
$ gcc -O3 -g -std=c99 -Wall -Wextra -Werror -pedantic -c retypedef.c
retypedef.c: In function ‘main’:
retypedef.c:4:17: error: redefinition of typedef ‘x’ [-Werror=pedantic]
typedef int x;
^
retypedef.c:3:17: note: previous declaration of ‘x’ was here
typedef int x;
^
cc1: all warnings being treated as errors
$
It doesn't complain unless -pedantic
is used, and then only if C99 is requested (it is standard compliant to redefine a typedef
in the same scope in C11).