If the error message of one is not very illuminating I often try the other compiler on the same piece of code. It is a good practice anyway and I should be doing more of that.
One claim that everyone will stand by is that the competition between the two has been a huge help.
It actually is a good idea to regularly build and test C/C++ codebases with both gcc and clang because not only error diagnostics are different but also warnings and optimizations, including crazy optimizations exploiting undefined behavior.
I discovered several bugs simply by compiling some code with different compilers and running the test suite each time.
foo(bar(), bar());
(where bar() was stateful)Discovering that g++ and clang++ compiled to one that did what I wanted and one that didn't was an interesting experience.
And before somebody wonders about currying and eager evaluation, the problem is not functions but type constructors, which aren't curried.
void test(a, b, c)
stack[0] == a
stack[1] == b
stack[2] == c
But to get the items in the stack in that order you have to... puch c
push b
push a
If you wanted to do that, and still allow for left to right evaluation you could... temp_a = a
temp_b = b
temp_c = c
push c
puch b
push a
That would be 2x instructions for every (already expensive at that time) function call. Defining unordered evaluation as UB was to avoid having to do temp_a, temp_b, temp_c. Now compiles can do that and trivially optimize that sort of thing out.Instead, the stackframe is created in one go with a single change to the stack pointer and then the values are filled in in whatever order the compiler / language desires.
Here is a typical example using GCC:
movq %rsp, %rbp
subq $16, %rsp
movl $12, -4(%rbp)
addl $1, -4(%rbp)
movl -4(%rbp), %eax
movl $14, %edx
movl %eax, %esi
movl $12, %edi
call f
Which moves the parameters using registers (subject to availability) as a further optimization. The 'subq' reserves space for the stackframe with addresses relative to rbp being the parameters.This is the accepted proposal:
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p014...
Although I have a long gcc bias I do use clang first as it is still faster to compile. Gcc still generates faster code for our codebase (and more importantly: faster where it matters to us) but they are pretty close and if I really had to decide between one and the other it would hardly matter.
G++-7-not-quite-released appears to have better C++17 support. We may be the only people who care yet :-)
In terms of exploit mitigation clang now has control flow integrity and safestack, as far as I'm aware nothing like this is available in gcc.
msan may not be such a big deal, because you could use clang for testing and gcc for production. But I hope more people adopt stronger exploit mitigations like CFI, and if gcc doesn't deliver them clang will win - at least for security sensitive areas.
asan, ubsan, tsan, and msan are important debugging features, but for my every day use in core analysis, local variables in gdb are very important.
Many warnings are available in both compilers and effort has been made to use the same names. Both compilers have some warnings exclusively. Clang prefers to raise warnings in the frontend only. Gcc in contrast will sometimes raise more warnings at higher optimization levels. If you can afford the overhead build with clang dbg, gcc O3 and MSVC.
(I'd say that this warning could be explicitly disabled for the scope is the macro... but alas, GCC broke _Pragma inside macros.)
Clang: https://godbolt.org/g/BVfy81
GCC: https://godbolt.org/g/uIN1gG
See the famous and now 12 years old GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=18501