gcc 4.5.3 (as shipped on cygwin) gave a rather unhelpful message for a root cause bug in cygwin's <sys/un.h>: http://cygwin.com/ml/cygwin/2013-05/msg00451.html $ cat foo.c #ifdef WORKAROUND # include <sys/socket.h> #endif #include <sys/un.h> #include <sys/socket.h> int main(void) { const struct msghdr msg; return sendmsg(0, &msg, 0); } $ gcc -o foo -Wall foo.c foo.c: In function 'main': foo.c:9:5: warning: passing argument 2 of 'sendmsg' from incompatible pointer type /usr/include/sys/socket.h:42:11: note: expected 'const struct msghdr *' but argument is of type 'const struct msghdr *' $ gcc -o foo -Wall foo.c -DWORKAROUND $ Huh? How can 'const struct msghdr *' not be compatible with itself? [It took me a while to finally understand: the bug in cygwin's <sys/un.h> causes the declaration of sendmsg() to declare a local 'struct msghdr' rather than using the global type] I checked other bugs that mention this message, but none of them apply (bug 37866, 14188, 30949). I've further reduced it down to this two-file example, as tested with gcc 4.7.2: $ cat foo.h #ifdef SILENT # pragma GCC system_header #endif extern int bar(struct foo *); struct foo { int i; }; $ cat foo.c #include "foo.h" int main(void) { struct foo f; return bar(&f); } $ gcc -c -o foo.o -Wall foo.c -DSILENT foo.c: In function ‘main’: foo.c:4:3: warning: passing argument 1 of ‘bar’ from incompatible pointer type [enabled by default] In file included from foo.c:1:0: foo.h:4:12: note: expected ‘struct foo *’ but argument is of type ‘struct foo *’ which mirrors the fact that Cygwin's <sys/un.h> is compiled as a system header, and therefore misses the more obvious real root cause: $ gcc -c -o foo.o -Wall foo.c In file included from foo.c:1:0: foo.h:4:23: warning: ‘struct foo’ declared inside parameter list [enabled by default] foo.h:4:23: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default] foo.c: In function ‘main’: foo.c:4:3: warning: passing argument 1 of ‘bar’ from incompatible pointer type [enabled by default] In file included from foo.c:1:0: foo.h:4:12: note: expected ‘struct foo *’ but argument is of type ‘struct foo *’ I think it would be useful if the incompatible pointer type error message would ALSO call out a note on where the two types are first declared (if they are not built-in types), so that cases like mine, where the earlier error message about a parameter-list-local declaration was squelched is not quite so confusing.
We could detect the special case where the spelling is the same and report where each type is declared. Also, Clang's warning is nicer: test.c:4:23: warning: declaration of 'struct foo' will not be visible outside of this function [-Wvisibility] extern int bar(struct foo *); ^ versus GCC: test.c:4:23: warning: ‘struct foo’ declared inside parameter list [enabled by default] extern int bar(struct foo *); ^ test.c:4:23: warning: its scope is only this definition or declaration, which is probably not what you want [enabled by default]
(In reply to Manuel López-Ibáñez from comment #1) > Also, Clang's warning is nicer: By what metric? Just fitting on one line?
(In reply to Manuel López-Ibáñez from comment #1) > We could detect the special case where the spelling is the same and report > where each type is declared. Be aware that "spelled the same" needs to disregard cv-qualification; the original message prompted this report was comparing 'const struct msghdr *' to 'struct msghdr *'; and I was left scratching my head why automatic 'const' wasn't being added.