I find it interesting that new programmers often don't read/understand error messages. I didn't when I was starting, and I just saw a thread where the error message was "class ... does not have member... " and someone had to point out to them that "no, the class does not have that member."
I think the big problem is that there's so much useless information surrounding the actual message, and the message uses cryptic terms.
Although I have gotten used to it by now, I also recently started using clang for a few projects, and it's quite a bit nicer. When I forget a semicolon as here:
static unsigned int i = 0;
ostringstream toDisplay
toDisplay << getVolume() << " | ";
XStoreName(dpy, DefaultRootWindow(dpy), toDisplay.str().c_str());
Instead of this with gcc:
sdwmstatus.cpp: In function ‘int main(int, char**)’:
sdwmstatus.cpp:214:9: error: expected initializer before ‘toDisplay’
sdwmstatus.cpp:225:49: error: ‘toDisplay’ was not declared in this scope
I get this with clang:
sdwmstatus.cpp:212:32: error: expected ';' at end of declaration
ostringstream toDisplay
^
;
1 error generated.
with "error" red, the caret light green, and the missing semicolon dark green.
Not only is this more friendly to the new programmer, it's also more friendly to the seasoned guru who, even though she immediately recognizes that it's a missing semicolon error despite the message not saying so, still has to go to line 214 and look up and also read the next message and figure out it was caused by the first, rather than being shown exactly where the error is.
Here's another example. I used a nonexistant constructor for a string:
sdwmstatus.cpp: In function ‘int main(int, char**)’:
sdwmstatus.cpp:210:23: error: invalid conversion from ‘int’ to ‘const char*’ [-fpermissive]
In file included from /usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/string:55:0,
from /usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/locale_classes.h:42,
from /usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/ios_base.h:43,
from /usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/ios:43,
from /usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/ostream:40,
from /usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/iostream:40,
from sdwmstatus.cpp:5:
/usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.tcc:214:5: error: initializing argument 1 of ‘std::basic_string<_CharT, _Traits, _Alloc>::basic_string(const _CharT*, const _Alloc&) [with _CharT = char; _Traits = std::char_traits<char>; _Alloc = std::allocator<char>]’ [-fpermissive]
clang:
csdwmstatus.cpp:210:12: error: no matching constructor for initialization of 'string' (aka 'basic_string<char>')
string thestring(5);
^ ~
/usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:444:7: note: candidate constructor not
viable: no known conversion from 'int' to 'const std::allocator<char>' for 1st argument
basic_string(const _Alloc& __a);
^
/usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:451:7: note: candidate constructor not
viable: no known conversion from 'int' to 'const std::basic_string<char>' for 1st argument
basic_string(const basic_string& __str);
^
/usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:486:7: note: candidate constructor not
viable: no known conversion from 'int' to 'const char *' for 1st argument
basic_string(const _CharT* __s, const _Alloc& __a = _Alloc());
^
/usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:528:9: note: candidate constructor
template not viable: requires at least 2 arguments, but 1 was provided
basic_string(_InputIterator __beg, _InputIterator __end,
^
/usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:433:7: note: candidate constructor not
viable: requires 0 arguments, but 1 was provided
basic_string()
^
/usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:458:7: note: candidate constructor not
viable: requires at least 2 arguments, but 1 was provided
basic_string(const basic_string& __str, size_type __pos,
^
/usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:467:7: note: candidate constructor not
viable: requires 4 arguments, but 1 was provided
basic_string(const basic_string& __str, size_type __pos,
^
/usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:479:7: note: candidate constructor not
viable: requires at least 2 arguments, but 1 was provided
basic_string(const _CharT* __s, size_type __n,
^
/usr/lib/gcc/i686-pc-linux-gnu/4.7.2/../../../../include/c++/4.7.2/bits/basic_string.h:493:7: note: candidate constructor not
viable: requires at least 2 arguments, but 1 was provided
basic_string(size_type __n, _CharT __c, const _Alloc& __a = _Alloc());
^
1 error generated.
Here, the clang message is much longer but actually identifies the error and suggests possible fixes and explains why it had to give an error.
It's also really nice that it indents the wraps when your terminal isn't big enough to display the whole thing.
Has anyone else tried out clang or have ideas about those pesky error messages, ie the only part of the compiler we really interact with?