Clang中的属性

 

介绍

此页面列出了Clang当前支持的属性。

功能属性

OMP的#pragma声明SIMD 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
     X 

该声明SIMD构建体可以被施加到函数,以使可以处理使用从以SIMD环单次调用的SIMD指令的多个参数的一个或多个版本的创建。该声明SIMD 指令是一种声明指令。 函数可能有多个declare simd指令。在函数上使用declare simd构造可以创建相关函数的SIMD版本,该版本可用于同时处理来自SIMD循环的单个调用的多个参数。declare simd结构的语法如下:

#pragma omp declare simd [clause[[,] clause] ...] new-line
[#pragma omp declare simd [clause[[,] clause] ...] new-line]
[...]
function definition or declaration

where子句是以下之一:

simdlen(length)
linear(argument-list[:constant-linear-step])
aligned(argument-list[:alignment])
uniform(argument-list)
inbranch
notinbranch

#pragma omp声明目标

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
     X 

该声明目标指令指定的变量和函数被映射到表示OpenMP卸载机构的装置。

declare target指令的语法如下:

#pragma omp declare target new-line
declarations-definition-seq
#pragma omp end declare target new-line

_Noreturn 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

声明为的函数_Noreturn不应返回其调用者。编译器将为声明为_Noreturn 能够返回其调用者的函数生成诊断。

abi_tag(gnu :: abi_tag)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

abi_tag属性可以应用于函数,变量,类或内联名称空间声明,以修改实体的受损名称。它能够区分同一实体的不同版本,但支持不同的ABI版本。例如,类的较新版本可以具有不同的数据成员集,因此具有不同的大小。使用该abi_tag属性,可以为类类型的全局变量设置不同的受损名称。因此,旧代码可以继续使用旧的manged名称,新代码将使用带有标记的新修改名称。

acquire_capability(acquire_shared_capability,clang :: acquire_capability,clang :: acquire_shared_capability)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

将功能标记为获取功能。

alloc_align(gnu :: alloc_align)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

__attribute__((alloc_align(<alignment>))在函数声明上使用以指定函数的返回值(必须是指针类型)至少与指示参数的值一致。参数由形式参数列表中的索引给出; 除非函数是C ++非静态成员函数,否则第一个参数具有索引1,在这种情况下,第一个参数具有索引2以考虑隐式this 参数。

// The returned pointer has the alignment specified by the first parameter.
void *a(size_t align) __attribute__((alloc_align(1)));

// The returned pointer has the alignment specified by the second parameter.
void *b(void *v, size_t align) __attribute__((alloc_align(2)));

// The returned pointer has the alignment specified by the second visible
// parameter, however it must be adjusted for the implicit 'this' parameter.
void *Foo::b(void *v, size_t align) __attribute__((alloc_align(3)));

请注意,此属性仅通知编译器函数始终返回充分对齐的指针。它不会导致编译器发出代码来强制执行该对齐。如果返回的poitner未充分对齐,则行为未定义。

alloc_size(gnu :: alloc_size)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

alloc_size属性可以放在返回指针的函数上,以便向编译器提示在返回的指针处有多少字节的内存可用。alloc_size需要一两个参数。

  • alloc_size(N) 意味着参数号N等于返回指针的可用字节数。
  • alloc_size(N, M) 意味着参数号N和参数号M的乘积等于返回指针的可用字节数。

参数编号从1开始。

一个如何使用的例子 alloc_size

void *my_malloc(int a) __attribute__((alloc_size(1)));
void *my_calloc(int a, int b) __attribute__((alloc_size(1, 2)));

int main() {
  void *const p = my_malloc(100);
  assert(__builtin_object_size(p, 0) == 100);
  void *const a = my_calloc(20, 5);
  assert(__builtin_object_size(a, 0) == 100);
}

注意

此属性在clang中的工作方式与在GCC中的工作方式不同。具体来说,clang只会跟踪const指针(如上所述); 我们放弃没有标记为的指针const。在绝大多数情况下,这并不重要,因为LLVM支持该alloc_size 属性。但是,当与其他属性一起使用时,这可能会导致轻微不直观的行为,例如enable_if

人造的(gnu :: artificial)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

artificial属性可以应用于内联函数。如果内联了这样的函数,则该属性指示调试器应将结果指令与调用站点相关联,而不是与内联调用者中的相应行相关联。

assert_capability(assert_shared_capability,clang :: assert_capability,clang :: assert_shared_capability)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

标记一个动态测试是否保持功能的函数,如果未保存,则暂停程序。

assume_aligned(gnu :: assume_aligned)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

__attribute__((assume_aligned(<alignment>[,<offset>]))在函数声明上使用以指定函数的返回值(必须是指针类型)具有指定的偏移量(以字节为单位),具有指定对齐的地址。如果省略,则偏移量为零。

// The returned pointer value has 32-byte alignment.
void *a() __attribute__((assume_aligned (32)));

// The returned pointer value is 4 bytes greater than an address having
// 32-byte alignment.
void *b() __attribute__((assume_aligned (32, 4)));

请注意,此属性向编译器提供有关代码已确保为真的条件的信息。它不会导致编译器强制执行提供的对齐假设。

可用性(clang :: availability,clang :: availability)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

availability属性可以放在声明上,以描述相对于操作系统版本的声明的生命周期。考虑假设函数的函数声明f

void f(void) __attribute__((availability(macos,introduced=10.4,deprecated=10.6,obsoleted=10.7)));

可用性属性表示f在macOS 10.4中引入,在macOS 10.6中已弃用,在macOS 10.7中已废弃。Clang使用此信息来确定何时使用它是安全的f:例如,如果指示Clang编译macOS 10.5的代码,则调用f() 成功。如果指示Clang编译macOS 10.6的代码,则调用成功,但Clang发出警告,指定该函数已弃用。最后,如果指示Clang编译macOS 10.7的代码,则调用失败,因为f()不再可用。

availability属性是以逗号分隔的列表,以平台名称开头,然后包括在声明的生命周期中指定重要里程碑的子句(以任何顺序)以及其他信息。这些条款可以是:

介绍= 版本

引入此声明的第一个版本。

不赞成= 版本

弃用此声明的第一个版本,意味着用户应该从此API迁移。

已废弃= 版本

此声明已废弃的第一个版本,意味着它已被完全删除且无法再使用。

不可用

此声明在此平台上永远不可用。

message = string-literal

Clang在发出有关使用已弃用或已废弃的声明的警告或错误时将提供的其他消息文本。用于将用户定向到替换API。

replacement = string-literal

Clang将在发出有关使用已弃用声明的警告时用于提供Fix-It的附加消息文本。Fix-It将使用指定的新声明替换已弃用的声明。

可以在声明上放置多个可用性属性,该声明可以对应于不同的平台。仅使用与目标平台对应的平台的可用性属性; 任何其他人都将被忽略。如果没有可用性属性指定当前目标平台的可用性,则忽略可用性属性。支持的平台是:

ios

Apple的iOS操作系统。最小部署目标由-mios-version-min=*version*-miphoneos-version-min=*version* 命令行参数指定。

macos

Apple的macOS操作系统。最小部署目标由-mmacosx-version-min=*version*命令行参数指定。 macosx支持出于向后兼容性的原因,但不推荐使用。

tvos

Apple的tvOS操作系统。最小部署目标由-mtvos-version-min=*version*命令行参数指定。

watchos

Apple的watchOS操作系统。最小部署目标由-mwatchos-version-min=*version*命令行参数指定。

即使在引入声明之前部署回平台版本,通常也可以使用声明。发生这种情况时,声明链接很弱,就好像weak_import属性已添加到声明中一样。弱链接声明可能存在也可能不存在运行时,并且程序可以通过检查该声明的地址是否为非NULL来确定是否存在声明。

strict在引入声明之前,该标志在部署回平台版本时不允许使用API​​。尝试在引入之前使用此API会导致硬错误。弱链接几乎总是更好的API选择,因为它允许用户在运行时查询可用性。

如果同一实体有多个声明,则可用性属性必须基于每个平台匹配,或者稍后声明必须不具有该平台的可用性属性。例如:

void g(void) __attribute__((availability(macos,introduced=10.4)));
void g(void) __attribute__((availability(macos,introduced=10.4))); // okay, matches
void g(void) __attribute__((availability(ios,introduced=4.0))); // okay, adds a new platform
void g(void); // okay, inherits both macos and ios availability from above.
void g(void) __attribute__((availability(macos,introduced=10.5))); // error: mismatch

当一个方法覆盖另一个方法时,覆盖方法可以比重写方法更广泛地使用,例如:

@interface A
- (id)method __attribute__((availability(macos,introduced=10.4)));
- (id)method2 __attribute__((availability(macos,introduced=10.4)));
@end

@interface B : A
- (id)method __attribute__((availability(macos,introduced=10.3))); // okay: method moved into base class later
- (id)method __attribute__((availability(macos,introduced=10.5))); // error: this method was available via the base class in 10.4
@end

从macOS 10.12 SDK开始,API_AVAILABLE宏 <os/availability.h>可以简化拼写:

@interface A
- (id)method API_AVAILABLE(macos(10.11)));
- (id)otherMethod API_AVAILABLE(macos(10.11), ios(11.0));
@end

另请参阅@available的文档

carries_dependency 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

carries_dependency属性指定进出函数的依赖关系传播。

当在函数或Objective-C方法上指定时,该carries_dependency 属性意味着返回值带有函数的依赖性,因此实现不需要在从该函数返回时约束排序。函数及其调用者的实现可以选择保留依赖性而不是发出诸如栅栏的存储器排序指令。

注意,此属性不会更改程序的含义,但可能会生成更高效的代码。

CODE_SEG 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
   X   

__declspec(code_seg)属性允许将代码放置到单独的命名段中,这些段可以单独分页或锁定在内存中。此属性用于控制实例化模板和编译器生成的代码的放置。请参阅MSDN上的__declspec(code_seg)文档。

收敛(clang :: convergent,clang :: convergent)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

convergent属性可以放在函数声明中。它被转换为LLVM convergent属性,该属性指示具有此属性的函数的调用指令不能依赖于任何其他值。

在为SPMD / SIMT编程模型设计的语言中,例如OpenCL或CUDA,具有此属性的函数的调用指令必须由工作组或子组中的所有工作项或线程执行。

该属性不同,noduplicate因为如果可以证明重复的函数调用不依赖于任何其他值,例如展开由所有工作项执行的循环,则它允许重复函数调用。

示例用法:.. code-block :: c

void convfunc(void)__ attribute __((convergent)); //将其设置为C ++ 11属性在C ++程序中也是有效的。// void convfunc(void)[[clang :: convergent]];

cpu_dispatch(clang :: cpu_dispatch,clang :: cpu_dispatch)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

cpu_specificcpu_dispatch属性用于定义和解决多版本的功能。这种形式的多版本化提供了一种机制,用于在翻译单元之间声明版本并手动指定已解析的功能列表。指定的CPU定义了一组要调用的函数所需的最小特性。结果是未来的处理器执行新处理器可以执行的功能的最严格版本。

功能版本定义为cpu_specific,它将一个或多个CPU名称作为参数。例如:

// Declares and defines the ivybridge version of single_cpu.
__attribute__((cpu_specific(ivybridge)))
void single_cpu(void){}

// Declares and defines the atom version of single_cpu.
__attribute__((cpu_specific(atom)))
void single_cpu(void){}

// Declares and defines both the ivybridge and atom version of multi_cpu.
__attribute__((cpu_specific(ivybridge, atom)))
void multi_cpu(void){}

可以在项目的源代码中的任何位置声明调度(或解析)函数cpu_dispatch。此属性将一个或多个CPU名称作为参数(如cpu_specific)。标记的函数cpu_dispatch不会被定义,只会被声明。如果这样的标记函数有定义,则忽略函数的任何副作用; 允许ICC兼容的普通函数体。

// Creates a resolver for single_cpu above.
__attribute__((cpu_dispatch(ivybridge, atom)))
void single_cpu(void){}

// Creates a resolver for multi_cpu, but adds a 3rd version defined in another
// translation unit.
__attribute__((cpu_dispatch(ivybridge, atom, sandybridge)))
void multi_cpu(void){}

请注意,可以使用基于比程序中存在的更多或更少选项来分派的解析函数。指定较少将导致在解析期间不考虑省略的选项。指定未在程序中定义的解析版本将导致链接失败。

generic如果执行的处理器不满足CPU名称中所需的功能,也可以指定将解析的CPU名称。在不满足多版本化功能的任何选项的处理器上执行的程序的行为是未定义的。

cpu_specific(clang :: cpu_specific,clang :: cpu_specific)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

cpu_specificcpu_dispatch属性用于定义和解决多版本的功能。这种形式的多版本化提供了一种机制,用于在翻译单元之间声明版本并手动指定已解析的功能列表。指定的CPU定义了一组要调用的函数所需的最小特性。结果是未来的处理器执行新处理器可以执行的功能的最严格版本。

功能版本定义为cpu_specific,它将一个或多个CPU名称作为参数。例如:

// Declares and defines the ivybridge version of single_cpu.
__attribute__((cpu_specific(ivybridge)))
void single_cpu(void){}

// Declares and defines the atom version of single_cpu.
__attribute__((cpu_specific(atom)))
void single_cpu(void){}

// Declares and defines both the ivybridge and atom version of multi_cpu.
__attribute__((cpu_specific(ivybridge, atom)))
void multi_cpu(void){}

可以在项目的源代码中的任何位置声明调度(或解析)函数cpu_dispatch。此属性将一个或多个CPU名称作为参数(如cpu_specific)。标记的函数cpu_dispatch不会被定义,只会被声明。如果这样的标记函数有定义,则忽略函数的任何副作用; 允许ICC兼容的普通函数体。

// Creates a resolver for single_cpu above.
__attribute__((cpu_dispatch(ivybridge, atom)))
void single_cpu(void){}

// Creates a resolver for multi_cpu, but adds a 3rd version defined in another
// translation unit.
__attribute__((cpu_dispatch(ivybridge, atom, sandybridge)))
void multi_cpu(void){}

请注意,可以使用基于比程序中存在的更多或更少选项来分派的解析函数。指定较少将导致在解析期间不考虑省略的选项。指定未在程序中定义的解析版本将导致链接失败。

generic如果执行的处理器不满足CPU名称中所需的功能,也可以指定将解析的CPU名称。在不满足多版本化功能的任何选项的处理器上执行的程序的行为是未定义的。

不推荐使用(gnu :: deprecated)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXXX   

deprecated属性可以应用于函数,变量或类型。在识别预期在程序的未来版本中删除的函数,变量或类型时,这非常有用。

考虑假设函数的函数声明f

void f(void) __attribute__((deprecated("message", "replacement")));

当拼写为__attribute __((不建议使用))时,不推荐使用的属性可以有两个可选的字符串参数。第一个是发出警告时要显示的消息; 第二个使编译器能够提供Fix-It以使用新名称替换已弃用的名称。否则,当拼写为 [[gnu :: deprecated]]或[[deprecated]]时,该属性可以有一个可选的字符串参数,该参数是发出警告时要显示的消息。

diagnose_if 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
X      

diagnose_if如果对属性函数的调用满足某些用户定义的条件,则可以将该属性放在函数声明上,以便在编译时发出警告或错误。例如:

void abs(int a)
  __attribute__((diagnose_if(a >= 0, "Redundant abs call", "warning")));
void must_abs(int a)
  __attribute__((diagnose_if(a >= 0, "Redundant abs call", "error")));

int val = abs(1); // warning: Redundant abs call
int val2 = must_abs(1); // error: Redundant abs call
int val3 = abs(val);
int val4 = must_abs(val); // Because run-time checks are not emitted for
                          // diagnose_if attributes, this executes without
                          // issue.

diagnose_ifenable_if与一些关键差异密切相关:

  • 重载分辨率不知道diagnose_if属性:仅在我们从给定候选集中选择最佳候选者之后才考虑它们。
  • 仅在其diagnose_if属性上不同的函数声明被认为是相同函数的重新声明(不是重载)。
  • 如果diagnose_if无法评估提供的条件,则不会发出诊断信息。

否则,diagnose_if基本上是逻辑上的否定enable_if

作为子弹二号的结果,diagnose_if属性将堆叠在同一个函数上。例如:

int foo() __attribute__((diagnose_if(1, "diag1", "warning")));
int foo() __attribute__((diagnose_if(1, "diag2", "warning")));

int bar = foo(); // warning: diag1
                 // warning: diag2
int (*fooptr)(void) = foo; // warning: diag1
                           // warning: diag2

constexpr int supportsAPILevel(int N) { return N < 5; }
int baz(int a)
  __attribute__((diagnose_if(!supportsAPILevel(10),
                             "Upgrade to API level 10 to use baz", "error")));
int baz(int a)
  __attribute__((diagnose_if(!a, "0 is not recommended.", "warning")));

int (*bazptr)(int) = baz; // error: Upgrade to API level 10 to use baz
int v = baz(0); // error: Upgrade to API level 10 to use baz

使用查询此功能__has_attribute(diagnose_if)

disable_tail_calls(clang :: disable_tail_calls,clang :: disable_tail_calls)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

disable_tail_calls属性指示后端不在标记的函数内执行尾调用优化。

例如:

int callee(int);

int foo(int a) __attribute__((disable_tail_calls)) {
  return callee(a); // This call is not tail-call optimized.
}

将虚拟功能标记disable_tail_calls为合法。

int callee(int);

class Base {
public:
  [[clang::disable_tail_calls]] virtual int foo1() {
    return callee(); // This call is not tail-call optimized.
  }
};

class Derived1 : public Base {
public:
  int foo1() override {
    return callee(); // This call is tail-call optimized.
  }
};

enable_if 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
X     X

注意

此属性的某些功能是实验性的。单个声明中的多个enable_if属性的含义可能会在将来的clang版本中发生更改。此外,ABI未标准化,并且在未来版本中名称修改可能会更改。为避免这种情况,请使用asm标签。

enable_if属性可以放在函数声明上,以根据函数参数的值控制选择哪个重载。与overloadable属性结合使用时,此功能也可在C中使用。

int isdigit(int c);
int isdigit(int c) __attribute__((enable_if(c <= -1 || c > 255, "chosen when 'c' is out of range"))) __attribute__((unavailable("'c' must have the value of an unsigned char or EOF")));

void foo(char c) {
  isdigit(c);
  isdigit(10);
  isdigit(-10);  // results in a compile-time error.
}

enable_if属性有两个参数,第一个是根据函数参数编写的表达式,第二个是一个字符串,解释了为什么无法选择在诊断中显示此重载候选项。表达式是函数签名的一部分,用于确定它是否是重新声明(遵循在确定C ++模板特化是否与ODR等效时使用的规则),但不是该类型的一部分。

enable_if表达式被计算为好像它是bool返回的constexpr函数的主体,该函数使用它所应用的函数的参数声明,然后使用调用站点处的参数调用。如果结果为false或无法通过常量表达式求值确定,则不会选择此重载,并且如果编译因此失败,则可以在诊断中使用提供的字符串。

因为enable_if表达式是未评估的上下文,所以没有全局状态更改,也没有将信息从enable_if表达式传递到函数体的能力。例如,假设我们想要调用strnlen(strbuf,maxlen)来解析为strnlen_chk(strbuf,maxlen,strbuf的大小),只有在可以确定strbuf的大小时:

__attribute__((always_inline))
static inline size_t strnlen(const char *s, size_t maxlen)
  __attribute__((overloadable))
  __attribute__((enable_if(__builtin_object_size(s, 0) != -1))),
                           "chosen when the buffer size is known but 'maxlen' is not")))
{
  return strnlen_chk(s, maxlen, __builtin_object_size(s, 0));
}

