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.  :-)

Reply via email to