如何告诉Clang停止假装其他编译器? [英] How to tell Clang to stop pretending to be other compilers?

查看:176
本文介绍了如何告诉Clang停止假装其他编译器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我过去曾遇到过此问题:LLVM定义 __GNUC__ ,但是它不能使用GCC可以使用的程序.我在Windows上再次遇到问题:LLVM定义了 _MSC_VER ,但是它不能使用VC ++可以使用的相同程序.令我感到烦恼的是,我们为LLVM Clang和Apple Clang提供了专门的代码路径(由于版本机制不同,定义也有所不同),我们必须与该工具进行斗争才能使其使用它们.

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.

我们如何告诉Clang停止假装其他编译器?有开关或选项吗?

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

Clang文档讨论了不必要的MS行为,但他们没有说明如何停止它:

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

为了与使用MSVC编译的现有代码兼容,clang定义了_MSC_VER和_MSC_FULL_VER宏.这些默认值分别为1800和180000000,使clang看起来像Visual C ++ 2013的早期版本.-fms-compatibility-version =标志将覆盖这些值.它接受带点缀的版本元组,例如19.00.23506.更改MSVC兼容版本会使Clang的行为更类似于MSVC的版本.例如,-fms-compatibility-version = 19将启用C ++ 14功能,并将char16_t和char32_t定义为内置类型.

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.

推荐答案

__GNUC__并非专门针对GCC..所有支持GNU C扩展的编译器都对其进行定义,包括clang和ICC.

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

检测GCC的正常方法是排除其他兼容"编译器

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

Clang前端定义了__clang__,但是其他使用LLVM后端的前端也定义了__llvm__(例如IBM XL C/C ++版本13.1.1至16.1).最好排除__clang__而不是__llvm__,这取决于要排除它的原因. (例如,出于解析原因,而出于优化原因,例如LLVM在进行内联之前评估__builtin_constant_p(),因此对内联函数的args无效.)

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.)

另请参见 https://sourceforge.net/p/predef/wiki/Compilers/以获得较大的列表.

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.

您应该抱怨的是,GCC本身并没有定义您可以检测到的特定于GCC的宏,仅定义了它支持的C的GNU方言的版本. (不幸的是, GNU C是一种语言,GCC是该语言的编译器.不幸的是,GCC的__GNUC_MINOR__/__GNUC_PATCHLEVEL__宏将两者结合在一起.)

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根据声称完全兼容的gcc版本定义__GNUC__/__GNUC_MINOR__/__GNUC_PATCHLEVEL__. (可能仅适用于GCC文档保证可以使用的内容,不适用于与该版本或更高版本的gcc一起使用的内容.对于GCC本身,提供文档=支持. 被编译器接受并不意味着它会在将来的GCC版本中得到支持和保证.也许这就是clang声称支持某些GNU C版本的理由.

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).

例如,clang 7.0.1将GNUC/MINOR/PATCHLEVEL定义为4/2/1,即与GCC 4.2.1兼容

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

例如来自 GCC手册

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

如果您正在测试最新的GCC支持但尚未提供最新的clang的特定GNU C功能(尚未),则您可能应该这样做.

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.

这篇关于如何告诉Clang停止假装其他编译器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