Clang 的 __has_builtin 并不总是有效

Clang's __has_builtin doesn't always work

对于以下测试代码,预期结果是由于 #error 指令而无法编译。

#if __has_builtin(__builtin_types_compatible_p)
#error ("Hello")
#endif

#include <stdio.h>

int main (void)
{
    if (__builtin_types_compatible_p(int, const int)) {
        printf("INT ARE SAME!!!\n");
    }
    return 0;
}

然而,它不仅编译而且还打印出 INT ARE SAME!!! 这意味着即使 __builtin_types_compatible_p 存在,__has_builtin 也没有检测到它。为什么?更重要的是,是否有其他方法可以检测可用的内置函数?

这是在 Clang 3.8 和 3.9(当前的稳定分支)上测试的。代码是使用 clang --std=c99 -Wall -Wextra test.c.

编译的

注意:自 Clang 10 起,此答案已过时。


根据 LLVM 开发人员的说法,

__has_builtin detects builtin functions.

在您的示例中,__builtin_types_compatible_p 是

not a function at all, since it takes a type, not a value.

所以,__has_builtin(__builtin_types_compatible_p) returns false,完全符合设计。

http://lists.llvm.org/pipermail/cfe-dev/2017-July/054590.html

在 Clang 10 之前,__has_builtin 只能识别 built-in 函数。像 __builtin_types_compatible_p 这样接受类型参数的构造不是函数,而是使用语法 有点 类似于函数的关键字——类似于 sizeof。 Clang 10 changed the behaviour of __has_builtin 以便某些 function-like 关键字被识别为 built-in。但是,从 Clang 11 开始,仍然无法识别既不是函数也不是关键字的 built-in(例如 __builtin_va_list 类型)。

如果您需要检查旧版本的 Clang 中是否存在 function-like 关键字,请使用包含该功能的 !__is_identifier(). Alternatively, you can search for an argument to __has_extension or __has_feature

GCC's implementation of __has_builtin 从一开始就支持 function-like 个关键字;它是在 GCC 10 中添加的。