xref: /llvm-project/clang/test/Sema/attr-nonblocking-syntax.cpp (revision 7fe43ada28c31a9e9d82a76650d987a8b209755e)
1f03cb005SDoug Wyatt // RUN: %clang_cc1 %s -ast-dump -fblocks | FileCheck %s
2f03cb005SDoug Wyatt 
3f03cb005SDoug Wyatt // Make sure that the attribute gets parsed and attached to the correct AST elements.
4f03cb005SDoug Wyatt 
5f03cb005SDoug Wyatt #pragma clang diagnostic ignored "-Wunused-variable"
6*7fe43adaSDoug Wyatt #pragma clang diagnostic ignored "-Wperf-constraint-implies-noexcept"
7f03cb005SDoug Wyatt 
8f03cb005SDoug Wyatt // =========================================================================================
9f03cb005SDoug Wyatt // Square brackets, true
10f03cb005SDoug Wyatt 
11f03cb005SDoug Wyatt namespace square_brackets {
12f03cb005SDoug Wyatt 
13f03cb005SDoug Wyatt // 1. On the type of the FunctionDecl
14f03cb005SDoug Wyatt void nl_function() [[clang::nonblocking]];
15f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'
16f03cb005SDoug Wyatt 
17f03cb005SDoug Wyatt // 2. On the type of the VarDecl holding a function pointer
18f03cb005SDoug Wyatt void (*nl_func_a)() [[clang::nonblocking]];
19f03cb005SDoug Wyatt // CHECK: VarDecl {{.*}} nl_func_a 'void (*)() __attribute__((nonblocking))'
20f03cb005SDoug Wyatt 
21f03cb005SDoug Wyatt // 3. On the type of the ParmVarDecl of a function parameter
22f03cb005SDoug Wyatt static void nlReceiver(void (*nl_func)() [[clang::nonblocking]]);
23f03cb005SDoug Wyatt // CHECK: ParmVarDecl {{.*}} nl_func 'void (*)() __attribute__((nonblocking))'
24f03cb005SDoug Wyatt 
25f03cb005SDoug Wyatt // 4. As an AttributedType within the nested types of a typedef
26f03cb005SDoug Wyatt typedef void (*nl_fp_type)() [[clang::nonblocking]];
27f03cb005SDoug Wyatt // CHECK: TypedefDecl {{.*}} nl_fp_type 'void (*)() __attribute__((nonblocking))'
28f03cb005SDoug Wyatt using nl_fp_talias = void (*)() [[clang::nonblocking]];
29f03cb005SDoug Wyatt // CHECK: TypeAliasDecl {{.*}} nl_fp_talias 'void (*)() __attribute__((nonblocking))'
30f03cb005SDoug Wyatt 
31f03cb005SDoug Wyatt // 5. From a typedef or typealias, on a VarDecl
32f03cb005SDoug Wyatt nl_fp_type nl_fp_var1;
33f03cb005SDoug Wyatt // CHECK: VarDecl {{.*}} nl_fp_var1 'nl_fp_type':'void (*)() __attribute__((nonblocking))'
34f03cb005SDoug Wyatt nl_fp_talias nl_fp_var2;
35f03cb005SDoug Wyatt // CHECK: VarDecl {{.*}} nl_fp_var2 'nl_fp_talias':'void (*)() __attribute__((nonblocking))'
36f03cb005SDoug Wyatt 
37f03cb005SDoug Wyatt // 6. On type of a FieldDecl
38f03cb005SDoug Wyatt struct Struct {
39f03cb005SDoug Wyatt   void (*nl_func_field)() [[clang::nonblocking]];
40f03cb005SDoug Wyatt // CHECK: FieldDecl {{.*}} nl_func_field 'void (*)() __attribute__((nonblocking))'
41f03cb005SDoug Wyatt };
42f03cb005SDoug Wyatt 
43f03cb005SDoug Wyatt // nonallocating should NOT be subsumed into nonblocking
44f03cb005SDoug Wyatt void nl1() [[clang::nonblocking]] [[clang::nonallocating]];
45f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} nl1 'void () __attribute__((nonblocking)) __attribute__((nonallocating))'
46f03cb005SDoug Wyatt 
47f03cb005SDoug Wyatt void nl2() [[clang::nonallocating]] [[clang::nonblocking]];
48f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} nl2 'void () __attribute__((nonblocking)) __attribute__((nonallocating))'
49f03cb005SDoug Wyatt 
50f03cb005SDoug Wyatt decltype(nl1) nl3;
51f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} nl3 'decltype(nl1)':'void () __attribute__((nonblocking)) __attribute__((nonallocating))'
52f03cb005SDoug Wyatt 
53f03cb005SDoug Wyatt // Attribute propagates from base class virtual method to overrides.
54f03cb005SDoug Wyatt struct Base {
55f03cb005SDoug Wyatt   virtual void nb_method() [[clang::nonblocking]];
56f03cb005SDoug Wyatt };
57f03cb005SDoug Wyatt struct Derived : public Base {
58f03cb005SDoug Wyatt   void nb_method() override;
59f03cb005SDoug Wyatt   // CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((nonblocking))'
60f03cb005SDoug Wyatt };
61f03cb005SDoug Wyatt 
62f03cb005SDoug Wyatt // Dependent expression
63f03cb005SDoug Wyatt template <bool V>
64f03cb005SDoug Wyatt struct Dependent {
65f03cb005SDoug Wyatt   void nb_method2() [[clang::nonblocking(V)]];
66f03cb005SDoug Wyatt   // CHECK: CXXMethodDecl {{.*}} nb_method2 'void () __attribute__((nonblocking(V)))'
67f03cb005SDoug Wyatt };
68f03cb005SDoug Wyatt 
69f03cb005SDoug Wyatt // --- Blocks ---
70f03cb005SDoug Wyatt 
71f03cb005SDoug Wyatt // On the type of the VarDecl holding a BlockDecl
72f03cb005SDoug Wyatt void (^nl_block1)() [[clang::nonblocking]] = ^() [[clang::nonblocking]] {};
73f03cb005SDoug Wyatt // CHECK: VarDecl {{.*}} nl_block1 'void (^)() __attribute__((nonblocking))'
74f03cb005SDoug Wyatt 
75f03cb005SDoug Wyatt int (^nl_block2)() [[clang::nonblocking]] = ^() [[clang::nonblocking]] { return 0; };
76f03cb005SDoug Wyatt // CHECK: VarDecl {{.*}} nl_block2 'int (^)() __attribute__((nonblocking))'
77f03cb005SDoug Wyatt 
78f03cb005SDoug Wyatt // The operand of the CallExpr is an ImplicitCastExpr of a DeclRefExpr -> nl_block which hold the attribute
79f03cb005SDoug Wyatt static void blockCaller() { nl_block1(); }
80f03cb005SDoug Wyatt // CHECK: DeclRefExpr {{.*}} 'nl_block1' 'void (^)() __attribute__((nonblocking))'
81f03cb005SDoug Wyatt 
82f03cb005SDoug Wyatt // --- Lambdas ---
83f03cb005SDoug Wyatt 
84f03cb005SDoug Wyatt // On the operator() of a lambda's CXXMethodDecl
85f03cb005SDoug Wyatt auto nl_lambda = []() [[clang::nonblocking]] {};
86f03cb005SDoug Wyatt // CHECK: CXXMethodDecl {{.*}} operator() 'void () const __attribute__((nonblocking))' inline
87f03cb005SDoug Wyatt 
88f03cb005SDoug Wyatt // =========================================================================================
89f03cb005SDoug Wyatt // Square brackets, false
90f03cb005SDoug Wyatt 
91f03cb005SDoug Wyatt void nl_func_false() [[clang::blocking]];
92f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} nl_func_false 'void () __attribute__((blocking))'
93f03cb005SDoug Wyatt 
94f03cb005SDoug Wyatt auto nl_lambda_false = []() [[clang::blocking]] {};
95f03cb005SDoug Wyatt // CHECK: CXXMethodDecl {{.*}} operator() 'void () const __attribute__((blocking))'
96f03cb005SDoug Wyatt 
97f03cb005SDoug Wyatt } // namespace square_brackets
98f03cb005SDoug Wyatt 
99f03cb005SDoug Wyatt // =========================================================================================
100f03cb005SDoug Wyatt // GNU-style attribute, true
101f03cb005SDoug Wyatt 
102f03cb005SDoug Wyatt namespace gnu_style {
103f03cb005SDoug Wyatt 
104f03cb005SDoug Wyatt // 1. On the type of the FunctionDecl
105f03cb005SDoug Wyatt void nl_function() __attribute__((nonblocking));
106f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'
107f03cb005SDoug Wyatt 
108f03cb005SDoug Wyatt // 1a. Alternate placement on the FunctionDecl
109f03cb005SDoug Wyatt __attribute__((nonblocking)) void nl_function();
110f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} nl_function 'void () __attribute__((nonblocking))'
111f03cb005SDoug Wyatt 
112f03cb005SDoug Wyatt // 2. On the type of the VarDecl holding a function pointer
113f03cb005SDoug Wyatt void (*nl_func_a)() __attribute__((nonblocking));
114f03cb005SDoug Wyatt // CHECK: VarDecl {{.*}} nl_func_a 'void (*)() __attribute__((nonblocking))'
115f03cb005SDoug Wyatt 
116f03cb005SDoug Wyatt // 2a. Alternate attribute placement on VarDecl
117f03cb005SDoug Wyatt __attribute__((nonblocking)) void (*nl_func_b)();
118f03cb005SDoug Wyatt // CHECK: VarDecl {{.*}} nl_func_b 'void (*)() __attribute__((nonblocking))'
119f03cb005SDoug Wyatt 
120f03cb005SDoug Wyatt // 3. On the type of the ParmVarDecl of a function parameter
121f03cb005SDoug Wyatt static void nlReceiver(void (*nl_func)() __attribute__((nonblocking)));
122f03cb005SDoug Wyatt // CHECK: ParmVarDecl {{.*}} nl_func 'void (*)() __attribute__((nonblocking))'
123f03cb005SDoug Wyatt 
124f03cb005SDoug Wyatt // 4. As an AttributedType within the nested types of a typedef
125f03cb005SDoug Wyatt // Note different placement from square brackets for the typealias.
126f03cb005SDoug Wyatt typedef void (*nl_fp_type)() __attribute__((nonblocking));
127f03cb005SDoug Wyatt // CHECK: TypedefDecl {{.*}} nl_fp_type 'void (*)() __attribute__((nonblocking))'
128f03cb005SDoug Wyatt using nl_fp_talias = __attribute__((nonblocking)) void (*)();
129f03cb005SDoug Wyatt // CHECK: TypeAliasDecl {{.*}} nl_fp_talias 'void (*)() __attribute__((nonblocking))'
130f03cb005SDoug Wyatt 
131f03cb005SDoug Wyatt // 5. From a typedef or typealias, on a VarDecl
132f03cb005SDoug Wyatt nl_fp_type nl_fp_var1;
133f03cb005SDoug Wyatt // CHECK: VarDecl {{.*}} nl_fp_var1 'nl_fp_type':'void (*)() __attribute__((nonblocking))'
134f03cb005SDoug Wyatt nl_fp_talias nl_fp_var2;
135f03cb005SDoug Wyatt // CHECK: VarDecl {{.*}} nl_fp_var2 'nl_fp_talias':'void (*)() __attribute__((nonblocking))'
136f03cb005SDoug Wyatt 
137f03cb005SDoug Wyatt // 6. On type of a FieldDecl
138f03cb005SDoug Wyatt struct Struct {
139f03cb005SDoug Wyatt   void (*nl_func_field)() __attribute__((nonblocking));
140f03cb005SDoug Wyatt // CHECK: FieldDecl {{.*}} nl_func_field 'void (*)() __attribute__((nonblocking))'
141f03cb005SDoug Wyatt };
142f03cb005SDoug Wyatt 
143f03cb005SDoug Wyatt } // namespace gnu_style
144f03cb005SDoug Wyatt 
145f03cb005SDoug Wyatt // =========================================================================================
146f03cb005SDoug Wyatt // nonallocating and allocating - quick checks because the code paths are generally
147f03cb005SDoug Wyatt // identical after parsing.
148f03cb005SDoug Wyatt 
149f03cb005SDoug Wyatt void na_function() [[clang::nonallocating]];
150f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} na_function 'void () __attribute__((nonallocating))'
151f03cb005SDoug Wyatt 
152f03cb005SDoug Wyatt void na_true_function() [[clang::nonallocating(true)]];
153f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} na_true_function 'void () __attribute__((nonallocating))'
154f03cb005SDoug Wyatt 
155f03cb005SDoug Wyatt void na_false_function() [[clang::nonallocating(false)]];
156f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} na_false_function 'void () __attribute__((allocating))'
157f03cb005SDoug Wyatt 
158f03cb005SDoug Wyatt void alloc_function() [[clang::allocating]];
159f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} alloc_function 'void () __attribute__((allocating))'
160f03cb005SDoug Wyatt 
161f03cb005SDoug Wyatt 
162f03cb005SDoug Wyatt // =========================================================================================
163f03cb005SDoug Wyatt // Non-blocking with an expression parameter
164f03cb005SDoug Wyatt 
165f03cb005SDoug Wyatt void t0() [[clang::nonblocking(1 - 1)]];
166f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} t0 'void () __attribute__((blocking))'
167f03cb005SDoug Wyatt void t1() [[clang::nonblocking(1 + 1)]];
168f03cb005SDoug Wyatt // CHECK: FunctionDecl {{.*}} t1 'void () __attribute__((nonblocking))'
169f03cb005SDoug Wyatt 
170f03cb005SDoug Wyatt template <bool V>
171f03cb005SDoug Wyatt struct ValueDependent {
172f03cb005SDoug Wyatt   void nb_method() [[clang::nonblocking(V)]];
173f03cb005SDoug Wyatt };
174f03cb005SDoug Wyatt 
175f03cb005SDoug Wyatt void t3() [[clang::nonblocking]]
176f03cb005SDoug Wyatt {
177f03cb005SDoug Wyatt   ValueDependent<false> x1;
178f03cb005SDoug Wyatt   x1.nb_method();
179f03cb005SDoug Wyatt // CHECK: ClassTemplateSpecializationDecl {{.*}} ValueDependent
180f03cb005SDoug Wyatt // CHECK: TemplateArgument integral 'false'
181f03cb005SDoug Wyatt // CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((blocking))'
182f03cb005SDoug Wyatt 
183f03cb005SDoug Wyatt    ValueDependent<true> x2;
184f03cb005SDoug Wyatt    x2.nb_method();
185f03cb005SDoug Wyatt // CHECK: ClassTemplateSpecializationDecl {{.*}} ValueDependent
186f03cb005SDoug Wyatt // CHECK: TemplateArgument integral 'true'
187f03cb005SDoug Wyatt // CHECK: CXXMethodDecl {{.*}} nb_method 'void () __attribute__((nonblocking))'
188f03cb005SDoug Wyatt }
189f03cb005SDoug Wyatt 
190f03cb005SDoug Wyatt template <typename X>
191f03cb005SDoug Wyatt struct TypeDependent {
192f03cb005SDoug Wyatt   void td_method() [[clang::nonblocking(X::is_nb)]];
193f03cb005SDoug Wyatt };
194f03cb005SDoug Wyatt 
195f03cb005SDoug Wyatt struct NBPolicyTrue {
196f03cb005SDoug Wyatt   static constexpr bool is_nb = true;
197f03cb005SDoug Wyatt };
198f03cb005SDoug Wyatt 
199f03cb005SDoug Wyatt struct NBPolicyFalse {
200f03cb005SDoug Wyatt   static constexpr bool is_nb = false;
201f03cb005SDoug Wyatt };
202f03cb005SDoug Wyatt 
203f03cb005SDoug Wyatt void t4()
204f03cb005SDoug Wyatt {
205f03cb005SDoug Wyatt   TypeDependent<NBPolicyFalse> x1;
206f03cb005SDoug Wyatt   x1.td_method();
207f03cb005SDoug Wyatt // CHECK: ClassTemplateSpecializationDecl {{.*}} TypeDependent
208f03cb005SDoug Wyatt // CHECK: TemplateArgument type 'NBPolicyFalse'
209f03cb005SDoug Wyatt // CHECK: CXXMethodDecl {{.*}} td_method 'void () __attribute__((blocking))'
210f03cb005SDoug Wyatt 
211f03cb005SDoug Wyatt   TypeDependent<NBPolicyTrue> x2;
212f03cb005SDoug Wyatt   x2.td_method();
213f03cb005SDoug Wyatt // CHECK: ClassTemplateSpecializationDecl {{.*}} TypeDependent
214f03cb005SDoug Wyatt // CHECK: TemplateArgument type 'NBPolicyTrue'
215f03cb005SDoug Wyatt // CHECK: CXXMethodDecl {{.*}} td_method 'void () __attribute__((nonblocking))'
216f03cb005SDoug Wyatt }
217f03cb005SDoug Wyatt 
218