http://gcc.gnu.org/bugzilla/show_bug.cgi?id=57475

            Bug ID: 57475
           Summary: "incompatible pointer type" message is not helpful
                    enough
           Product: gcc
           Version: 4.7.2
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ebb9 at byu dot net

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.

Reply via email to