如何告诉Clang不要假装成其他编译器?

时间:2016-07-21 08:52:51

标签: gcc visual-c++ clang llvm

我过去遇到过这个问题:LLVM定义__GNUC__,但它不能使用GCC可以使用的程序。我在Windows上再次遇到它:LLVM定义_MSC_VER,但它不能使用VC ++可以使用的相同程序。加重的事情(对我来说)是我们有LLVM Clang和Apple Clang的特殊代码路径(由于不同的版本方案而定义不同),我们必须使用该工具来使它们使用它们。

我们如何告诉Clang不要假装成其他编译器?有没有开关或选项来做?

Clang文档discuss the unwanted MS behavior,但他们没有说如何阻止它:

  

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

4 个答案:

答案 0 :(得分:1)

__GNUC__并非专门针对GCC。。所有支持GNU C扩展的编译器都对其进行定义,包括clang和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无效。)

有关大型列表,另请参见https://sourceforge.net/p/predef/wiki/Compilers/

https://blog.kowalczyk.info/article/j/guide-to-predefined-macros-in-c-compilers-gcc-clang-msvc-etc..html也出现在Google搜索结果中,但不够完整。


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

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

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

例如来自the GCC manual

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

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

答案 1 :(得分:1)

我也很惊讶地发现 Clang 定义了 _MSC_VER,但我所做的是做这样的事情:

#if defined(_MSC_VER) && !defined(__clang__)
// Real MSVC here
#elif defined(__clang__)
// Real CLANG here

答案 2 :(得分:0)

似乎clang现在对此有一个选择。参见the docs for clang

-fgnuc-version =

此标志控制 GNUC 和相关宏的值。此标志不会启用或禁用在Clang中实现的任何GCC扩展。将版本设置为零会导致Clang留下未定义的 GNUC 和其他以GNU命名的宏,例如 GXX_WEAK

因此,要禁用此行为,请在clang命令行上指定-fgnuc-version=0

答案 3 :(得分:-1)

  

我们如何告诉Clang停止假装其他编译器?

我不知道该怎么做,也不知道它是否可行。为什么要这样做?我觉得您想这样做可以解决问题,但是也许有更好的解决方案。

  

[在Windows上,] LLVM定义_MSC_VER,

因为您可能正在使用标准库进行检查,以生成兼容的代码。

Clang在Windows上的目标不仅是生成在Windows上运行的独立代码,而且是可以与使用VC ++编译的库链接的代码。从源代码的角度来看,是使用clang还是VC ++进行编译应该没有区别。

如果您希望能够调用现有DLL,并且其头文件检查_MSC_VER,则需要设置它是使用VC ++还是使用clang。

  

但是[Windows上的clang]不能使用VC ++可以使用的相同程序。

自撰写此问题以来,

Clang在Windows上的功能已得到很大改进。现在有几个主要项目在Windows版本中使用clang。

如果找到VC ++可以接受但clang不能接受的正确程序,请提交错误报告。在大多数情况下,这可能是疏忽大意。有少量功能和VC ++扩展未在Windows的clang中实现,因为它们的优先级不够高。如果他们是您的重中之重,请告诉我们。