多个enable_if属性可以应用于单个声明。在这种情况下,以下面的方式从左到右评估enable_if表达式。首先,丢弃其enable_if表达式求值为false或无法求值的候选者。如果其余候选者不共享ODR等效的enable_if表达式,则重载决策是不明确的。否则,enable_if重载解析将继续执行尚未被丢弃且具有剩余enable_if属性的候选项的下一个enable_if属性。通过这种方式,我们使用enable_if从许多可行的重载中选择最具体的重载。

void f() __attribute__((enable_if(true, "")));  // #1
void f() __attribute__((enable_if(true, ""))) __attribute__((enable_if(true, "")));  // #2

void g(int i, int j) __attribute__((enable_if(i, "")));  // #1
void g(int i, int j) __attribute__((enable_if(j, ""))) __attribute__((enable_if(true)));  // #2

在这个例子中,对f()的调用总是被解析为#2,因为第一个enable_if表达式对于两个声明都是ODR等效的,但#1没有另一个enable_if表达式来继续评估,所以下一轮评估已经只有一个候选人。在对g(1,1)的调用中,即使#2具有更多的enable_if属性,调用也是不明确的,因为第一个enable_if表达式不是ODR等效的。

使用查询此功能__has_attribute(enable_if)

请注意,具有一个或多个enable_if属性的函数可能没有其地址,除非所述条件指定的所有条件 enable_if都是常量true。例如:

const int TrueConstant = 1;
const int FalseConstant = 0;
int f(int a) __attribute__((enable_if(a > 0, "")));
int g(int a) __attribute__((enable_if(a == 0 || a != 0, "")));
int h(int a) __attribute__((enable_if(1, "")));
int i(int a) __attribute__((enable_if(TrueConstant, "")));
int j(int a) __attribute__((enable_if(FalseConstant, "")));

void fn() {
  int (*ptr)(int);
  ptr = &f; // error: 'a > 0' is not always true
  ptr = &g; // error: 'a == 0 || a != 0' is not a truthy constant
  ptr = &h; // OK: 1 is a truthy constant
  ptr = &i; // OK: 'TrueConstant' is a truthy constant
  ptr = &j; // error: 'FalseConstant' is a constant, but not truthy
}

由于enable_if评估在重载解析期间发生,因此 enable_if与模板一起使用时可能会产生不直观的结果,具体取决于何时解决重载。在下面的例子,铛将发出诊断有关没有可行的重载foobar,但不是在baz

double foo(int i) __attribute__((enable_if(i > 0, "")));
void *foo(int i) __attribute__((enable_if(i <= 0, "")));
template <int I>
auto bar() { return foo(I); }

template <typename T>
auto baz() { return foo(T::number); }

struct WithNumber { constexpr static int number = 1; };
void callThem() {
  bar<sizeof(WithNumber)>();
  baz<WithNumber>();
}

这是因为,在barfoo先于模板实例解决,所以该值I是未知的(因此,既enable_if 为条件foo失败)。然而,在bazfoo在模板实例化过程中解决了,所以价值T::number是已知的。

external_source_symbol(clang :: external_source_symbol,clang :: external_source_symbol)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

external_source_symbol属性指定声明源自外部源并描述该源的性质。

Clang能够识别外部定义的声明这一事实可用于为依赖于自动生成的代码的混合语言项目或项目提供更好的工具支持。例如,使用Clang并支持混合语言项目的IDE可以使用此属性来提供正确的“跳转到定义”功能。有关具体示例,请考虑在Swift文件中定义的协议:

@objc public protocol SwiftProtocol {
  func method()
}

通过包含由Swift编译器生成的头文件,可以从Objective-C代码使用此协议。该标头中的声明可以使用该external_source_symbol属性使Clang意识到SwiftProtocol实际上源自Swift模块的事实:

__attribute__((external_source_symbol(language="Swift",defined_in="module")))
@protocol SwiftProtocol
@required
- (void) method;
@end

因此,当在引用的位置执行“跳转到定义”时SwiftProtocol,IDE可以跳转到Swift源文件中的原始定义,而不是跳转到自动生成的头文件中的Objective-C声明。

external_source_symbol属性是以逗号分隔的列表,其中包含描述特定声明的来源和性质的子句。这些条款可以是:

language = string-literal

定义此声明的源语言的名称。

defined_in = string-literal

定义声明的源容器的名称。源容器的确切定义是特定于语言的,例如Swift的源容器是模块,因此defined_in应指定Swift模块名称。

generated_declaration

该声明由某些工具自动生成。

条款可以按任何顺序指定。上面列出的子句都是可选的,但属性必须至少有一个子句。

flatten(gnu :: flatten)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

flatten除非无法执行此操作,否则该属性会导致属性函数内的调用内联,例如,如果被调用者的主体不可用或者被调用者具有该noinline属性。

force_align_arg_pointer(gnu :: force_align_arg_pointer)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

使用此属性强制堆栈对齐。

旧版x86代码使用4字节堆栈对齐。与堆栈一起使用的较新的对齐SSE指令(如“movaps”)要求操作数为16字节对齐。此属性在函数序言中重新对齐堆栈,以确保堆栈可以与SSE指令一起使用。

请注意,x86_64 ABI强制呼叫站点处的16字节堆栈对齐。因此,x86_64上不需要'force_align_arg_pointer',除非在极少数情况下调用者没有正确对齐堆栈(例如,从i386 arch代码跳转)。

__attribute__ ((force_align_arg_pointer))
void f () {
  ...
}

format(gnu :: format)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

铛支持format属性,它表示该函数接受printfscanf样格式字符串和相应的参数或va_list包含这些参数。

有关格式属性,请参阅GCC文档以查找有关属性语法的详细信息。

