[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 --- Comment #10 from Lewis Hyatt --- (In reply to Jonathan Wakely from comment #9) > That looks pretty good to me. What does it produce for the operator<< > example in comment 1? With the default options: = iowarn2.cpp: In function ‘void f(std::ostream&, const A&)’: iowarn2.cpp:13:5: error: no match for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream’} and ‘const A’) 13 | o << a; | ~ ^~ ~ | || | |const A | std::ostream {aka std::basic_ostream} iowarn2.cpp:13:5: note: declining to output 34 candidates (limit 7); compile with ‘-foverload-candidates-stop-level=34’ to see them = With the suggestion from the diagnostic -foverload-candidates-stop-level=34, so this is the ~50% abbreviated mode: = iowarn2.cpp: In function ‘void f(std::ostream&, const A&)’: iowarn2.cpp:13:5: error: no match for ‘operator<<’ (operand types are ‘std::ostream’ {aka ‘std::basic_ostream’} and ‘const A’) 13 | o << a; | ~ ^~ ~ | || | |const A | std::ostream {aka std::basic_ostream} In file included from iowarn2.cpp:1: /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:108:7: note: candidate: ‘std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(__ostream_type& (*)(__ostream_type&)) [with _CharT = char; _Traits = std::char_traits; __ostream_type = std::basic_ostream]’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:108:36: note: no known conversion for argument 1 from ‘const A’ to ‘std::basic_ostream::__ostream_type& (*)(std::basic_ostream::__ostream_type&)’ {aka ‘std::basic_ostream& (*)(std::basic_ostream&)’} /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:117:7: note: candidate: ‘std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(__ios_type& (*)(__ios_type&)) [with _CharT = char; _Traits = std::char_traits; __ostream_type = std::basic_ostream; __ios_type = std::basic_ios]’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:117:32: note: no known conversion for argument 1 from ‘const A’ to ‘std::basic_ostream::__ios_type& (*)(std::basic_ostream::__ios_type&)’ {aka ‘std::basic_ios& (*)(std::basic_ios&)’} /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:127:7: note: candidate: ‘std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char; _Traits = std::char_traits; __ostream_type = std::basic_ostream]’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:127:30: note: no known conversion for argument 1 from ‘const A’ to ‘std::ios_base& (*)(std::ios_base&)’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:166:7: note: candidate: ‘std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char; _Traits = std::char_traits; __ostream_type = std::basic_ostream]’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:166:23: note: no known conversion for argument 1 from ‘const A’ to ‘long int’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:170:7: note: candidate: ‘std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char; _Traits = std::char_traits; __ostream_type = std::basic_ostream]’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:170:32: note: no known conversion for argument 1 from ‘const A’ to ‘long unsigned int’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:174:7: note: candidate: ‘std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char; _Traits = std::char_traits; __ostream_type = std::basic_ostream]’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:174:23: note: no known conversion for argument 1 from ‘const A’ to ‘bool’ In file included from /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:833: /home/lewis/gccdev/dev/rel/include/c++/13.0.0/bits/ostream.tcc:91:5: note: candidate: ‘std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char; _Traits = std::char_traits]’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/bits/ostream.tcc:92:22: note: no known conversion for argument 1 from ‘const A’ to ‘short int’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:181:7: note: candidate: ‘std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char; _Traits = std::char_traits; __ostream_type = std::basic_ostream]’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/ostream:181:33: note: no known conversion for argument 1 from ‘const A’ to ‘short unsigned int’ /home/lewis/gccdev/dev/rel/include/c++/13.0.0/bits/ostream.tcc:105:5: note
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 --- Comment #9 from Jonathan Wakely --- That looks pretty good to me. What does it produce for the operator<< example in comment 1?
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 Lewis Hyatt changed: What|Removed |Added CC||lhyatt at gcc dot gnu.org --- Comment #8 from Lewis Hyatt --- Created attachment 53108 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=53108&action=edit One possible approach Hello- What do you all think of this approach? The new options -foverload-candidates-reduce-level and -foverload-candidates-stop-level would configure the amount of information that is output regarding overload candidates. When the number of overloads exceeds -foverload-candidates-reduce-level (default 3), then the source lines are no longer printed for each candidate, cutting the output length in half. The source lines seem rarely useful anyway, since the diagnostic's first line already prints the overload being considered. When the number of overloads exceeds -foverload-candidates-stop-level (default 7), none of the overloads is printed, since this is presumably a case such as a heavily overloaded operator where the large number of candidates is less likely to be helpful in fixing the problem. For a testcase like this common (for me) typo: = #include void f(std::ostream& o, int a) { o << a < '\n'; } = GCC then outputs: = iowarn.cpp: In function ‘void f(std::ostream&, int)’: iowarn.cpp:3:12: error: no match for ‘operator<’ (operand types are ‘std::basic_ostream’ and ‘char’) 3 | o << a < '\n'; | ~~ ^ | | | | | char | std::basic_ostream iowarn.cpp:3:12: note: declining to output 15 candidates (limit 7); compile with ‘-foverload-candidates-stop-level=15’ to see them = which at least for this specific case feels like an improvement to me... It's obvious what is wrong now. If you follow the suggestion and add the flag to the compile, then you see: = iowarn.cpp: In function ‘void f(std::ostream&, int)’: iowarn.cpp:3:12: error: no match for ‘operator<’ (operand types are ‘std::basic_ostream’ and ‘char’) 3 | o << a < '\n'; | ~~ ^ | | | | | char | std::basic_ostream iowarn.cpp:3:12: note: candidate: ‘operator<(int, int)’ (built-in) iowarn.cpp:3:12: note: no known conversion for argument 1 from ‘std::basic_ostream’ to ‘int’ In file included from /home/lewis/gccdev/release/include/c++/13.0.0/string:46, from /home/lewis/gccdev/release/include/c++/13.0.0/bits/locale_classes.h:40, from /home/lewis/gccdev/release/include/c++/13.0.0/bits/ios_base.h:41, from /home/lewis/gccdev/release/include/c++/13.0.0/ios:42, from /home/lewis/gccdev/release/include/c++/13.0.0/ostream:38, from iowarn.cpp:1: /home/lewis/gccdev/release/include/c++/13.0.0/bits/stl_iterator.h:451:5: note: candidate: ‘template constexpr bool std::operator<(const reverse_iterator<_Iterator>&, const reverse_iterator<_Iterator>&)’ /home/lewis/gccdev/release/include/c++/13.0.0/bits/stl_iterator.h:451:5: note: template argument deduction/substitution failed: iowarn.cpp:3:14: note: ‘std::basic_ostream’ is not derived from ‘const std::reverse_iterator<_Iterator>’ /home/lewis/gccdev/release/include/c++/13.0.0/bits/stl_iterator.h:496:5: note: candidate: ‘template constexpr bool std::operator<(const reverse_iterator<_Iterator>&, const reverse_iterator<_IteratorR>&)’ /home/lewis/gccdev/release/include/c++/13.0.0/bits/stl_iterator.h:496:5: note: template argument deduction/substitution failed: iowarn.cpp:3:14: note: ‘std::basic_ostream’ is not derived from ‘const std::reverse_iterator<_Iterator>’ /home/lewis/gccdev/release/include/c++/13.0.0/bits/stl_iterator.h:1683:5: note: candidate: ‘template constexpr bool std::operator<(const move_iterator<_IteratorL>&, const move_iterator<_IteratorR>&)’ /home/lewis/gccdev/release/include/c++/13.0.0/bits/stl_iterator.h:1683:5: note: template argument deduction/substitution failed: iowarn.cpp:3:14: note: ‘std::basic_ostream’ is not derived from ‘const std::move_iterator<_IteratorL>’ /home/lewis/gccdev/release/include/c++/13.0.0/bits/stl_iterator.h:1748:5: note: candidate: ‘template constexpr bool std::operator<(const move_iterator<_IteratorL>&, const move_iterator<_IteratorL>&)’ /home/lewis/gccdev/release/include/c++/13.0.0/bits/stl_iterator.h:1748:5: note: template argument deduction/substitution failed: iowarn.cpp:3:14: note: ‘std::basic_ostream’ is not derived from ‘const std::move_iterator<_IteratorL>’ In file included from /home/lewis/gccdev/release/include/c++/13.0.0/bits/stl_algobase.h:64, from /home/lewis/gccdev/release/include/c++/13.0.0/string:49: /home/lewis/gccdev/release/include/c++/13.0.0/bits/stl_pair.h:665:5: note: candidate: ‘template constexpr bool std::
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 Jonathan Wakely changed: What|Removed |Added Target Milestone|9.5 |---
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 Mikko Rasa changed: What|Removed |Added CC||tdb at tdb dot fi --- Comment #7 from Mikko Rasa --- Is this still being worked on? I regularly run into spammy output, especially with the == and != operators. Just now I accidentally used std::find on an std::map, which obviously didn't work - but spewed nearly 500 lines of notes about all the operator== overloads it considered from several stdlib headers. At that point the notes cease to be useful and just make it harder to find out where the actual error was. This occurs with both g++-10 and g++-11.
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 Richard Biener changed: What|Removed |Added Target Milestone|9.4 |9.5 --- Comment #6 from Richard Biener --- GCC 9.4 is being released, retargeting bugs to GCC 9.5.
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 Jakub Jelinek changed: What|Removed |Added Target Milestone|9.3 |9.4 --- Comment #5 from Jakub Jelinek --- GCC 9.3.0 has been released, adjusting target milestone.
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 Jakub Jelinek changed: What|Removed |Added Target Milestone|9.2 |9.3 --- Comment #4 from Jakub Jelinek --- GCC 9.2 has been released.
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 Jakub Jelinek changed: What|Removed |Added Target Milestone|9.0 |9.2 --- Comment #3 from Jakub Jelinek --- GCC 9.1 has been released.
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 Eric Gallager changed: What|Removed |Added Status|UNCONFIRMED |ASSIGNED Last reconfirmed||2018-06-18 CC||egallager at gcc dot gnu.org Ever confirmed|0 |1 --- Comment #2 from Eric Gallager --- (In reply to David Malcolm from comment #0) > As reported by user "jcoffland" on Hacker News: > https://news.ycombinator.com/item?id=16598071 > > > One improvement I'd like to see is a simplified error message > > for mismatched overloaded calls. If you make an overloaded call > > for which the is no matching conversion or if the conversation is > > ambiguous the compiler will "helpfully" dump a list of possibly > > matching overloaded function signatures. The list can be hundreds > > of lines long. > > > > For example, when you try to pipe a class to std::cout that > > doesn't have an std::ostream &operator<<(std::ostream &, const X &). > > Perhaps instead of dumping the complete function signatures it > > could show one function signature followed by a list of types > > accepted as the second parameter. Since the signatures are > > otherwise the same. Such improvements could also reduce > > template error spew. > > I hope to have a look at this in the GCC 9 timeframe, so filing this here. OK, changing status to ASSIGNED then
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 --- Comment #1 from Jonathan Wakely --- (In reply to David Malcolm from comment #0) > As reported by user "jcoffland" on Hacker News: > https://news.ycombinator.com/item?id=16598071 > > > One improvement I'd like to see is a simplified error message > > for mismatched overloaded calls. If you make an overloaded call > > for which the is no matching conversion or if the conversation is > > ambiguous the compiler will "helpfully" dump a list of possibly > > matching overloaded function signatures. The list can be hundreds > > of lines long. It's rare to get hundreds of lines in general. That usually only happens for iostream operator<< and operator>>, because not many operators have as many overloads all in the same namespace. But a general solution wouldn't hurt. > > For example, when you try to pipe a class to std::cout that > > doesn't have an std::ostream &operator<<(std::ostream &, const X &). > > Perhaps instead of dumping the complete function signatures it > > could show one function signature followed by a list of types > > accepted as the second parameter. Since the signatures are > > otherwise the same. I like the idea, but this isn't *strictly* true, as there's a function template taking an rvalue stream as the first parameter, but that should accept all the same types as the version for lvalue streams, so showing it doesn't add much value. The other advantages of the signatures is that they include the location info, so if an overload doesn't match because of a SFINAE constraint you can go and check the source, e.g. given #include template struct A { T value; }; template auto operator<<(std::ostream& o, const A& a) -> decltype(o << a.value) { return o << a.value; } struct Y { }; void f(std::ostream& o, const A& a) { o << a; } Included in the output is: a.cc:5:6: note: candidate: template decltype ((o << a.value)) operator<<(std::ostream&, const A&) auto operator<<(std::ostream& o, const A& a) ^~~~ a.cc:5:6: note: template argument deduction/substitution failed: a.cc: In substitution of ‘template decltype ((o << a.value)) operator<<(std::ostream&, const A&) [with T = Y]’: a.cc:13:8: required from here a.cc:6:15: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream}’ and ‘const Y’) -> decltype(o << a.value) ~~^~ which points to a.cc:5:6 as the location of the overload, and the expression at a.cc:6:15 is potentially useful infomration. Maybe we could special-case the overloads from namespace std, since they are usually less interesting. Usually. More generally, maybe add -foverload-candidates-limit=N so if the overload set is above the limit don't show the notes with the reasons overload resolution failed, just show the candidates.
[Bug c++/84920] Better handling of unmatched/ambiguous calls
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84920 David Malcolm changed: What|Removed |Added Assignee|unassigned at gcc dot gnu.org |dmalcolm at gcc dot gnu.org Target Milestone|--- |9.0