此页面列出了Clang当前支持的属性。
GNU | C ++ 11 | C2X | __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
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
该声明目标指令指定的变量和函数被映射到表示OpenMP卸载机构的装置。
declare target指令的语法如下:
#pragma omp declare target new-line
declarations-definition-seq
#pragma omp end declare target new-line
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
声明为的函数_Noreturn
不应返回其调用者。编译器将为声明为_Noreturn
能够返回其调用者的函数生成诊断。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
该abi_tag
属性可以应用于函数,变量,类或内联名称空间声明,以修改实体的受损名称。它能够区分同一实体的不同版本,但支持不同的ABI版本。例如,类的较新版本可以具有不同的数据成员集,因此具有不同的大小。使用该abi_tag
属性,可以为类类型的全局变量设置不同的受损名称。因此,旧代码可以继续使用旧的manged名称,新代码将使用带有标记的新修改名称。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
将功能标记为获取功能。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
__attribute__((alloc_align(
在函数声明上使用以指定函数的返回值(必须是指针类型)至少与指示参数的值一致。参数由形式参数列表中的索引给出; 除非函数是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未充分对齐,则行为未定义。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | 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 | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
该artificial
属性可以应用于内联函数。如果内联了这样的函数,则该属性指示调试器应将结果指令与调用站点相关联,而不是与内联调用者中的相应行相关联。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
标记一个动态测试是否保持功能的函数,如果未保存,则暂停程序。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
__attribute__((assume_aligned(
在函数声明上使用以指定函数的返回值(必须是指针类型)具有指定的偏移量(以字节为单位),具有指定对齐的地址。如果省略,则偏移量为零。
// 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)));
请注意,此属性向编译器提供有关代码已确保为真的条件的信息。它不会导致编译器强制执行提供的对齐假设。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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
宏
可以简化拼写:
@interface A
- (id)method API_AVAILABLE(macos(10.11)));
- (id)otherMethod API_AVAILABLE(macos(10.11), ios(11.0));
@end
另请参阅@available的文档
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
该carries_dependency
属性指定进出函数的依赖关系传播。
当在函数或Objective-C方法上指定时,该carries_dependency
属性意味着返回值带有函数的依赖性,因此实现不需要在从该函数返回时约束排序。函数及其调用者的实现可以选择保留依赖性而不是发出诸如栅栏的存储器排序指令。
注意,此属性不会更改程序的含义,但可能会生成更高效的代码。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
该__declspec(code_seg)
属性允许将代码放置到单独的命名段中,这些段可以单独分页或锁定在内存中。此属性用于控制实例化模板和编译器生成的代码的放置。请参阅MSDN上的__declspec(code_seg)文档。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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]];
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
将cpu_specific
和cpu_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 | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
将cpu_specific
和cpu_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 | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
该deprecated
属性可以应用于函数,变量或类型。在识别预期在程序的未来版本中删除的函数,变量或类型时,这非常有用。
考虑假设函数的函数声明f
:
void f(void) __attribute__((deprecated("message", "replacement")));
当拼写为__attribute __((不建议使用))时,不推荐使用的属性可以有两个可选的字符串参数。第一个是发出警告时要显示的消息; 第二个使编译器能够提供Fix-It以使用新名称替换已弃用的名称。否则,当拼写为 [[gnu :: deprecated]]或[[deprecated]]时,该属性可以有一个可选的字符串参数,该参数是发出警告时要显示的消息。
GNU | C ++ 11 | C2X | __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_if
enable_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)
。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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.
}
};
GNU | C ++ 11 | C2X | __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
与模板一起使用时可能会产生不直观的结果,具体取决于何时解决重载。在下面的例子,铛将发出诊断有关没有可行的重载foo
中bar
,但不是在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>();
}
这是因为,在bar
,foo
先于模板实例解决,所以该值I
是未知的(因此,既enable_if
为条件foo
失败)。然而,在baz
,foo
在模板实例化过程中解决了,所以价值T::number
是已知的。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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
该声明由某些工具自动生成。
条款可以按任何顺序指定。上面列出的子句都是可选的,但属性必须至少有一个子句。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
flatten
除非无法执行此操作,否则该属性会导致属性函数内的调用内联,例如,如果被调用者的主体不可用或者被调用者具有该noinline
属性。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
使用此属性强制堆栈对齐。
旧版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 () {
...
}
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
铛支持format
属性,它表示该函数接受printf
或scanf
样格式字符串和相应的参数或va_list
包含这些参数。
有关格式属性,请参阅GCC文档以查找有关属性语法的详细信息。
Clang使用此属性实现两种检查。
Clang检查带有format
属性的函数是否使用格式字符串调用,该格式字符串使用允许的格式说明符,并且该参数与格式字符串匹配。这是-Wformat
警告,默认情况下处于启用状态。
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
将收到警告。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
__attribute__((ifunc("resolver")))
用于标记应在运行时通过调用解析器函数来解析声明的地址。
解析器函数的符号名称以引号给出。必须在当前翻译单元中定义具有此名称的函数(在修改之后); 它可能是static
。解析器函数应该不带参数并返回指针。
该ifunc
属性只能用于函数声明。具有ifunc
属性的函数声明被视为声明的实体的定义。该实体不得具有薄弱的联系; 例如,在C ++中,如果将该位置的定义视为内联,则不能将其应用于声明。
并非所有目标都支持此属性。使用binutils v2.20.1或更高版本以及glibc v2.11.1或更高版本时,ELF目标支持此属性。非ELF目标目前不支持此属性。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
该internal_linkage
属性将声明的链接类型更改为internal。这类似于C风格static
,但可以用于类和类方法。应用于类定义时,此属性会影响该类的所有方法和静态数据成员。这可以用于通过从导出表中排除不需要的类方法来包含C ++库的ABI。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
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”的序列。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
Clang支持__attribute__((interrupt))
AVR目标上的GNU样式属性。该属性可以附加到函数定义,并指示后端生成适当的函数入口/出口代码,以便它可以直接用作中断服务例程。
在AVR上,硬件在执行中断时全局禁用中断。使用此属性声明的中断处理程序的第一条指令是重新启用中断的SEI指令。另请参见未插入SEI指令的signal属性。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
Clang支持__attribute__((interrupt("ARGUMENT")))
MIPS目标上的GNU样式属性。该属性可以附加到函数定义,并指示后端生成适当的函数入口/出口代码,以便它可以直接用作中断服务例程。
默认情况下,编译器将生成一个函数序言和结尾,适用于处理外部中断控制器(eic)生成的中断的中断服务程序。可以使用“eic”参数显式请求此行为。
否则,为了使用向量中断模式,传递的参数应为“vector = LEVEL”形式,其中LEVEL是以下值之一:“sw0”,“sw1”,“hw0”,“hw1”,“hw2” ,“hw3”,“hw4”,“hw5”。然后,编译器将中断屏蔽设置为相应的级别,该级别将屏蔽所有中断,包括参数。
语义如下:
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
Clang支持__attribute__((interrupt))
RISCV目标上的GNU样式属性。该属性可以附加到函数定义,并指示后端生成适当的函数入口/出口代码,以便它可以直接用作中断服务例程。
此参数允许值是user
,supervisor
和machine
。如果没有参数,则默认为机器。
同一声明上的重复中断属性将导致发出警告。如果重复声明,则以最后一个声明为准。
请参阅:https : //gcc.gnu.org/onlinedocs/gcc/RISC-V-Function-Attributes.html https://riscv.org/specifications/privileged-isa/ RISC-V指令集手册第二卷:特权架构版本1.10。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
__attribute__((kernel))
用于kernel
在RenderScript中标记函数。
在RenderScript中,kernel
函数用于表示数据并行计算。RenderScript运行时有效地并行化kernel
函数以在诸如多核CPU和GPU之类的计算资源上运行。有关更多信息,请参阅RenderScript文档。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
该lifetimebound
属性指示由注释函数的返回值(或者,对于构造函数的参数,在构造对象的值中)保留由函数参数或隐式对象参数拥有的资源。它仅在C ++中受支持。
此属性提供了C ++委员会文件[ http://wg21.link/p0936r0](P0936R0)中描述的工具的实验性实现,并且随着相应功能的设计更改而可能会发生变化。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
铛支持__attribute__((long_call))
,__attribute__((far))
以及__attribute__((near))
对MIPS目标的属性。这些属性只能添加到函数声明中,并在直接调用函数时更改编译器生成的代码。该near
属性允许使用该jal
指令调用该函数,该指令要求该函数位于与调用者相同的自然对齐的256MB段中。在long_call
和far
属性是同义词和要求使用作品的功能之间的距离,无论不同的调用序列。
这些属性对与位置无关的代码没有影响。
这些属性优先于命令行开关,例如-mlong-calls
和-mno-long-calls
。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
Clang支持MIPS目标上的GNU样式__attribute__((micromips))
和 __attribute__((nomicromips))
属性。这些属性可以附加到函数定义,并指示后端生成或不生成该函数的microMIPS代码。
这些属性会覆盖命令行上的-mmicromips和-mno-micromips选项。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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
影响代码。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
使用此属性指示指定的函数没有调用者保存的寄存器。也就是说,除了用于将参数传递给函数或从函数返回参数的寄存器之外,所有寄存器都是被调用者保存的。编译器保存并恢复未用于向函数传递或返回参数的任何已修改寄存器。
用户可以从中断处理程序调用使用'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之外的任何修改的寄存器。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
使用no_sanitize
函数或全局变量声明中的属性指定不应用特定检测或一组检测。该属性采用字符串文字列表,其含义与-fno-sanitize=
标志接受的值相同 。例如,指定不应将AddressSanitizer和ThreadSanitizer应用于函数或变量。__attribute__((no_sanitize("address", "thread")))
有关支持的清理程序标志的完整列表,请参阅控制代码生成。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
使用__attribute__((no_sanitize_address))
上的功能或全局变量声明指定地址的安全规范(如AddressSanitizer)不应适用。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
__attribute__((no_sanitize_memory))
在函数声明上使用以指定不应插入对未初始化内存的检查(例如,通过MemorySanitizer)。该工具仍然可以检测该功能,以避免在其他地方出现误报。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
使用__attribute__((no_sanitize_thread))
函数声明来指定ThreadSanitizer不应插入对普通(非原子)内存访问的数据争用检查。该工具仍然使用该工具来避免误报并提供有意义的堆栈跟踪。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
该no_split_stack
属性禁用特定功能的拆分堆栈前导码的发射。如果-fsplit-stack
未指定,则无效。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
Clang支持在__attribute__((no_stack_protector))
指定函数上禁用堆栈保护程序的属性。在使用-fstack-protector
编译器选项构建时,此属性对于在某些函数上有选择地禁用堆栈保护程序非常有用 。
例如,它禁用了函数的堆栈保护程序,foo
但bar
仍然使用带有-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.
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
该noalias
属性表示函数内部唯一的内存访问是从其指针类型参数指向的对象加载和存储,具有任意偏移。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
面向跳转的编程攻击依赖于篡改间接调用/ jmp使用的地址,例如将控制流重定向到二进制文件中的非程序员预期字节。X86支持间接分支跟踪(IBT),作为控制流强制技术(CET)的一部分。IBT工具ENDBR指令用于指定间接调用/ jmp的有效目标。该nocf_check
属性有两个作用:1。对函数的附加 - 不要在函数的开头添加ENDBR指令。2.对函数指针的附加 - 不跟踪该指针的目标函数(通过向间接调用指令添加nocf_check前缀)。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
Clang支持在可疑情况下丢弃函数调用表达式的结果时进行诊断的能力。当函数或其返回类型标记为[[nodiscard]]
(或__attribute__((warn_unused_result))
)并且函数调用显示为未明确转换为void的潜在评估的丢弃值表达式时, 将生成诊断。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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”的调用是重复的并且陷入条件的两个分支。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
Clang支持MIPS目标上的GNU样式__attribute__((micromips))
和 __attribute__((nomicromips))
属性。这些属性可以附加到函数定义,并指示后端生成或不生成该函数的microMIPS代码。
这些属性会覆盖命令行上的-mmicromips和-mno-micromips选项。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
声明为的函数[[noreturn]]
不应返回其调用者。编译器将为声明为[[noreturn]]
能够返回其调用者的函数生成诊断。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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;
};
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
Clang支持GNU样式__attribute__((nothrow))
和Microsoft样式 __declspec(nothrow)
属性,相当于函数声明中的noexcept。此属性通知编译器注释函数不会引发异常。这可以防止异常展开。此属性对C标准库中保证不会引发异常的函数特别有用。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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);
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
Objective-C中的许多方法具有由其选择器确定的常规含义。尽管没有正确的选择器,或者不具有其选择器所暗示的传统含义,但有时能够将方法标记为具有特定的传统含义是有用的。对于这些用例,我们提供了一个属性来专门描述方法所属的“方法族”。
使用方法:__attribute__((objc_method_family(X)))
,其中X
是一个 none
,alloc
,copy
,init
,mutableCopy
,或new
。此属性只能放在方法声明的末尾:
- (NSString *)initMyStringValue __attribute__((objc_method_family(none)));
用户谁不希望改变的方法的传统含义,谁只是想记录其非标准的保留和释放语义,应该使用固定行为属性(ns_returns_retained
, ns_returns_not_retained
,等)。
使用查询此功能__has_attribute(objc_method_family)
。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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{};
^
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
默认情况下,Objective-C接口或协议标识符用于该对象的元数据名称。该objc_runtime_name 属性允许注解的接口或协议来使用对象的元数据的名称,而不是默认名称为指定字符串参数。
用法:__attribute__((objc_runtime_name("MyLocalName")))
。此属性只能放在@protocol或@interface声明之前:
__attribute__((objc_runtime_name("MyLocalName")))
@interface Message
@end
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
此属性指定它应用的Objective-C类对Objective-C运行时可见,但对链接器不可见。使用此属性注释的类不能进行子类化,也不能为它们定义类别。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
该optnone
属性基本上抑制了函数或方法的所有优化,而不管整个编译单元应用的优化级别如何。当您需要调试特定函数时,这尤其有用,但是在没有优化的情况下构建整个应用程序是不可行的。避免对指定函数进行优化可以提高该函数的调试信息的质量。
此属性与always_inline
和minsize
属性不兼容。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
Clang在C中提供对C ++函数重载的支持overloadable
。使用该属性引入C中的函数重载。例如,一个可能会提供一个的几个重载版本tgsin
调用适当的标准函数计算值的正弦与功能float
, double
或者精度:long double
#include
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-具体语义:
float
或double
到被列为一个浮点推广(每C99),而不是作为一个浮点转换(如在C ++)。long double
T*
指针到类型U*
指针的转换被认为是指针转换(具有转换等级)if T
和U
是兼容类型。T
到类型的值U
是允许的,如果T
和U
是兼容的类型。该转换被赋予“转换”等级。T*
的指针转换为类型的指针U*
,其中T
和U
不兼容。此转化次数低于所有其他类型的转化次数。请注意:U
缺少存在的限定符T
就足够T
且U
不相容。的声明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
分别。使用名称修改有两个注意事项:
staticinline
overloadable
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)
。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
将功能标记为释放功能。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
铛支持__attribute__((long_call))
,__attribute__((far))
, __attribute__((short__call))
,和__attribute__((near))
在MIPS目标的属性。这些属性只能添加到函数声明中,并在直接调用函数时更改编译器生成的代码。的short_call
和near
属性是同义词,并允许使用该被制成的函数调用jal
指令,这需要为位于同一自然对齐256MB段作为呼叫者的功能。在long_call
和far
属性是同义词和要求使用作品的功能之间的距离,无论不同的调用序列。
这些属性对与位置无关的代码没有影响。
这些属性优先于命令行开关,例如-mlong-calls
和-mno-long-calls
。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
Clang支持__attribute__((signal))
AVR目标上的GNU样式属性。该属性可以附加到函数定义,并指示后端生成适当的函数入口/出口代码,以便它可以直接用作中断服务例程。
使用signal属性定义的中断处理程序函数不会重新启用中断。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | 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
(后备)实现,否则该函数的使用被视为无效。另外,功能在首次使用后可能不会成为多版本。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
标记尝试获取功能的功能。该功能可能无法实际获得该功能; 它们接受一个布尔值,确定获取能力是否意味着成功(真实),或者无法获得能力意味着成功(错误)。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
该__declspec(dllexport)
属性声明要从模块导出的变量,函数或Objective-C接口。它在 -fdeclspec
标志下可用于兼容各种编译器。主要用于COFF目标文件,它明确指定哪些接口可供外部使用。有关更多信息,请参阅MSDN上的dllexport文档。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
该__declspec(dllimport)
属性声明要从外部模块导入的变量,函数或Objective-C接口。它在-fdeclspec
标志下可用于兼容各种编译器。主要用于COFF目标文件,它明确指定从外部模块导入的接口。有关更多信息,请参阅MSDN上的dllimport文档。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
应用的属性控制发出全局初始化函数指针的部分。它只适用于。通常,此函数指针在Windows上发出。用户可以通过使用具有相同前缀的不同部分名称和在标准部分之前或之后按字典顺序排序的后缀来更改初始化的顺序 。有关 更多信息,请参阅MSDN上的init_seg文档。pragma init_seg()
-fms-extensions
.CRT$XCU
.CRT$XC
.CRT$XCU
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
将-Wunused
标志传递给Clang时,可以诊断程序未使用的实体。的[[maybe_unused]]
(或 __attribute__((unused))
)属性可用于沉默这样的诊断时的实体不能被移除。例如,局部变量可能仅存在于assert()
语句中,这使得局部变量在NDEBUG
定义时未使用。
该属性可以应用于类的声明,typedef,变量,函数或方法,函数参数,枚举,枚举器,非静态数据成员或标签。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
该nodebug
属性允许您抑制函数或方法的调试信息,或者不是参数或非静态数据成员的变量的调试信息。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
noescape
放置在指针类型的函数参数上用于通知编译器指针不能转义:也就是说,指针指向的对象没有引用从参数值派生的对象将在函数返回后继续存在。用户有责任确保注释的参数noescape
不会真正逃脱。
例如:
int *gp;
void nonescapingFunc(__attribute__((noescape)) int *p) {
*p += 100; // OK.
}
void escapingFunc(__attribute__((noescape)) int *p) {
gp = p; // Not OK.
}
此外,当参数是块指针
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.
}
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
OpenCL 2.0支持__attribute__((nosvm))
指针变量的可选限定符。它通知编译器指针不引用共享虚拟内存区域。有关详细信息,请参见OpenCL v2.0 s6.7.2。
由于它没有被广泛使用并且已从OpenCL 2.1中删除,因此它被Clang忽略。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
注意
带有注释参数的函数的 pass_object_size
修改可能会发生变化。您可以通过使用__asm__("foo")
明确命名函数来解决这个问题,从而保留您的ABI; 此外,不可重载的C函数pass_object_size
不会被破坏。
该pass_object_size(Type)
属性可以放在函数参数上,以指示clang 在所述函数的每个调用点调用,并在注释参数后直接 将该调用的结果作为类型的不可见参数隐式传递。Clang还将通过所述隐式参数替换函数中的任何调用 。__builtin_object_size(param, Type)
size_t
pass_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
在其函数的定义中标记。GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | 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.
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
该section
属性允许您指定翻译后全局变量或函数应包含的特定部分。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
该swift_context
属性将swiftcall
函数的参数标记为具有特殊的上下文参数ABI处理。
这种处理通常将特定寄存器中的上下文值传递,该寄存器通常是被调用者保留的。
甲swift_context
参数必须是最后一个参数或必须跟一个swift_error_result
参数(其本身必须始终是最后一个参数)。
上下文参数必须具有指针或引用类型。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
该swift_error_result
属性将swiftcall
函数的参数标记为具有特殊错误结果ABI处理。
这种处理通常通过特殊寄存器将基本的错误值传入和传出函数,该寄存器通常是被调用者保留的。这是通过假装寄存器是可寻址存储器在C中建模的:
一个swift_error_result
参数必须是最后一个参数,它必须由前面swift_context
的参数。
甲swift_error_result
参数必须具有类型T**
或T*&
某种类型T.注意,没有限定词被允许在中间电平。
如果调用者未将指针或引用传递给有效对象,则它是未定义的行为。
标准约定是函数入口时错误值本身(即存储在explicit参数中的值)将为null,但ABI不强制执行此操作。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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)。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
该swiftcall
属性指示应使用函数或函数指针的Swift调用约定来调用函数。
正如Swift ABI文档所描述的那样,Swift调用约定的降低发生在多个阶段。第一个“高级”阶段将形式参数和结果分解为天生的直接和间接组件,为通用签名添加隐式参数,并将上下文和错误ABI处理分配给适用的参数。第二阶段分解第一阶段的直接参数和结果,并将它们分配给寄存器或堆栈。该swiftcall
公约只处理第二阶段的降低; C函数类型必须准确反映第一阶段的结果,如下所示:
swift_indirect_result
属性的参数。void
。swift_context
属性的尾随参数。swift_error_result
属性的尾随参数(始终遵循上下文参数) 。swiftcall
不支持可变参数或非原型函数。
参数ABI处理属性是函数类型的方面。将ABI处理属性应用于参数的函数类型与不具有其他相同函数类型的函数类型不同。单个参数可能没有多个ABI处理属性。
对此功能的支持是依赖于目标的,尽管它应该支持Swift支持的每个目标。查询此支持__has_attribute(swiftcall)
。这意味着为支撑 swift_context
,swift_error_result
和swift_indirect_result
属性。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
该__declspec(thread)
属性声明一个带有线程本地存储的变量。它在-fms-extensions
MSVC兼容性的标志下可用。请参阅MSDN上的__declspec(线程)文档。
在Clang中,__declspec(thread)
功能通常与GNU __thread
关键字相同。变量必须没有析构函数,并且必须具有常量初始值设定项(如果有)。该属性仅适用于使用静态存储持续时间声明的变量,例如全局变量,类静态数据成员和静态本地变量。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
该tls_model
属性允许您指定要使用的线程本地存储模型。它接受以下字符串:
TLS模型是互斥的。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | 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
在以下情况下,属性无效:
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
此关键字集合在下面启用-fms-extensions
并控制*-*-win32
目标上使用的指向成员的表示。
的*-*-win32
目标利用指针到构件表示这在取决于底层类的定义尺寸和对齐而变化。
但是,当前向声明仅可用且尚未定义时,这是有问题的。在这种情况下,Clang被迫使用最常用的代表。
这些关键字使得可以使用除最常规之外的指针到成员表示,而不管该定义是否将出现在当前翻译单元中。
这个关键字系列属于class-key
和class-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 {};
GNU | C ++ 11 | C2X | __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) { ... }
如果指针值在运行时没有指定的对齐方式,则程序的行为是未定义的。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
empty_bases属性允许编译器更频繁地利用空基优化。此属性仅适用于struct,class和union类型。仅在使用Microsoft C ++ ABI时才支持它。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
属性enum_extensibility
用于区分可扩展的枚举定义和不可扩展的枚举定义。该属性可以采用 closed
或open
作为参数。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
}
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
可以将此属性添加到枚举器,以向编译器发出信号,表明它将用作标志类型。这将导致编译器假定该类型的范围包括在发出警告时通过操纵枚举器的位可以获得的所有值。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
layout_version属性请求编译器使用特定编译器版本的类布局规则。此属性仅适用于struct,class和union类型。仅在使用Microsoft C ++ ABI时才支持它。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
请参阅LTO可见性。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
可以将此属性添加到类声明或定义中,以向编译器发出信号,表明构造函数和析构函数不会引用虚函数表。仅在使用Microsoft C ++ ABI时才支持它。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | X |
可以将此属性添加到Objective-C @interface
声明中,以确保不能对此类进行子类化。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
此属性附属于全局符号,导致其具有弱定义( linkonce ),允许链接器选择任何定义。
有关更多信息,请参阅 gcc文档 或msvc文档。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
此属性可以应用于联合,以更改对具有透明联合类型的参数的函数的调用行为。编译器行为以下列方式更改:
C ++不支持透明联合。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
该指令允许为后续循环指定循环优化提示。该指令允许启用或禁用矢量化,交错和展开。可以手动指定矢量宽度以及交错和展开计数。有关 详情,请参阅 语言扩展#pragma clang loop
GNU | C ++ 11 | C2X | __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)
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
可选属性intel_reqd_sub_group_size可用于指示必须使用指定的子组大小编译和执行内核。当存在此属性时,get_max_sub_group_size()保证返回指定的整数值。这对于许多子组算法的正确性很重要,并且在某些情况下编译器可以使用它来生成更优的代码。有关 详细信息,请参阅cl_intel_required_subgroup_size
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
opencl_unroll_hint属性限定符可用于指定可以展开循环(for,while和do循环)。此属性限定符可用于指定按指定量完全展开或部分展开。这是编译器提示,编译器可能会忽略此指令。有关 详细信息,请参阅 OpenCL v2.0 s6.11.5。
GNU | C ++ 11 | C2X | __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节中找到。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
的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();
}
GNU | C ++ 11 | C2X | __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")]];
...
}
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
扁平工作组大小是分派内核时指定的工作组大小中的工作项数。它是工作组的x,y和z维度大小的乘积。
Clang支持AMDGPU目标的 属性。此属性可以附加到内核函数定义,并且是优化提示。__attribute__((amdgpu_flat_work_group_size(
参数指定最小平面工作组大小,
参数指定
内核的所有调度将符合的最大平面工作组大小(必须大于 )。传递 为暗示默认行为()。0, 0
128, 256
如果指定,AMDGPU目标后端可能能够通过估计可用的组段大小来生成更好的障碍机器代码并执行临时促销。
如果出现以下错误:
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
Clang支持AMDGPU目标的属性__attribute__((amdgpu_num_sgpr(
和 __attribute__((amdgpu_num_vgpr(
属性。这些属性可以附加到内核函数定义,并且是优化提示。
如果指定了这些属性,则AMDGPU目标后端将尝试将所使用的SGPR和/或VGPR的数量限制为指定值。所使用的SGPR和/或VGPR的数量可以进一步向上舍入以满足子目标的分配要求或约束。传递0
为 num_sgpr
和/或num_vgpr
暗示默认行为(无限制)。
这些属性可用于测试AMDGPU目标后端。建议使用该amdgpu_waves_per_eu
属性来控制SGPR和VGPR等资源,因为它知道不同子目标的限制。
如果出现以下错误:
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
Clang支持AMDGPU目标的属性__attribute__((amdgpu_num_sgpr(
和 __attribute__((amdgpu_num_vgpr(
属性。这些属性可以附加到内核函数定义,并且是优化提示。
如果指定了这些属性,则AMDGPU目标后端将尝试将所使用的SGPR和/或VGPR的数量限制为指定值。所使用的SGPR和/或VGPR的数量可以进一步向上舍入以满足子目标的分配要求或约束。传递0
为 num_sgpr
和/或num_vgpr
暗示默认行为(无限制)。
这些属性可用于测试AMDGPU目标后端。建议使用该amdgpu_waves_per_eu
属性来控制SGPR和VGPR等资源,因为它知道不同子目标的限制。
如果出现以下错误:
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
计算单元(CU)负责执行工作组的波前。它由一个或多个执行单元(EU)组成,它们负责执行波前。欧盟可以拥有足够的资源来维持多个执行波阵面的状态。这允许EU通过以类似于CPU上的对称多线程的方式在波前之间切换来隐藏延迟。为了使多个波前的状态适合欧盟,单个波前使用的资源必须受到限制。例如,SGPR和VGPR的数量。限制这样的资源可以允许更大的延迟隐藏,但是可能导致必须将一些寄存器状态溢出到存储器。
Clang支持 AMDGPU目标的属性。此属性可以附加到内核函数定义,并且是优化提示。__attribute__((amdgpu_waves_per_eu(
参数指定每个EU请求的最小波数, 可选
参数指定每个EU请求的最大波数(必须大于指定的最大波数
)。如果
省略,则除了由编译内核的硬件规定的波数之外,对每个EU的最大波数没有限制。传递 的暗示的默认行为(没有限制)。0, 0
如果指定,则此属性允许高级开发人员调整能够适应EU资源的波前数量。AMDGPU目标后端可以使用此信息来限制资源,例如SGPR的数量,VGPR的数量,可用组的大小和私有内存段,从而保证至少
波前和最多
波前能够适应欧盟的资源。请求更多波前可能会隐藏内存延迟,但会限制可能导致溢出的可用寄存器。请求更少的波前可以帮助减少缓存抖动,但可以减少内存延迟隐藏。
此属性控制AMDGPU目标后端生成的机器代码,以确保它能够满足请求的值。但是,当执行内核时,可能还有其他原因阻止满足请求,例如,可能存在来自欧盟上执行的其他内核的波前。
如果出现以下错误:
Clang支持几种不同的调用约定,具体取决于目标平台和体系结构。用于函数的调用约定确定如何传递参数,如何将结果返回给调用者,以及调用函数的其他低级细节。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
在32位x86目标上,此属性更改函数的调用约定,以使用ECX和EDX作为寄存器参数,并在返回时清除堆栈中的参数。此约定不支持C中的可变参数调用或非原型函数,并且对x86_64目标没有影响。支持此调用约定主要是为了与现有代码兼容。寻求寄存器参数的用户应该使用该regparm
属性,该属性不需要被调用者清理。请参阅MSDN上的__fastcall文档。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
在非Windows x86_64目标上,此属性更改函数的调用约定以匹配Windows x86_64上使用的默认约定。此属性对Windows目标或非x86_64目标没有影响。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
在ARM目标上,此属性可用于选择类似于stdcall
x86的调用约定。有效参数值为“aapcs”和“aapcs-vfp”。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
在X86-64和AArch64目标上,此属性更改函数的调用约定。该preserve_all
调用约定试图使代码甚至比较少干扰呼叫者preserve_most
调用约定。此调用约定的行为与C
调用约束和返回值的方式相同,但它使用一组不同的调用者/被调用者保存的寄存器。这消除了在调用者中调用之前和之后保存和恢复大型寄存器集的负担。如果参数在被调用者保存的寄存器中传递,则调用者将在整个调用中保留它们。这不适用于被调用者保存的寄存器中返回的值。
此约定背后的想法是支持对不需要调用任何其他函数的运行时函数的调用。
与调用约定一样,此preserve_most
调用约定将由Objective-C运行时的未来版本使用,此时应被视为实验。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
在X86-64和AArch64目标上,此属性更改函数的调用约定。该preserve_most
调用约定试图使调用者的代码作为非侵入越好。此约定的行为与C
关于如何传递参数和返回值的调用约定相同,但它使用一组不同的调用者/被调用者保存的寄存器。这减轻了在呼叫者呼叫之前和之后保存和恢复大寄存器组的负担。如果参数在被调用者保存的寄存器中传递,则调用者将在整个调用中保留它们。这不适用于被调用者保存的寄存器中返回的值。
此约定背后的想法是支持对具有热路径和冷路径的运行时函数的调用。热路径通常是一小段代码,不使用许多寄存器。冷路径可能需要调用另一个函数,因此只需要保留调用者保存的寄存器,这些寄存器尚未被调用者保存。该 preserve_most调用约定是非常相似的cold
在主叫/被叫保存寄存器方面的调用约定,但它们用于不同类型的函数调用。coldcc
是用于很少执行的函数调用,而preserve_most函数调用是在热路径上并且肯定执行很多。此外preserve_most
不会阻止内联器内联函数调用。
此调用约定将由Objective-C运行时的未来版本使用,因此此时仍应被视为实验。虽然创建此约定是为了优化对Objective-C运行时的某些运行时调用,但它不仅限于此运行时,并且将来也可能被其他运行时使用。当前的实现仅支持X86-64和AArch64,但目的是在未来支持更多的体系结构。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
在x86目标上,此属性将调用约定更改为 __regcall约定。该惯例旨在尽可能多地在寄存器中传递参数。它还尝试在可能的情况下利用寄存器作为返回值。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
在32位x86目标上,regparm属性使编译器传递EAX,EDX和ECX中的前三个整数参数,而不是堆栈上的参数。此属性对可变参数函数没有影响,并且所有参数都正常地通过堆栈传递。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
在32位x86目标上,此属性更改函数的调用约定,以在返回时清除堆栈中的参数。此约定不支持C中的可变参数调用或非原型函数,并且对x86_64目标没有影响。Windows API和COM应用程序广泛使用此调用约定。请参阅MSDN上的__stdcall文档。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
在32位x86目标上,此属性更改函数的调用约定,以将ECX用作第一个参数(通常this
是C ++方法的隐式参数),并在返回时清除堆栈中的参数。此约定不支持C中的可变参数调用或非原型函数,并且对x86_64目标没有影响。请参阅MSDN上的__thiscall文档。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X | 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支持用于检查基本资源管理属性的其他属性,特别是对于具有单个拥有引用的唯一对象。目前支持以下属性,但这些注释的实现目前正在开发中并且可能会发生变化。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
使用__attribute__((callable_when(...)))
来表示什么状态的方法可以被调用。有效状态为未消费,消费,还是个未知数。此属性的每个参数都必须是带引号的字符串。例如:
__attribute__((callable_when("unconsumed", "unknown")))
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
每个class
使用任何typestate注释必须先使用标记consumable
属性。如果不这样做将导致警告。
此属性接受必须是下列之一的单个参数: unknown
,consumed
,或unconsumed
。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
此属性指定对函数参数的期望。如果相应的参数未处于预期状态,则对带有注释参数的函数的调用将发出警告。该属性还用于在分析函数体时设置参数的初始状态。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
该return_typestate
属性可以应用于函数或参数。应用于函数时,该属性指定返回值的状态。检查函数的主体以确保它始终返回指定状态的值。在调用者端,注释函数返回的值被初始化为给定状态。
应用于函数参数时,它会在调用函数返回后修改参数的状态。检查函数的主体以确保参数在返回之前处于预期状态。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
注释用于将对象转换为新状态的方法 __attribute__((set_typestate(new_state)))
。新状态必须是未消耗的,消耗的或未知的。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
使用__attribute__((test_typestate(tested_state)))
以表示方法,如果对象是在指定的状态返回true ..
Clang支持其他属性以启用检查C类型系统无法强制执行的类型安全属性。要查看这些检查产生的警告,请确保已启用-Wtype-safety。用例包括:
MPI_Datatype
;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);
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
在函数声明上使用以指定函数接受确定某个其他参数类型的类型标记。__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.
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
在函数声明上使用以指定函数接受一个类型标记,该标记确定某个其他指针参数的指针类型。__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.
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
声明变量时,用于 创建与赋予属性的参数绑定的类型标记。__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_idx
或ptr_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支持以下地址空间:__ 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节中找到。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
常量地址空间属性表示对象位于常量(不可修改的)存储区域中。它适用于所有工作项目。任何类型都可以使用常量地址空间属性进行注释。具有常量地址空间限定符的对象可以在任何范围内声明,并且必须具有初始化程序。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
通用地址空间属性仅适用于OpenCL v2.0及更高版本。它可以与指针类型一起使用。全局和局部范围中的变量以及非内核函数中的函数参数可以具有通用地址空间类型属性。除了OpenCL代码中的“__constant”之外,它可以作为任何其他地址空间的占位符,可以与多个地址空间一起使用。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
全局地址空间属性指定在全局内存中分配对象,所有工作项都可以访问该内存。存储在此内存区域中的内容在内核执行之间持续存在。允许全局地址空间的指针类型作为函数参数或局部变量。从OpenCL v2.0开始,全局地址空间也可以与全局(程序范围)变量和静态局部变量一起使用。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
本地地址空间指定在本地(工作组)内存区域中分配对象,该区域可供同一工作组中的所有工作项访问。内核执行结束后,无法访问存储在此内存区域中的内容。在内核函数作用域中,任何变量都可以在本地地址空间中。在其他范围中,仅允许指向本地地址空间的指针类型。本地地址空间变量不能有初始化程序。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
专用地址空间指定在私有(工作项)内存中分配对象。其他工作项无法访问相同的内存区域,并且在工作项执行结束后其内容将被销毁。可以在专用地址空间中声明局部变量。函数参数始终位于专用地址空间中。指针或数组类型的内核函数参数不能指向专用地址空间。
当使用C族语言中的指针时,特定指针是否为“空”是一个重要的问题。各种可空性属性指示特定指针是否可以为空,这使得API更具表现力,并且可以帮助静态分析工具识别涉及空指针的错误。Clang支持几种可为空性属性:nonnull
和returns_nonnull
属性指示哪些函数或方法参数和结果类型永远不能为空,而可空性类型限定符指示哪些指针类型可以为null(_Nullable
)或不能为null(_Nonnull
)。
nullability(type)限定符表示给定指针类型的值是否为null(_Nullable
限定符),null(限定符)没有定义的含义_Nonnull
,或者null的目的不明确(_Null_unspecified
限定符) 。因为可空性限定符在类型系统中表示,所以它们比nonnull
和returns_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
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
的_Nonnull
空性限定符表示null不是所述的值的有意义的值_Nonnull
的指针类型。例如,给出如下声明:
int fetch(int * _Nonnull ptr);
调用者不fetch
应该提供空值,如果编译器看到传递给它的文字空值,它将产生警告fetch
。请注意,与声明属性不同nonnull
,存在_Nonnull
并不意味着传递null是未定义的行为:fetch
可以自由地考虑空未定义行为或(可能出于向后兼容性原因)防御性地处理null。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
的_Null_unspecified
空性限定符表示既没有_Nonnull
也不_Nullable
限定词意义特定指针类型。它主要用于表示null和带有特定指针的null在可空性注释头中的作用不明确,例如,由于过度复杂的实现或具有长期API的历史因素。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X |
的_Nullable
空性限定符指示的值_Nullable
的指针类型可以为空。例如,给定:
int fetch_or_zero(int * _Nullable ptr);
调用者fetch_or_zero
可以提供null。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X |
该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
类型限定符表明,在更一般的方式的指针不能为空(因为它是类型系统的一部分),并不意味着未定义的行为,使之更广泛地适用。
GNU | C ++ 11 | C2X | __declspec | 关键词 | 附注 | Pragma clang属性 |
---|---|---|---|---|---|---|
X | X | X |
该returns_nonnull
属性指示特定函数(或Objective-C方法)始终返回非空指针。例如,malloc
可能会定义一个特定系统,以便在内存不可用时终止进程,而不是返回空指针:
extern void * malloc (size_t size) __attribute__((returns_nonnull));
该returns_nonnull
属性意味着返回空指针是未定义的行为,优化器可以利用该行为。该_Nonnull
类型限定符表明,在更一般的方式的指针不能为空(因为它是类型系统的一部分),并不意味着未定义的行为,使之更广泛地适用