GCC, Clang, and MSVC compilers with C++
Perfect Match
![](/var/linux_magazin/storage/images/issues/2018/207/compilers-and-standards/coverstoryimage-2_207.png/720324-1-eng-US/CoverStoryImage-2_207.png_medium.png)
Due to the fast pace of updates of the C++ standards, compiler builders have been busy. How do the most popular compilers fit with the standards and what are the differences?
The quiet times are over for C++. A full 13 years passed between the C++98 and C++11 standards, but since then, new standards have appeared every three years, with C++14, C++17, and preliminary work on C++20. The C++ standardization committee already shows signs of enthusiasm for the next cycle.
With so many versions of C++ out in the world (see the "Blessings of Diversity" box), a developer could easily wonder, how do the compiler makers keep up with it all? This article looks at support for C++ standards in three popular compiler alternatives:
- GCC: The GNU Compiler Collection (GCC) [1] is the quintessential free software compiler. Originally created by Richard Stallman in 1987 as the compiler for the GNU project, GCC is now supported by a large community of developers and is found on almost all Linux distributions.
- Clang: This popular free compiler collection [2] uses the LLVM compiler as a back end. Clang is actually the front-end component. Clang/LLVM is designed for a high degree of compatibility with GCC. The Clang project enjoys the support of several major vendors, including Apple, Google, Microsoft, Intel, and AMD, possibly because they find Clang's permissive free software license easier to integrate with commercial projects than the GPL3 license attached to GCC.
- MSVC: This compiler is for Microsoft's Visual C++ (MSVC) environment [3]. In the past, Linux support in a major Microsoft development tool would have been unthinkable, but today, versions of MSVC run on Linux, and extensions are available for developing Linux applications on MSVC.
Blessings of Diversity
Some may wonder why so many different compilers exist. The fact that many computer architectures exist is only half the answer. The rest of the answer is that different compilers have different distinguishing features.
All three major compilers run on the x86 architecture, and each of the three has a special area in which it impresses. The Clang compiler scores points with understandable error messages and an open architecture that supports many powerful tools. GCC is distinguished by the fact that it supports most hardware architectures and is consequently gaining in importance in the embedded world with the GNU ARM Embedded Toolchain [4]. For MSVC, integration with Visual Studio adds massive value for many C++ developers.
Ultimately, this diversity in compilers is a blessing for all C++ developers. Each of the three compilers sets standards and, at the same time, sets the bar higher for the others. The fact that the compilers continue to compete for developers' favor will ultimately benefit the developers at the end of the day.
In this article, you'll also learn about some online compiler front ends that let you test your code for different compilers and standards, which often leads to valuable insights, optimizations, and troubleshooting tips.
Compilers and Standards
An estimated 95 percent of all C++ developers rely on the GCC, Clang, or MSVC compilers. The timeline in Figure 1 shows the existing C++ standards, with the exception of C++03, which was only released as a bug fix for C++98 in 2003. This article focuses on C++11, C++14, and C++17. I will avoid looking back (C++98) or into the future (C++20).
Table 1 shows which compiler versions support the C++11, C++14, and C++17 standards.
Table 1
Compiler Support
C++ Compiler | C++11 | C++14 | C++17 |
---|---|---|---|
GCC |
4.8.1 |
5.0 |
7 |
Clang |
3.3 |
3.4 |
5 |
MSVC |
19.0 |
19.1 |
19.1(in part) |
The table refers to support for the C++ core language. Sometimes that support is only partially complete. MSVC 19.1, for instance, only partially supports C++17, and this support requires the third update. Tables 2 and 3 show all the details of C++17 support [5].
Table 2
C++17 Support (Part 1)
C++17 Features | Paper | Version | GCC | Clang | MSVC |
---|---|---|---|---|---|
New auto rules for direct-list-initialization |
N3922 |
c++17-lang |
5 |
3.8 |
19.0 |
|
N3928 |
c++17-lang |
6 |
2.5 |
19.1 |
Typename in a template template parameter |
N4051 |
c++17-lang |
5 |
3.5 |
19.0 |
Removing trigraphs |
N4086 |
c++17-lang |
5.1 |
3.5 |
16.0 |
Nested namespace definition |
N4230 |
c++17-lang |
6 |
3.6 |
19.0 |
Attributes for namespaces and enumerators |
N4266 |
c++17-lang |
4.9 (Namespaces), 6 (Enumerators) |
3.6 |
19.0 |
|
N4267 |
c++17-lang |
6 |
3.6 |
19.0 |
Allow constant evaluation for all non-type template arguments |
N4268 |
c++17-lang |
6 |
3.6 |
no |
Fold expressions |
N4295 |
c++17-lang |
6 |
3.6 |
no |
Remove deprecated use of the register keyword |
P0001R1 |
c++17-lang |
7 |
3.8 |
19.1 |
Remove deprecated |
P0002R1 |
c++17-lang |
7 |
3.8 |
19.1 |
Removing deprecated exception specifications from C++17 |
P0003R5 |
c++17-lang |
7 |
4 |
no |
Make exception specifications part of the type system |
P0012R1 |
c++17-lang |
7 |
4 |
no |
Aggregate initialization of classes with base classes |
P0017R1 |
c++17-lang |
7 |
3.9 |
no |
Lambda capture of |
P0018R3 |
c++17-lang |
7 |
3.9 |
19.1 |
Using attribute namespaces without repetition |
P0028R4 |
c++17-lang |
7 |
3.9 |
19.1 |
Dynamic memory allocation for over-aligned data |
P0035R4 |
c++17-lang |
7 |
4 |
no |
Unary fold expressions and empty parameter packs |
P0036R0 |
c++17-lang |
6 |
3.9 |
no |
|
P0061R1 |
c++17-lang |
5 |
yes |
19.1 |
Table 3
C++17-Support (Part 2)
C++17 Features | Paper | Version | GCC | Clang | MSVC |
---|---|---|---|---|---|
Template argument deduction for class templates |
P0091R3 |
c++17-lang |
7 |
5 |
no |
Non-type template parameters with auto type |
P0127R2 |
c++17-lang |
7 |
4 |
no |
Guaranteed copy elision |
P0135R1 |
c++17-lang |
7 |
4 |
no |
New specification for inheriting constructors (DR1941 et al) |
P0136R1 |
c++17-lang |
7 |
3.9 |
no |
Direct-list-initialization of enumerations |
P0138R2 |
c++17-lang |
7 |
3.9 |
19.1 |
Stricter expression evaluation order |
P0145R3 |
c++17-lang |
7 |
4 |
no |
|
P0170R1 |
c++17-lang |
7 |
5 |
19.1 |
Differing begin and end types in range-based for |
P0184R0 |
c++17-lang |
6 |
3.9 |
19.1 |
|
P0188R1 |
c++17-lang |
7 |
3.9 |
19.1 |
|
P0189R1 |
c++17-lang |
7 |
3.9 |
19.1 |
Pack expansions in using-declarations |
P0195R2 |
c++17-lang |
7 |
4 |
no |
|
P0212R1 |
c++17-lang |
7 |
3.9 |
19.1 |
Structured bindings |
P0217R3 |
c++17-lang |
7 |
4 |
19.1 |
Hexadecimal floating-point literals |
P0245R1 |
c++17-lang |
3 |
yes |
no |
Ignore unknown attributes |
P0283R2 |
c++17-lang |
yes |
3.9 |
no |
|
P0292R2 |
c++17-lang |
7 |
3.9 |
19.1 |
Init-statements for |
P0305R1 |
c++17-lang |
7 |
3.9 |
19.1 |
Inline variables |
P0386R2 |
c++17-lang |
7 |
3.9* |
no |
DR: Matching of template template-arguments excludes compatible templates |
P0522R0 |
c++17-lang |
7 |
4 |
no |
Standardization of parallelism TS |
P0024R2 |
c++17 |
|
|
no |
|
N4259 |
c++17 |
6 |
3.7 |
19.0 |
Splicing maps and sets |
P0083R3 |
c++17 |
7 |
|
no |
Improving |
N4387 |
c++17 |
yes |
4 |
19.0 |
Improving |
N4387 |
c++17 |
yes |
4 |
19.0 |
Elementary string conversions |
P0067R5 |
c++17 |
|
|
no |
|
N3921 |
c++17 |
7 |
4 |
19.1 |
If you are not satisfied with the information provided on the big three compilers, or if you are interested in the C++ compilers that other Unix platforms have to offer, you can also find more detailed information on the current C++ standards at the C++ Reference website [5].
Support for the C++ standard library (STL) varies a little. There is currently no implementation of the parallel STL in C++17. You have to do some tinkering work to find a solution: The High Performance Parallex (HPX) library [6], for instance, is a framework for parallel and distributed applications that already implements the parallel STL.
Important Compiler Flags
In order to use the correct C++ standard, you need to specify it for GCC or Clang. Both support the same flags. Thus the
g++ -std=c++11 dataRace.cpp
call compiles the dataRace.cpp
file source code according to the C++11 standard. You can also specify C++14 or C++17. This step is not necessary for newer versions of GCC and Clang, but not all compiler-to-C++ standard combinations can cope without this specification, and it will not do any harm to specify. MSVC does not require you to specify the C++ standard.
There are some other interesting compiler flags for developers. For example, -O3
(for GCC and Clang) and /Ox
(for MSVC), for example, generate a maximum optimized program, and -Wall
(for GCC and Clang) or /Wall
(for MSVC) set the maximum warning level.
Sanitize
Sanitizer [7], a tool that checks whether the code correctly uses addresses, threads, and memory, has been available since GCC 4.8 and Clang 3.2. MSVC users will have to try their luck with a Windows port [8].
A small example will help illustrate the power of the Thread Sanitizer [9]. The program in Listing 1 contains code that can clearly lead to a race condition, since several threads access the globalVal
variable at the same time. More precisely, both threads try to change the variable at the same time.
Listing 1
A Simple Race Condition
Compile Thread Sanitizer into GCC and Clang by using the -fsanitize=thread
flag:
g++ -std=c++11 dataRace.cpp -fsanitize=thread -pthread -g -o dataRace
then run the program compiled here with GCC; it will generate output that identifies the potential race condition (Figure 2). At the end, the output also shows the sequence of the built-in data race.
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
![Learn More](https://www.linux-magazine.com/var/linux_magazin/storage/images/media/linux-magazine-eng-us/images/misc/learn-more/834592-1-eng-US/Learn-More_medium.png)
News
-
NVIDIA Released Driver for Upcoming NVIDIA 560 GPU for Linux
Not only has NVIDIA released the driver for its upcoming CPU series, it's the first release that defaults to using open-source GPU kernel modules.
-
OpenMandriva Lx 24.07 Released
If you’re into rolling release Linux distributions, OpenMandriva ROME has a new snapshot with a new kernel.
-
Kernel 6.10 Available for General Usage
Linus Torvalds has released the 6.10 kernel and it includes significant performance increases for Intel Core hybrid systems and more.
-
TUXEDO Computers Releases InfinityBook Pro 14 Gen9 Laptop
Sporting either AMD or Intel CPUs, the TUXEDO InfinityBook Pro 14 is an extremely compact, lightweight, sturdy powerhouse.
-
Google Extends Support for Linux Kernels Used for Android
Because the LTS Linux kernel releases are so important to Android, Google has decided to extend the support period beyond that offered by the kernel development team.
-
Linux Mint 22 Stable Delayed
If you're anxious about getting your hands on the stable release of Linux Mint 22, it looks as if you're going to have to wait a bit longer.
-
Nitrux 3.5.1 Available for Install
The latest version of the immutable, systemd-free distribution includes an updated kernel and NVIDIA driver.
-
Debian 12.6 Released with Plenty of Bug Fixes and Updates
The sixth update to Debian "Bookworm" is all about security mitigations and making adjustments for some "serious problems."
-
Canonical Offers 12-Year LTS for Open Source Docker Images
Canonical is expanding its LTS offering to reach beyond the DEB packages with a new distro-less Docker image.
-
Plasma Desktop 6.1 Released with Several Enhancements
If you're a fan of Plasma Desktop, you should be excited about this new point release.