Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to tell Clang to stop pretending to be other compilers?

Tags:

I've run into this issue in the past: LLVM defines __GNUC__, but it can't consume a program GCC can. I'm experiencing it again on Windows: LLVM defines _MSC_VER, but it can't consume the same program VC++ can. The aggravating thing (for me) is we have specialized code paths for LLVM Clang and Apple Clang (different defines due to different version schemes), and we have to fight with the tool to get it to use them.

How do we tell Clang to stop pretending to be other compilers? Is there a switch or option to do it?


The Clang docs discuss the unwanted MS behavior, but they don't say how to stop it:

For compatibility with existing code that compiles with MSVC, clang defines the _MSC_VER and _MSC_FULL_VER macros. These default to the values of 1800 and 180000000 respectively, making clang look like an early release of Visual C++ 2013. The -fms-compatibility-version= flag overrides these values. It accepts a dotted version tuple, such as 19.00.23506. Changing the MSVC compatibility version makes clang behave more like that version of MSVC. For example, -fms-compatibility-version=19 will enable C++14 features and define char16_t and char32_t as builtin types.

like image 893
jww Avatar asked Jul 21 '16 08:07

jww


People also ask

How do I use GCC instead of Clang?

If you want to use clang instead of GCC, you can add -DCMAKE_C_COMPILER=/path/to/clang -DCMAKE_CXX_COMPILER=/path/to/clang++ . You can also use ccmake , which provides a curses interface to configure CMake variables.

Can Clang compile itself?

Clang C++ can parse GCC 4.2 libstdc++ and generate working code for non-trivial programs, and can compile itself.

Why is GCC using Clang?

Clang is a C, C++, Objective-C, or Objective-C++ compiler that is compiled in C++ based on LLVM and released under the Apache 2.0 license. Clang is mainly used to provide performance superior to that of GCC. Through long-term development and iteration, GCC, Clang, and LLVM have become mature compilers in the industry.

Does Google use Clang or GCC?

Since a few months back Google switched from GCC to Clang for compiling their production builds of the Chrome web-browser on Linux. A Google developer has now shed some light on the switch with backing up their own reasons for switching to Clang.


2 Answers

__GNUC__ doesn't mean GCC specifically. All compilers that support GNU C extensions define it, including clang and ICC.

The normal way to detect specifically GCC is by excluding other "compatible" compilers

#if defined(__GNUC__) && !defined(__llvm__) && !defined(__INTEL_COMPILER) #define REAL_GCC   __GNUC__ // probably #endif 

The Clang front-end defines __clang__, but other front-ends that use the LLVM back-end also define __llvm__ (e.g. IBM XL C/C++ versions 13.1.1 through 16.1). It might be better to just exclude __clang__ instead of __llvm__, depending on why you want to exclude it. (e.g. for parsing reasons, vs. for optimization reasons like LLVM evaluating __builtin_constant_p() before doing inlining, so it's useless on args of an inline function.)

See also https://sourceforge.net/p/predef/wiki/Compilers/ for a large list.

https://blog.kowalczyk.info/article/j/guide-to-predefined-macros-in-c-compilers-gcc-clang-msvc-etc..html came up in google results, too, but is less complete.


The thing you should be complaining about is that GCC itself doesn't define a GCC-specific macro you can detect, only the version of the GNU dialect of C it supports. (GNU C is a language, GCC is a compiler for that language. GCC's __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ macros conflate the two, unfortunately.)

Clang defines __GNUC__ / __GNUC_MINOR__ / __GNUC_PATCHLEVEL__ according to the version of gcc that it claims full compatibility with. (Probably only for stuff that GCC documentation guarantees will work, not for stuff that happens to work with that version or later of gcc. For GCC itself, documented = supported. Being accepted by the compiler doesn't imply it's supported and guaranteed for future GCC versions. That might be how clang justifies claiming support for some GNU C versions).

For example, clang 7.0.1 defines GNUC/MINOR/PATCHLEVEL as 4/2/1, i.e. compat with GCC 4.2.1

e.g. from the GCC manual

#define GCC_VERSION (__GNUC__ * 10000 \                      + __GNUC_MINOR__ * 100 \                      + __GNUC_PATCHLEVEL__) … /* Test for GCC > 3.2.0 */ #if GCC_VERSION > 30200 

If you're testing for a specific GNU C feature that recent GCC supports but recent clang doesn't support (yet), you should probably be doing something like that.

like image 179
Peter Cordes Avatar answered Sep 19 '22 00:09

Peter Cordes


It seems that starting with release 10 clang now has an option for this. See the docs for clang:

-fgnuc-version=

This flag controls the value of GNUC and related macros. This flag does not enable or disable any GCC extensions implemented in Clang. Setting the version to zero causes Clang to leave GNUC and other GNU-namespaced macros, such as GXX_WEAK, undefined.

So to disable this behaviour, specify -fgnuc-version=0 on the clang commandline.

like image 45
Matthijs Kooijman Avatar answered Sep 22 '22 00:09

Matthijs Kooijman