__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.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…