使用Clang作为编译器 —— Clang 语言扩展

2023-11-15

1. 介绍

本文档描述了 Clang 提供的语言扩展。除了这里列出的语言扩展之外,Clang 还旨在支持广泛的 GCC 扩展。有关这些扩展的更多信息,请参阅 GCC手册

2. 特性检查宏

语言扩展可能非常有用,但只有在您知道可以依赖它们的情况下。为了允许细粒度特性检查,我们支持三个内置类似函数的宏。这允许您直接测试代码中的某个特性,而不必求助于autoconf或脆弱的“编译器版本检查”。

2.1 __has_builtin

这个类似函数的宏只接受一个标识符参数,即一个内置函数的名称。如果支持构建,它的值为1;如果不支持,它的值为0。它可以这样使用:

#ifndef __has_builtin         // Optional of course.
  #define __has_builtin(x) 0  // Compatibility with non-clang compilers.
#endif

...
#if __has_builtin(__builtin_trap)
  __builtin_trap();
#else
  abort();
#endif
...
2.2 __has_feature 和 __has_extension

这些类似函数的宏只接受一个标识符参数,即特性的名称。在当前语言标准中,如果特性是由 Clang 支持和被标准化,__has_feature的值为1;或如果不是,它的值为0(但见下文),而在当前语言中(作为一个语言扩展或一个标准语言特性),如果特性是由 Clang 支持,__has_extension的值为1;如果不是,它的值为0。它们可以这样使用:

#ifndef __has_feature         // Optional of course.
  #define __has_feature(x) 0  // Compatibility with non-clang compilers.
#endif
#ifndef __has_extension
  #define __has_extension __has_feature // Compatibility with pre-3.0 compilers.
#endif

...
#if __has_feature(cxx_rvalue_references)
// This code will only be compiled with the -std=c++11 and -std=gnu++11
// options, because rvalue references are only standardized in C++11.
#endif

#if __has_extension(cxx_rvalue_references)
// This code will be compiled with the -std=c++11, -std=gnu++11, -std=c++98
// and -std=gnu++98 options, because rvalue references are supported as a
// language extension in C++98.
#endif

为了向后兼容性,还可以使用_has_feature测试对非标准化特性的支持,即不带前缀c_cxx_objc_的特性。
has_feature的另一个用途是检查与语言标准无关的编译器特性,例如 AddressSanitizer
如果提供了-pedantic-errors选项,那么_has_extension等同于_has_feature
特性 tag 和下面的语言特性一起描述。
特性名或扩展名也可以用前面和后面添加__(双下划线)指定,以避免来自同名宏的干扰。例如,可以使用__cxx_rvalue_references__代替cxx_rvalue_references

2.3 __has_cpp_attribute

默认情况下,这个类似函数的宏在 C++2a 中可用,并在早期的语言标准中作为扩展提供。它接受一个参数,该参数是双方括号样式属性的名称。参数可以是单个标识符,也可以是范围标识符。如果支持该属性,则返回一个非零值。如果该属性是基于标准的属性,则该宏根据该属性投票进入工作草案的年份和月份返回一个非零值。有关基于标准的属性返回的值列表,请参见 WG21 SD-6。如果当前编译目标不支持该属性,则此宏的计算值为0。它可以这样使用:

#ifndef __has_cpp_attribute         // For backwards compatibility
  #define __has_cpp_attribute(x) 0
#endif

...
#if __has_cpp_attribute(clang::fallthrough)
#define FALLTHROUGH [[clang::fallthrough]]
#else
#define FALLTHROUGH
#endif
...

属性范围令牌clang和_Clang是可互换的,属性范围令牌gnu和_gnu__也是可互换的。这些名称空间中的任何一个中的属性标记都可以用__(双下划线)前后指定,以避免来自具有相同名称的宏的干扰。例如,gnu::_ const__可以代替gnu::const。

2.4 __has_c_attribute

这个类似函数的宏接受一个参数,该参数是在C模式下使用双方括号语法公开的属性的名称。参数可以是单个标识符,也可以是范围标识符。如果支持该属性,则返回一个非零值。如果当前编译目标不支持该属性,则此宏的计算值为0。它可以这样使用:

#ifndef __has_c_attribute         // Optional of course.
  #define __has_c_attribute(x) 0  // Compatibility with non-clang compilers.
#endif

...
#if __has_c_attribute(fallthrough)
  #define FALLTHROUGH [[fallthrough]]
#else
  #define FALLTHROUGH
