189

I'm in college, and for a project we're using C. We've explored GCC and Clang, and Clang appears to be much more user friendly than GCC. As a result, I'm wondering what the advantages or disadvantages are to using clang, as opposed to GCC, for developing in C and C++ on Linux?

In my case this would be used for student level programs, not production.

If I use Clang, should I debug with GDB and use GNU Make, or use another debugger and make utility?

jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
haziz
  • 12,994
  • 16
  • 54
  • 75
  • 8
    As far as I can tell, Clang is still far from "mature", especially concerning standard library support. Nonetheless, it has fantastic error messages, so you can always approach a mysterious compiler error by trying the code on Clang. Clang can also compile C++ to C, I believe. – Kerrek SB Nov 21 '11 at 00:06
  • 3
    @KerrekSB: what element of "standard library support" is missing from clang? – Stephen Canon Nov 21 '11 at 00:14
  • 2
    @StephenCanon: Last time I tried it, I had to use libstdc++ (which isn't part of Clang as far as I understand). And just the other day we had [this issue](http://stackoverflow.com/questions/8194375/clang-hello-world-link-errors-in-windows). Anyway, I'm not following the bleeding edge, so my view may be entirely obsolete. – Kerrek SB Nov 21 '11 at 00:17
  • 4
    @KerrekSB: Regarding your link, Clang does not work on pure Windows. It works in MinGW though. Regarding the standard library, there is no real standard library part of Clang at the moment. Clang is bundled with libc++ on OSX, however libc++ is not fully ported in other environments, so on those Clang need another Standard Library implementation to be installed. On Linux, libstdc++ works. – Matthieu M. Nov 21 '11 at 08:06
  • @MatthieuM.: How complete is libc++? – Kerrek SB Nov 21 '11 at 08:09
  • 1
    @KerrekSB: C++98 is 100% supported. C++11 is mostly supported (last I checked, `` is not supported, perhaps some other small things are missing... I can't use it, so I'm not entirely up to speed with it). – James McNellis Nov 21 '11 at 08:15
  • @MatthieuM.: You can build clang with VC10. You can't use clang to compile code using the VC10 Standard Library, though (among other reasons, the VC10 headers rely on many VC implementation details... reasonably so). – James McNellis Nov 21 '11 at 08:17
  • @JamesMcNellis: to be fair, I think that `` is not complete on libstdc++ either. The last discussion I saw on the Clang mailing list (with the participation of one of the gcc dev) implied that things were not totally decided on the low-level facilities to be provided to write those atomics. – Matthieu M. Nov 21 '11 at 08:19
  • @JamesMcNellis: Sorry if I was unclear. I was indeed speaking of generating VC++ compatible code. – Matthieu M. Nov 21 '11 at 08:21
  • The answers to this question will always be horribly out of date. – rubenvb May 28 '13 at 14:36

6 Answers6

135

EDIT:

The gcc guys really improved the diagnosis experience in gcc (ah competition). They created a wiki page to showcase it here. gcc 4.8 now has quite good diagnostics as well (gcc 4.9x added color support). Clang is still in the lead, but the gap is closing.


Original:

For students, I would unconditionally recommend Clang.

The performance in terms of generated code between gcc and Clang is now unclear (though I think that gcc 4.7 still has the lead, I haven't seen conclusive benchmarks yet), but for students to learn it does not really matter anyway.

On the other hand, Clang's extremely clear diagnostics are definitely easier for beginners to interpret.

Consider this simple snippet:

#include <string>
#include <iostream>

struct Student {
std::string surname;
std::string givenname;
}

std::ostream& operator<<(std::ostream& out, Student const& s) {
  return out << "{" << s.surname << ", " << s.givenname << "}";
}

int main() {
  Student me = { "Doe", "John" };
  std::cout << me << "\n";
}

You'll notice right away that the semi-colon is missing after the definition of the Student class, right :) ?

Well, gcc notices it too, after a fashion:

prog.cpp:9: error: expected initializer before ‘&’ token
prog.cpp: In function ‘int main()’:
prog.cpp:15: error: no match for ‘operator<<’ in ‘std::cout << me’
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:112: note: candidates are: std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ostream<_CharT, _Traits>& (*)(std::basic_ostream<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:121: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_ios<_CharT, _Traits>& (*)(std::basic_ios<_CharT, _Traits>&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:131: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::ios_base& (*)(std::ios_base&)) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:169: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:173: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:177: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(bool) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:97: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:184: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(short unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:111: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:195: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:204: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:208: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long long unsigned int) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:213: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:217: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(float) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:225: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(long double) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/ostream:229: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(const void*) [with _CharT = char, _Traits = std::char_traits<char>]
/usr/lib/gcc/i686-pc-linux-gnu/4.3.4/include/g++-v4/bits/ostream.tcc:125: note:                 std::basic_ostream<_CharT, _Traits>& std::basic_ostream<_CharT, _Traits>::operator<<(std::basic_streambuf<_CharT, _Traits>*) [with _CharT = char, _Traits = std::char_traits<char>]

And Clang is not exactly starring here either, but still:

/tmp/webcompile/_25327_1.cc:9:6: error: redefinition of 'ostream' as different kind of symbol
std::ostream& operator<<(std::ostream& out, Student const& s) {
     ^
In file included from /tmp/webcompile/_25327_1.cc:1:
In file included from /usr/include/c++/4.3/string:49:
In file included from /usr/include/c++/4.3/bits/localefwd.h:47:
/usr/include/c++/4.3/iosfwd:134:33: note: previous definition is here
  typedef basic_ostream<char>           ostream;        ///< @isiosfwd
                                        ^
/tmp/webcompile/_25327_1.cc:9:13: error: expected ';' after top level declarator
std::ostream& operator<<(std::ostream& out, Student const& s) {
            ^
            ;
2 errors generated.

I purposefully choose an example which triggers an unclear error message (coming from an ambiguity in the grammar) rather than the typical "Oh my god Clang read my mind" examples. Still, we notice that Clang avoids the flood of errors. No need to scare students away.

ideasman42
  • 42,413
  • 44
  • 197
  • 320
Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
  • 2
    Um... last time I checked I read an article that published various benchmarks where clang pretty much blew gcc out of the water in ever test. Source: http://clang.llvm.org/features.html#performance –  Dec 08 '11 at 00:29
  • 33
    @AscensionSystems: beware, those tests show the performance of the Clang binary itself (and that was a while ago), not the performance of the binary you were compiling. – Matthieu M. Dec 08 '11 at 07:09
  • That's a good point I'd be interested to see a stand up comparison between the compiled executables. I'm under the impression that clang does a much better job at optimization but I havn't actually seen any benchmarks. I'll check it out. –  Dec 08 '11 at 12:25
  • Most recent benchmarks done are showing that there is no one compiler which is overall better than the other. In some tests one dominates the other and vise versa, but these instances are pretty evenly split. Link: http://www.phoronix.com/scan.php?page=article&item=gcc_46_llvm29&num=2 –  Dec 08 '11 at 12:41
  • 4
    @AscensionSystems: here is the latest bench I am aware of comparing [gcc 4.6 to llvm 3.0](http://www.phoronix.com/scan.php?page=article&item=llvm3_gcc_open64&num=1) which shows a net advantage of gcc in average. Also interesting may be the [DragonEgg bench](http://www.phoronix.com/scan.php?page=article&item=llvm_dragonegg_30&num=3), DragonEgg is a plugin that allows using the gcc front-end (and possibly optimizer) and then the LLVM backend to generate the code. – Matthieu M. Dec 08 '11 at 13:04
  • 1
    Last time I checked, phoronix benchmarks were very untrustworthy: compiler flags weren't properly documented, but the results suggested things weren't being set properly. – Eamon Nerbonne Feb 11 '12 at 14:45
  • @EamonNerbonne: still they are one of the few benchmarks available. Of interest to you may be a [benchmark by the Chromium team](http://old.nabble.com/Compile-time-measurements-in-Chromium-p33273359.html) with recent versions of both clang and gcc. Although it is only the build time. – Matthieu M. Feb 12 '12 at 12:44
  • Good find! I also came across these SPEC benchmark runs: http://vmakarov.fedorapeople.org/spec/2011/llvmgcc32.html and http://vmakarov.fedorapeople.org/spec/2011/llvmgcc64.html. http://vmakarov.fedorapeople.org/spec/ also has some older results. – Eamon Nerbonne Feb 13 '12 at 10:37
  • @EamonNerbonne: very nice, it would be great if we had the same benchmarks for llvm 3.0 / gcc 4.6. – Matthieu M. Feb 13 '12 at 12:47
  • With the release of GCC 4.8, I wonder how the competition in clarity of error messages and warnings now stacks up? – haziz Apr 02 '13 at 12:29
  • @haziz: I wish I knew too, according to gcc they do much better than they used to, but then Clang is also improving (notably with an algorithm to compute (and print) a diff between two template types), and neither side has made updates. – Matthieu M. Apr 02 '13 at 12:33
  • @ideasman42: I just saw your edit, it amused me because looking at the [revision history](http://stackoverflow.com/posts/8208827/revisions), you were the one adding this "available in gcc 4.9" bit nearly 2 years ago! In any case, thanks for polishing this answer. – Matthieu M. Aug 21 '15 at 09:12
37

As of right now, GCC has much better and more complete support for C++11 features than Clang. Also, the code generator for GCC performs better optimisation than the one in Clang (in my experience, I have not seen any exhaustive tests).

On the other hand, Clang often compiles code more quickly than GCC, and produces better error messages when there is something wrong with your code.

The choice of which one to use really depends on what things are important to you. I value C++11 support and code generation quality more than I value convenience of compilation. Because of this, I use GCC. For you, the trade-offs could be different.

Frank
  • 191
  • 1
  • 6
Mankarse
  • 39,818
  • 11
  • 97
  • 141
  • 3
    Here is the latest Phoronix article comparing [GCC 4.6 vs Clang 3.0](http://www.phoronix.com/scan.php?page=article&item=llvm3_gcc_open64&num=1) as well as a [previous article](http://www.phoronix.com/scan.php?page=article&item=amd_bulldozer_compilers&num=1) specific to the bulldozer platform. Depending on the benchmarks, the winner is either one or the other (on the previous article, gcc 4.7 appears too), so I personally find it unclear which is performing better. – Matthieu M. Nov 21 '11 at 07:50
  • Why not use both? Clang for development, and GCC for production. – segfault Jan 02 '13 at 16:58
  • 5
    @segfault: That is what I am doing currently. This answer is quite old, and it is no longer entirely true. Both Clang and GCC have improved significantly since I wrote it (in particular, Clang now matches GCC overall C++11 support, and GCC has improved its error messages and compilation speed). Now I would suggest using both, with a slight preference towards Clang because the Clang source code is a lot easier to understand than the GCC source. – Mankarse Jan 03 '13 at 01:17
26

I use both because sometimes they give different, useful error messages.

The Python project was able to find and fix a number of small buglets when one of the core developers first tried compiling with clang.

Raymond Hettinger
  • 216,523
  • 63
  • 388
  • 485
  • 1
    What are your thoughts on using clang for debug builds but gcc for optimised releases? – Olical Dec 10 '12 at 18:50
  • 5
    It's reasonable to develop with Clang and release with GCC, but be sure your GCC release passes your test suite (both with and without NDEBUG). – Raymond Hettinger Dec 12 '12 at 17:32
  • 2
    Thanks for the response. I have been trying it out for a bit and it works really well. I get different sets of warnings too, which is great. – Olical Dec 13 '12 at 10:55
12

I use both Clang and GCC, I find Clang has some useful warnings, but for my own ray-tracing benchmarks - its consistently 5-15% slower then GCC (take that with grain of salt of course, but attempted to use similar optimization flags for both).

So for now I use Clang static analysis and its warnings with complex macros: (though now GCC's warnings are pretty much as good - gcc4.8 - 4.9).

Some considerations:

  • Clang has no OpenMP support, only matters if you take advantage of that but since I do, its a limitation for me. (*****)
  • Cross compilation may not be as well supported (FreeBSD 10 for example still use GCC4.x for ARM), gcc-mingw for example is available on Linux... (YMMV).
  • Some IDE's don't yet support parsing Clangs output (QtCreator for example *****). EDIT: QtCreator now supports Clang's output
  • Some aspects of GCC are better documented and since GCC has been around for longer and is widely used, you might find it easier to get help with warnings / error messages.

***** - these areas are in active development and may soon be supported

Victor Tran
  • 516
  • 4
  • 16
ideasman42
  • 42,413
  • 44
  • 197
  • 320
  • I use OpenMP as well but I am thinking of switching to TBB which I guess would work with Clang. –  May 25 '13 at 08:11
  • 1
    TBB may be a viable alternative for OpenMP in some cases (but only for C++ as far as I can tell), for C its not supported - also for large projects, switching from OpenMP to something else might not be worthwhile especially if Clang will eventually support OpenMP anyway. – ideasman42 Feb 01 '14 at 02:27
8

For student level programs, Clang has the benefit that it is, by default, stricter wrt. the C standard. For example, the following K&R version of Hello World is accepted without warning by GCC, but rejected by Clang with some pretty descriptive error messages:

main()
{
    puts("Hello, world!");
}

With GCC, you have to give it -Werror to get it to really make a point about this not being a valid C89 program. Also, you still need to use c99 or gcc -std=c99 to get the C99 language.

Fred Foo
  • 355,277
  • 75
  • 744
  • 836
  • 9
    `gcc` should generally be invoked with at least `-Wall`, which does warn for this program. `clang` does produce good warnings/errors, though. – caf Nov 21 '11 at 00:10
  • 2
    @caf: which is exactly the point I'm trying to make, with GCC you have to pass it options. Out of the box, it may be too tolerant for teaching purposes. – Fred Foo Nov 21 '11 at 00:11
  • That may be true, but it's a fairly minor point. What's more important is the *quality* of the error messages. GCC 4.6 has got pretty good, though I understand that clang is doing some real magic there. – Kerrek SB Nov 21 '11 at 00:14
  • I think GCC used to (not sure if it still does) default to its own dialect of the C language called `gnu89`, which is C89 plus a few features GNU put in (some of which are found in C99). – dreamlax Nov 21 '11 at 02:54
  • 2
    @dreamlax: True; there's also `gnu99`, and `gnu++98` and `gnu++0x`. I think those are genuine *extensions*, though, i.e. they will compile conforming ISO-standard code without a hitch. Here are the details: [for C](http://www.dis.com/gnu/gcc/C-Extensions.html), [for C++](http://www.dis.com/gnu/gcc/C_002b_002b-Extensions.html). – Kerrek SB Nov 21 '11 at 08:18
  • 1
    This program shouldn't produce errors or warnings. It conforms to the standard. – Miles Rout Jan 11 '13 at 09:20
  • @MilesRout Not for C++ afaik. – Etherealone May 30 '14 at 21:22
  • Indeed true, C, not C++. – Miles Rout May 31 '14 at 01:27
  • Good to note that GCC's c++ default to C++14 in version 6.1 or higher – Rahly May 31 '17 at 17:21
  • @MilesRout it doesn't conform to *the* standard. It conforms to an old revoked edition of the standard. You wouldn't say "this is legal" about something that only conforms to laws of 18th century either... – Antti Haapala -- Слава Україні Aug 09 '17 at 05:33
3

I think clang could be an alternative.

GCC and clang have some differences on expressions like a+++++a, and I've got many different answers with my peer who use clang on Mac while I use gcc.

GCC has become the standard, and clang could be an alternative. Because GCC is very stable and clang is still under developing.

Ziming Song
  • 1,176
  • 1
  • 9
  • 22
  • 5
    Clang is rapidly preparing to replace GCC completely in the Linux world, and has largely done so in the BSD world. It replaced GCC on Mac years ago. Clang is good stuff. I think GCC could become an alternative, personally, and I would happy about that. – coder543 Jun 24 '13 at 19:57
  • 6
    The expression a+++++a is undefined so expect to get a different answer on each compiler, or even on different versions of the same compiler. You could even get different results for that expression on the same compiler when compiled at different times. That's what "undefined" means. – Lelanthran Apr 16 '14 at 05:33
  • 2
    `a+++++a` should fail, as it's parsed as `a ++ ++ + a` which is a syntax error. – Miles Rout May 31 '14 at 01:30
  • @Lelanthran that is not what undefined means. It has undefined behaviour so the compiler can fail to compile that, or it can throw at runtime or lock the CPU so that you need to do hard reset or something even more sinister. – Antti Haapala -- Слава Україні Aug 09 '17 at 05:36