190

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?

10
  • 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
    Commented Nov 21, 2011 at 0:06
  • 3
    @KerrekSB: what element of "standard library support" is missing from clang? Commented Nov 21, 2011 at 0: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. Anyway, I'm not following the bleeding edge, so my view may be entirely obsolete.
    – Kerrek SB
    Commented Nov 21, 2011 at 0:17
  • 5
    @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. Commented Nov 21, 2011 at 8:06
  • 1
    @KerrekSB: C++98 is 100% supported. C++11 is mostly supported (last I checked, <atomic> 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). Commented Nov 21, 2011 at 8:15

6 Answers 6

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.

12
  • 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: clang.llvm.org/features.html#performance
    – user562566
    Commented Dec 8, 2011 at 0: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. Commented Dec 8, 2011 at 7: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.
    – user562566
    Commented Dec 8, 2011 at 12:25
  • 4
    @AscensionSystems: here is the latest bench I am aware of comparing gcc 4.6 to llvm 3.0 which shows a net advantage of gcc in average. Also interesting may be the DragonEgg bench, DragonEgg is a plugin that allows using the gcc front-end (and possibly optimizer) and then the LLVM backend to generate the code. Commented Dec 8, 2011 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. Commented Feb 11, 2012 at 14:45
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.

3
  • 3
    Here is the latest Phoronix article comparing GCC 4.6 vs Clang 3.0 as well as a previous article 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. Commented Nov 21, 2011 at 7:50
  • Why not use both? Clang for development, and GCC for production.
    – segfault
    Commented Jan 2, 2013 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
    Commented Jan 3, 2013 at 1: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.

3
  • 1
    What are your thoughts on using clang for debug builds but gcc for optimised releases?
    – Olical
    Commented Dec 10, 2012 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). Commented Dec 12, 2012 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
    Commented Dec 13, 2012 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

2
  • I use OpenMP as well but I am thinking of switching to TBB which I guess would work with Clang.
    – user2088790
    Commented May 25, 2013 at 8: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
    Commented Feb 1, 2014 at 2: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.

10
  • 9
    gcc should generally be invoked with at least -Wall, which does warn for this program. clang does produce good warnings/errors, though.
    – caf
    Commented Nov 21, 2011 at 0: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
    Commented Nov 21, 2011 at 0: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
    Commented Nov 21, 2011 at 0:14
  • 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, for C++.
    – Kerrek SB
    Commented Nov 21, 2011 at 8:18
  • 1
    This program shouldn't produce errors or warnings. It conforms to the standard.
    – mrr
    Commented Jan 11, 2013 at 9:20
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.

4
  • 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
    Commented Jun 24, 2013 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
    Commented Apr 16, 2014 at 5:33
  • 2
    a+++++a should fail, as it's parsed as a ++ ++ + a which is a syntax error.
    – mrr
    Commented May 31, 2014 at 1: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. Commented Aug 9, 2017 at 5:36

Not the answer you're looking for? Browse other questions tagged or ask your own question.