Gcc vs. Clang for Error Messages

So the gcc vs. clang debate flamed up again. I thought I would deliver my few cents too.

It is claimed from time to time that clang has more helpful error messages. It is, in my opinion, a clain that is just plain wrong. They both stink. Let’s look at a few samples:

static int foo (int a, int b) { return a + b; }
int bar (int a) { return foo (a (4 + 1) * 2); }

gcc says (excerpts):

e1.c:2:33: error: called object ‘a’ is not a function or function pointer
e1.c:2:1: error: too few arguments to function ‘foo’

clang says (excerpts):

e1.c:2:33: error: called object type 'int' is not a function or function pointer

The best thing you can say about the error messages here is that they at least point you to the right location. gcc is a tad better by virtue of printing the second error message which at least hints of the real problem, but neither compiler tell us what the problem is: “missing comma”. It looks like clang is suppressing the second and further errors on a line. Note, however, that in this case it has suppressed the more informative error.

Moving on with a missing opening parenthesis:

static int foo (int a, int b) { return a + b; }
int bar (int a) { return foo a); }

From gcc we get the wisdom

e2.c:2:19: warning: return makes integer from pointer without a cast [enabled by default]
e2.c:2:30: error: expected ‘;’ before ‘a’
e2.c:2:31: error: expected statement before ‘)’ token

while clang produces

e2.c:2:26: warning: incompatible pointer to integer conversion returning
'int (int, int)' from a function with result type 'int' [-Wint-conversion]
e2.c:2:29: error: expected ';' after return statement

I don’t see that one set of utter nonsense is better than the other and spending time colour coding the output shows a dubious set of priorities. Clang would do well to add hyphens to “pointer to integer”.

How about this?

#include <stdio.h>
#define EMIT(c) fprintf(stderr,"%c",(c))

Nothing from gcc, nothing from clang, nothing from sparse. Yet it’s a clear violation of C99’s paragraph 7.26.3.

C++ doesn’t fare any better:

#include <vector>
std::vector<int,int> foo; // should have been map

gcc delivers 67 lines of nonsense starting with

/usr/include/c++/4.8/ext/alloc_traits.h:199:53: error: ‘int’ is not a class, str
uct, or union type
typedef typename _Alloc::pointer pointer;

whereas clang emits 87 lines of garbage starting with

/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../include/c++/4.8/ext/alloc_traits.h
:199:22: error: type 'int' cannot be used prior to '::' because it has no member
typedef typename _Alloc::pointer pointer;

Again, the error messages are startingly useless in both cases. A sane error message would start with “type int is not valid for the second template argument to std::vector”.

The quality of error messages has been the subject of jokes for decades. Insofar clang is new code, it would appear that they have squandered any opportunity for making real improvements opting instead for putting lipstick on a pig.