Clang使用此属性实现两种检查。

  1. Clang检查带有format属性的函数是否使用格式字符串调用,该格式字符串使用允许的格式说明符,并且该参数与格式字符串匹配。这是-Wformat警告,默认情况下处于启用状态。

  2. Clang检查格式字符串参数是文字字符串。这是-Wformat-nonliteral警告,默认情况下是关闭的。

    Clang的实现方式与GCC大致相同,但接受va_list参数的函数存在差异(例如vprintf)。GCC不会-Wformat-nonliteral对这些函数的调用发出警告。如果格式字符串来自函数参数,Clang不会发出警告,其中函数使用兼容属性进行注释,否则会发出警告。例如:

    __attribute__((__format__ (__scanf__, 1, 3)))
    void foo(const char* s, char *buf, ...) {
      va_list ap;
      va_start(ap, buf);
    
      vprintf(s, ap); // warning: format string is not a string literal
    }
    

    在这种情况下,我们警告因为s包含类似scanf函数的格式字符串 ,但它被传递给类似printf函数。

    如果删除该属性,则clang仍然会发出警告,因为格式字符串不是字符串文字。

    另一个例子:

    __attribute__((__format__ (__printf__, 1, 3)))
    void foo(const char* s, char *buf, ...) {
      va_list ap;
      va_start(ap, buf);
    
      vprintf(s, ap); // warning
    }
    

    在这种情况下,Clang不会发出警告,因为格式字符串s和相应的参数都是注释的。如果参数不正确,则调用者foo将收到警告。

ifunc(gnu :: ifunc)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

__attribute__((ifunc("resolver"))) 用于标记应在运行时通过调用解析器函数来解析声明的地址。

解析器函数的符号名称以引号给出。必须在当前翻译单元中定义具有此名称的函数(在修改之后); 它可能是static。解析器函数应该不带参数并返回指针。

ifunc属性只能用于函数声明。具有ifunc属性的函数声明被视为声明的实体的定义。该实体不得具有薄弱的联系; 例如,在C ++中,如果将该位置的定义视为内联,则不能将其应用于声明。

并非所有目标都支持此属性。使用binutils v2.20.1或更高版本以及glibc v2.11.1或更高版本时,ELF目标支持此属性。非ELF目标目前不支持此属性。

internal_linkage(clang :: internal_linkage,clang :: internal_linkage)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

internal_linkage属性将声明的链接类型更改为internal。这类似于C风格static,但可以用于类和类方法。应用于类定义时,此属性会影响该类的所有方法和静态数据成员。这可以用于通过从导出表中排除不需要的类方法来包含C ++库的ABI。

中断(ARM)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

Clang支持__attribute__((interrupt("TYPE")))ARM目标上的GNU样式属性。该属性可以附加到函数定义,并指示后端生成适当的函数入口/出口代码,以便它可以直接用作中断服务例程。

传递给interrupt属性的参数是可选的,但如果提供,它必须是具有以下值之一的字符串文字:“IRQ”,“FIQ”,“SWI”,“ABORT”,“UNDEF”。

语义如下:

  • 如果函数是AAPCS,则Clang指示后端在进入时将堆栈重新对齐为8个字节。这是公共接口上AAPCS的一般要求,但在发生异常时可能不成立。这样做可以调用其他AAPCS函数。

  • 如果CPU是M级,则需要完成所有这些操作,因为架构本身的设计方式使得遵循正常AAPCS ABI约束的函数是有效的异常处理程序。

  • 如果CPU不是M级,则修改序言和结尾以保存所有使用的非库存寄存器,以便在返回时用户模式状态不会被破坏。请注意,为避免不必要的开销,只能以这种方式保存通用(整数)寄存器。如果需要VFP操作,则必须手动保存该状态。

    具体而言,“FIQ”以外的中断种类将保存除“lr”和“sp”之外的所有核心寄存器。“FIQ”中断将保存r0-r7。

  • 如果CPU不是M-class,则返回指令将更改为体系结构允许的规范序列之一以进行异常返回。在可能的情况下,功能本身将进行必要的“lr”调整,以便选择“首选返回地址”。

    遗憾的是,编译器无法为“UNDEF”处理程序提供此保证,其中从“lr”到首选返回地址的偏移量取决于生成异常的代码的执行状态。在这种情况下,将使用等同于“movs pc,lr”的序列。

中断(AVR)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

Clang支持__attribute__((interrupt))AVR目标上的GNU样式属性。该属性可以附加到函数定义,并指示后端生成适当的函数入口/出口代码,以便它可以直接用作中断服务例程。

在AVR上,硬件在执行中断时全局禁用中断。使用此属性声明的中断处理程序的第一条指令是重新启用中断的SEI指令。另请参见未插入SEI指令的signal属性。

中断(MIPS)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

Clang支持__attribute__((interrupt("ARGUMENT")))MIPS目标上的GNU样式属性。该属性可以附加到函数定义,并指示后端生成适当的函数入口/出口代码,以便它可以直接用作中断服务例程。

默认情况下,编译器将生成一个函数序言和结尾,适用于处理外部中断控制器(eic)生成的中断的中断服务程序。可以使用“eic”参数显式请求此行为。

否则,为了使用向量中断模式,传递的参数应为“vector = LEVEL”形式,其中LEVEL是以下值之一:“sw0”,“sw1”,“hw0”,“hw1”,“hw2” ,“hw3”,“hw4”,“hw5”。然后,编译器将中断屏蔽设置为相应的级别,该级别将屏蔽所有中断,包括参数。

语义如下:

  • 修改序言,以便将异常程序计数器(EPC)和状态协处理器寄存器保存到堆栈中。设置中断屏蔽,以便只能通过更高优先级的中断来中断该功能。结语将恢复以前的EPC和状态值。
  • 修改序言和结尾以根据需要保存和恢复所有非内核寄存器。
  • FPU在序言中被禁用,因为浮动指针寄存器没有溢出到堆栈。
  • 函数返回序列被更改为使用异常返回指令。
  • 该参数设置与指定的中断级别对应的功能的中断屏蔽。如果未指定掩码,则中断掩码默认为“eic”。

中断(RISCV)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

Clang支持__attribute__((interrupt))RISCV目标上的GNU样式属性。该属性可以附加到函数定义,并指示后端生成适当的函数入口/出口代码,以便它可以直接用作中断服务例程。

此参数允许值是usersupervisormachine。如果没有参数,则默认为机器。

同一声明上的重复中断属性将导致发出警告。如果重复声明,则以最后一个声明为准。

请参阅:https : //gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html https://riscv.org/specifications/privileged-isa/ RISC-V指令集手册第二卷:特权架构版本1.10。

内核

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
X     X

__attribute__((kernel))用于kernel在RenderScript中标记函数。

在RenderScript中,kernel函数用于表示数据并行计算。RenderScript运行时有效地并行化kernel 函数以在诸如多核CPU和GPU之类的计算资源上运行。有关更多信息,请参阅RenderScript文档。

lifetimebound(clang :: lifetimebound)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

lifetimebound属性指示由注释函数的返回值(或者,对于构造函数的参数,在构造对象的值中)保留由函数参数或隐式对象参数拥有的资源。它仅在C ++中受支持。

