clanguage-lawyerc11function-declarationc17

Which C rules allow to use in function declarator an identifier, which was previously defined as a type?


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:

  1. Which C rules allow to use in function declarator an identifier, which was previously defined as a type?
  2. If msvc says nonstandard extension, then why standard conforming gcc / clang does not say anything?

Solution

  • 1

    1. 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.

    2

    1. 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.