Clang Language Extensions 您所在的位置:网站首页 sync_bool_compare_and_swap Clang Language Extensions

Clang Language Extensions

#Clang Language Extensions | 来源: 网络整理| 查看: 265

Clang Language Extensions¶ Introduction¶

This document describes the language extensions provided by Clang. In addition to the language extensions listed here, Clang aims to support a broad range of GCC extensions. Please see the GCC manual for more information on these extensions.

Feature Checking Macros¶

Language extensions can be very useful, but only if you know you can depend on them. In order to allow fine-grain features checks, we support three builtin function-like macros. This allows you to directly test for a feature in your code without having to resort to something like autoconf or fragile “compiler version checks”.

__has_builtin¶

This function-like macro takes a single identifier argument that is the name of a builtin function, a builtin pseudo-function (taking one or more type arguments), or a builtin template. It evaluates to 1 if the builtin is supported or 0 if not. It can be used like this:

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

Note

Prior to Clang 10, __has_builtin could not be used to detect most builtin pseudo-functions.

__has_builtin should not be used to detect support for a builtin macro; use #ifdef instead.

__has_constexpr_builtin¶

This function-like macro takes a single identifier argument that is the name of a builtin function, a builtin pseudo-function (taking one or more type arguments), or a builtin template. It evaluates to 1 if the builtin is supported and can be constant evaluated or 0 if not. It can be used for writing conditionally constexpr code like this:

#ifndef __has_constexpr_builtin // Optional of course. #define __has_constexpr_builtin(x) 0 // Compatibility with non-clang compilers. #endif ... #if __has_constexpr_builtin(__builtin_fmax) constexpr #endif double money_fee(double amount) { return __builtin_fmax(amount * 0.03, 10.0); } ...

For example, __has_constexpr_builtin is used in libcxx’s implementation of the header file to conditionally make a function constexpr whenever the constant evaluation of the corresponding builtin (for example, std::fmax calls __builtin_fmax) is supported in Clang.

__has_feature and __has_extension¶

These function-like macros take a single identifier argument that is the name of a feature. __has_feature evaluates to 1 if the feature is both supported by Clang and standardized in the current language standard or 0 if not (but see below), while __has_extension evaluates to 1 if the feature is supported by Clang in the current language (either as a language extension or a standard language feature) or 0 if not. They can be used like this:

#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

For backward compatibility, __has_feature can also be used to test for support for non-standardized features, i.e. features not prefixed c_, cxx_ or objc_.

Another use of __has_feature is to check for compiler features not related to the language standard, such as e.g. AddressSanitizer.

If the -pedantic-errors option is given, __has_extension is equivalent to __has_feature.

The feature tag is described along with the language feature below.

The feature name or extension name can also be specified with a preceding and following __ (double underscore) to avoid interference from a macro with the same name. For instance, __cxx_rvalue_references__ can be used instead of cxx_rvalue_references.

__has_cpp_attribute¶

This function-like macro is available in C++20 by default, and is provided as an extension in earlier language standards. It takes a single argument that is the name of a double-square-bracket-style attribute. The argument can either be a single identifier or a scoped identifier. If the attribute is supported, a nonzero value is returned. If the attribute is a standards-based attribute, this macro returns a nonzero value based on the year and month in which the attribute was voted into the working draft. See WG21 SD-6 for the list of values returned for standards-based attributes. If the attribute is not supported by the current compilation target, this macro evaluates to 0. It can be used like this:

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

The attribute scope tokens clang and _Clang are interchangeable, as are the attribute scope tokens gnu and __gnu__. Attribute tokens in either of these namespaces can be specified with a preceding and following __ (double underscore) to avoid interference from a macro with the same name. For instance, gnu::__const__ can be used instead of gnu::const.

__has_c_attribute¶

