[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 --- Comment #11 from Manuel López-Ibáñez --- And Clang output: :5:13: error: invalid operands to binary expression ('std::ostream' (aka 'basic_ostream') and 'foo') std::cout << bar; ~ ^ ~~~ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/system_error:279:5: note: candidate function template not viable: no known conversion from 'foo' to 'const std::error_code' for 2nd argument operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:505:5: note: candidate function template not viable: no known conversion from 'foo' to 'char' for 2nd argument operator<<(basic_ostream<_CharT, _Traits>& __out, char __c) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:511:5: note: candidate function template not viable: no known conversion from 'foo' to 'char' for 2nd argument operator<<(basic_ostream& __out, char __c) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:517:5: note: candidate function template not viable: no known conversion from 'foo' to 'signed char' for 2nd argument operator<<(basic_ostream& __out, signed char __c) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:522:5: note: candidate function template not viable: no known conversion from 'foo' to 'unsigned char' for 2nd argument operator<<(basic_ostream& __out, unsigned char __c) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:600:5: note: candidate function template not viable: no known conversion from 'foo' to 'const char *' for 2nd argument operator<<(basic_ostream& __out, const char* __s) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:613:5: note: candidate function template not viable: no known conversion from 'foo' to 'const signed char *' for 2nd argument operator<<(basic_ostream& __out, const signed char* __s) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:618:5: note: candidate function template not viable: no known conversion from 'foo' to 'const unsigned char *' for 2nd argument operator<<(basic_ostream& __out, const unsigned char* __s) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/ostream.tcc:302:5: note: candidate function template not viable: no known conversion from 'foo' to 'const char *' for 2nd argument operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:500:5: note: candidate template ignored: deduced conflicting types for parameter '_CharT' ('char' vs. 'foo') operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/bits/basic_string.h:3591:5: note: candidate template ignored: could not match 'basic_string' against 'foo' operator<<(basic_ostream<_CharT, _Traits>& __os, ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:583:5: note: candidate template ignored: could not match 'const _CharT *' against 'foo' operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/type_traits:2230:46: note: candidate template ignored: disabled by 'enable_if' [with _Ostream = std::basic_ostream &, _Tp = foo] using __enable_if_t = typename enable_if<_Cond, _Tp>::type; ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:108:7: note: candidate function not viable: no known conversion from 'foo' to 'std::basic_ostream::__ostream_type &(*)(std::basic_ostream::__ostream_type &)' (aka 'basic_ostream> &(*)(basic_ostream> &)') for 1st argument operator<<(__ostream_type& (*__pf)(__ostream_type&)) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:117:7: note: candidate function not viable: no known conversion from 'foo' to 'std::basic_ostream::__ios_type &(*)(std::basic_ostream::__ios_type &)' (aka 'basic_ios> &(*)(basic_ios> &)') for 1st argument operator<<(__ios_type& (*__pf)(__ios_type&)) ^ /opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/12.0.0/../../../../include/c++/12.0.0/ostream:127:7: note: candidate function not viable:
[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 --- Comment #10 from Manuel López-Ibáñez --- This is the current GCC output: ``` : In function 'int main()': :5:13: error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream'} and 'foo') 5 | std::cout << bar; | ~ ^~ ~~~ || | || foo |std::ostream {aka std::basic_ostream} In file included from /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.0.0/iostream:39, from :1: /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.0.0/ostream:108:7: note: candidate: 'std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ostream_type& (*)(std::basic_ostream<_CharT, _Traits>::__ostream_type&)) [with _CharT = char; _Traits = std::char_traits; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream]' 108 | operator<<(__ostream_type& (*__pf)(__ostream_type&)) | ^~~~ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.0.0/ostream:108:36: note: no known conversion for argument 1 from 'foo' to 'std::basic_ostream::__ostream_type& (*)(std::basic_ostream::__ostream_type&)' {aka 'std::basic_ostream& (*)(std::basic_ostream&)'} 108 | operator<<(__ostream_type& (*__pf)(__ostream_type&)) | ~~^~ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.0.0/ostream:117:7: note: candidate: 'std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>::__ios_type& (*)(std::basic_ostream<_CharT, _Traits>::__ios_type&)) [with _CharT = char; _Traits = std::char_traits; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream; std::basic_ostream<_CharT, _Traits>::__ios_type = std::basic_ios]' 117 | operator<<(__ios_type& (*__pf)(__ios_type&)) | ^~~~ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.0.0/ostream:117:32: note: no known conversion for argument 1 from 'foo' to 'std::basic_ostream::__ios_type& (*)(std::basic_ostream::__ios_type&)' {aka 'std::basic_ios& (*)(std::basic_ios&)'} 117 | operator<<(__ios_type& (*__pf)(__ios_type&)) | ~~^~ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.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; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream]' 127 | operator<<(ios_base& (*__pf) (ios_base&)) | ^~~~ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.0.0/ostream:127:30: note: no known conversion for argument 1 from 'foo' to 'std::ios_base& (*)(std::ios_base&)' 127 | operator<<(ios_base& (*__pf) (ios_base&)) | ^ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.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; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream]' 166 | operator<<(long __n) | ^~~~ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.0.0/ostream:166:23: note: no known conversion for argument 1 from 'foo' to 'long int' 166 | operator<<(long __n) | ~^~~ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.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; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream]' 170 | operator<<(unsigned long __n) | ^~~~ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.0.0/ostream:170:32: note: no known conversion for argument 1 from 'foo' to 'long unsigned int' 170 | operator<<(unsigned long __n) | ~~^~~ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.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; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream]' 174 | operator<<(bool __n) | ^~~~ /opt/compiler-explorer/gcc-trunk-20210823/include/c++/12.0.0/ostream:174:23: note: no known conversion for argument 1 from 'foo' to 'bool' 174 | operator<<(bool __n) | ~^~~ In file included from
[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 Andrew Pinski changed: What|Removed |Added Last reconfirmed|2015-09-08 00:00:00 |2021-8-22 --- Comment #9 from Andrew Pinski --- Maybe when there are so many overloads don't display them? Though that feels worse but at least we do have the first line: : In function 'int main()': :6:13: error: no match for 'operator<<' (operand types are 'std::ostream' {aka 'std::basic_ostream'} and 'foo') 6 | std::cout << bar; | ~ ^~ ~~~ || | || foo |std::ostream {aka std::basic_ostream} MSVC outputs 18 overloads. ICC/EDG outputs no overloads. GCC and clang outputs a lot (libc++ has less than libstdc++).
[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 --- Comment #8 from Manuel López-Ibáñez --- > If we were outputting html, it would be much easier, we could print the > error message and have javascript so that clicking in appropriate places > displays the candidates, the reason for substitution failure, what a type is > an alias for, etc. This is something IDEs could do. But with text, we have > to print everything that might be useful. GCC outputting html (or XML: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=19165#c10 and later comments) seems much more unlikely than someone deciding to implement at least one of my points above. Anyone that needs such HTML output will already use Clang, which had HTML output 6 years ago) instead of spending a few years trying to implement it in GCC.
[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 --- Comment #6 from Marc Glisse --- (In reply to Manuel López-Ibáñez from comment #5) > /usr/include/c++/4.8/ostream:548:5: note: template > std::basic_ostream& std::operator<<(std::basic_ostream _Traits>&, const unsigned char*) > operator<<(basic_ostream & __out, const unsigned char* > __s) > ^ > /usr/include/c++/4.8/ostream:548:5: note: template argument > deduction/substitution failed: cannot convert type ‘foo’ to type ‘const > unsigned char*’ I am against removing information, most of it is useful in some cases. You can organize things better, have some overridable limits, etc, but in a number of cases g++ is actually printing too little information, not too much. We need to make the wall of text easier to understand / navigate, not remove information from it. In the example above, you dropped the information that it is 'bar' (the second argument) that cannot be converted, which, for a function with more arguments and templates and typedefs all over the place, might not be obvious at all. If we were outputting html, it would be much easier, we could print the error message and have javascript so that clicking in appropriate places displays the candidates, the reason for substitution failure, what a type is an alias for, etc. This is something IDEs could do. But with text, we have to print everything that might be useful.
[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 --- Comment #7 from Manuel López-Ibáñez --- (In reply to Marc Glisse from comment #6) > In the example above, you dropped the > information that it is 'bar' (the second argument) that cannot be converted, > which, for a function with more arguments and templates and typedefs all > over the place, might not be obvious at all. This info is already implied by the error: test.cc:5:15: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream}’ and ‘foo’) std::cout << bar; ^ It is also inconsistently printed for some conversions: /usr/include/c++/4.8/ostream:543:5: note: template std::basic_ostream& std::operator<<(std::basic_ostream &, const signed char*) operator<<(basic_ostream & __out, const signed char* __s) ^ /usr/include/c++/4.8/ostream:543:5: note: template argument deduction/substitution failed: test.cc:5:18: note: cannot convert ‘bar’ (type ‘foo’) to type ‘const signed char*’ std::cout << bar; ^ but not for others: /usr/include/c++/4.8/ostream:245:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char; _Trai ts = std::char_traits; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream] operator<<(const void* __p) ^ /usr/include/c++/4.8/ostream:245:7: note: no known conversion for argument 1 from ‘foo’ to ‘const void*’ Note that I'm ok with printing: /usr/include/c++/4.8/ostream:543:5: note: template argument deduction/substitution failed: cannot convert ‘bar’ (type ‘foo’) to type ‘const signed char*’ or even: /usr/include/c++/4.8/ostream:543:5: note: template argument deduction/substitution failed: cannot convert ‘bar’ (type ‘foo’) to type ‘const signed char*’ for argument 1 My point is to not print: test.cc:5:18: note: X std::cout << bar; ^ for the error AND for every candidate. For example, we could print: test.cc:5:15: error: no match for ‘operator<<’ (operand types are ‘std::ostream {aka std::basic_ostream}’ and ‘foo’) std::cout << bar; ^ test.cc:5:18: note: template argument deduction/substitution failed: cannot convert ‘bar’ (type ‘foo’) std::cout << bar; ^ /usr/include/c++/4.8/ostream:245:7: note: candidate 1: no known conversion for argument 1 from ‘foo’ to ‘const void*’ for 'std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char; _Traits = std::char_traits; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream]' operator<<(const void* __p) ^ /usr/include/c++/4.8/ostream:543:5: note: candidate 2: cannot convert type ‘foo’ to type ‘const signed char*’ for 'template std::basic_ostream & std::operator<<(std::basic_ostream &, const signed char*)' operator<<(basic_ostream & __out, const signed char* __s) ^ [etc.] > If we were outputting html, it would be much easier, we could print the > error message and have javascript so that clicking in appropriate places > displays the candidates, the reason for substitution failure, what a type is > an alias for, etc. This is something IDEs could do. But with text, we have > to print everything that might be useful. We could still print it in a smarter, nicer looking and consistent way, without repeating the same info several times (in the example above, there are only 108 unique lines out of 193).
[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 --- Comment #4 from Markus Trippelsdorf --- Well, clang isn't much better by default: markus@x4 tmp % clang++ -stdlib=libc++ -c foo.cxx 2>&1 | wc -l 97 markus@x4 tmp % clang++ -c foo.cxx 2>&1 | wc -l 88
[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 Markus Trippelsdorf changed: What|Removed |Added CC||trippels at gcc dot gnu.org --- Comment #1 from Markus Trippelsdorf --- -Wfatal-errors is always an option.
[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 Manuel López-Ibáñez changed: What|Removed |Added CC||manu at gcc dot gnu.org --- Comment #5 from Manuel López-Ibáñez --- There are several ways this output could be "easily" improved: 1) One problem with GCC's output is that it becomes difficult to track where each candidate is listed in the wall of text. We could print something like (also currently the candidates are not actually quoted, which is unusual when printing source code): note: candidate 1: %qD ... note: candidate 2: %qD 2) Also, we print two times the same include stack for two different candidates because we print a candidate from a different file in the middle. In file included from /usr/include/c++/4.8/ostream:612:0, from /usr/include/c++/4.8/iostream:39, from test.cc:1: /usr/include/c++/4.8/bits/ostream.tcc:91:5: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char; _Traits = std::char_traits] basic_ostream<_CharT, _Traits>:: ^ /usr/include/c++/4.8/bits/ostream.tcc:91:5: note: no known conversion for argument 1 from ‘foo’ to ‘short int’ In file included from /usr/include/c++/4.8/iostream:39:0, from test.cc:1: /usr/include/c++/4.8/ostream:181:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char; _Traits = std::char_traits; std::basic_ostream<_CharT, _Traits>::__ostr eam_type = std::basic_ostream] operator<<(unsigned short __n) ^ /usr/include/c++/4.8/ostream:181:7: note: no known conversion for argument 1 from ‘foo’ to ‘short unsigned int’ In file included from /usr/include/c++/4.8/ostream:612:0, from /usr/include/c++/4.8/iostream:39, from test.cc:1: /usr/include/c++/4.8/bits/ostream.tcc:105:5: note: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char; _Traits = std::char_traits] basic_ostream<_CharT, _Traits>:: ^ This is a lot of repetitive noise. The candidates could be sorted to reduce this noise. 3) We print the reason in a different line than the candidate, with the caret line in the middle. Thus, the caret line does not serve as a visual separation between candidates. /usr/include/c++/4.8/ostream:232:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char; _Traits = std::char_traits; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream] operator<<(long double __f) ^ /usr/include/c++/4.8/ostream:232:7: note: no known conversion for argument 1 from ‘foo’ to ‘long double’ /usr/include/c++/4.8/ostream:245:7: note: std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char; _Traits = std::char_traits; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream] operator<<(const void* __p) ^ /usr/include/c++/4.8/ostream:245:7: note: no known conversion for argument 1 from ‘foo’ to ‘const void*’ Instead, we could print the reason after the candidate, perhaps even within the same line. Maybe: /usr/include/c++/4.8/ostream:232:7: note: candidate 5: no known conversion for argument 1 from ‘foo’ to ‘long double’ for 'std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char; _Traits = std::char_traits; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream]' operator<<(long double __f) ^ /usr/include/c++/4.8/ostream:245:7: note: candidate 6: no known conversion for argument 1 from ‘foo’ to ‘const void*’ for 'std::basic_ostream<_CharT, _Traits>::__ostream_type& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char; _Traits = std::char_traits; std::basic_ostream<_CharT, _Traits>::__ostream_type = std::basic_ostream]' operator<<(const void* __p) ^ 4) The candidate output is too verbose in some cases: /usr/include/c++/4.8/ostream:548:5: note: template std::basic_ostream& std::operator<<(std::basic_ostream &, const unsigned char*) operator<<(basic_ostream & __out, const unsigned char* __s) ^ /usr/include/c++/4.8/ostream:548:5: note: template argument deduction/substitution failed: test.cc:5:18: note: cannot convert ‘bar’ (type ‘foo’) to type ‘const unsigned char*’ std::cout << bar; ^ The above could simply say: /usr/include/c++/4.8/ostream:548:5: note: template std::basic_ostream & std::operator<<(std::basic_ostream
[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 Jonathan Wakely changed: What|Removed |Added Keywords||diagnostic Status|UNCONFIRMED |NEW Last reconfirmed||2015-09-08 Ever confirmed|0 |1 Severity|normal |enhancement --- Comment #2 from Jonathan Wakely --- For the specific case of ostreams and operator<< see also PR 58713
[Bug c++/67499] c++ template/overload diagnostic compression
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=67499 --- Comment #3 from David Malcolm --- (we were chatting on IRC, I suggested Frank file this) It might be worth looking at Clang for inspiration; see e.g.: http://clang.llvm.org/diagnostics.html ("Template Type Diffing") though that's not quite the same thing.