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();
#elseabort();
#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编译代码可以使用模块。

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

使用Clang作为编译器 —— Clang 语言扩展相关推荐

  1. 使用Clang作为编译器 —— Clang 中的Diagnostic flags

    Clang 中的Diagnostic flags(未完成) 1. 介绍 2. 诊断标记(Diagnostic flags) 2.1 -W 2.2 -W#pragma-messages 2.3 -W#w ...

  2. gcc/g++/clang/cl编译器

    编译器一般构成 传统的编译器通常分为三个部分,前端(frontEnd),优化器(Optimizer)和后端(backEnd).在编译过程中,前端主要负责词法和语法分析,将源代码转化为抽象语法树:优化器 ...

  3. [转] 编译器Clang介绍

    LLVM 与 Clang 介绍 { 撰文/guest } 来源:http://linuxtoy.org/archives/llvm-and-clang.html LLVM 是 Low Level Vi ...

  4. 业界编译器Clang介绍

    http://baike.baidu.com/link?url=2cAQ-ZePNxPoPNll06fdZKaG5oSOpAhfmCoJ5hIS1sBG1Psy9c8wlcguVAsronSVYDc5 ...

  5. 使用Clang作为库 —— Clang Plugins

    Clang Plugins 1. 介绍 2. 编写一个PluginASTAction 3. 注册一个plugin 4. 定义pragmas 5. 把它们放在一起 6. 运行此plugin 6.1 使用 ...

  6. 用C语言扩展PHP功能

    用C语言扩展PHP功能 建议读者群:熟悉c,linux,php    PHP经过最近几年的发展已经非常的流行,而且PHP也提供了各种各样非常丰富的函数. 但有时候我们还是需要来扩展PHP.比如:我们自 ...

  7. R语言扩展包dplyr——数据清洗和整理

    R语言扩展包dplyr--数据清洗和整理 标签: 数据R语言数据清洗数据整理 2015-01-22 18:04 7357人阅读 评论(0) 收藏 举报  分类: R Programming(11)  ...

  8. Python:C语言扩展

    Python:C语言扩展 (2013-05-29 14:38:02) 转载▼ 标签: 杂谈 分类:Python   没有什么比对着书敲的代码仍然出错更令人沮丧了.<Python编程入门经典> ...

  9. 用C语言扩展Python的功能的实例

    用C语言扩展Python的功能的实例 分类: C/C++ 编程技巧 Programes 2008-04-23 09:31 1232人阅读 评论(0)收藏 举报 python扩展语言cmethodsnu ...

最新文章

  1. Qt利用avilib实现录屏功能_利用“别名”实现Sendmail的邮件群发和邮件备份功能...
  2. 单链表-删除并释放以L为表头指针的单链表的所有结点(双指针法)
  3. 解决ftp上传connection reset错误
  4. Go语言程序记录日志
  5. 前端学习(2387):组件库使用说明
  6. 高清网络视频无损FLV教程
  7. 【InnoDB】体系结构
  8. 算法总结之 打印二叉树的边界节点
  9. 用python做数据分析教程_Python运用于数据分析的简单教程
  10. 获取rabbitmq连接对象_NET Core使用RabbitMQ
  11. 极大似然估计法的理解
  12. Innovation - 3W咖啡馆 - 这里是互联网人的社交圈子
  13. 万万没想到,低功耗也会烧毁元器件?
  14. struct files_struct和struct fdtable
  15. 最长上升子序列 CSU - 1047 ( LIS LCS )
  16. HDU_多重背包系列
  17. STM32F429IGT6使用SDRAM(W9825G6KH-6)
  18. 【rk3399】AIO-3399J Linux_SDK Recovery按键无法进入Loader模式
  19. 简易QQ聊天室,socket多线程编程(C语言实现),简单易懂
  20. MFC 消息分类 (II)

热门文章

  1. php的构造函数理解
  2. PHP构造函数的继承
  3. KCSJ-13 课程设计-“手柄套“零件机械加工工艺及Φ12孔钻孔夹具设计(说明书+CAD装配图 零件图 毛坯图+工序卡+过程卡)
  4. project1--1.1UART串口通信
  5. 57个Google产品分享(总有你需要的)
  6. ora-01031 linux,ORA-01031 :insufficient privileges
  7. 第一个小游戏,被我卖了。。。
  8. OpenCV用MSER 算法提取特征区域
  9. 雅思词汇之万词plan:第7-365天
  10. 【云周刊】第127期:数据可视化最强CP登场!DataV接入ECharts图表库