https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82594
Bug ID: 82594 Summary: Please provide better parameter / argument mismatch warnings/notes Product: gcc Version: unknown Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: palves at redhat dot com Target Milestone: --- While working on GDB, I came across a case where I wish GCC's diagnostics could have spared me a few greps. Here, reduced: ~~~ struct S1; struct S2; /* Declared in some header. */ void set_delete_thread (struct S1 *, void (*) (struct S2 *)); /* Declared in some other header. */ void delete_thread (struct S2 *); void initialize () { set_delete_thread (delete_thread); } ~~~ For simplicity, above 'set_delete_thread' and 'delete_thread' are 'initialize' are all declared/defined in the same translation unit. But please assume that they're declared in separate headers, as indicated by the comments, and that you don't really know by heart which headers those are. Compiling the above, we get, with current trunk (gcc version 8.0.0 20171017): ~~~ $ /opt/gcc/bin/g++ mismatch.cc -c -o mismatch mismatch.cc: In function ‘void initialize()’: mismatch.cc:12:35: error: cannot convert ‘void (*)(S2*)’ to ‘S1*’ for argument ‘1’ to ‘void set_delete_thread(S1*, void (*)(S2*))’ set_delete_thread (delete_thread); ^ ~~~ What I wish GCC would do is print a couple notes showing where are delete_thread [the argument] and set_delete_thread [the called function] defined. Something like: ~~~~~~ foo.h:4:5: note: ‘set_delete_thread’ declared here void set_delete_thread (struct S1 *, void (*) (struct S2 *)); nat/bar.h:10:5: note: ‘delete_thread’ declared here void delete_thread (struct S2 *); ~~~~~~ And likely another note for where S1 is declared too. For reference here's what clang 3.7 shows: ~~~ $ clang++ mismatch.cc -c -o mismatch mismatch.cc:12:3: error: no matching function for call to 'set_delete_thread' set_delete_thread (delete_thread); ^~~~~~~~~~~~~~~~~ mismatch.cc:5:6: note: candidate function not viable: requires 2 arguments, but 1 was provided void set_delete_thread (struct S1 *, void (*) (struct S2 *)); ^ 1 error generated. ~~~ If you remove the second parameter of set_delete_thread so that the number of arguments matches the number of parameters, we get instead (with clang): ~~~~ mismatch.cc:12:3: error: no matching function for call to 'set_delete_thread' set_delete_thread (delete_thread); ^~~~~~~~~~~~~~~~~ mismatch.cc:5:6: note: candidate function not viable: no known conversion from 'void (struct S2 *)' to 'struct S1 *' for 1st argument void set_delete_thread (struct S1 *); ^ ~~~~ I've found these clang "note: candidate function not viable" notes quite useful to see before, particularly when working with template code relying heavily on SFINAE. Maybe GCC could combine the best of both worlds and also consider my suggestion. Hey, asking is cheap. :-)