#endif
...

属性范围令牌clang和_Clang是可互换的,属性范围令牌gnu和_gnu__也是可互换的。这些名称空间中的任何一个中的属性标记都可以用__(双下划线)前后指定,以避免来自具有相同名称的宏的干扰。例如,gnu::_ const__可以代替gnu::const。

2.5 __has_attribute

这个类似函数的宏接受一个标识符参数,该参数是一个GNU-style属性的名称。如果当前编译目标支持该属性,则计算为1;如果不支持,则为0。它可以这样使用:

#ifndef __has_attribute         // Optional of course.
  #define __has_attribute(x) 0  // Compatibility with non-clang compilers.
#endif

...
#if __has_attribute(always_inline)
#define ALWAYS_INLINE __attribute__((always_inline))
#else
#define ALWAYS_INLINE
#endif
...

属性名也可以用前面和后面的__(双下划线)来指定,以避免来自同名宏的干扰。例如,可以使用_always_inline__代替always_inline。

2.6 __has_declspec_attribute

这个类似函数的宏接受一个标识符参数,该参数是作为microsoft风格的_declspec属性实现的属性的名称。如果当前编译目标支持该属性,则计算为1;如果不支持,则为0。它可以这样使用:

#ifndef __has_declspec_attribute         // Optional of course.
  #define __has_declspec_attribute(x) 0  // Compatibility with non-clang compilers.
#endif

...
#if __has_declspec_attribute(dllexport)
#define DLLEXPORT __declspec(dllexport)
#else
#define DLLEXPORT
#endif
...

属性名也可以用前面和后面的__(双下划线)来指定,以避免来自同名宏的干扰。例如,可以使用_dllexport__代替dllexport。

2.7 __is_identifier

这个类似函数的宏接受一个标识符参数,该参数可以是保留字,也可以是常规标识符。如果参数只是常规标识符而不是保留字,那么它的值为1,因为它可以用作用户定义的函数或变量的名称。否则它的值为0。它可以这样使用:

...
#ifdef __is_identifier          // Compatibility with non-clang compilers.
  #if __is_identifier(__wchar_t)
    typedef wchar_t __wchar_t;
  #endif
#endif

__wchar_t WideCharacter;
...

3. Include文件检查宏

不是所有的开发系统都有相同的包含文件。在执行可能失败的#include指令之前,可以使用_has_include和_has_include_next宏检查包含文件是否存在。Include文件检查宏必须用作#if或#elif预处理指令中的表达式。

3.1 __has_include

这个类似函数的宏接受一个文件名字符串参数,即包含文件的名称。如果可以使用include路径找到文件,则计算为1,否则为0:

// Note the two possible file name string formats.
#if __has_include("myinclude.h") && __has_include(<stdint.h>)
# include "myinclude.h"
#endif

要测试这个特性,请使用#if defined(_has_include)

// To avoid problem with non-clang compilers not having this macro.
#if defined(__has_include)
#if __has_include("myinclude.h")
# include "myinclude.h"
#endif
#endif
3.2 __has_include_next

这个类似函数的宏接受一个文件名字符串参数,即包含文件的名称。它类似于……has_include,只是它查找在include路径中找到的给定文件的第二个实例。如果可以使用include路径找到文件的第二个实例,则计算为1,否则为0:

// Note the two possible file name string formats.
#if __has_include_next("myinclude.h") && __has_include_next(<stdint.h>)
# include_next "myinclude.h"
#endif

// To avoid problem with non-clang compilers not having this macro.
#if defined(__has_include_next)
#if __has_include_next("myinclude.h")
# include_next "myinclude.h"
#endif
#endif

注意,与GNU extension #include_next指令一样,_has_include_next仅用于头文件中,如果在顶级编译文件中使用,则会发出警告。如果在文件参数中使用绝对路径,也会发出警告。

3.3 __has_warning

这个类似函数的宏接受一个字符串文字,它表示警告的命令行选项,如果是有效的警告选项,则返回true。

#if __has_warning("-Wformat")
...
#endif

