[clang] Implement lifetime analysis for lifetime_capture_by(X) (#115921)
[llvm-project.git] / clang / test / Sema / attr-nonblocking-syntax.cpp
blob90d074d01708f40ce3d41ba47ed195bb2de451f8
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
38 struct Struct {
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))'
50 decltype(nl1) nl3;
51 // CHECK: FunctionDecl {{.*}} nl3 'decltype(nl1)':'void () __attribute__((nonblocking)) __attribute__((nonallocating))'
53 // Attribute propagates from base class virtual method to overrides.
54 struct Base {
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
63 template <bool V>
64 struct Dependent {
65 void nb_method2() [[clang::nonblocking(V)]];
66 // CHECK: CXXMethodDecl {{.*}} nb_method2 'void () __attribute__((nonblocking(V)))'
69 // --- Blocks ---
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))'
82 // --- Lambdas ---
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
138 struct Struct {
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))'
170 template <bool V>
171 struct ValueDependent {
172 void nb_method() [[clang::nonblocking(V)]];
175 void t3() [[clang::nonblocking]]
177 ValueDependent<false> x1;
178 x1.nb_method();
179 // CHECK: ClassTemplateSpecializationDecl {{.*}} ValueDependent
180 // CHECK: TemplateArgument integral 'false'
181 // CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((blocking))'
183 ValueDependent<true> x2;
184 x2.nb_method();
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;
203 void t4()
205 TypeDependent<NBPolicyFalse> x1;
206 x1.td_method();
207 // CHECK: ClassTemplateSpecializationDecl {{.*}} TypeDependent
208 // CHECK: TemplateArgument type 'NBPolicyFalse'
209 // CHECK: CXXMethodDecl {{.*}} td_method 'void () __attribute__((blocking))'
211 TypeDependent<NBPolicyTrue> x2;
212 x2.td_method();
213 // CHECK: ClassTemplateSpecializationDecl {{.*}} TypeDependent
214 // CHECK: TemplateArgument type 'NBPolicyTrue'
215 // CHECK: CXXMethodDecl {{.*}} td_method 'void () __attribute__((nonblocking))'