此属性提供了C ++委员会文件[ http://wg21.link/p0936r0](P0936R0)中描述的工具的实验性实现,并且随着相应功能的设计更改而可能会发生变化。

long_call(gnu :: long_call,gnu :: far)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

铛支持__attribute__((long_call))__attribute__((far))以及__attribute__((near))对MIPS目标的属性。这些属性只能添加到函数声明中,并在直接调用函数时更改编译器生成的代码。该near属性允许使用该jal指令调用该函数,该指令要求该函数位于与调用者相同的自然对齐的256MB段中。在long_callfar属性是同义词和要求使用作品的功能之间的距离,无论不同的调用序列。

这些属性对与位置无关的代码没有影响。

这些属性优先于命令行开关,例如-mlong-calls-mno-long-calls

micromips(gnu :: micromips)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

Clang支持MIPS目标上的GNU样式__attribute__((micromips))和 __attribute__((nomicromips))属性。这些属性可以附加到函数定义,并指示后端生成或不生成该函数的microMIPS代码。

这些属性会覆盖命令行上的-mmicromips和-mno-micromips选项。

min_vector_width(clang :: min_vector_width,clang :: min_vector_width)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

Clang支持该__attribute__((min_vector_width(width)))属性。该属性可以附加到函数并且通知后端该函数期望生成至少该宽度的向量。特定于目标的最大矢量宽度仍然适用。这意味着即使您要求的内容大于目标支持,您也只能获得目标支持的内容。此属性旨在作为控制目标启发式的提示,可以生成比目标硬件支持的更窄的向量。

目前,X86目标使用它来允许一些支持512位向量的CPU限制为使用256位向量以避免频率损失。目前,-prefer-vector-width=256命令行选项已启用此功能。该min_vector_width属性可用于防止后端尝试拆分向量操作以匹配prefer-vector-width。来自x86intrin.h的所有X86向量内在函数都已设置此属性。此外,使用任何特定于X86的向量内置函数将在调用函数上隐式设置此属性。目的是使用X86内在函数显式编写矢量代码将防止prefer-vector-width影响代码。

no_caller_saved_registers(gnu :: no_caller_saved_registers)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

使用此属性指示指定的函数没有调用者保存的寄存器。也就是说,除了用于将参数传递给函数或从函数返回参数的寄存器之外,所有寄存器都是被调用者保存的。编译器保存并恢复未用于向函数传递或返回参数的任何已修改寄存器。

用户可以从中断处理程序调用使用'no_caller_saved_registers'属性指定的函数,而无需保存和恢复所有调用被破坏的寄存器。

请注意,'no_caller_saved_registers'属性不是调用约定。实际上,它只会覆盖调用者应该保存哪些寄存器的决定,而不是如何将参数从调用者传递给被调用者。

例如:

__attribute__ ((no_caller_saved_registers, fastcall))
void f (int arg1, int arg2) {
  ...
}

在这种情况下,参数'arg1'和'arg2'将在寄存器中传递。在这种情况下,在32位x86目标上,函数“f”将使用ECX和EDX作为寄存器参数。但是,它不会假设任何临时寄存器,并且应该保存和恢复除ECX和EDX之外的任何修改的寄存器。

no_sanitize(clang :: no_sanitize,clang :: no_sanitize)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

使用no_sanitize函数或全局变量声明中的属性指定不应用特定检测或一组检测。该属性采用字符串文字列表,其含义与-fno-sanitize=标志接受的值相同 。例如,指定不应将AddressSanitizer和ThreadSanitizer应用于函数或变量。__attribute__((no_sanitize("address", "thread")))

有关支持的清理程序标志的完整列表,请参阅控制代码生成

no_sanitize_address(no_address_safety_analysis,gnu :: no_address_safety_analysis,gnu :: no_sanitize_address)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

使用__attribute__((no_sanitize_address))上的功能或全局变量声明指定地址的安全规范(如AddressSanitizer)不应适用。

no_sanitize_memory 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

__attribute__((no_sanitize_memory))在函数声明上使用以指定不应插入对未初始化内存的检查(例如,通过MemorySanitizer)。该工具仍然可以检测该功能,以避免在其他地方出现误报。

no_sanitize_thread 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

使用__attribute__((no_sanitize_thread))函数声明来指定ThreadSanitizer不应插入对普通(非原子)内存访问的数据争用检查。该工具仍然使用该工具来避免误报并提供有意义的堆栈跟踪。

no_split_stack(gnu :: no_split_stack)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

no_split_stack属性禁用特定功能的拆分堆栈前导码的发射。如果-fsplit-stack 未指定,则无效。

no_stack_protector(clang :: no_stack_protector,clang :: no_stack_protector)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

Clang支持在__attribute__((no_stack_protector))指定函数上禁用堆栈保护程序的属性。在使用-fstack-protector编译器选项构建时,此属性对于在某些函数上有选择地禁用堆栈保护程序非常有用 。

例如,它禁用了函数的堆栈保护程序,foobar仍然使用带有-fstack-protector 选项的堆栈保护程序构建函数 。

int __attribute__((no_stack_protector))
foo (int x); // stack protection will be disabled for foo.

int bar(int y); // bar can be built with the stack protector.

noalias 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
   X   

noalias属性表示函数内部唯一的内存访问是从其指针类型参数指向的对象加载和存储,具有任意偏移。

nocf_check(gnu :: nocf_check)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

面向跳转的编程攻击依赖于篡改间接调用/ jmp使用的地址,例如将控制流重定向到二进制文件中的非程序员预期字节。X86支持间接分支跟踪(IBT),作为控制流强制技术(CET)的一部分。IBT工具ENDBR指令用于指定间接调用/ jmp的有效目标。该nocf_check属性有两个作用:1。对函数的附加 - 不要在函数的开头添加ENDBR指令。2.对函数指针的附加 - 不跟踪该指针的目标函数(通过向间接调用指令添加nocf_check前缀)。

nodiscard,warn_unused_result,铛:: warn_unused_result,GNU :: warn_unused_result 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

Clang支持在可疑情况下丢弃函数调用表达式的结果时进行诊断的能力。当函数或其返回类型标记为[[nodiscard]] (或__attribute__((warn_unused_result)))并且函数调用显示为未明确转换为void的潜在评估的丢弃值表达式时, 将生成诊断。

noduplicate(clang :: noduplicate,clang :: noduplicate)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

noduplicate属性可以放在函数声明上,以控制是否可以通过优化来复制对此函数的函数调用。这对于具有某些特殊要求的函数的实现是必需的,例如OpenCL“barrier”函数,它可能需要由在硬件上以锁步执行的所有线程并发运行。例如,在下面的代码中应用于函数“nodupfunc”的这个属性避免了:

void nodupfunc() __attribute__((noduplicate));
// Setting it as a C++11 attribute is also valid
// void nodupfunc() [[clang::noduplicate]];
void foo();
void bar();

nodupfunc();
if (a > n) {
  foo();
} else {
  bar();
}

可能会通过一些优化修改为类似于此的代码:

if (a > n) {
  nodupfunc();
  foo();
} else {
  nodupfunc();
  bar();
}

其中对“nodupfunc”的调用是重复的并且陷入条件的两个分支。

nomicromips(gnu :: nomicromips)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

Clang支持MIPS目标上的GNU样式__attribute__((micromips))和 __attribute__((nomicromips))属性。这些属性可以附加到函数定义,并指示后端生成或不生成该函数的microMIPS代码。

这些属性会覆盖命令行上的-mmicromips和-mno-micromips选项。

不返回的

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
 X    X

声明为的函数[[noreturn]]不应返回其调用者。编译器将为声明为[[noreturn]] 能够返回其调用者的函数生成诊断。

not_tail_called(clang :: not_tail_called,clang :: not_tail_called)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

not_tail_called属性可防止静态绑定调用的尾调用优化。它对间接调用没有影响。标记为的虚函数,objective-c方法和函数always_inline无法标记为not_tail_called

例如,它可以防止在以下情况下进行尾调用优化:

int __attribute__((not_tail_called)) foo1(int);

int foo2(int a) {
  return foo1(a); // No tail-call optimization on direct calls.
}

但是,在这种情况下,它不会阻止尾调用优化:

int __attribute__((not_tail_called)) foo1(int);

int foo2(int a) {
  int (*fn)(int) = &foo1;

  // not_tail_called has no effect on an indirect call even if the call can be
  // resolved at compile time.
  return (*fn)(a);
}

将虚函数标记为not_tail_called错误:

class Base {
public:
  // not_tail_called on a virtual function is an error.
  [[clang::not_tail_called]] virtual int foo1();

  virtual int foo2();

  // Non-virtual functions can be marked ``not_tail_called``.
  [[clang::not_tail_called]] int foo3();
};

class Derived1 : public Base {
public:
  int foo1() override;

  // not_tail_called on a virtual function is an error.
  [[clang::not_tail_called]] int foo2() override;
};

nothrow(gnu :: nothrow)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX X  X

Clang支持GNU样式__attribute__((nothrow))和Microsoft样式 __declspec(nothrow)属性,相当于函数声明中的noexcept。此属性通知编译器注释函数不会引发异常。这可以防止异常展开。此属性对C标准库中保证不会引发异常的函数特别有用。

objc_boxable(clang :: objc_boxable,clang :: objc_boxable)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

标有该objc_boxable属性的结构和联合可以与Objective-C盒装表达式语法一起使用@(...)

用法__attribute__((objc_boxable))。此属性只能放在可复制的结构或联合的声明上:

struct __attribute__((objc_boxable)) some_struct {
  int i;
};
union __attribute__((objc_boxable)) some_union {
  int i;
  float f;
};
typedef struct __attribute__((objc_boxable)) _some_struct some_struct;

// ...

some_struct ss;
NSValue *boxed = @(ss);

objc_method_family(clang :: objc_method_family,clang :: objc_method_family)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

Objective-C中的许多方法具有由其选择器确定的常规含义。尽管没有正确的选择器,或者不具有其选择器所暗示的传统含义,但有时能够将方法标记为具有特定的传统含义是有用的。对于这些用例,我们提供了一个属性来专门描述方法所属的“方法族”。

使用方法__attribute__((objc_method_family(X))),其中X是一个 nonealloccopyinitmutableCopy,或new。此属性只能放在方法声明的末尾:

- (NSString *)initMyStringValue __attribute__((objc_method_family(none)));

用户谁不希望改变的方法的传统含义,谁只是想记录其非标准的保留和释放语义,应该使用固定行为属性(ns_returns_retained, ns_returns_not_retained,等)。

使用查询此功能__has_attribute(objc_method_family)

objc_requires_super(clang :: objc_requires_super,clang :: objc_requires_super)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

一些Objective-C类允许子类覆盖父类中的特定方法,但期望覆盖方法还调用父类中的重写方法。对于这些情况,我们提供了一个属性来指定方法需要super在子类中的重写方法中“调用”。

用法__attribute__((objc_requires_super))。此属性只能放在方法声明的末尾:

- (void)foo __attribute__((objc_requires_super));

此属性只能应用于类中的方法声明,而不能应用于协议。目前,此属性不会强制执行在重写方法中发生调用的位置(例如,在 -dealloc调用必须出现在最后的情况下)。它仅检查它是否存在。

请注意,在OS X和iOS上,Foundation框架提供了一个方便的宏NS_REQUIRES_SUPER,为此属性提供语法糖:

- (void)foo NS_REQUIRES_SUPER;

根据编译器对此属性的支持,有条件地定义此宏。如果编译器不支持该属性,宏将扩展为空。

在操作上,当方法具有此批注时,编译器将警告子类中的覆盖的实现是否不调用super。例如:

warning: method possibly missing a [super AnnotMeth] call
- (void) AnnotMeth{};
                   ^

objc_runtime_name(clang :: objc_runtime_name,clang :: objc_runtime_name)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

默认情况下,Objective-C接口或协议标识符用于该对象的元数据名称。该objc_runtime_name 属性允许注解的接口或协议来使用对象的元数据的名称,而不是默认名称为指定字符串参数。

用法__attribute__((objc_runtime_name("MyLocalName")))。此属性只能放在@protocol或@interface声明之前:

__attribute__((objc_runtime_name("MyLocalName")))
@interface Message
@end

objc_runtime_visible(clang :: objc_runtime_visible,clang :: objc_runtime_visible)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

此属性指定它应用的Objective-C类对Objective-C运行时可见,但对链接器不可见。使用此属性注释的类不能进行子类化,也不能为它们定义类别。

optnone(clang :: optnone,clang :: optnone)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

optnone属性基本上抑制了函数或方法的所有优化,而不管整个编译单元应用的优化级别如何。当您需要调试特定函数时,这尤其有用,但是在没有优化的情况下构建整个应用程序是不可行的。避免对指定函数进行优化可以提高该函数的调试信息的质量。

此属性与always_inlineminsize 属性不兼容。

overable(clang :: overloadable,clang :: overloadable)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

Clang在C中提供对C ++函数重载的支持overloadable。使用该属性引入C中的函数重载。例如,一个可能会提供一个的几个重载版本tgsin调用适当的标准函数计算值的正弦与功能float, double或者精度:long double

#include <math.h>
float __attribute__((overloadable)) tgsin(float x) { return sinf(x); }
double __attribute__((overloadable)) tgsin(double x) { return sin(x); }
long double __attribute__((overloadable)) tgsin(long double x) { return sinl(x); }

给定这些声明,可以tgsin使用float值来调用以接收float结果,使用a double来接收double结果等.C中的函数重载遵循C ++函数重载的规则,以在给定调用参数的情况下选择最佳重载,并使用一些C-具体语义:

  • 转换从floatdouble到被列为一个浮点推广(每C99),而不是作为一个浮点转换(如在C ++)。long double
  • 从类型T*指针到类型U*指针的转换被认为是指针转换(具有转换等级)if TU是兼容类型。
  • 从类型A转换T到类型的值U是允许的,如果T 和U是兼容的类型。该转换被赋予“转换”等级。
  • 如果没有可行的候选者可用,我们允许从类型T*的指针转换为类型的指针U*,其中TU不兼容。此转化次数低于所有其他类型的转化次数。请注意:U缺少存在的限定符T就足够TU不相容。

的声明overloadable功能仅限于函数声明和定义。如果函数用overloadable 属性标记,那么具有该名称的函数的所有声明和定义(除了最多一个(参见下面关于未标记重载的注释))必须具有该overloadable属性。此外,具有该overloadable属性的函数的重新声明必须具有该overloadable属性,并且没有该overloadable属性的函数的重新声明必须 具有该overloadable属性。例如,

int f(int) __attribute__((overloadable));
float f(float); // error: declaration of "f" must have the "overloadable" attribute
int f(int); // error: redeclaration of "f" must have the "overloadable" attribute

int g(int) __attribute__((overloadable));
int g(int) { } // error: redeclaration of "g" must also have the "overloadable" attribute

int h(int);
int h(int) __attribute__((overloadable)); // error: declaration of "h" must not
                                          // have the "overloadable" attribute

标记的功能overloadable必须具有原型。因此,以下代码格式错误:

int h() __attribute__((overloadable)); // error: h does not have a prototype

但是,overloadable即使没有命名参数(如C ++中允许的话),也允许函数使用省略号。与unavailable属性结合使用时,此功能特别有用:

void honeypot(...) __attribute__((overloadable, unavailable)); // calling me is an error

使用该overloadable属性声明的函数的名称会根据与C ++函数名称相同的规则进行修改。例如,三个 tgsin在我们的激励功能。例如让错位的名称 _Z5tgsinf_Z5tgsind_Z5tgsine分别。使用名称修改有两个注意事项:

  • Clang的未来版本可能会更改在C中重载的函数的名称修改,因此您不应该依赖于特定的修改。为了保证绝对安全,我们强烈敦促使用与 功能。staticinlineoverloadable
  • overloadable在C ++中使用时,该属性几乎没有任何意义,因为名称已经被破坏,函数已经可以重载。但是,当一个overloadable函数出现在一个 链接规范中时,它的名称将以与它在C中相同的方式被破坏。extern "C"

出于向后兼容的目的,最多一个与其他overloadable函数同名的函数可以省略该overloadable 属性。在这种情况下,没有overloadable属性的函数将不会损坏其名称。

例如:

// Notes with mangled names assume Itanium mangling.
int f(int);
int f(double) __attribute__((overloadable));
void foo() {
  f(5); // Emits a call to f (not _Z1fi, as it would with an overload that
        // was marked with overloadable).
  f(1.0); // Emits a call to _Z1fd.
}

某些版本的clang中不存在对未标记重载的支持。您可以使用查询它__has_extension(overloadable_unmarked)

使用查询此属性__has_attribute(overloadable)

release_capability(release_shared_capability,clang :: release_capability,clang :: release_shared_capability)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

将功能标记为释放功能。

short_call(gnu :: short_call,gnu :: near)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

铛支持__attribute__((long_call))__attribute__((far)), __attribute__((short__call)),和__attribute__((near))在MIPS目标的属性。这些属性只能添加到函数声明中,并在直接调用函数时更改编译器生成的代码。的short_callnear属性是同义词,并允许使用该被制成的函数调用jal指令,这需要为位于同一自然对齐256MB段作为呼叫者的功能。在long_callfar属性是同义词和要求使用作品的功能之间的距离,无论不同的调用序列。

这些属性对与位置无关的代码没有影响。

这些属性优先于命令行开关,例如-mlong-calls-mno-long-calls

signal(gnu :: signal)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

Clang支持__attribute__((signal))AVR目标上的GNU样式属性。该属性可以附加到函数定义,并指示后端生成适当的函数入口/出口代码,以便它可以直接用作中断服务例程。

使用signal属性定义的中断处理程序函数不会重新启用中断。

target(gnu :: target)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

Clang支持GNU样式__attribute__((target("OPTIONS")))属性。此属性可以附加到函数定义,并指示后端使用与在命令行上传递的不同的代码生成选项。

当前的选项集对应于目标的现有“子目标特征”,对应于缺少特征的前面有或没有“-mno-”,以及arch="CPU"将改变该函数的默认“CPU”。

来自x86后端的示例“子目标功能”包括:“mmx”,“sse”,“sse4.2”,“avx”,“xop”,并且主要对应于前端处理的机器特定选项。

此外,此属性支持基于ELF的x86 / x86-64目标的功能多版本化,可用于创建同一功能的多个实现,这些实现将在运行时根据其target属性字符串的优先级进行解析。函数被认为是多版本功能,如果功能的任何两个声明具有不同的target属性字符串,或者如果它有一个target属性字符串default。例如:

__attribute__((target("arch=atom")))
void foo() {} // will be called on 'atom' processors.
__attribute__((target("default")))
void foo() {} // will be called on any other processors.

所有多版本化函数必须包含default(后备)实现,否则该函数的使用被视为无效。另外,功能在首次使用后可能不会成为多版本。

try_acquire_capability(try_acquire_shared_capability,clang :: try_acquire_capability,clang :: try_acquire_shared_capability)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

标记尝试获取功能的功能。该功能可能无法实际获得该功能; 它们接受一个布尔值,确定获取能力是否意味着成功(真实),或者无法获得能力意味着成功(错误)。

xray_always_instrument(clang :: xray_always_instrument),xray_never_instrument(clang :: xray_never_instrument),xray_log_args(clang :: xray_log_args)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

__attribute__((xray_always_instrument))或者[[clang::xray_always_instrument]]用于标记成员函数(在C ++中),方法(在Objective C中)和自由函数(在C,C ++和Objective C中)以使用XRay进行检测。这将导致函数在开始和退出点始终具有空间以允许运行时修补。

相反,__attribute__((xray_never_instrument))[[clang::xray_never_instrument]]将抑制这些仪器点的插入。

如果函数不具有这些属性,则它们将受到用于确定是否应该检测函数的XRay启发式方法的约束。

__attribute__((xray_log_args(N)))或者[[clang::xray_log_args(N)]]用于保存日志记录功能的N个函数参数。目前,仅支持N == 1。

xray_always_instrument(clang :: xray_always_instrument),xray_never_instrument(clang :: xray_never_instrument),xray_log_args(clang :: xray_log_args)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

__attribute__((xray_always_instrument))或者[[clang::xray_always_instrument]]用于标记成员函数(在C ++中),方法(在Objective C中)和自由函数(在C,C ++和Objective C中)以使用XRay进行检测。这将导致函数在开始和退出点始终具有空间以允许运行时修补。

相反,__attribute__((xray_never_instrument))[[clang::xray_never_instrument]]将抑制这些仪器点的插入。

如果函数不具有这些属性,则它们将受到用于确定是否应该检测函数的XRay启发式方法的约束。

__attribute__((xray_log_args(N)))或者[[clang::xray_log_args(N)]]用于保存日志记录功能的N个函数参数。目前,仅支持N == 1。

变量属性

dllexport(gnu :: dllexport)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX X  X

__declspec(dllexport)属性声明要从模块导出的变量,函数或Objective-C接口。它在 -fdeclspec标志下可用于兼容各种编译器。主要用于COFF目标文件,它明确指定哪些接口可供外部使用。有关更多信息,请参阅MSDN上的dllexport文档。

dllimport(gnu :: dllimport)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX X  X

__declspec(dllimport)属性声明要从外部模块导入的变量,函数或Objective-C接口。它在-fdeclspec标志下可用于兼容各种编译器。主要用于COFF目标文件,它明确指定从外部模块导入的接口。有关更多信息,请参阅MSDN上的dllimport文档。

init_seg 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
     X 

应用的属性控制发出全局初始化函数指针的部分。它只适用于。通常,此函数指针在Windows上发出。用户可以通过使用具有相同前缀的不同部分名称和在标准部分之前或之后按字典顺序排序的后缀来更改初始化的顺序 。有关 更多信息,请参阅MSDN上的init_seg文档。pragma init_seg()-fms-extensions.CRT$XCU.CRT$XC.CRT$XCU

maybe_unused,未使用的,GNU ::未使用

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX    

-Wunused标志传递给Clang时,可以诊断程序未使用的实体。的[[maybe_unused]](或 __attribute__((unused)))属性可用于沉默这样的诊断时的实体不能被移除。例如,局部变量可能仅存在于assert()语句中,这使得局部变量在NDEBUG定义时未使用。

该属性可以应用于类的声明,typedef,变量,函数或方法,函数参数,枚举,枚举器,非静态数据成员或标签。

nodebug(gnu :: nodebug)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

nodebug属性允许您抑制函数或方法的调试信息,或者不是参数或非静态数据成员的变量的调试信息。

noescape(clang :: noescape,clang :: noescape)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

noescape放置在指针类型的函数参数上用于通知编译器指针不能转义:也就是说,指针指向的对象没有引用从参数值派生的对象将在函数返回后继续存在。用户有责任确保注释的参数noescape不会真正逃脱。

例如:

int *gp;

void nonescapingFunc(__attribute__((noescape)) int *p) {
  *p += 100; // OK.
}

void escapingFunc(__attribute__((noescape)) int *p) {
  gp = p; // Not OK.
}

此外,当参数是块指针<https://clang.llvm.org/docs/BlockLanguageSpec.html>时,相同的限制适用于块的副本。例如:

typedef void (^BlockTy)();
BlockTy g0, g1;

void nonescapingFunc(__attribute__((noescape)) BlockTy block) {
  block(); // OK.
}

void escapingFunc(__attribute__((noescape)) BlockTy block) {
  g0 = block; // Not OK.
  g1 = Block_copy(block); // Not OK either.
}

nosvm 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
X     X

OpenCL 2.0支持__attribute__((nosvm))指针变量的可选限定符。它通知编译器指针不引用共享虚拟内存区域。有关详细信息,请参见OpenCL v2.0 s6.7.2。

由于它没有被广泛使用并且已从OpenCL 2.1中删除,因此它被Clang忽略。

pass_object_size(clang :: pass_object_size,clang :: pass_object_size)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

注意

带有注释参数的函数的 pass_object_size修改可能会发生变化。您可以通过使用__asm__("foo")明确命名函数来解决这个问题,从而保留您的ABI; 此外,不可重载的C函数pass_object_size不会被破坏。

pass_object_size(Type)属性可以放在函数参数上,以指示clang 在所述函数的每个调用点调用,并在注释参数后直接 将该调用的结果作为类型的不可见参数隐式传递。Clang还将通过所述隐式参数替换函数中的任何调用 。__builtin_object_size(param, Type)size_tpass_object_size__builtin_object_size(param, Type)

用法示例:

int bzero1(char *const p __attribute__((pass_object_size(0))))
    __attribute__((noinline)) {
  int i = 0;
  for (/**/; i < (int)__builtin_object_size(p, 0); ++i) {
    p[i] = 0;
  }
  return i;
}

int main() {
  char chars[100];
  int n = bzero1(&chars[0]);
  assert(n == sizeof(chars));
  return 0;
}

如果无法在callsite上成功进行评估,则会传入“failed”值。因此,使用上面的定义,以下代码将干净地退出:__builtin_object_size(param, Type)bzero1

int main2(int argc, char *argv[]) {
  int n = bzero1(argv);
  assert(n == -1);
  return 0;
}

pass_object_size在超载分辨率中起作用。如果两个过载候选者在其他方面同样好,则pass_object_size优选具有一个或多个参数的过载。这意味着在两个相同的重载之间选择pass_object_size一个或多个参数将始终是模糊的; 因此,有两个这样的过载是非法的。例如:

#define PS(N) __attribute__((pass_object_size(N)))
// OK
void Foo(char *a, char *b); // Overload A
// OK -- overload A has no parameters with pass_object_size.
void Foo(char *a PS(0), char *b PS(0)); // Overload B
// Error -- Same signature (sans pass_object_size) as overload B, and both
// overloads have one or more parameters with the pass_object_size attribute.
void Foo(void *a PS(0), void *b);

// OK
void Bar(void *a PS(0)); // Overload C
// OK
void Bar(char *c PS(1)); // Overload D

void main() {
  char known[10], *unknown;
  Foo(unknown, unknown); // Calls overload B
  Foo(known, unknown); // Calls overload B
  Foo(unknown, known); // Calls overload B
  Foo(known, known); // Calls overload B

  Bar(known); // Calls overload D
  Bar(unknown); // Calls overload D
}

目前,pass_object_size在使用方面有点受限:

  • pass_object_size每个参数只允许使用一次。
  • pass_object_size在任何参数上使用函数的地址是错误的。如果您希望这样做,您可以创建一个不带pass_object_size任何参数的重载。
  • pass_object_size属性应用于非指针的参数是错误的。此外,pass_object_size应用于的任何参数都必须const在其函数的定义中标记。

require_constant_initialization(clang :: require_constant_initialization)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

此属性指定 根据[basic.start.static]的规则,它所附加的变量具有常量初始值设定项。该变量需要具有静态或线程存储持续时间。如果变量的初始化不是常量初始化器,则会产生错误。此属性只能在C ++中使用。

请注意,在C ++ 03中,不会进行严格的常量表达式检查。相反,该属性报告Clang是否可以将变量作为常量发出,即使它在技术上不是“常量初始化器”。此行为是不可移植的。

具有常量初始化程序的静态存储持续时间变量避免了由动态初始化的不确定顺序导致的难以发现的错误。它们还可以在翻译单元的动态初始化期间安全使用。

此属性充当编译时断言,表明已满足常量初始化的要求。由于这些要求在方言之间发生变化并且存在细微的缺陷,因此快速失败而不是无声地回退动态初始化非常重要。

// -std=c++14
#define SAFE_STATIC [[clang::require_constant_initialization]]
struct T {
  constexpr T(int) {}
  ~T(); // non-trivial
};
SAFE_STATIC T x = {42}; // Initialization OK. Doesn't check destructor.
SAFE_STATIC T y = 42; // error: variable does not have a constant initializer
// copy initialization is not a constant expression on a non-literal type.

section(gnu :: section,__ declspec(allocate))

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX X  X

section属性允许您指定翻译后全局变量或函数应包含的特定部分。

swift_context(clang :: swift_context,clang :: swift_context)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

swift_context属性将swiftcall 函数的参数标记为具有特殊的上下文参数ABI处理。

这种处理通常将特定寄存器中的上下文值传递,该寄存器通常是被调用者保留的。

swift_context参数必须是最后一个参数或必须跟一个swift_error_result参数(其本身必须始终是最后一个参数)。

上下文参数必须具有指针或引用类型。

swift_error_result(clang :: swift_error_result,clang :: swift_error_result)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

swift_error_result属性将swiftcall 函数的参数标记为具有特殊错误结果ABI处理。

这种处理通常通过特殊寄存器将基本的错误值传入和传出函数,该寄存器通常是被调用者保留的。这是通过假装寄存器是可寻址存储器在C中建模的:

  • 调用者似乎传递了指针类型变量的地址。该变量的当前值在调用之前被复制到寄存器中; 如果调用正常返回,则将值复制回变量。
  • 被调用者似乎接收变量的地址。该地址实际上是其自己堆栈中的隐藏位置,在进入时使用寄存器的值进行初始化。当函数正常返回时,该隐藏位置的值将被写回寄存器。

一个swift_error_result参数必须是最后一个参数,它必须由前面swift_context的参数。

swift_error_result参数必须具有类型T**T*&某种类型T.注意,没有限定词被允许在中间电平。

如果调用者未将指针或引用传递给有效对象,则它是未定义的行为。

标准约定是函数入口时错误值本身(即存储在explicit参数中的值)将为null,但ABI不强制执行此操作。

swift_indirect_result(clang :: swift_indirect_result,clang :: swift_indirect_result)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

swift_indirect_result属性将swiftcall 函数的参数标记为具有特殊的间接结果ABI处理。

该处理使参数成为目标的正常间接结果ABI处理,这可能涉及使其与普通参数不同地传递。但是,只有第一个间接结果才会得到这种治疗。此外,低级别降低可能决定必须间接返回直接结果; 如果是这样,这将优先于 swift_indirect_result参数。

一个swift_indirect_result参数必须是第一个参数或跟随其他swift_indirect_result参数。

一个swift_indirect_result参数必须有类型T*T&对某些对象类型T。如果T在函数定义点处是完整类型,则如果参数值未指向存储足够大小并且对齐类型值,则它是未定义的行为T

在签名中使间接结果显式化允许C函数直接将对象构造到它们中,而不依赖于语言优化,如C ++的命名返回值优化(NRVO)。

swiftcall(clang :: swiftcall,clang :: swiftcall)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX    

swiftcall属性指示应使用函数或函数指针的Swift调用约定来调用函数。

正如Swift ABI文档所描述的那样,Swift调用约定的降低发生在多个阶段。第一个“高级”阶段将形式参数和结果分解为天生的直接和间接组件,为通用签名添加隐式参数,并将上下文和错误ABI处理分配给适用的参数。第二阶段分解第一阶段的直接参数和结果,并将它们分配给寄存器或堆栈。该swiftcall公约只处理第二阶段的降低; C函数类型必须准确反映第一阶段的结果,如下所示:

  • 通过高级别降低分类为间接的结果应表示为具有该swift_indirect_result属性的参数。
  • 通过高级别降低分类为直接的结果应表示如下:
    • 首先,删除任何空的直接结果。
    • 如果没有直接结果,则应该是C结果类型void
    • 如果有一个直接结果,则C结果类型应该是具有该结果类型的确切布局的类型。
    • 如果存在多个直接结果,则C结果类型应为结构类型,其具有这些结果的元组的确切布局。
  • 通过高级降低分类为间接的参数应表示为指针类型的参数。
  • 如果属于空类型,则应省略通过高级降低分类为直接的参数; 否则,它们应表示为参数类型,其布局与Swift参数类型的布局完全匹配。
  • context参数(如果存在)应表示为具有该swift_context属性的尾随参数。
  • 错误结果参数(如果存在)应该表示为具有该swift_error_result属性的尾随参数(始终遵循上下文参数) 。

swiftcall 不支持可变参数或非原型函数。

参数ABI处理属性是函数类型的方面。将ABI处理属性应用于参数的函数类型与不具有其他相同函数类型的函数类型不同。单个参数可能没有多个ABI处理属性。

对此功能的支持是依赖于目标的,尽管它应该支持Swift支持的每个目标。查询此支持__has_attribute(swiftcall)。这意味着为支撑 swift_contextswift_error_resultswift_indirect_result 属性。

线程

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
   X   

__declspec(thread)属性声明一个带有线程本地存储的变量。它在-fms-extensionsMSVC兼容性的标志下可用。请参阅MSDN上的__declspec(线程)文档。

在Clang中,__declspec(thread)功能通常与GNU __thread关键字相同。变量必须没有析构函数,并且必须具有常量初始值设定项(如果有)。该属性仅适用于使用静态存储持续时间声明的变量,例如全局变量,类静态数据成员和静态本地变量。

tls_model(gnu :: tls_model)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

tls_model属性允许您指定要使用的线程本地存储模型。它接受以下字符串:

  • 全球动态
  • 地方动态
  • 初始EXEC
  • 当地EXEC

TLS模型是互斥的。

trivial_abi(clang :: trivial_abi)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

trivial_abi属性可以应用于C ++类,结构或联合。它指示编译器使用C ABI为基础类型传递和返回类型,否则为了调用,类型将被视为非平凡的类型。使用trivial_abi注释的类可以具有非平凡的析构函数或复制/移动构造函数,而不会出于调用的目的而自动变为非平凡的。例如:

// A is trivial for the purposes of calls because `trivial_abi` makes the
// user-provided special functions trivial.
struct __attribute__((trivial_abi)) A {
  ~A();
  A(const A &);
  A(A &&);
  int x;
};

// B's destructor and copy/move constructor are considered trivial for the
// purpose of calls because A is trivial.
struct B {
  A a;
};

如果一个类型对于调用而言是微不足道的,具有非平凡的析构函数,并且作为参数按值传递,则约定是被调用者将在返回之前销毁该对象。

trivial_abi在以下情况下,属性无效:

  • 该类直接声明虚拟基础或虚拟方法。
  • 该类有一个基类,对于调用而言是非常重要的。
  • 该类具有非静态数据成员,其类型对于调用而言是非平凡的,其中包括:
    • 对于调用而言非常重要的类
    • Objective-C ++中的__weak限定类型
    • 任何上述阵列

类型属性

__single_inhertiance,__multiple_inheritance,__virtual_inheritance 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

此关键字集合在下面启用-fms-extensions并控制*-*-win32目标上使用的指向成员的表示。

*-*-win32目标利用指针到构件表示这在取决于底层类的定义尺寸和对齐而变化。

但是,当前向声明仅可用且尚未定义时,这是有问题的。在这种情况下,Clang被迫使用最常用的代表。

这些关键字使得可以使用除最常规之外的指针到成员表示,而不管该定义是否将出现在当前翻译单元中。

这个关键字系列属于class-keyclass-name

struct __single_inheritance S;
int S::*i;
struct S {};

此关键字可以应用于类模板,但仅在完全特化时使用时才有效:

template <typename T, typename U> struct __single_inheritance A; // warning: inheritance model ignored on primary template
template <typename T> struct __multiple_inheritance A<T, T>; // warning: inheritance model ignored on partial specialization
template <> struct __single_inheritance A<int, float>;

请注意,选择一般性不是严格必要的继承模型是一个错误:

struct __multiple_inheritance S; // error: inheritance model does not match definition
int S::*i;
struct S {};

align_value 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
X     X

align_value属性可以添加到指针类型的typedef或指针或引用类型的变量的声明中。它指定指针将指向,或引用将仅绑定到至少具有提供的对齐的对象。此对齐值必须是2的正幂。

typedef double * aligned_double_ptr __attribute__((align_value(64)));
void foo(double & x  __attribute__((align_value(128)),
         aligned_double_ptr y) { ... }

如果指针值在运行时没有指定的对齐方式,则程序的行为是未定义的。

empty_bases 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
   X   

empty_bases属性允许编译器更频繁地利用空基优化。此属性仅适用于struct,class和union类型。仅在使用Microsoft C ++ ABI时才支持它。

enum_extensibility(clang :: enum_extensibility,clang :: enum_extensibility)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

属性enum_extensibility用于区分可扩展的枚举定义和不可扩展的枚举定义。该属性可以采用 closedopen作为参数。closed表示枚举类型的变量采用与枚举定义中列出的枚举数之一对应的值,或者,当枚举用枚举时flag_enum,使用可以使用与枚举数对应的值构造的值。open 表示枚举类型的变量可以采用标准允许的任何值,并指示在发出警告时clang更宽松。

enum __attribute__((enum_extensibility(closed))) ClosedEnum {
  A0, A1
};

enum __attribute__((enum_extensibility(open))) OpenEnum {
  B0, B1
};

enum __attribute__((enum_extensibility(closed),flag_enum)) ClosedFlagEnum {
  C0 = 1 << 0, C1 = 1 << 1
};

enum __attribute__((enum_extensibility(open),flag_enum)) OpenFlagEnum {
  D0 = 1 << 0, D1 = 1 << 1
};

void foo1() {
  enum ClosedEnum ce;
  enum OpenEnum oe;
  enum ClosedFlagEnum cfe;
  enum OpenFlagEnum ofe;

  ce = A1;           // no warnings
  ce = 100;          // warning issued
  oe = B1;           // no warnings
  oe = 100;          // no warnings
  cfe = C0 | C1;     // no warnings
  cfe = C0 | C1 | 4; // warning issued
  ofe = D0 | D1;     // no warnings
  ofe = D0 | D1 | 4; // no warnings
}

flag_enum(clang :: flag_enum,clang :: flag_enum)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

可以将此属性添加到枚举器,以向编译器发出信号,表明它将用作标志类型。这将导致编译器假定该类型的范围包括在发出警告时通过操纵枚举器的位可以获得的所有值。

layout_version的

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
   X   

layout_version属性请求编译器使用特定编译器版本的类布局规则。此属性仅适用于struct,class和union类型。仅在使用Microsoft C ++ ABI时才支持它。

lto_visibility_public(clang :: lto_visibility_public,clang :: lto_visibility_public)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

请参阅LTO可见性

novtable 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
   X   

可以将此属性添加到类声明或定义中,以向编译器发出信号,表明构造函数和析构函数不会引用虚函数表。仅在使用Microsoft C ++ ABI时才支持它。

objc_subclassing_restricted(clang :: objc_subclassing_restricted,clang :: objc_subclassing_restricted)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX   X

可以将此属性添加到Objective-C @interface声明中,以确保不能对此类进行子类化。

selectany(gnu :: selectany)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX X   

此属性附属于全局符号,导致其具有弱定义( linkonce ),允许链接器选择任何定义。

有关更多信息,请参阅 gcc文档 或msvc文档

transparent_union(gnu :: transparent_union)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

此属性可以应用于联合,以更改对具有透明联合类型的参数的函数的调用行为。编译器行为以下列方式更改:

  • 类型为透明联合的任何成员的值可以作为参数传递,而无需强制转换该值。
  • 使用透明联合的第一个成员的调用约定将参数传递给函数。因此,透明联合的所有成员应具有与其第一个成员相同的调用约定。

C ++不支持透明联合。

语句属性

#pragma clang循环

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
     X 

该指令允许为后续循环指定循环优化提示。该指令允许启用或禁用矢量化,交错和展开。可以手动指定矢量宽度以及交错和展开计数。有关 详情,请参阅 语言扩展#pragma clang loop

为#pragma unroll,的#pragma nounroll 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
     X 

可以使用和 指定循环展开优化提示。该pragma紧接在for,while,do-while或c ++ 11基于范围的for循环之前。#pragma unroll#pragma nounroll

如果在编译时已知行程计数,则指定不带参数指示循环展开器尝试完全展开循环,如果在编译时未知行程计数,则尝试部分展开循环:#pragma unroll

#pragma unroll
for (...) {
  ...
}

指定可选参数,指示展开器展开循环时间。参数可以选择括在括号中:#pragma unroll _value__value_

#pragma unroll 16
for (...) {
  ...
}

#pragma unroll(16)
for (...) {
  ...
}

指定表示不应展开循环:#pragma nounroll

#pragma nounroll
for (...) {
  ...
}

#pragma unroll和具有相同的语义 和 分别。 相当于。有关 详细信息,请参阅 语言扩展,包括展开提示的限制。#pragma unroll _value_#pragma clang loopunroll(full)#pragma clang loop unroll_count(_value_)#pragma nounroll#pragma clang loop unroll(disable)

__attribute __((intel_reqd_sub_group_size))

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
X     X

可选属性intel_reqd_sub_group_size可用于指示必须使用指定的子组大小编译和执行内核。当存在此属性时,get_max_sub_group_size()保证返回指定的整数值。这对于许多子组算法的正确性很重要,并且在某些情况下编译器可以使用它来生成更优的代码。有关 详细信息,请参阅cl_intel_required_subgroup_size <https://www.khronos.org/registry/OpenCL/extensions/intel/cl_intel_required_subgroup_size.txt>。

__attribute __((opencl_unroll_hint))

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
X      

opencl_unroll_hint属性限定符可用于指定可以展开循环(for,while和do循环)。此属性限定符可用于指定按指定量完全展开或部分展开。这是编译器提示,编译器可能会忽略此指令。有关 详细信息,请参阅 OpenCL v2.0 s6.11.5。

__read_only,__ write_only,__ read_write(read_only,write_only,read_write)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

访问限定符必须与image对象参数或管道参数一起使用,以声明它们是由内核或函数读取还是写入。

read_only / __ read_only,write_only / __ write_only和read_write / __ read_write名称保留用作访问限定符,否则不得使用。

kernel void
foo (read_only image2d_t imageA,
     write_only image2d_t imageB) {
  ...
}

在上面的示例中,imageA是只读2D图像对象,而imageB是只写2D图像对象。

read_write(或__read_write)限定符不能与管道一起使用。

更多细节可以在OpenCL C语言Spec v2.0的6.6节中找到。

通电路,铛::下通

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
 XX    

fallthrough(或clang::fallthrough)属性被用于注释故意落空开关标签之间。它只能应用于放置在任何语句和下一个开关标签之间的执行点的空语句。通常使用特定注释标记这些位置,但此属性旨在用更严格的注释替换注释,编译器可以检查注释。此属性不会更改代码的语义,并且可以在发生预期掉落的任何位置使用。它被设计为模仿控制流语句break;,因此它可以放在大多数break;可以的地方,但前提是它与下一个开关标签之间的执行路径上没有语句。

默认情况下,Clang不会对从一个switch 案例到另一个案例的未注释的通过进行警告。可以使用-Wimplicit-fallthrough参数启用没有相应注释的fallthrough诊断。

这是一个例子:

// compile with -Wimplicit-fallthrough
switch (n) {
case 22:
case 33:  // no warning: no statements between case labels
  f();
case 44:  // warning: unannotated fall-through
  g();
  [[clang::fallthrough]];
case 55:  // no warning
  if (x) {
    h();
    break;
  }
  else {
    i();
    [[clang::fallthrough]];
  }
case 66:  // no warning
  p();
  [[clang::fallthrough]]; // warning: fallthrough annotation does not
                          //          directly precede case label
  q();
case 77:  // warning: unannotated fall-through
  r();
}

suppress(gsl :: suppress)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
 X     

[[gsl::suppress]]属性以可移植的方式抑制了对C ++核心指南规则的特定铿锵声诊断。该属性可以附加到声明,语句和命名空间范围。

[[gsl::suppress("Rh-public")]]
void f_() {
  int *p;
  [[gsl::suppress("type")]] {
    p = reinterpret_cast<int*>(7);
  }
}
namespace N {
  [[clang::suppress("type", "bounds")]];
  ...
}

AMD GPU属性

amdgpu_flat_work_group_size(clang :: amdgpu_flat_work_group_size)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

扁平工作组大小是分派内核时指定的工作组大小中的工作项数。它是工作组的x,y和z维度大小的乘积。

Clang支持AMDGPU目标的 属性。此属性可以附加到内核函数定义,并且是优化提示。__attribute__((amdgpu_flat_work_group_size(<min>, <max>)))

<min>参数指定最小平面工作组大小,<max> 参数指定<min>内核的所有调度将符合的最大平面工作组大小(必须大于 )。传递 为暗示默认行为()。0, 0<min>,<max>128, 256

如果指定,AMDGPU目标后端可能能够通过估计可用的组段大小来生成更好的障碍机器代码并执行临时促销。

如果出现以下错误:

  • 指定的值违反了子目标规范;
  • 指定的值与通过其他属性提供的值不兼容。

amdgpu_num_sgpr(clang :: amdgpu_num_sgpr)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

Clang支持AMDGPU目标的属性__attribute__((amdgpu_num_sgpr(<num_sgpr>)))和 __attribute__((amdgpu_num_vgpr(<num_vgpr>)))属性。这些属性可以附加到内核函数定义,并且是优化提示。

如果指定了这些属性,则AMDGPU目标后端将尝试将所使用的SGPR和/或VGPR的数量限制为指定值。所使用的SGPR和/或VGPR的数量可以进一步向上舍入以满足子目标的分配要求或约束。传递0为 num_sgpr和/或num_vgpr暗示默认行为(无限制)。

这些属性可用于测试AMDGPU目标后端。建议使用该amdgpu_waves_per_eu属性来控制SGPR和VGPR等资源,因为它知道不同子目标的限制。

如果出现以下错误:

  • 指定的值违反了子目标规范;
  • 指定的值与通过其他属性提供的值不兼容;
  • AMDGPU目标后端无法创建可满足请求的机器代码。

amdgpu_num_vgpr(clang :: amdgpu_num_vgpr)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

Clang支持AMDGPU目标的属性__attribute__((amdgpu_num_sgpr(<num_sgpr>)))和 __attribute__((amdgpu_num_vgpr(<num_vgpr>)))属性。这些属性可以附加到内核函数定义,并且是优化提示。

如果指定了这些属性,则AMDGPU目标后端将尝试将所使用的SGPR和/或VGPR的数量限制为指定值。所使用的SGPR和/或VGPR的数量可以进一步向上舍入以满足子目标的分配要求或约束。传递0为 num_sgpr和/或num_vgpr暗示默认行为(无限制)。

这些属性可用于测试AMDGPU目标后端。建议使用该amdgpu_waves_per_eu属性来控制SGPR和VGPR等资源,因为它知道不同子目标的限制。

如果出现以下错误:

  • 指定的值违反了子目标规范;
  • 指定的值与通过其他属性提供的值不兼容;
  • AMDGPU目标后端无法创建可满足请求的机器代码。

amdgpu_waves_per_eu(clang :: amdgpu_waves_per_eu)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

计算单元(CU)负责执行工作组的波前。它由一个或多个执行单元(EU)组成,它们负责执行波前。欧盟可以拥有足够的资源来维持多个执行波阵面的状态。这允许EU通过以类似于CPU上的对称多线程的方式在波前之间切换来隐藏延迟。为了使多个波前的状态适合欧盟,单个波前使用的资源必须受到限制。例如,SGPR和VGPR的数量。限制这样的资源可以允许更大的延迟隐藏,但是可能导致必须将一些寄存器状态溢出到存储器。

Clang支持 AMDGPU目标的属性。此属性可以附加到内核函数定义,并且是优化提示。__attribute__((amdgpu_waves_per_eu(<min>[, <max>])))

<min>参数指定每个EU请求的最小波数, 可选 <max>参数指定每个EU请求的最大波数(必须大于指定的最大波数<min>)。如果<max>省略,则除了由编译内核的硬件规定的波数之外,对每个EU的最大波数没有限制。传递 的暗示的默认行为(没有限制)。0, 0<min>, <max>

如果指定,则此属性允许高级开发人员调整能够适应EU资源的波前数量。AMDGPU目标后端可以使用此信息来限制资源,例如SGPR的数量,VGPR的数量,可用组的大小和私有内存段,从而保证至少<min>波前和最多 <max>波前能够适应欧盟的资源。请求更多波前可能会隐藏内存延迟,但会限制可能导致溢出的可用寄存器。请求更少的波前可以帮助减少缓存抖动,但可以减少内存延迟隐藏。

此属性控制AMDGPU目标后端生成的机器代码,以确保它能够满足请求的值。但是,当执行内核时,可能还有其他原因阻止满足请求,例如,可能存在来自欧盟上执行的其他内核的波前。

如果出现以下错误:

  • 指定的值违反了子目标规范;
  • 指定的值与通过其他属性提供的值不兼容;
  • AMDGPU目标后端无法创建可满足请求的机器代码。

召唤约定

Clang支持几种不同的调用约定,具体取决于目标平台和体系结构。用于函数的调用约定确定如何传递参数,如何将结果返回给调用者,以及调用函数的其他低级细节。

fastcall(gnu :: fastcall,__ fastcall,_fastcall)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX  X  

在32位x86目标上,此属性更改函数的调用约定,以使用ECX和EDX作为寄存器参数,并在返回时清除堆栈中的参数。此约定不支持C中的可变参数调用或非原型函数,并且对x86_64目标没有影响。支持此调用约定主要是为了与现有代码兼容。寻求寄存器参数的用户应该使用该regparm属性,该属性不需要被调用者清理。请参阅MSDN上的__fastcall文档。

ms_abi(gnu :: ms_abi)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

在非Windows x86_64目标上,此属性更改函数的调用约定以匹配Windows x86_64上使用的默认约定。此属性对Windows目标或非x86_64目标没有影响。

pcs(gnu :: pcs)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

在ARM目标上,此属性可用于选择类似于stdcallx86的调用约定。有效参数值为“aapcs”和“aapcs-vfp”。

preserve_all(clang :: preserve_all,clang :: preserve_all)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX    

在X86-64和AArch64目标上,此属性更改函数的调用约定。该preserve_all调用约定试图使代码甚至比较少干扰呼叫者preserve_most调用约定。此调用约定的行为与C调用约束和返回值的方式相同,但它使用一组不同的调用者/被调用者保存的寄存器。这消除了在调用者中调用之前和之后保存和恢复大型寄存器集的负担。如果参数在被调用者保存的寄存器中传递,则调用者将在整个调用中保留它们。这不适用于被调用者保存的寄存器中返回的值。

  • 在X86-64上,被调用者保留所有通用寄存器,R11除外。R11可用作临时寄存器。此外,它还保留所有浮点寄存器(XMM / YMM)。

此约定背后的想法是支持对不需要调用任何其他函数的运行时函数的调用。

与调用约定一样,此preserve_most调用约定将由Objective-C运行时的未来版本使用,此时应被视为实验。

preserve_most(clang :: preserve_most,clang :: preserve_most)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX    

在X86-64和AArch64目标上,此属性更改函数的调用约定。该preserve_most调用约定试图使调用者的代码作为非侵入越好。此约定的行为与C关于如何传递参数和返回值的调用约定相同,但它使用一组不同的调用者/被调用者保存的寄存器。这减轻了在呼叫者呼叫之前和之后保存和恢复大寄存器组的负担。如果参数在被调用者保存的寄存器中传递,则调用者将在整个调用中保留它们。这不适用于被调用者保存的寄存器中返回的值。

  • 在X86-64上,被调用者保留所有通用寄存器,R11除外。R11可用作临时寄存器。浮点寄存器(XMM / YMM)不会被保留,需要由调用者保存。

此约定背后的想法是支持对具有热路径和冷路径的运行时函数的调用。热路径通常是一小段代码,不使用许多寄存器。冷路径可能需要调用另一个函数,因此只需要保留调用者保存的寄存器,这些寄存器尚未被调用者保存。该 preserve_most调用约定是非常相似的cold在主叫/被叫保存寄存器方面的调用约定,但它们用于不同类型的函数调用。coldcc是用于很少执行的函数调用,而preserve_most函数调用是在热路径上并且肯定执行很多。此外preserve_most 不会阻止内联器内联函数调用。

此调用约定将由Objective-C运行时的未来版本使用,因此此时仍应被视为实验。虽然创建此约定是为了优化对Objective-C运行时的某些运行时调用,但它不仅限于此运行时,并且将来也可能被其他运行时使用。当前的实现仅支持X86-64和AArch64,但目的是在未来支持更多的体系结构。

regcall(gnu :: regcall,__ regcall)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX  X  

在x86目标上,此属性将调用约定更改为 __regcall约定。该惯例旨在尽可能多地在寄存器中传递参数。它还尝试在可能的情况下利用寄存器作为返回值。

regparm(gnu :: regparm)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

在32位x86目标上,regparm属性使编译器传递EAX,EDX和ECX中的前三个整数参数,而不是堆栈上的参数。此属性对可变参数函数没有影响,并且所有参数都正常地通过堆栈传递。

stdcall(gnu :: stdcall,__ stdcall,_stdcall)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX  X  

在32位x86目标上,此属性更改函数的调用约定,以在返回时清除堆栈中的参数。此约定不支持C中的可变参数调用或非原型函数,并且对x86_64目标没有影响。Windows API和COM应用程序广泛使用此调用约定。请参阅MSDN上的__stdcall文档。

thiscall(gnu :: thiscall,__ thiscall,_thiscall)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX  X  

在32位x86目标上,此属性更改函数的调用约定,以将ECX用作第一个参数(通常this 是C ++方法的隐式参数),并在返回时清除堆栈中的参数。此约定不支持C中的可变参数调用或非原型函数,并且对x86_64目标没有影响。请参阅MSDN上的__thiscall文档。

vectorcall(clang :: vectorcall,clang :: vectorcall,__ vectorcall,_vectorcall)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX X  

在32位x86  x86_64目标上,此属性更改函数的调用约定以在SSE寄存器中传递向量参数。

在32位x86目标上,此调用约定类似于__fastcall。前两个整数参数在ECX和EDX中传递。后续整数参数在内存中传递,被调用者清除堆栈。在x86_64的目标,被叫方也清除栈和整数参数在RCX,RDX,R8过去了,R9作为为默认的Windows x64的调用约定完成。

在32位x86和x86_64目标上,向量和浮点参数在XMM0-XMM5中传递。如果足够可用,则在顺序SSE寄存器中传递最多四个元素的同构向量聚合。如果启用AVX,则在YMM0-YMM5中传递256位向量。由于任何原因无法在寄存器中传递的任何向量或聚合类型都通过引用传递,这允许调用者对齐参数存储器。

有关更多详细信息,请参阅MSDN上__vectorcall的文档。

消耗的注释检查

Clang支持用于检查基本资源管理属性的其他属性,特别是对于具有单个拥有引用的唯一对象。目前支持以下属性,但这些注释的实现目前正在开发中并且可能会发生变化。

callable_when(clang :: callable_when)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

使用__attribute__((callable_when(...)))来表示什么状态的方法可以被调用。有效状态为未消费,消费,还是个未知数。此属性的每个参数都必须是带引号的字符串。例如:

__attribute__((callable_when("unconsumed", "unknown")))

消耗品(clang :: consumable)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

每个class使用任何typestate注释必须先使用标记consumable属性。如果不这样做将导致警告。

此属性接受必须是下列之一的单个参数: unknownconsumed,或unconsumed

param_typestate(clang :: param_typestate)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

此属性指定对函数参数的期望。如果相应的参数未处于预期状态,则对带有注释参数的函数的调用将发出警告。该属性还用于在分析函数体时设置参数的初始状态。

return_typestate(clang :: return_typestate)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

return_typestate属性可以应用于函数或参数。应用于函数时,该属性指定返回值的状态。检查函数的主体以确保它始终返回指定状态的值。在调用者端,注释函数返回的值被初始化为给定状态。

应用于函数参数时,它会在调用函数返回后修改参数的状态。检查函数的主体以确保参数在返回之前处于预期状态。

set_typestate(clang :: set_typestate)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

注释用于将对象转换为新状态的方法 __attribute__((set_typestate(new_state)))。新状态必须是未消耗的,消耗的或未知的。

test_typestate(clang :: test_typestate)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

使用__attribute__((test_typestate(tested_state)))以表示方法,如果对象是在指定的状态返回true ..

类型安全检查

Clang支持其他属性以启用检查C类型系统无法强制执行的类型安全属性。要查看这些检查产生的警告,请确保已启用-Wtype-safety。用例包括:

  • MPI库实现,其中这些属性允许检查缓冲区类型是否与传递的匹配MPI_Datatype;
  • 对于HDF5库,MPI有类似的用例;
  • 检查类似fcntl()和的函数的可变函数参数的类型 ioctl()

您可以使用检测这些属性的支持__has_attribute()。例如:

#if defined(__has_attribute)
#  if __has_attribute(argument_with_type_tag) && \
      __has_attribute(pointer_with_type_tag) && \
      __has_attribute(type_tag_for_datatype)
#    define ATTR_MPI_PWT(buffer_idx, type_idx) __attribute__((pointer_with_type_tag(mpi,buffer_idx,type_idx)))
/* ... other macros ...  */
#  endif
#endif

#if !defined(ATTR_MPI_PWT)
# define ATTR_MPI_PWT(buffer_idx, type_idx)
#endif

int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
    ATTR_MPI_PWT(1,3);

argument_with_type_tag 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX    

在函数声明上使用以指定函数接受确定某个其他参数类型的类型标记。__attribute__((argument_with_type_tag(arg_kind, arg_idx, type_tag_idx)))

此属性主要用于检查可变参数函数的参数(pointer_with_type_tag可用于大多数非可变参数的情况)。

在上面的属性原型中:

  • arg_kind 是注释所有适用的类型标记时应使用的标识符。
  • arg_idx提供函数参数的位置。此函数参数的预期类型将由指定的函数参数确定type_tag_idx。在下面的代码示例中,“3”表示函数的第三个参数的类型将由type_tag_idx
  • type_tag_idx提供函数参数的位置。此函数参数将是类型标记。type标签将确定由其指定的参数的预期类型arg_idx。在下面的代码示例中,“2”表示与函数的第二个参数关联的类型标记应该与指定的参数的类型一致arg_idx

例如:

int fcntl(int fd, int cmd, ...)
    __attribute__(( argument_with_type_tag(fcntl,3,2) ));
// The function's second argument will be a type tag; this type tag will
// determine the expected type of the function's third argument.

pointer_with_type_tag 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX    

在函数声明上使用以指定函数接受一个类型标记,该标记确定某个其他指针参数的指针类型。__attribute__((pointer_with_type_tag(ptr_kind, ptr_idx,type_tag_idx)))

在上面的属性原型中:

  • ptr_kind 是注释所有适用的类型标记时应使用的标识符。
  • ptr_idx提供函数参数的位置; 这个函数参数将有一个指针类型。此指针类型的预期指针类型将由指定的函数参数确定 type_tag_idx。在下面的代码示例中,“1”表示函数的第一个参数的指针类型将由type_tag_idx
  • type_tag_idx提供函数参数的位置; 这个函数参数将是一个类型标记。type标签将确定指定的指针参数的预期指针类型ptr_idx。在下面的代码示例中,“3”表示与函数的第三个参数关联的类型标记应该与指定的指针参数的指针类型一致ptr_idx

例如:

typedef int MPI_Datatype;
int MPI_Send(void *buf, int count, MPI_Datatype datatype /*, other args omitted */)
    __attribute__(( pointer_with_type_tag(mpi,1,3) ));
// The function's 3rd argument will be a type tag; this type tag will
// determine the expected pointee type of the function's 1st argument.

type_tag_for_datatype(clang :: type_tag_for_datatype,clang :: type_tag_for_datatype)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XXX    

声明变量时,用于 创建与赋予属性的参数绑定的类型标记。__attribute__((type_tag_for_datatype(kind, type)))type

在上面的属性原型中:

  • kind 是注释所有适用的类型标记时应使用的标识符。
  • type 表示类型的名称。

Clang支持注释两种形式的类型标签。

  • 键入标记,它是对声明的标识符的引用。在声明该标识符时 使用:__attribute__((type_tag_for_datatype(kind, type)))

    typedef int MPI_Datatype;
    extern struct mpi_datatype mpi_datatype_int
        __attribute__(( type_tag_for_datatype(mpi,int) ));
    #define MPI_INT ((MPI_Datatype) &mpi_datatype_int)
    // &mpi_datatype_int is a type tag. It is tied to type "int".
    
  • 键入标记,它是一个完整的文字。 声明一个带有初始化值的变量并附加 在该声明上:static const__attribute__((type_tag_for_datatype(kind,type)))

    typedef int MPI_Datatype;
    static const MPI_Datatype mpi_datatype_int
        __attribute__(( type_tag_for_datatype(mpi,int) )) = 42;
    #define MPI_INT ((MPI_Datatype) 42)
    // The number 42 is a type tag. It is tied to type "int".
    

type_tag_for_datatype属性还接受一个可选的第三个参数,该参数确定如何将函数参数的类型指定为 arg_idxptr_idx与类型标记关联的类型进行比较。(回想一下,对于argument_with_type_tag属性,指定的函数参数arg_idx的类型与类型标记关联的类型进行比较。还要记住,对于pointer_with_type_tag 属性,指定的函数参数的指针类型ptr_idx与与之关联的类型进行比较。 type tag。)这个可选的第三个参数有两个支持的值:

  • layout_compatible将导致类型根据布局兼容性规则进行比较(在C ++ 11 [class.mem]第17,18页,请参阅两个标准布局结构类型和两个标准布局联合类型的布局兼容性规则) 。在创建与struct或union类型关联的类型标记时,这很有用。例如:

    /* In mpi.h */
    typedef int MPI_Datatype;
    struct internal_mpi_double_int { double d; int i; };
    extern struct mpi_datatype mpi_datatype_double_int
        __attribute__(( type_tag_for_datatype(mpi,
                        struct internal_mpi_double_int, layout_compatible) ));
    
    #define MPI_DOUBLE_INT ((MPI_Datatype) &mpi_datatype_double_int)
    
    int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...)
        __attribute__(( pointer_with_type_tag(mpi,1,3) ));
    
    /* In user code */
    struct my_pair { double a; int b; };
    struct my_pair *buffer;
    MPI_Send(buffer, 1, MPI_DOUBLE_INT /*, ...  */); // no warning because the
                                                     // layout of my_pair is
                                                     // compatible with that of
                                                     // internal_mpi_double_int
    
    struct my_int_pair { int a; int b; }
    struct my_int_pair *buffer2;
    MPI_Send(buffer2, 1, MPI_DOUBLE_INT /*, ...  */); // warning because the
                                                      // layout of my_int_pair
                                                      // does not match that of
                                                      // internal_mpi_double_int
    
  • must_be_null指定由arg_idx(对于argument_with_type_tag属性)或ptr_idx(对于pointer_with_type_tag属性)指定的函数参数 应该是空指针常量。该type_tag_for_datatype属性的第二个参数将被忽略。例如:

    /* In mpi.h */
    typedef int MPI_Datatype;
    extern struct mpi_datatype mpi_datatype_null
        __attribute__(( type_tag_for_datatype(mpi, void, must_be_null) ));
    
    #define MPI_DATATYPE_NULL ((MPI_Datatype) &mpi_datatype_null)
    int MPI_Send(void *buf, int count, MPI_Datatype datatype, ...)
        __attribute__(( pointer_with_type_tag(mpi,1,3) ));
    
    /* In user code */
    struct my_pair { double a; int b; };
    struct my_pair *buffer;
    MPI_Send(buffer, 1, MPI_DATATYPE_NULL /*, ...  */); // warning: MPI_DATATYPE_NULL
                                                        // was specified but buffer
                                                        // is not a null pointer
    

OpenCL地址空间

地址空间限定符可用于指定用于分配对象的内存区域。OpenCL支持以下地址空间:__ generic(generic),__ global(global),__ local(local),__ private(private),__ constant(constant)。

__constant int c = ...;

__generic int* foo(global int* g) {
  __local int* l;
  private int p;
  ...
  return l;
}

更多细节可以在OpenCL C语言Spec v2.0的6.5节中找到。

常量(__constant)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

常量地址空间属性表示对象位于常量(不可修改的)存储区域中。它适用于所有工作项目。任何类型都可以使用常量地址空间属性进行注释。具有常量地址空间限定符的对象可以在任何范围内声明,并且必须具有初始化程序。

通用(__generic)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

通用地址空间属性仅适用于OpenCL v2.0及更高版本。它可以与指针类型一起使用。全局和局部范围中的变量以及非内核函数中的函数参数可以具有通用地址空间类型属性。除了OpenCL代码中的“__constant”之外,它可以作为任何其他地址空间的占位符,可以与多个地址空间一起使用。

全局(__global)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

全局地址空间属性指定在全局内存中分配对象,所有工作项都可以访问该内存。存储在此内存区域中的内容在内核执行之间持续存在。允许全局地址空间的指针类型作为函数参数或局部变量。从OpenCL v2.0开始,全局地址空间也可以与全局(程序范围)变量和静态局部变量一起使用。

本地(__local)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

本地地址空间指定在本地(工作组)内存区域中分配对象,该区域可供同一工作组中的所有工作项访问。内核执行结束后,无法访问存储在此内存区域中的内容。在内核函数作用域中,任何变量都可以在本地地址空间中。在其他范围中,仅允许指向本地地址空间的指针类型。本地地址空间变量不能有初始化程序。

私人(__私人)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

专用地址空间指定在私有(工作项)内存中分配对象。其他工作项无法访问相同的内存区域,并且在工作项执行结束后其内容将被销毁。可以在专用地址空间中声明局部变量。函数参数始终位于专用地址空间中。指针或数组类型的内核函数参数不能指向专用地址空间。

可空性属性

当使用C族语言中的指针时,特定指针是否为“空”是一个重要的问题。各种可空性属性指示特定指针是否可以为空,这使得API更具表现力,并且可以帮助静态分析工具识别涉及空指针的错误。Clang支持几种可为空性属性:nonnullreturns_nonnull属性指示哪些函数或方法参数和结果类型永远不能为空,而可空性类型限定符指示哪些指针类型可以为null(_Nullable)或不能为null(_Nonnull)。

nullability(type)限定符表示给定指针类型的值是否为null(_Nullable限定符),null(限定符)没有定义的含义_Nonnull,或者null的目的不明确(_Null_unspecified限定符) 。因为可空性限定符在类型系统中表示,所以它们比nonnullreturns_nonnull属性更通用,允许表达(例如)可空指针到非空指针数组。可空性限定符写在它们应用的指针的右侧。例如:

// No meaningful result when 'ptr' is null (here, it happens to be undefined behavior).
int fetch(int * _Nonnull ptr) { return *ptr; }

// 'ptr' may be null.
int fetch_or_zero(int * _Nullable ptr) {
  return ptr ? *ptr : 0;
}

// A nullable pointer to non-null pointers to const characters.
const char *join_strings(const char * _Nonnull * _Nullable strings, unsigned n);

在Objective-C中,可以使用上下文相关的非下划线关键字在Objective-C方法和属性中使用可替换限定符的替代拼写。例如:

@interface NSView : NSResponder
  - (nullable NSView *)ancestorSharedWithView:(nonnull NSView *)aView;
  @property (assign, nullable) NSView *superview;
  @property (readonly, nonnull) NSArray *subviews;
@end

_Nonnull 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

_Nonnull空性限定符表示null不是所述的值的有意义的值_Nonnull的指针类型。例如,给出如下声明:

int fetch(int * _Nonnull ptr);

调用者不fetch应该提供空值,如果编译器看到传递给它的文字空值,它将产生警告fetch。请注意,与声明属性不同nonnull,存在_Nonnull并不意味着传递null是未定义的行为:fetch可以自由地考虑空未定义行为或(可能出于向后兼容性原因)防御性地处理null。

_Null_unspecified 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

_Null_unspecified空性限定符表示既没有_Nonnull也不_Nullable限定词意义特定指针类型。它主要用于表示null和带有特定指针的null在可空性注释头中的作用不明确,例如,由于过度复杂的实现或具有长期API的历史因素。

_Nullable 

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
    X  

_Nullable空性限定符指示的值_Nullable的指针类型可以为空。例如,给定:

int fetch_or_zero(int * _Nullable ptr);

调用者fetch_or_zero可以提供null。

nonnull(gnu :: nonnull)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX     

nonnull属性指示某些函数参数不能为空,并且可以以多种不同方式使用。它的原始用法(来自GCC)是一个函数(或Objective-C方法)属性,它指定函数的哪些参数在逗号分隔列表中是非空的。例如:

extern void * my_memcpy (void *dest, const void *src, size_t len)
                __attribute__((nonnull (1, 2)));

这里,nonnull属性指示参数1和2不能具有空值。省略带括号的参数索引列表意味着指针类型的所有参数都不能为空:

extern void * my_memcpy (void *dest, const void *src, size_t len)
                __attribute__((nonnull));

Clang还允许将nonnull属性直接放在函数(或Objective-C方法)参数上,从而无需在类型之前指定参数索引。例如:

extern void * my_memcpy (void *dest __attribute__((nonnull)),
                         const void *src __attribute__((nonnull)), size_t len);

注意,该nonnull属性指示将null传递给非null参数是未定义的行为,优化器可以利用该行为来例如移除空检查。该_Nonnull类型限定符表明,在更一般的方式的指针不能为空(因为它是类型系统的一部分),并不意味着未定义的行为,使之更广泛地适用。

returns_nonnull(gnu :: returns_nonnull)

支持的语法
GNUC ++ 11C2X__declspec关键词附注Pragma clang属性
XX    X

returns_nonnull属性指示特定函数(或Objective-C方法)始终返回非空指针。例如,malloc可能会定义一个特定系统,以便在内存不可用时终止进程,而不是返回空指针:

extern void * malloc (size_t size) __attribute__((returns_nonnull));

returns_nonnull属性意味着返回空指针是未定义的行为,优化器可以利用该行为。该_Nonnull类型限定符表明,在更一般的方式的指针不能为空(因为它是类型系统的一部分),并不意味着未定义的行为,使之更广泛地适用

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值