This function-like macro takes a single argument that is the name of an attribute exposed with the double square-bracket syntax in C mode. The argument can either be a single identifier or a scoped identifier. If the attribute is supported, a nonzero value is returned. If the attribute is not supported by the current compilation target, this macro evaluates to 0. It can be used like this:

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

The attribute scope tokens clang and _Clang are interchangeable, as are the attribute scope tokens gnu and __gnu__. Attribute tokens in either of these namespaces can be specified with a preceding and following __ (double underscore) to avoid interference from a macro with the same name. For instance, gnu::__const__ can be used instead of gnu::const.

__has_attribute¶

This function-like macro takes a single identifier argument that is the name of a GNU-style attribute. It evaluates to 1 if the attribute is supported by the current compilation target, or 0 if not. It can be used like this:

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

The attribute name can also be specified with a preceding and following __ (double underscore) to avoid interference from a macro with the same name. For instance, __always_inline__ can be used instead of always_inline.

__has_declspec_attribute¶

This function-like macro takes a single identifier argument that is the name of an attribute implemented as a Microsoft-style __declspec attribute. It evaluates to 1 if the attribute is supported by the current compilation target, or 0 if not. It can be used like this:

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

The attribute name can also be specified with a preceding and following __ (double underscore) to avoid interference from a macro with the same name. For instance, __dllexport__ can be used instead of dllexport.

__is_identifier¶

This function-like macro takes a single identifier argument that might be either a reserved word or a regular identifier. It evaluates to 1 if the argument is just a regular identifier and not a reserved word, in the sense that it can then be used as the name of a user-defined function or variable. Otherwise it evaluates to 0. It can be used like this:

... #ifdef __is_identifier // Compatibility with non-clang compilers. #if __is_identifier(__wchar_t) typedef wchar_t __wchar_t; #endif #endif __wchar_t WideCharacter; ... Include File Checking Macros¶

Not all developments systems have the same include files. The __has_include and __has_include_next macros allow you to check for the existence of an include file before doing a possibly failing #include directive. Include file checking macros must be used as expressions in #if or #elif preprocessing directives.

__has_include¶

This function-like macro takes a single file name string argument that is the name of an include file. It evaluates to 1 if the file can be found using the include paths, or 0 otherwise:

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

To test for this feature, use #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 __has_include_next¶

This function-like macro takes a single file name string argument that is the name of an include file. It is like __has_include except that it looks for the second instance of the given file found in the include paths. It evaluates to 1 if the second instance of the file can be found using the include paths, or 0 otherwise:

// Note the two possible file name string formats. #if __has_include_next("myinclude.h") && __has_include_next() # 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

Note that __has_include_next, like the GNU extension #include_next directive, is intended for use in headers only, and will issue a warning if used in the top-level compilation file. A warning will also be issued if an absolute path is used in the file argument.

__has_warning¶

This function-like macro takes a string literal that represents a command line option for a warning and returns true if that is a valid warning option.

#if __has_warning("-Wformat") ... #endif Builtin Macros¶ __BASE_FILE__

Defined to a string that contains the name of the main input file passed to Clang.

__FILE_NAME__

Clang-specific extension that functions similar to __FILE__ but only renders the last path component (the filename) instead of an invocation dependent full path to that file.

__COUNTER__

Defined to an integer value that starts at zero and is incremented each time the __COUNTER__ macro is expanded.

__INCLUDE_LEVEL__

Defined to an integral value that is the include depth of the file currently being translated. For the main file, this value is zero.

__TIMESTAMP__

Defined to the date and time of the last modification of the current source file.

__clang__

Defined when compiling with Clang

__clang_major__

Defined to the major marketing version number of Clang (e.g., the 2 in 2.0.1). Note that marketing version numbers should not be used to check for language features, as different vendors use different numbering schemes. Instead, use the Feature Checking Macros.

__clang_minor__

Defined to the minor version number of Clang (e.g., the 0 in 2.0.1). Note that marketing version numbers should not be used to check for language features, as different vendors use different numbering schemes. Instead, use the Feature Checking Macros.

