I have two identical files , u1.c and u2.c which only contain
the line
typedef int Q ;
When I issue "splint u1.c u2.c" I get
u2.c:1:13: Datatype Q defined more than once
A function or variable is redefined. One of the declarations should use
extern. (Use -redef to inhibit warning)
u1.c:1:13: Previous definition of Q
Finished checking --- 1 code warning
Is this warning justified ? I thought that typedef's have file scope.
A "typedef" has the same scope as any ordinary declaration: if
it appears inside a function, for instance, it has block scope.
A typedef at file scope thus has file scope (as you noted).
It seems likely that splint is complaining because the typedef is
in different *source files*, rather than different translation
units. That is, splint is tracing the "typedef" line to a specific
file, and if multiple compilation units get the same typename from
*separate* files, it gripes. This is presumably to prevent you
from doing something like this:
% cat foo.h
Temperature measure(void);
% cat foo.c
typedef int Temperature;
#include "foo.h"
Temperature measure(void) { return 42; }
% cat main.c
typedef double Temperature;
#include "foo.h"
int main(void) {
printf("it's %f degrees\n", measure());
return 0;
}
These code fragments will most likely compile, yet when run, will
produce nonsense: main.c believes that measure() returns a double,
while foo.c's measure() actually returns an "int". The header
foo.h is shared between foo.c and main.c, but refers to a typedef
that is defined *differently* in the two .c files. If the typedef
line were also in the .h file, it would be impossible to get it
wrong in one of the .c files.
As for the "explanation" below the warning, it is just wrong. The
"extern" keyword is a storage-class-specifier, as is the typedef
keyword (even though the latter is an s-c-specifier purely for
syntactic reasons), and only one s-c-specifier keyword is allowed
in any declaration. (Probably splint has just one command line
option -- "-redef" -- that affects both ordinary, non-"typedef"
identifiers -- where you *can* use extern -- and "typedef" identifiers,
where you cannot.)