Consider this code (t0.c):
typedef int T;
void f(int T);
Invocations:
gcc -std=c11 -Wall -Wextra -pedantic -c t0.c
<nothing>
clang -std=c11 -Wall -Wextra -pedantic -c t0.c
<nothing>
cl /std:c11 /Za /c t0.c
t0.c(2): warning C4224: nonstandard extension used: formal parameter 'T' was previously defined as a type
Questions:
nonstandard extension
, then why standard conforming gcc / clang does not say anything?
- Which C rule allows to use in function declarator an identifier, which was previously defined as a type?
First, a typedef
name is an identifier. C 2018 6.2.1 1 says:
An identifier can denote an object; a function; a tag or a member of a structure, union, or enumeration; a typedef name; a label name; a macro name; or a macro parameter…
The same paragraph says we can use the same identifier to denote different entities:
… The same identifier can denote different entities at different points in the program…
Paragraph 4 tells us the T
declared inside the function prototype hides the earlier T
:
… Within the inner scope, the identifier designates the entity declared in the inner scope; the entity declared in the outer scope is hidden (and not visible) within the inner scope.
- If msvc says nonstandard extension, then why standard conforming gcc / clang does not say anything?
GCC and Clang do not say anything because the code is fine according to the C standard, and their implementors have not chosen to issue any warning.
MSVC is allowed by the C standard to report diagnostics beyond what the standard requires, as all C implementations are, but it is incorrect to allege it is a non-standard extension.