__clang_patchlevel__

Defined to the marketing patch level of Clang (e.g., the 1 in 2.0.1).

__clang_version__

Defined to a string that captures the Clang marketing version, including the Subversion tag or revision number, e.g., “1.5 (trunk 102332)”.

__clang_literal_encoding__

Defined to a narrow string literal that represents the current encoding of narrow string literals, e.g., "hello". This macro typically expands to “UTF-8” (but may change in the future if the -fexec-charset="Encoding-Name" option is implemented.)

__clang_wide_literal_encoding__

Defined to a narrow string literal that represents the current encoding of wide string literals, e.g., L"hello". This macro typically expands to “UTF-16” or “UTF-32” (but may change in the future if the -fwide-exec-charset="Encoding-Name" option is implemented.)

Vectors and Extended Vectors¶

Supports the GCC, OpenCL, AltiVec, NEON and SVE vector extensions.

OpenCL vector types are created using the ext_vector_type attribute. It supports the V.xyzw syntax and other tidbits as seen in OpenCL. An example is:

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; }

Query for this feature with __has_attribute(ext_vector_type).

Giving -maltivec option to clang enables support for AltiVec vector syntax and functions. For example:

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

NEON vector types are created using neon_vector_type and neon_polyvector_type attributes. For example:

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; }

GCC vector types are created using the vector_size(N) attribute. The argument N specifies the number of bytes that will be allocated for an object of this type. The size has to be multiple of the size of the vector element type. For example:

// OK: This declares a vector type with four 'int' elements typedef int int4 __attribute__((vector_size(4 * sizeof(int)))); // ERROR: '11' is not a multiple of sizeof(int) typedef int int_impossible __attribute__((vector_size(11))); int4 foo(int4 a) { int4 v; v = a; return v; } Boolean Vectors¶

Clang also supports the ext_vector_type attribute with boolean element types in C and C++. For example:

// legal for Clang, error for GCC: typedef bool bool4 __attribute__((ext_vector_type(4))); // Objects of bool4 type hold 8 bits, sizeof(bool4) == 1 bool4 foo(bool4 a) { bool4 v; v = a; return v; }

Boolean vectors are a Clang extension of the ext vector type. Boolean vectors are intended, though not guaranteed, to map to vector mask registers. The size parameter of a boolean vector type is the number of bits in the vector. The boolean vector is dense and each bit in the boolean vector is one vector element.

The semantics of boolean vectors borrows from C bit-fields with the following differences:

Distinct boolean vectors are always distinct memory objects (there is no packing).

Only the operators ?:, !, ~, |, &, ^ and comparison are allowed on boolean vectors.

Casting a scalar bool value to a boolean vector type means broadcasting the scalar value onto all lanes (same as general ext_vector_type).

It is not possible to access or swizzle elements of a boolean vector (different than general ext_vector_type).

The size and alignment are both the number of bits rounded up to the next power of two, but the alignment is at most the maximum vector alignment of the target.

Vector Literals¶

Vector literals can be used to create vectors from a set of scalars, or vectors. Either parentheses or braces form can be used. In the parentheses form the number of literal values specified must be one, i.e. referring to a scalar value, or must match the size of the vector type being created. If a single scalar literal value is specified, the scalar literal value will be replicated to all the components of the vector type. In the brackets form any number of literals can be specified. For example:

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)); Vector Operations¶

The table below shows the support for each operation by vector extension. A dash indicates that an operation is not accepted according to a corresponding specification.

Operator

OpenCL

AltiVec

GCC

NEON

SVE

[]

yes

yes

yes

yes

yes

unary operators +, –

yes

yes

yes

yes

yes

++, – –

yes

yes

yes

no

no

+,–,*,/,%

yes

yes

yes

yes

yes

bitwise operators &,|,^,~

yes

yes

yes

yes

yes

>>,



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有