Want to read Slashdot from your mobile device? Point it at m.slashdot.org and keep reading!

 



Forgot your password?
typodupeerror
×
Programming IT

Developing In C/C++? Why You Should Consider Clang Over GCC (dice.com) 255

Nerval's Lobster writes: The idea with Clang, a compiler front-end for C, C++, Objective-C++, and Objective-C, and LLVM (a compiler infrastructure) is that you can mix the compiler front-end with a targeted back-end and end up with highly portable and efficient compiler. Clang can perform static analysis of your code, and lets you write tools that give you information about a program. Although many developers prefer developing in C/C++ using GCC, developer David Bolton (in a new Dice article) makes an argument for why you should switch to Clang. While GCC is probably still best when it comes to speed, he argues, Clang is improving release by release, and features tools that developers could find useful.
This discussion has been archived. No new comments can be posted.

Developing In C/C++? Why You Should Consider Clang Over GCC

Comments Filter:
  • Translation (Score:3, Insightful)

    by RightwingNutjob ( 1302813 ) on Monday December 07, 2015 @08:52PM (#51077333)

    While GCC is probably still best when it comes to speed, he argues, Clang is improving release by release, and features tools that developers could find useful

    Translation: "network tran--I mean speed is a feature that most of our users don't need, so it's not in our development plan"

    • Re:Translation (Score:5, Informative)

      by ShanghaiBill ( 739463 ) on Monday December 07, 2015 @09:11PM (#51077425)

      Translation: "network tran--I mean speed is a feature that most of our users don't need, so it's not in our development plan"

      No. Clang produces faster code [phoronix.com]. What TFA means is that GCC compiles faster. But if slightly faster compiles are that important, just turn off the optimizer, or buy a faster computer. How much time does a modern developer spend waiting for the compiler to finish? For me, it is less than 1%. Far more important is the better error messages, warnings, and static analysis from Clang. Those save me way more time than the speed of the compiler.

      • by Shados ( 741919 )

        How much time does a modern developer spend waiting for the compiler to finish

        In C/C++? All the freagin time. Large applications can take -forever- to compile, even if its not a clean compile.

        • Re:Translation (Score:5, Informative)

          by ShanghaiBill ( 739463 ) on Monday December 07, 2015 @09:38PM (#51077569)

          Large applications can take -forever- to compile, even if its not a clean compile.

          Many complaints about slow compiles are due to dysfunctional workflow. You should be using precompiled headers, and set up your makefiles for multiple cores. But most importantly, you should be using TDD to develop and debug code outside of the application. So instead of compiling and linking the entire application repeatedly as you track down a bug, you only integrate after all your unit tests are written and passed in isolation.

          But, anyway, it isn't clear that Gcc actually compiles faster than Clang. Here are some benchmarks [phoronix.com], and the results are mixed. Sometimes Clang is faster, sometimes Gcc is faster. For a large app, they would likely be about even in compile time. But Clang would likely generate better code, and almost certainly generate more helpful errors/warnings/analysis.

          I can't see any rational reason to prefer Gcc.

        • by mikael ( 484 )

          I've seen cross-compile builds of large code bases of 2 million+ lines take 10 minutes. Change one header file of a low-level module, and the whole stack has to be rebuilt. Just because BaseClassA has had a new boolean flag added, DerivedClassB to DerivedClassJ have to be recompiled along with container classes, interface classes, then the GUI layer with custom widgets, the plugins for third-party editors, the dynamic linked libraries, and finally the application itself.

          • by Yokaze ( 70883 ) on Tuesday December 08, 2015 @02:45AM (#51078819)

            If you are running into that issue often, consider the Pimpl-pattern.

            As always, C++ doesn't take the decision away from you. If you cannot live with the overhead in runtime from one pointer indirection, you have to live with the other downside.

            From my standpoint and experience, most compile time issues were due to people putting things into the headers out of convenience.
            In order to save some forward declarations or pimpl implementations, things were put into the header, which caused constant recompiles,and long compile times.

        • C++ (in GCC at least) is vastly slower than C, for the same input source. That's without doing the complicated stuff. You can speed a lot of with parallel builds, but a lot of people don't set up their build systems to make that easy (just passing -j to a recursive make can break).

          A decade ago I had an 18 hour build. So bad that people would start shouting if someone tweaked a major header file. Much of the slowdown was from the commercial compiler, and part of the slowdown was by using Visual Studio as

      • by epyT-R ( 613989 )

        No. Sometimes Clang produces faster code. Read the rest of that review.

      • G++ versus Clang++ (Score:5, Informative)

        by ShakaUVM ( 157947 ) on Monday December 07, 2015 @11:23PM (#51078223) Homepage Journal

        >better error messages, warnings, and static analysis from Clang. Those save me way more time than the speed of the compiler.

        This is the truth. Ain't nobody got time to read through a hundred lines of error messages to track down a single bug.

        As a simple test, I wrote the following code which has a simple mistake (using an integer instead of an int array in a range-based for loop):

        test.cc:

        #include
        int main() {
                int x = 0;
                for (int i: x) std::cout constexpr const _Tp* std::end(std::initializer_list)
                  end(initializer_list __ils) noexcept"

        2 lines for a single straightforward error in clang++ 3.7 (with colors even!):

        "test2.cc:5:12: error: invalid range expression of type 'int'; no viable 'begin' function available
                        for (int i: x) std::cout i;"

        I currently use g++ with new programmers, and will be switching soon to clang++.

        Plus Clang does cool things like interoperate with things like YouCompleteMe to do real time compiling and error message generation for syntax completion in VIM.

        • (Sigh, Slashdot. Stop eating code snippets in Plain Old Text mode. This is a place for geeks.)

          Here's the code that generated the bug, without Slashcode mangling it:

          int x;
          for (int i: x) std::cout i;

          109 lines of error messages in g++, 2 lines in clang++

          • I'd be willing to bet that there's supposed to be less-than or greater-than symbols in there. Slashcode helpfully treats them as some sort of html tag, and ignores what it doesn't recognize.

        • My previous job we used C++ with template heavy usage and I ended up being the unofficial translator of G++ error messages. This is really the only part of GCC I dislike (and it's only on the C++ side which I'm not using now).

        • If you're marvelling over clang producing coloured error messages, then you're using an old version of gcc. Try switching to something in the new gcc-5 series. Contrary to popular belief, it's quite slow, but not hard to compile. Also, many distros have gcc-5 packages available.

          PS, both versions of your code got mangled, so I can't see what you're referring to precisely.

      • Comment removed based on user account deletion
        • ... sources ... on a RAM disk.

          Whenever anybody loses a fair chunk of a day's work due to a crash / power failure / other dumbass mistake, I always advise them "it's easier the second time around."

          Nobody ever appreciates the advice.

          • Oh yeah. Get an SSD.
          • Comment removed based on user account deletion
          • by DamonHD ( 794830 )

            Been there, done that (because of a sysamdin who thought that doing diagrams with pretty pictures was MUCH more important than doing backups for any of my team for many weeks, on one occasion) and you know what?

            You're right!

            Rgds

            Damon

            PS. Not that I advocate it as normal workflow for the sake of everyone's blood pressure for a start!

        • Have you benchmarked it recently? I tried this on our build machines (32 cores, 256GB of RAM, 512GB SSD split mostly as L2ARC with a small amount as log device, 3TB spinning rust in a ZFS mirror) a while ago. The amount of I/O that actually goes to the spinning rust is tiny (object files are written out, but never read back), pretty much all I/O comes from the buffer cache. Putting it on a RAM drive reduced the writes, but there's no synchronisation required for them so they never became a bottleneck. I

    • Re:Translation (Score:5, Insightful)

      by Darinbob ( 1142669 ) on Tuesday December 08, 2015 @03:57AM (#51078945)

      Apple migrated over to Clang, but they left a bastardized GCC in it's place as a "transition". The preprocessor swears up and down that it's GCC but if you use inline assembler it barfs. So it's basically lying. It's a GCC front end and LLVM back-end, and the solution is to manually install a real GCC in its place (easier than porting the code, easier than ifdef OSX vs Linux, etc). And it's a major pain in the ass for new developers to set up a development environment, and inevitably someone eventually screws up their PATH to pick up the broken compiler...

      Anyway screw it. Clang may be ok, but there's production code that assumes GCC, it's cross-platform code so having stability on x86 doesn't necessarily mean anything about all those other CPUs that GCC supports well. Ie, GCC supports ARM, and ARM supports GCC, so if I go to the team and say "hey guys, I'm going to mix things up for a few months and try out a different compiler, things might break unexpectedly but in the long run you might like it, what do you think?" then I won't get positive feedback.

      Until there are drawbacks to GCC there's no much reason to change.

      • GCC supports ARM, and ARM supports GCC

        ARM has a lot more people working on LLVM than they do on GCC and they're slowly transitioning everything across. Their customers fell into two categories: ones that don't care about the license and ones that won't touch GPLv3. If you want a compiler with long-term support for ARM, then GCC probably isn't your best bet.

  • by Anonymous Coward on Monday December 07, 2015 @08:55PM (#51077343)

    Compile in both. And visual studio too if possible. Enable all warnings. They are all good at identifying different categories of problems and code that compiles cleanly under multiple compilers will prove easier to maintain.

  • by Anonymous Coward on Monday December 07, 2015 @08:55PM (#51077347)

    I strongly recommend Clang. It's speed is about on par with GCC, but the output and syntax checking is so much better. I tried it a bit a few years back and I have been hooked on Clang since. Using GCC feels like a big step backward now because it's so fussy and its warnings are so cryptic in comparison.

    • by lgw ( 121541 )

      I strongly recommend Clang. It's speed is about on par with GCC, but the output and syntax checking is so much better. I tried it a bit a few years back and I have been hooked on Clang since. Using GCC feels like a big step backward now because it's so fussy and its warnings are so cryptic in comparison.

      Last time I looked, Clang didn't recognize idiomatic "rotate", e.g.:
      (x << 3) | (x >> 29)
      That should compile to a single opcode, dammit. Anyone know if that problem is still there.

      • On what processor would that be a single opcode? I'm curious.

        • Assuming 'uint32_t x' and ignoring any needed shuffling to load 'x' into the appropriate processor register, any 32-bit processor with a native bit rotation instruction.
          • But you fail to give an example ;D
            Which opcode, on an x86 e.g. can rotate left and right simultaniously and OR the two results together: simultaniously? Feel free to pick a different architecture. Not even on an ARM you can do that in one opcode.

            • I see the problem. GP didn't write the complete bitwise rotation idiom but I knew what they meant whereas you're evaluating it exactly as written. This is what I'm referring to and what GP was almost certainly trying to refer to as well. https://en.wikipedia.org/wiki/... [wikipedia.org]
              • Ah, I'm coming closer to it. But I have not grasped it yet.
                I shift left 3 times and or the result with the same register shifted right 29 times, both together is a rotate? Never thought about that. I have to test that on paper, does not really look plausible on the first attempt.

                • Sounds like you've got the gist of it. C only has a bitwise shift (where the end that the shift would "empty" is filled with zeroes for unsigned integers), not a bitwise rotate (ex. 00001011 rotated right by 2 becomes 11000010), so the closest thing to saying "bitwise rotate this" is using a set of expressions that would have the same behavior. Since a bitwise rotate is the same as splitting the binary number into two parts (of sizes determined by the desired rotation amount) you just have to create the two

        • SHL and SHR...been a long time since I used them, but pretty sure they will still be around.

          • You missed the parent:
            He claimed that instant of
            LDC R1 #value1
            LDC R2 #value2
            SHR R1,something
            SHL R2,something
            OR R3,R1,R2

            You can do the above in a single opcode ... it is beyond me how he would do that or if that is possible because the constants in his example are "special".

            Assuming the registers R1 and R2 already hold the values in question: you need minimum 3 opcodes or a special architecture like ARM, but on an ARM I believe you minimum would need 2 opcodes.

      • Actually, that should compile to a single opcode only if x is a 32-bit unsigned integer.
      • Re: (Score:2, Informative)

        by Anonymous Coward

        $ cat rol3.c

        #include <stdint.h>
        uint32_t rol3(uint32_t x) {
        return (x << 3) | (x >> 29);
        }

        $ gcc -c rol3.c
        $ objdump -d rol3.o

        0000000000000000 <rol3>:
        0: 55 push %rbp
        1: 48 89 e5 mov %rsp,%rbp
        4: 89 7d fc mov %edi,-0x4(%rbp)
        7: 8b 45 fc mov -0x4(%rbp),%eax
        a: c1 c0 03 rol $0x3,%eax
        d: 5d pop %rbp
        e: c3 retq

        $ gcc -O1 -c rol3.c
        $ objdump -d rol3.o

        0000000

    • by mikael ( 484 )

      You can put function calls inside a switch statement but outside the case statements in gcc. Does that happen in Clang? Even old Borland C++ compilers from 1990's would catch that one.

    • fussy? What do you mean? They both pretty much support the entire standard very well. If gcc is failing to accept code, you're probably doing something non standard tha clang has as an extension.

  • When people say gcc beats clang on speed, so they mean compile speed or run-time speed?
    • by Chris Mattern ( 191822 ) on Monday December 07, 2015 @09:07PM (#51077401)

      If I can be modded down for being a troll, can I be modded up for being an orc, or a balrog?

      Nope, those still get you modded down. To be modded up, you'll need to be an elf or a hobbit...

      • If I can be modded down for being a troll, can I be modded up for being an orc, or a balrog?

        Nope, those still get you modded down. To be modded up, you'll need to be an elf or a hobbit...

        I hear you can also get modded up for being an ent, but it can take years.

  • One neat thing about LLVM/clang is that theoretically you could provide your application as IR files, which can be flattened to machine-specfic code on the fly by a platform-specific backend.

    I think at some point it was fast enough to generate that code on the fly. I vaguely remember Apple doing that with its OpenGL stuff.

    • by sribe ( 304414 )

      I vaguely remember Apple doing that with its OpenGL stuff.

      CoreImage transforms.

    • I think at some point it was fast enough to generate that code on the fly.

      Many interpreters are embedding LLVM for JIT these days.

    • One neat thing about LLVM/clang is that theoretically you could provide your application as IR files, which can be flattened to machine-specfic code on the fly by a platform-specific backend.

      Is this a relatively new feature? The last time I looked at LLVM IR for this purpose, there was no general "pointer-sized" data type that could accomplish this. It would be really cool if this were no longer the case.

      • Chrome's PNaCl defines a stable sub-set of LLVM IR, targeting a generic little-endian 32-bit CPU.
      • The grandparent is partly right. You can do this for microarchitectural optimisations. I believe that Apple now does this for their app store: if you upload the app as LLVM IR then they will generate versions specialised for each of the ARM cores that they've shipped. This can be quite a big difference (costs of different vector operations on different cores means that you can have quite different decisions in the autovectoriser, for example). You can't do it for different architectures, even if LLVM IR
  • Use both (Score:2, Interesting)

    by Anonymous Coward

    To make sure my code is not using any compiler features I compile my code on both.

  • Does Clang compile to intermediate formats, such as Bytecode or any other formats? On the GCC side, I believe that the FSF (read RMS) is opposed to it

    • You mean, like GIMPLE?

    • by dmoen ( 88623 )

      Clang can compile to the LLVM "IR" format, which is a mostly machine-independent Intermediate Representation. Kind of like bytecode.

      The IR file format has two variations: a human readable text format, and a more compact binary format.

      Given an IR file, you can optimize it, which produces another IR file, or you can compile it into an object file.

      • LLVM "IR" format, which is a mostly machine-independent Intermediate Representation

        LLVM IR is target agnostic, not target independent. The format itself is the same across all targets, but various things (e.g. calling conventions - how you split structs between registers and the stack) will be different for different targets.

  • by danbob999 ( 2490674 ) on Monday December 07, 2015 @09:23PM (#51077491)

    Isn't LLVM/clang all about the license (non-GPL)? Otherwise if clang is good, then we should fork it and make a GPL version of it.

    • Re:License (Score:5, Informative)

      by dmoen ( 88623 ) on Monday December 07, 2015 @10:10PM (#51077791) Homepage

      No, LLVM/clang is all about having a superior architecture to GCC, so that a lot of new applications become possible. One of the key ideas is that the optimizer and code generator are libraries with a C++ API. One cool application of this is that you can use the LLVM library to implement a JIT compiler for your interpreted language: you generate the machine code directly into memory (instead of to a file), then execute it.

      LLVM has many more developers than GCC, and is evolving and improving more quickly than GCC can. This is because of the licence: it turns out that corporations like Apple are more willing to provide developer resources for this open source project if the licence isn't copyleft. For this particular project, this means that the BSD license is more successful than the GPL. Of course, there are other projects for which the GPL produces better results in the real world.

      If you want to make a GPL fork of LLVM just for the pure pleasure of fucking over the original project due their heresy in choosing a license you don't approve of, well, good luck with that.

      • Re:License (Score:5, Interesting)

        by phantomfive ( 622387 ) on Monday December 07, 2015 @11:43PM (#51078295) Journal

        This is because of the licence: it turns out that corporations like Apple are more willing to provide developer resources for this open source project if the licence isn't copyleft.

        That's not really true, Apple contributed to GCC for years before LLVM. The problem was that Apple wanted features, and GCC wouldn't allow those features to be built. So finally Apple just gave up and built their own.

        This is the rule of running an open source project (and Linus does a really good job of it): give users what they want, or the users will leave.

        • Re:License (Score:4, Informative)

          by tlhIngan ( 30335 ) <slashdot.worf@net> on Tuesday December 08, 2015 @03:24AM (#51078883)

          This is because of the licence: it turns out that corporations like Apple are more willing to provide developer resources for this open source project if the licence isn't copyleft.

          That's not really true, Apple contributed to GCC for years before LLVM. The problem was that Apple wanted features, and GCC wouldn't allow those features to be built. So finally Apple just gave up and built their own.

          This is the rule of running an open source project (and Linus does a really good job of it): give users what they want, or the users will leave.

          True, but Apple could also see the writing on the wall with the GPLv3 and what that could mean to their use of the compiler. Which is also why they poured a lot of effort into LLVM and wrote clang. This effort dated way back too - the earliest versions of OS X that started coming out with LLVM as an option was around the 10.4 era.

          A lot of companies saw what the GPLv3 was bringing to the table, and they didn't like it, so they moved on. Some, like Apple, realized they could stick around and fight with GCC and GPLv3, or work on an alternative.

          GCC is deliberately obtuse as well - Apple wanted a nice front end to help parse and recompile code in real time, and GCC is intentionally twisty to prevent that (and if you want to write a parser for code, why not reuse what the compiler actually uses?). LLVM is more modular and makes it easier to integrate with an IDE

          And in the end, I think having the diversity we do in compilers is refreshing - even if you hate LLVM with a passion, at least it's also brought forth development on GCC, which seems to have a history of stalling in development before someone else decides to fork it, revamp things, and have the fork become the official GCC.

          FYI - the very last checkin to GCC by Apple was related to Grand Central Dispatch to the Obj-C compiler - basically about blocks.

          • Why GCC is deliberately obtuse?
        • The problem was that Apple wanted features, and GCC wouldn't allow those features to be built. So finally Apple just gave up and built their own.

          This was not the issue. Apple maintained their own branch of GCC in the FSF's svn repository for a long time. Lots of features (e.g. blocks support, some Objective-C features) never made it back into the FSF's branch, but this was not a problem for Apple. The problem was that GCC could not be used, for both technical and legal reasons, in some of the places where Apple wanted to use it. Syntax highlighting was one simple example. GCC does constant folding in the front end, so by the time that you have

        • Apple started LLVM due to GPL v3. If you know anything about why they switched, that much is obvious ... being that they flat out said thats why they were switching among other things.

  • From up-close-and-personal experience with Objective C and C++ (also Smalltalk), these languages have substantially different semantics regarding class identity (primarily: what version of overridden member functions you get) during construction and destruction. I wouldn't be surprised if Objectivce-C++ had yet another semantics, pulling "features" from both, and I have no clue about LVMM.)

    Building a frontend to compile to them, interchangeably, is a recipe for subtle bugs, if the frontend doesn't deal with these issues. Efficiency may go out the window if the frontend tries to impose one language's construction/destruction semantics on another. Doing so also brings up the issue of which semantics the compiler exposes to the programmer - each has its good and bad points, and each enables different - and incompatible - useful programming features.

    I'd be interested in what (if anything) Clang has done about this issue. (Unfortunately, I'm busy on other stuff, so I'll have to depend on others to elucidate this.)

    • Evidence? (Score:4, Interesting)

      by mveloso ( 325617 ) on Monday December 07, 2015 @10:08PM (#51077779)

      I would think that if these subtle bugs exist they'd be caught by the test suites. Do you have any actual evidence of these subtle bugs?

      • No, the trouble is that you just cannot implement an efficient garbage collector in C/++. So Java and .Net do their own compiling. C is only efficient if you think "C".

    • From up-close-and-personal experience with Objective C and C++ (also Smalltalk), these languages have substantially different semantics regarding class identity (primarily: what version of overridden member functions you get) during construction and destruction. I wouldn't be surprised if Objectivce-C++ had yet another semantics, pulling "features" from both, and I have no clue about LVMM.)

      Objective-C++ mixes the syntax of the two languages, and allows you to use either a C++ object or an Objective-C object at will, however it does not make C++ objects into Objective-C objects or vice versa. Any semantics relating to C++ objects still applies to C++ objects, and no additional semantics are implied.

      In short: things work as you'd expect, and there are no hidden gotchas.

      The only real complexities are what happens when you embed a C++ object as a member inside an Objective-C object (this doesn't

  • Once I checked, clang was not good at generating vector instructions from simple loops. Unless it has improved lately, that would be a show stopper for a class of code.

    • It's been hugely improved in the last couple of releases. Linaro did quite a bit of work on the vectoriser, as did Apple.
  • I periodically run both just to get the warnings that each is able to provide. And I clean up all warnings, even if I know that they are harmless, so I won't miss a blunder buried in the noise. Turning on all warnings has saved me from having to chase down more bugs than I care to admit. gcc *.c -o xxx -O -Wall -Wextra -Wmissing-prototypes \ -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-align \ -Wredundant-decls -Wnested-externs -Winline \ -Wno-long-long -Wconversion -Wstrict-prototypes -ansi -
    • Damn, picked wrong formatting.

      gcc *.c -o xxx -O -Wall -Wextra -Wmissing-prototypes \ -Wmissing-declarations -Wshadow -Wpointer-arith -Wcast-align \ -Wredundant-decls -Wnested-externs -Winline \ -Wno-long-long -Wconversion -Wstrict-prototypes -ansi -pedantic

      clang *.c -o xxx -Wall -Wextra

  • I care how fast my compiler compiles (as long as it's not insane) about as much as I care how fast my system boots (as long as it's not insane).

    Seriously. Whatever planet you weird devs came from, can you return to it? (And take Lennart with you?)... Spend your free time re-optimizing your cut-and-paste chef recipes or something, and leave the engineering to the rest of us?

  • by Gravis Zero ( 934156 ) on Tuesday December 08, 2015 @02:54AM (#51078841)

    while clang is probably fine for most projects, if your project needs -std=c++14 then you should be warned that sometimes Clang can't properly deduce (even when you are explicit) variadic template parameters.

    for example, this code will not compile on Clang no matter what but works fine with G++.

    template<typename... ArgTypes> using deeper = void(*)(ArgTypes...);
    template<typename... ArgTypes> void shallow(deeper<ArgTypes...> arg) { }

    int main(int argc, char* argv[])
    {
        deeper<int> arg;
        shallow<int>(arg);
        return 0;
    }

  • the guy who developed clang - Chris Lattner - also wrote swift.

    he first modernized the architecture of the compiler, and then wrote a better language on top of it that is capaable of doing system level things like C++ with a cleaner semantic style.

    ++

Math is like love -- a simple idea but it can get complicated. -- R. Drabek

Working...