https://gcc.gnu.org/bugzilla/show_bug.cgi?id=53281
David Malcolm <dmalcolm at gcc dot gnu.org> changed: What |Removed |Added ---------------------------------------------------------------------------- CC| |dmalcolm at gcc dot gnu.org Assignee|unassigned at gcc dot gnu.org |dmalcolm at gcc dot gnu.org Target Milestone|--- |9.0 --- Comment #6 from David Malcolm <dmalcolm at gcc dot gnu.org> --- Another example, given by reddit user "agcpp" here: https://www.reddit.com/r/cpp/comments/84op5c/usability_improvements_in_gcc_8/dvvry8y/ > I'm little late to the party but want to add another example > where diagnostics will improve overall experience - > https://godbolt.org/g/kGKowz > > The diagnostics produced by MSVC here are just perfect, clang does > seem a bit verbose but readable otoh gcc confuses anyone who > hasn't been writing c++ for about 5 years :D ************************************************************ Code at that godbolt link: #include <string> using std::string; void func(string &s) { s.clear(); } int main() { const string s = "20"; func(s); } ************************************************************ MSVC 19 2017: /opt/compiler-explorer/windows/19.10.25017/lib/native/include/xlocale(314): warning C4530: C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc <source>(10): error C2664: 'void func(std::string &)': cannot convert argument 1 from 'const std::string' to 'std::string &' <source>(10): note: Conversion loses qualifiers ************************************************************ clang trunk: <source>:10:5: error: no matching function for call to 'func' func(s); ^~~~ <source>:4:6: note: candidate function not viable: 1st argument ('const std::__cxx11::string' (aka 'const basic_string<char>')) would lose const qualifier void func(string &s) { ^ 1 error generated. Compiler returned: 1 ************************************************************ gcc trunk: <source>: In function 'int main()': <source>:10:10: error: binding reference of type 'std::__cxx11::string&' {aka 'std::__cxx11::basic_string<char>&'} to 'const string' {aka 'const std::__cxx11::basic_string<char>'} discards qualifiers func(s); ^ <source>:4:6: note: initializing argument 1 of 'void func(std::__cxx11::string&)' void func(string &s) { ^~~~ Compiler returned: 1 ************************************************************ Part of the verbosity here relates to PR c++/84897 (reporting std::string rather than std::__cxx11::string). We're emitting a 28 words/~170 chars to seemingly talk about how: Compiler: "did you know that std::string is actually a std::basic_string?" mumble mumble, something about a qualifier. where the user has to spot the most pertinent word: "const" appearing in the 2nd pair of types, absent in the 1st pair of types. Among other issues, the aka seems redundant/unhelpful here. It seems best to special-case the "const member fn/param called with non-const" cases and to report them directly in terms of the types in user's source with and without "const", and to be explicit about which qualifier(s) are lost. We should also underline the param, or the "const" token. Proposed output for the above: error: binding reference of type 'std::string&' to 'const string' discards 'const' qualifier func(s); ^ note: initializing non-'const' argument 1 of 'void func(std::string&)' void func(string &s) { ~~~~~~~^~ (though even that is a bit "compiler-ese"; might want to talk about it being a call up-front) Proposed output for the case in comment #3: cv.cc: In member function ‘void Foo::bar2(const Foo&)’: cv.cc:4:26: error: passing ‘const Foo’ as ‘this’ argument discards 'const' qualifier [-fpermissive] foo.bar1(); ^ cv.cc:2:14: note: in call to ‘void Foo::bar1()’ which is non-const void bar1() {} ^~~~ I hope to fix these for gcc 9.