1 // RUN: %clang_cc1 %s -ast-dump -fblocks | FileCheck %s
3 // Make sure that the attribute gets parsed and attached to the correct AST elements.
5 #pragma clang diagnostic ignored "-Wunused-variable"
6 #pragma clang diagnostic ignored "-Wperf-constraint-implies-noexcept"
8 // =========================================================================================
9 // Square brackets, true
11 namespace square_brackets
{
13 // 1. On the type of the FunctionDecl
14 void nl_function() [[clang::nonblocking
]];
15 // CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'
17 // 2. On the type of the VarDecl holding a function pointer
18 void (*nl_func_a
)() [[clang::nonblocking
]];
19 // CHECK: VarDecl {{.*}} nl_func_a 'void (*)() __attribute__((nonblocking))'
21 // 3. On the type of the ParmVarDecl of a function parameter
22 static void nlReceiver(void (*nl_func
)() [[clang::nonblocking
]]);
23 // CHECK: ParmVarDecl {{.*}} nl_func 'void (*)() __attribute__((nonblocking))'
25 // 4. As an AttributedType within the nested types of a typedef
26 typedef void (*nl_fp_type
)() [[clang::nonblocking
]];
27 // CHECK: TypedefDecl {{.*}} nl_fp_type 'void (*)() __attribute__((nonblocking))'
28 using nl_fp_talias
= void (*)() [[clang::nonblocking
]];
29 // CHECK: TypeAliasDecl {{.*}} nl_fp_talias 'void (*)() __attribute__((nonblocking))'
31 // 5. From a typedef or typealias, on a VarDecl
32 nl_fp_type nl_fp_var1
;
33 // CHECK: VarDecl {{.*}} nl_fp_var1 'nl_fp_type':'void (*)() __attribute__((nonblocking))'
34 nl_fp_talias nl_fp_var2
;
35 // CHECK: VarDecl {{.*}} nl_fp_var2 'nl_fp_talias':'void (*)() __attribute__((nonblocking))'
37 // 6. On type of a FieldDecl
39 void (*nl_func_field
)() [[clang::nonblocking
]];
40 // CHECK: FieldDecl {{.*}} nl_func_field 'void (*)() __attribute__((nonblocking))'
43 // nonallocating should NOT be subsumed into nonblocking
44 void nl1() [[clang::nonblocking
]] [[clang::nonallocating
]];
45 // CHECK: FunctionDecl {{.*}} nl1 'void () __attribute__((nonblocking)) __attribute__((nonallocating))'
47 void nl2() [[clang::nonallocating
]] [[clang::nonblocking
]];
48 // CHECK: FunctionDecl {{.*}} nl2 'void () __attribute__((nonblocking)) __attribute__((nonallocating))'
51 // CHECK: FunctionDecl {{.*}} nl3 'decltype(nl1)':'void () __attribute__((nonblocking)) __attribute__((nonallocating))'
53 // Attribute propagates from base class virtual method to overrides.
55 virtual void nb_method() [[clang::nonblocking
]];
57 struct Derived
: public Base
{
58 void nb_method() override
;
59 // CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((nonblocking))'
62 // Dependent expression
65 void nb_method2() [[clang::nonblocking(V
)]];
66 // CHECK: CXXMethodDecl {{.*}} nb_method2 'void () __attribute__((nonblocking(V)))'
71 // On the type of the VarDecl holding a BlockDecl
72 void (^nl_block1
)() [[clang::nonblocking
]] = ^() [[clang::nonblocking
]] {};
73 // CHECK: VarDecl {{.*}} nl_block1 'void (^)() __attribute__((nonblocking))'
75 int (^nl_block2
)() [[clang::nonblocking
]] = ^() [[clang::nonblocking
]] { return 0; };
76 // CHECK: VarDecl {{.*}} nl_block2 'int (^)() __attribute__((nonblocking))'
78 // The operand of the CallExpr is an ImplicitCastExpr of a DeclRefExpr -> nl_block which hold the attribute
79 static void blockCaller() { nl_block1(); }
80 // CHECK: DeclRefExpr {{.*}} 'nl_block1' 'void (^)() __attribute__((nonblocking))'
84 // On the operator() of a lambda's CXXMethodDecl
85 auto nl_lambda
= []() [[clang::nonblocking
]] {};
86 // CHECK: CXXMethodDecl {{.*}} operator() 'void () const __attribute__((nonblocking))' inline
88 // =========================================================================================
89 // Square brackets, false
91 void nl_func_false() [[clang::blocking
]];
92 // CHECK: FunctionDecl {{.*}} nl_func_false 'void () __attribute__((blocking))'
94 auto nl_lambda_false
= []() [[clang::blocking
]] {};
95 // CHECK: CXXMethodDecl {{.*}} operator() 'void () const __attribute__((blocking))'
97 } // namespace square_brackets
99 // =========================================================================================
100 // GNU-style attribute, true
102 namespace gnu_style
{
104 // 1. On the type of the FunctionDecl
105 void nl_function() __attribute__((nonblocking
));
106 // CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'
108 // 1a. Alternate placement on the FunctionDecl
109 __attribute__((nonblocking
)) void nl_function();
110 // CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'
112 // 2. On the type of the VarDecl holding a function pointer
113 void (*nl_func_a
)() __attribute__((nonblocking
));
114 // CHECK: VarDecl {{.*}} nl_func_a 'void (*)() __attribute__((nonblocking))'
116 // 2a. Alternate attribute placement on VarDecl
117 __attribute__((nonblocking
)) void (*nl_func_b
)();
118 // CHECK: VarDecl {{.*}} nl_func_b 'void (*)() __attribute__((nonblocking))'
120 // 3. On the type of the ParmVarDecl of a function parameter
121 static void nlReceiver(void (*nl_func
)() __attribute__((nonblocking
)));
122 // CHECK: ParmVarDecl {{.*}} nl_func 'void (*)() __attribute__((nonblocking))'
124 // 4. As an AttributedType within the nested types of a typedef
125 // Note different placement from square brackets for the typealias.
126 typedef void (*nl_fp_type
)() __attribute__((nonblocking
));
127 // CHECK: TypedefDecl {{.*}} nl_fp_type 'void (*)() __attribute__((nonblocking))'
128 using nl_fp_talias
= __attribute__((nonblocking
)) void (*)();
129 // CHECK: TypeAliasDecl {{.*}} nl_fp_talias 'void (*)() __attribute__((nonblocking))'
131 // 5. From a typedef or typealias, on a VarDecl
132 nl_fp_type nl_fp_var1
;
133 // CHECK: VarDecl {{.*}} nl_fp_var1 'nl_fp_type':'void (*)() __attribute__((nonblocking))'
134 nl_fp_talias nl_fp_var2
;
135 // CHECK: VarDecl {{.*}} nl_fp_var2 'nl_fp_talias':'void (*)() __attribute__((nonblocking))'
137 // 6. On type of a FieldDecl
139 void (*nl_func_field
)() __attribute__((nonblocking
));
140 // CHECK: FieldDecl {{.*}} nl_func_field 'void (*)() __attribute__((nonblocking))'
143 } // namespace gnu_style
145 // =========================================================================================
146 // nonallocating and allocating - quick checks because the code paths are generally
147 // identical after parsing.
149 void na_function() [[clang::nonallocating
]];
150 // CHECK: FunctionDecl {{.*}} na_function 'void () __attribute__((nonallocating))'
152 void na_true_function() [[clang::nonallocating(true)]];
153 // CHECK: FunctionDecl {{.*}} na_true_function 'void () __attribute__((nonallocating))'
155 void na_false_function() [[clang::nonallocating(false)]];
156 // CHECK: FunctionDecl {{.*}} na_false_function 'void () __attribute__((allocating))'
158 void alloc_function() [[clang::allocating
]];
159 // CHECK: FunctionDecl {{.*}} alloc_function 'void () __attribute__((allocating))'
162 // =========================================================================================
163 // Non-blocking with an expression parameter
165 void t0() [[clang::nonblocking(1 - 1)]];
166 // CHECK: FunctionDecl {{.*}} t0 'void () __attribute__((blocking))'
167 void t1() [[clang::nonblocking(1 + 1)]];
168 // CHECK: FunctionDecl {{.*}} t1 'void () __attribute__((nonblocking))'
171 struct ValueDependent
{
172 void nb_method() [[clang::nonblocking(V
)]];
175 void t3() [[clang::nonblocking
]]
177 ValueDependent
<false> x1
;
179 // CHECK: ClassTemplateSpecializationDecl {{.*}} ValueDependent
180 // CHECK: TemplateArgument integral 'false'
181 // CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((blocking))'
183 ValueDependent
<true> x2
;
185 // CHECK: ClassTemplateSpecializationDecl {{.*}} ValueDependent
186 // CHECK: TemplateArgument integral 'true'
187 // CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((nonblocking))'
190 template <typename X
>
191 struct TypeDependent
{
192 void td_method() [[clang::nonblocking(X::is_nb
)]];
195 struct NBPolicyTrue
{
196 static constexpr bool is_nb
= true;
199 struct NBPolicyFalse
{
200 static constexpr bool is_nb
= false;
205 TypeDependent
<NBPolicyFalse
> x1
;
207 // CHECK: ClassTemplateSpecializationDecl {{.*}} TypeDependent
208 // CHECK: TemplateArgument type 'NBPolicyFalse'
209 // CHECK: CXXMethodDecl {{.*}} td_method 'void () __attribute__((blocking))'
211 TypeDependent
<NBPolicyTrue
> x2
;
213 // CHECK: ClassTemplateSpecializationDecl {{.*}} TypeDependent
214 // CHECK: TemplateArgument type 'NBPolicyTrue'
215 // CHECK: CXXMethodDecl {{.*}} td_method 'void () __attribute__((nonblocking))'