We have already had a long discussion and argument for ‘include’ mechanism in C/C++, no matter good or bad, and this is not my intention here. I am writing this post to show a confusing compiler error we have recently encountered and debugged for some time and trying to make my point – why static code analysis (SCA) is important for modern C/C++ projects. I am not saying compiler’s not good but saying SCA+compiler making the world better!
/home/daveti/Ctest/cCompiler: cat badHeader.h // A bad header missing ';' // badHeader.h typedef struct _boringStruct { int a; int b; int c; } BoringStruct /home/daveti/Ctest/cCompiler: cat useBadHeader.c #include <stdio.h> #include "badHeader.h" int main() { BoringStruct bs; bs.a = 1; bs.b = 2; bs.c = 3; printf( "a=%d, b=%d, c=%dn", bs.a, bs.b, bs.c); return 0; } /home/daveti/Ctest/cCompiler: gcc -o useBadHeader useBadHeader.c useBadHeader.c:4: syntax error before "int" useBadHeader.c: In function `main': useBadHeader.c:6: `BoringStruct' undeclared (first use in this function) useBadHeader.c:6: (Each undeclared identifier is reported only once useBadHeader.c:6: for each function it appears in.) useBadHeader.c:6: parse error before "bs" useBadHeader.c:7: `bs' undeclared (first use in this function) /home/daveti/Ctest/cCompiler: gcc -o useBadHeader.E -E useBadHeader.c /home/daveti/Ctest/cCompiler: cat useBadHeader.E ...... extern void funlockfile (FILE *__stream) ; # 679 "/usr/include/stdio.h" 3 # 2 "useBadHeader.c" 2 # 1 "badHeader.h" 1 typedef struct _boringStruct { int a; int b; int c; } BoringStruct # 3 "useBadHeader.c" 2 int main() { BoringStruct bs; bs.a = 1; bs.b = 2; bs.c = 3; printf( "a=%d, b=%d, c=%dn", bs.a, bs.b, bs.c); return 0; } /home/daveti/Ctest/cCompiler: cp useBadHeader.E useBadHeader.c /home/daveti/Ctest/cCompiler: gcc -o useBadHeader useBadHeader.c useBadHeader.c:4: syntax error before "int" useBadHeader.c: In function `main': useBadHeader.c:6: `BoringStruct' undeclared (first use in this function) useBadHeader.c:6: (Each undeclared identifier is reported only once useBadHeader.c:6: for each function it appears in.) useBadHeader.c:6: parse error before "bs" useBadHeader.c:7: `bs' undeclared (first use in this function) /home/daveti/Ctest/cCompiler: cat useBadHeader_hack.c #include <stdio.h> #include "badHeader.h" /* Hack */ ; int main() { BoringStruct bs; bs.a = 1; bs.b = 2; bs.c = 3; printf( "a=%d, b=%d, c=%dn", bs.a, bs.b, bs.c); return 0; } /home/daveti/Ctest/cCompiler: gcc -o useBadHeader_hack useBadHeader_hack.c /home/daveti/Ctest/cCompiler: ./useBadHeader_hack a=1, b=2, c=3 /home/daveti/Ctest/cCompiler: gcc -o useBadHeader_hack.E -E useBadHeader_hack.c /home/daveti/Ctest/cCompiler: cat useBadHeader_hack.E ...... extern void funlockfile (FILE *__stream) ; # 679 "/usr/include/stdio.h" 3 # 2 "useBadHeader_hack.c" 2 # 1 "badHeader.h" 1 typedef struct _boringStruct { int a; int b; int c; } BoringStruct # 3 "useBadHeader_hack.c" 2 ; int main() { BoringStruct bs; bs.a = 1; bs.b = 2; bs.c = 3; printf( "a=%d, b=%d, c=%dn", bs.a, bs.b, bs.c); return 0; } [root@localhost cCompiler]# ll total 32 drwxr-xr-x 2 root root 4096 May 29 01:09 . drwxr-xr-x 3 root root 4096 May 29 01:06 .. -rw-r--r-- 1 root root 134 May 29 01:07 badHeader.h -rw-r--r-- 1 root root 212 May 29 01:09 useBadHeader.c [root@localhost cCompiler]# splint * Splint 3.1.1 --- 19 Jul 2006 badHeader.h:9:1: Parse Error. (For help on parse errors, see splint -help parseerrors.) *** Cannot continue. [root@localhost cCompiler]#