4. 内置宏(Builtin Macros)

  • __BASE_FILE__
    定义为包含传递给Clang的主输入文件的名称的字符串。
  • `FILE_NAME``
    特定于clang的扩展,其功能类似于_ file__,但只呈现最后一个路径组件(文件名),而不是依赖于调用的文件的完整路径。
  • __COUNTER__
    定义为一个整数值,该整数值从0开始,并且在每次扩展_counter__宏时递增。
  • __INCLUDE_LEVEL__
    定义为一个整数值,即当前正在翻译的文件的包含深度。对于主文件,这个值为零。
  • __TIMESTAMP__
    定义为最近一次修改当前源文件的日期和时间。
  • __clang__
    使用Clang编译时定义
  • __clang_major__
    定义为Clang的主要营销版本号(例如2.0.1中的2)。注意,营销版本号不应该用于检查语言特性,因为不同的供应商使用不同的编号方案。相反,使用特性检查宏
  • __clang_minor__
    定义为Clang的次要版本号(例如2.0.1中的0)。注意,营销版本号不应该用于检查语言特性,因为不同的供应商使用不同的编号方案。相反,使用特性检查宏
  • __clang_patchlevel__
    定义为Clang的市场补丁级别(例如2.0.1中的1)。
  • __clang_version__
    定义为捕获Clang marketing版本的字符串,包括Subversion标记或版本号,例如“1.5 (trunk 102332)”。

5. 向量和扩展向量

支持GCC、OpenCL、AltiVec和NEON向量扩展。

OpenCL向量类型是使用ext_vector_type属性创建的。它支持V。xyzw语法和OpenCL中的其他花絮。一个例子是:

typedef float float4 __attribute__((ext_vector_type(4)));
typedef float float2 __attribute__((ext_vector_type(2)));

float4 foo(float2 a, float2 b) {
  float4 c;
  c.xz = a;
  c.yw = b;
  return c;
}

使用_has_extension(attribute_ext_vector_type)查询此特性。

为clang提供-maltivec选项支持AltiVec向量语法和函数。例如:

vector float foo(vector int a) {
  vector int b;
  b = vec_add(a, a) + a;
  return (vector float)b;
}

NEON 向量类型是使用neon_vector_type和neon_polyvector_type属性创建的。例如:

typedef __attribute__((neon_vector_type(8))) int8_t int8x8_t;
typedef __attribute__((neon_polyvector_type(16))) poly8_t poly8x16_t;

int8x8_t foo(int8x8_t a) {
  int8x8_t v;
  v = a;
  return v;
}
5.1 向量文字(Vector Literals)

向量文字可用于从一组标量或向量创建向量。可以使用圆括号或大括号形式。在圆括号中,指定的文字值的数量必须为1,即引用标量值,或者必须匹配正在创建的向量类型的大小。如果指定单个标量文字值,则该标量文字值将复制到向量类型的所有组件。在括号中可以指定任意数量的文字。例如:

typedef int v4si __attribute__((__vector_size__(16)));
typedef float float4 __attribute__((ext_vector_type(4)));
typedef float float2 __attribute__((ext_vector_type(2)));

v4si vsi = (v4si){1, 2, 3, 4};
float4 vf = (float4)(1.0f, 2.0f, 3.0f, 4.0f);
vector int vi1 = (vector int)(1);    // vi1 will be (1, 1, 1, 1).
vector int vi2 = (vector int){1};    // vi2 will be (1, 0, 0, 0).
vector int vi3 = (vector int)(1, 2); // error
vector int vi4 = (vector int){1, 2}; // vi4 will be (1, 2, 0, 0).
vector int vi5 = (vector int)(1, 2, 3, 4);
float4 vf = (float4)((float2)(1.0f, 2.0f), (float2)(3.0f, 4.0f));
5.2 向量操作(Vector Operations)

下表显示了对每个向量扩展操作的支持。破折号表示根据相应的规范不接受操作。

Operator OpenCL AltiVec GCC NEON
[] yes yes yes
unary operators +, – yes yes yes
++, – – yes yes yes
+,–,*,/,% yes yes yes
bitwise operators &,|,^,~ yes yes yes
>>,<< yes yes yes
!, &&, yes
==, !=, >, <, >=, <= yes yes
= yes yes yes yes
:? yes
sizeof yes yes yes yes
C-style cast yes yes yes no
reinterpret_cast yes no yes no
static_cast yes no yes no
const_cast no no no no

还请参见_builtin_shufflevector_builtin_convertvector

6. Half-Precision浮点

Clang支持两种半精度(16位)浮点类型:_fp16和_Float16。所有语言模式都支持这些类型。

每个目标都支持_fp16,因为它纯粹是一种存储格式;见下文。_Float16目前只在以下目标上受支持,还有一些目标有待ABI标准化:- 32位ARM - 64位ARM (AArch64) - SPIR _Float16将在更多的目标上受支持,因为它们为它定义了ABIs。

仅是存储和交换格式。这意味着当在算术运算中使用时,会立即(至少)将……fp16的值提升为浮点数,因此,例如,添加两个……fp16值的结果具有float类型。_fp16的行为由ARM C语言扩展(ACLE)指定。Clang使用来自IEEE 754-2008的二进制16格式来处理_fp16,而不是ARM的替代格式。

_Float16是一个扩展的浮点类型。这意味着,就像对float或double的运算一样,对_Float16操作数的运算也是以_Float16类型正式执行的,例如,添加两个_Float16值的结果具有_Float16类型。_Float16的行为由ISO/IEC TS 18661- 3:15(“C的浮点扩展”)指定。与使用_fp16一样,Clang对_Float16使用IEEE 754-2008中的二进制16格式。

_Float16算法将使用本机半精度支持在目标上执行(例如在ARMv8.2a上);否则,它将以更高的精度执行(当前总是浮点数),然后截断为_Float16。注意,C和c++允许计算表达式的中间浮点操作数,其精度比在它们的类型中所能表达的精度更高,因此在某些情况下,Clang可以避免中间截断;这可能导致与本机算法不一致的结果。

建议可移植代码使用_Float16而不是_fp16,因为C标准委员会已经定义了它,它的行为对大多数程序员来说更熟悉。

因为总是立即将……fp16操作数提升为float,所以对于通常的算术转换而言,常见的实际类型是float。

可以使用后缀f16指定_Float16类型;例如:’ 3.14f16 ’

因为默认参数提升只适用于标准浮点类型,所以当作为可变参数或无类型参数传递时,_Float16值不会提升为double。因此,在使用_Float16的某些库设施时必须谨慎;例如,_Float16没有printf格式说明符,而且(与float不同)它在传递给printf时不会被隐式地提升为double,所以程序员必须显式地将它转换为double,然后再使用%f或类似的说明符。
关于废弃和不可用属性的消息
可以将可选字符串消息添加到不推荐的和不可用的属性中。例如:

void explode(void) __attribute__((deprecated("extremely unsafe, use 'combust' instead!!!")));

如果使用不赞成的或不可用的声明,则该消息将并入适当的诊断:

harmless.c:4:3: warning: 'explode' is deprecated: extremely unsafe, use 'combust' instead!!!
      [-Wdeprecated-declarations]
  explode();
  ^

使用_has_extension(attribute_deprecated_with_message)_has_extension(attribute_unavailable_with_message)查询此特性。

7. 枚举成员上的属性

Clang允许在单个枚举器上编写属性。这允许不推荐枚举数,使之不可用,等等。属性必须出现在枚举器名称之后和任何初始化器之前,如下所示:

enum OperationMode {
  OM_Invalid,
  OM_Normal,
  OM_Terrified __attribute__((deprecated)),
  OM_AbortOnError __attribute__((deprecated)) = 4
};

枚举声明上的属性不适用于单个枚举数。

使用_has_extension(enumerator_attributes)查询此特性。

指定的系统框架
Clang提供了一种机制,通过这种机制可以构建框架,使它们始终被视为“系统框架”,即使它们不在系统框架目录中。对于希望能够使用框架的开发构建测试构建其他应用程序(包括编译器更改系统头的警告行为的方式)的系统框架开发人员来说,这非常有用。

框架开发人员可以通过创建“。在它们的框架的顶层的system_framework文件。也就是说,框架应该包含以下内容:

.../TestFramework.framework
.../TestFramework.framework/.system_framework
.../TestFramework.framework/Headers
.../TestFramework.framework/Headers/TestFramework.h
...

Clang将把这个文件的存在视为一个指示符,指示框架应该被视为一个系统框架,而不管它是如何在框架搜索路径中找到的。为了保持一致性,我们建议这种文件永远不要包含在框架的安装版本中。

检查标准语言特性
如果启用了某些标准语言特性,可以使用_has_feature宏来查询。在编译不提供语言特性的标准时,可以使用_has_extension宏查询语言特性是否可用作扩展。这里列出了可以测试的特性。

自Clang 3.4以来,还支持c++ SD-6特性测试宏。这些宏的名称为格式为_cpp_<feature_name>,旨在作为一种可移植的方式来查询编译器支持的特性。</feature_name>有关每个Clang版本支持的SD-6版本的信息,以及该建议修订版提供的宏,请参阅c++状态页。

C + + 98
下面列出的特性是c++ 98标准的一部分。编译c++代码时默认启用这些特性。

c++异常
使用_has_feature(cxx_exception)来确定是否启用了c++异常。例如,使用-fno-exception编译代码将禁用c++异常。

c++ RTTI
使用_has_feature(cxx_rtti)来确定是否启用了c++ RTTI。例如,使用-fno-rtti编译代码将禁用RTTI的使用。

c++ 11
下面列出的特性是c++ 11标准的一部分。因此,在编译c++代码时,所有这些特性都是使用-std=c++11或-std=gnu++11选项启用的。

c++ 11 SFINAE包含访问控制
使用_has_feature(cxx_access_control_sfinae)或_has_extension(cxx_access_control_sfinae)来确定访问控制错误(例如,调用私有构造函数)是否被认为是每个c++ DR1170的模板参数推断错误(也称为SFINAE错误)。

c++模板11别名
使用_has_feature(cxx_alias_templates)或_has_extension(cxx_alias_templates)来确定是否支持c++ 11的别名声明和别名模板。

c++ 11对齐说明符
使用_has_feature(cxx_alignas)或_has_extension(cxx_alignas)来确定是否启用了对使用alignas的对齐说明符的支持。

使用_has_feature(cxx_alignof)或_has_extension(cxx_alignof)来确定是否启用了对alignof关键字的支持。

c++ 11属性
使用_has_feature(cxx_attributes)或_has_extension(cxx_attributes)来确定是否支持使用c++ 11的方括号符号进行属性解析。

c++ 11通用常数表达式
使用_has_feature(cxx_constexpr)来确定是否支持通用常量表达式(例如,constexpr)。

c++ 11 decltype ()
使用_has_feature(cxx_decltype)或_has_extension(cxx_decltype)来确定是否启用了对decltype()说明符的支持。c++ 11的decltype不需要函数调用表达式的类型完整性。使用_has_feature(cxx_decltype_incomplete_return_types)或_has_extension(cxx_decltype_incomplete_return_types)来确定是否启用了对该特性的支持。
函数模板中的11个默认模板参数
使用_has_feature(cxx_default_function_template_args)或_has_extension(cxx_default_function_template_args)来确定是否启用了函数模板中对默认模板参数的支持。

c++ 11违约的功能
使用_has_feature(cxx_defaulted_functions)或_has_extension(cxx_defaulted_functions)来确定是否启用了对默认函数定义的支持(使用= default)。

c++ 11委托构造函数
使用_has_feature(cxx_delegating_constructors)来确定是否启用了对委托构造函数的支持。

c++ 11删除功能
使用_has_feature(cxx_deleted_functions)或_has_extension(cxx_deleted_functions)来确定是否启用了对已删除函数定义的支持(使用= delete)。

c++ 11显式转换函数
使用_has_feature(cxx_explicit_conversions)来确定是否启用了对显式转换函数的支持。

c++ 11广义初始值设定项
使用_has_feature(cxx_generalized_initialalizer)来确定是否启用了对通用初始化器的支持(使用带括号的列表和std::initializer_list)。

c++ 11隐式移动构造函数/赋值运算符
使用_has_feature(cxx_implicit_moves)来确定Clang是否会隐式地生成move构造函数,并在需要的地方生成move赋值操作符。

c++ 11继承的构造函数
使用_has_feature(cxx_inheriting_constructors)来确定是否启用了对继承构造函数的支持。

11 c++内联名称空间
使用_has_feature(cxx_inline_namespaces)或_has_extension(cxx_inline_namespaces)来确定是否启用了对内联名称空间的支持。

c++ 11λ
使用_has_feature(cxx_lambdas)或_has_extension(cxx_lambdas)来确定是否启用了对lambdas的支持。

c++ 11局部类型和未命名类型作为模板参数
使用_has_feature(cxx_local_type_template_args)或_has_extension(cxx_local_type_template_args)来确定是否支持将局部类型和未命名类型作为模板参数。

11 noexcept c++
使用_has_feature(cxx_noexcept)或_has_extension(cxx_noexcept)来确定是否启用了对noexcept异常规范的支持。

类内非静态数据成员初始化
使用_has_feature(cxx_nonstatic_member_init)来确定是否启用了非静态数据成员的类内初始化。

11 nullptr c++
使用_has_feature(cxx_nullptr)或_has_extension(cxx_nullptr)来确定是否启用了对nullptr的支持。

c++ 11覆盖控制
使用_has_feature(cxx_override_control)或_has_extension(cxx_override_control)来确定是否启用了对覆盖控件关键字的支持。

c++ 11 reference-qualified功能
使用_has_feature(cxx_reference_qualified_functions)或_has_extension(cxx_reference_qualified_functions)来确定是否启用了对引用限定函数的支持(例如,具有&或&&应用于*this的成员函数)。

基于c++ 11范围的for循环
使用_has_feature(cxx_range_for)或_has_extension(cxx_range_for)来确定是否启用了对基于范围的for循环的支持。
c++ 11原始字符串文字
使用_has_feature(cxx_raw_string_literals)来确定是否启用了对原始字符串文字的支持(例如,R"x(foo\bar)x")。

c++ 11右值引用
使用_has_feature(cxx_rvalue_references)或_has_extension(cxx_rvalue_references)来确定是否启用了对rvalue引用的支持。

c++ 11 static_assert ()
使用_has_feature(cxx_static_assert)或_has_extension(cxx_static_assert)来确定是否启用了对使用static_assert的编译时断言的支持。

11 thread_local c++
使用_has_feature(cxx_thread_local)来确定是否启用了对thread_local变量的支持。

c++ 11类型推断
使用_has_feature(cxx_auto_type)或_has_extension(cxx_auto_type)来确定使用自动说明符支持c++ 11类型推断。如果禁用此功能,auto将作为存储类说明符,如C或c++ 98中所示。

c++ 11强类型枚举
使用_has_feature(cxx_strong_enums)或_has_extension(cxx_strong_enums)来确定是否启用了对强类型、范围枚举的支持。

c++ 11尾随返回类型
使用_has_feature(cxx_trailing_return)或_has_extension(cxx_trailing_return)来确定是否启用了对带有尾随返回类型的替代函数声明语法的支持。

c++ 11 Unicode字符串文字
使用_has_feature(cxx_unicode_literals)来确定是否启用了对Unicode字符串常量的支持。

c++ 11无限制的工会
使用_has_feature(cxx_unrestricted ted_unions)来确定是否启用了对非受限联合的支持。

c++ 11用户定义的文字
使用_has_feature(cxx_user_literals)来确定是否启用了对用户定义的文字的支持。

c++ 11可变模板
使用_has_feature(cxx_variadic_templates)或_has_extension(cxx_variadic_templates)来确定是否启用了对可变参数模板的支持。

c++ 14
下面列出的特性是c++ 14标准的一部分。因此,在编译c++代码时,所有这些特性都是通过-std= c++ 14或-std=gnu++14选项启用的。

c++ 14二进制字面值
使用_has_feature(cxx_binary_literals)或_has_extension(cxx_binary_literals)来确定是否识别二进制文字(例如,0b10010)。Clang在所有语言模式中都支持此功能作为扩展。

c++ 14上下文转换
使用__has_feature (cxx_contextual_conversions)或__has_extension (cxx_contextual_conversions)来确定c++ 14当执行一个隐式转换规则是用于数组绑定在一个新的表达式,delete-expression的操作数,一个积分常数表达式,switch语句或条件。

c++ 14 decltype(汽车)
使用_has_feature(cxx_decltype_auto)或_has_extension(cxx_decltype_auto)来确定是否启用了对decltype(auto)占位符类型的支持。

用于聚合的c++ 14默认初始化器
使用_has_feature(cxx_aggregate_nsdmi)或_has_extension(cxx_aggregate_nsdmi)来确定是否支持聚合成员中的默认初始化器。

c++ 14位分隔符
使用_cpp_digit_separator来确定是否支持使用单引号的数字分隔符(例如,10,000)。此时,没有对应的_has_feature名称

c++ 14通用lambda捕获
使用_has_feature(cxx_init_capture)或_has_extension(cxx_init_capture)来确定是否启用了对带有显式初始化器的lambda capture的支持(例如,[n(0)] {return ++n;})。

c++ 14通用λ
使用_has_feature(cxx_generic_lambdas)或_has_extension(cxx_generic_lambdas)来确定是否启用了对泛型(多态)lambdas的支持(例如,[](auto x) {return x + 1;})。

c++ constexpr 14放松
使用_has_feature(cxx_relaxed_constexpr)或_has_extension(cxx_relaxed_constexpr)来确定是否允许在constexpr函数中声明变量、修改局部变量和控制流构造。

c++ 14返回类型扣除
使用_has_feature(cxx_return_type_演绎)或_has_extension(cxx_return_type_演绎)来确定是否支持函数的返回类型演绎(使用auto作为返回类型)。

c++ 14 runtime-sized数组
使用_has_feature(cxx_runtime_array)或_has_extension(cxx_runtime_array)来确定是否启用了对运行时绑定数组(可变长度数组的受限形式)的支持。Clang对该特性的实现还不完整。

c++模板14个变量
使用_has_feature(cxx_variable_templates)或_has_extension(cxx_variable_templates)来确定是否启用了对模板化变量声明的支持。

C11
下面列出的特性是C11标准的一部分。因此,在编译C代码时使用-std=c11或-std=gnu11选项启用了所有这些特性。此外,由于这些特性都是向后兼容的,所以它们可以作为所有语言模式的扩展。

C11对齐说明符
使用_has_feature(c_alignas)或_has_extension(c_alignas)来确定是否启用了对使用_Alignas的对齐说明符的支持。

使用_has_feature(c_alignof)或_has_extension(c_alignof)来确定是否启用了对_Alignof关键字的支持。

C11原子操作
使用_has_feature(c_atomic)或_has_extension(c_atomic)来确定是否启用了对使用_Atomic的原子类型的支持。Clang还提供了一组内建函数,可用于实现<stdatomic。< span="">h>对_Atomic类型的操作。使用_has_include(<stdatomic.h>)来确定C11的<stdatomic。< span="">h>报头可用。</stdatomic。<></stdatomic.h></stdatomic。<>

Clang将使用系统的<stdatomic。< span="">h>头时,一个可用,否则将使用自己的。当使用它自己的操作时,原子操作的实现作为宏提供。在C11还需要一个实函数的情况下,这个头文件只提供了该函数的声明(以及一个隐藏的宏实现),如果您使用它而不是宏,则必须链接到一个库,该库提供了函数的定义。</stdatomic。<>

C11通用的选择
使用_has_feature(c_generic_selection)或_has_extension(c_generic_selection)来确定是否启用了对泛型选择的支持。

作为扩展,C11通用选择表达式在Clang支持的所有语言中都可用。语法与C11标准中给出的相同。

在C语言中,类型兼容性是根据适当标准中给出的规则来决定的,但是在c++中,缺少C语言中使用的类型兼容性规则,只有当类型是等价的时,才会认为类型是兼容的。

C11 _Static_assert ()
使用_has_feature(c_static_assert)或_has_extension(c_static_assert)来确定是否启用了对使用_Static_assert的编译时断言的支持。

C11 _Thread_local
使用_has_feature(c_thread_local)或_has_extension(c_thread_local)来确定是否启用了对_Thread_local变量的支持。

模块
使用_has_feature(模块)来确定是否启用了模块。例如,使用-fmodules编译代码可以使用模块。

更多信息可以在这里找到。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用Clang作为编译器 —— Clang 语言扩展 的相关文章

随机推荐

  • 计算机丢失d3dx9_41.dll,d3dx9_41.dll

    不知道怎么下载 点我 游戏介绍 d3dx9 41 dll 当运行程序或者游戏时 系统弹出错误提示 找不到 d3dx9 41 dll 或者 没有找到 d3dx9 41 dll 时 说明您系统中缺失这个dll文件或者该dll文件没有被注册 您需
  • “视频云营业厅”-阿里云 mPaaS 加速金融机构数字化转型

    视频云营业厅 发布 蚂蚁 mPaaS 加速金融机构数字化转型 移动终端时代 随着 5G 基础设施的高速发展 AI 技术的日渐成熟 相关政策的鼓励和加持 以及当前疫情大环境的催化 远程无接触的业务办理方式由创新模式快速走向通用 通过多媒体音视
  • Doris数据模型

    目录 基本概念 Aggregate 模型 示例1 导入数据聚合 示例2 保留明细数据 示例3 导入数据与已有数据聚合 Unique 模型 读时合并 与聚合模型相同的实现方式 写时合并 Duplicate 模型 聚合模型的局限性 Unique
  • 【常见错误】UART接收不到数据错误

    利用FPGA控制DAC产生波形的实验 在完成利用FPGA控制DAC的实验中 在对UART发送数据时 显示中断已经打开 但是把数据发送过去时 并没有显示中断 相当于数据知识发送出去 而没有被接收到 经过debug后 发现原来是在硬件中 viv
  • python上传Excel文件

    python上传Excel文件 方法一 直接使用requests的data files参数 方法二 使用MultipartEncoder 方法一 直接使用requests的data files参数 直接上代码吧 def import car
  • python基础(一)

    python基础 1 数据类型 整数 浮点数 字符串 布尔值 True False 注意大小写 空值 是none 列表list 相当于别的语言里的数组 字典 2 编码设置与注释 编码 coding utf 8 注释 使用 或者是 和 这种表
  • redis的编译安装

    下载 http download redis io releases redis 5 0 8 tar gz tar xzvf redis 5 0 8 tar gz cd redis 5 0 8 hadoop node1 redis 5 0
  • 8位二进制数的原码、反码、补码以及它能表示的范围

    1 正数的反码和补码都与原码相同 2 而负数的反码为对该数的原码除符号位外各位取反 3 负数的补码为对该数的原码除符号位外各位取反 然后在最后一位加1 1 原码表示法规定 用符号位和数值表示带符号数 正数的符号位用 0 表示 负数的符号位用
  • 【Kubernetes存储篇】StorageClass存储类动态生成PV详解

    文章目录 一 StorageClass存储类理论 二 案例 Storageclass存储类实战演示 1 搭建NFS服务端 2 搭建NFS供应商 provisioner 3 创建StorageClass存储类 4 创建PVC 通过Storag
  • 2023年1月9日--1月15日(osg+glsl+ue+socket,42小时,合计1859小时,剩余8141小时)

    目前 ue视频教程进行到了mysql 7 1 tf1 4 11 oss 12 2 蓝图反射 1 9 moba 1 5 webapp 2 4 mmoarpg 00A 04 socket 2 57 Opengl 5 9 GLSL 2 8 周一到
  • Conda建立虚拟环境及torch安装

    本人的系统环境 Ubuntu 16 04 Cuda 9 0 Cudnn 7 0 5 Python 3 7 Anaconda 3 这里推荐大家使用Anaconda 可以比较方便的创建Python虚拟环境 避免不同的Python库之间产生冲突
  • C语言-基本运算

    1 除法运算 整数除于整数 还是整数 参与运算的操作数必须是同类型 1 2的值是0 参与运算的操作数是什么类型 得出的值就是什么类型 10 5 10将右边的10提升为了double类型 自动类型提升 int b 10 5 1 7 自动将大类
  • 李宏毅 - 卷积神经网络(CNN)

    李宏毅 卷积神经网络 CNN 卷积神经网络主要用于图像分类 一张图片通过我们的卷积神经网络也就是Model计算出概率值 通过Cross entropy 交叉熵 归一化到0和1 概率最大的显示为1 其余显示为0 那么一张图片是怎么输入到Mod
  • php批量保存网页上的图片,php网络图片下载至本地(可批量下载)

    class dlImageByWeb 下载图片 public function dl url dir orgName 0 state file get contents url 0 null 0 1 获取网络资源的字符内容 dlDir di
  • 多线程、线程同步及其相关类、死锁、线程池

    多线程 线程创建 1 自定义类继承Thread 重写run Thread t new 自定义类 t start jvm会调用t的run方法 同时当前线程会返回调用处 继续往下执行 2 实现Runnable 实现run Thread t ne
  • 两个栈共享一个数组

    代码 include
  • java 拨打电话,Java API拨打电话

    Is there any Java API to make a phone call to a mobile provided that service provider support will be arranged to make t
  • python采集高德地图上商家信息代码(亲测OK)

    项目场景 项目场景 我需要采集本地的商户信息 获得相关的行业信息数据 分析一下 描述 我之前有想过从企查查拿企业信息 但是我想获得更多的个体商户信息 想对当前城市做一个数据统计 分析出到底哪一行业更多 更有热度 然后可以帮我去定位到如果我去
  • 你所不知道的抖音赚钱方法,原来可以这样玩!

    这篇文章略长 但是承载了非常多的干货 望你认真看完 我相信在18年没有谁不知道抖音的火爆程度 当你出行或者朋友聚会的时候 总能看到低头刷抖音的身影 而在大街逛街或者公园散步的时候 也随处可见随着魔性的音乐释放青春活力的 姐 而各种音乐播放软
  • 使用Clang作为编译器 —— Clang 语言扩展

    1 介绍 本文档描述了 Clang 提供的语言扩展 除了这里列出的语言扩展之外 Clang 还旨在支持广泛的 GCC 扩展 有关这些扩展的更多信息 请参阅 GCC手册 2 特性检查宏 语言扩展可能非常有用 但只有在您知道可以依赖它们的情况下