Bug 57475 - "incompatible pointer type" message is not helpful enough
Summary: "incompatible pointer type" message is not helpful enough
Status: NEW
Alias: None
Product: gcc
Classification: Unclassified
Component: c (show other bugs)
Version: 4.7.2
: P3 normal
Target Milestone: ---
Assignee: Not yet assigned to anyone
URL:
Keywords: diagnostic
Depends on:
Blocks:
 
Reported: 2013-05-30 18:14 UTC by Eric Blake
Modified: 2024-12-01 01:52 UTC (History)
2 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2013-05-31 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Eric Blake 2013-05-30 18:14:11 UTC
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.
Comment 1 Manuel López-Ibáñez 2013-05-31 10:29:00 UTC
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]
Comment 2 Jonathan Wakely 2013-05-31 10:41:15 UTC
(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?
Comment 3 Eric Blake 2013-05-31 14:37:08 UTC
(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.