xref: /llvm-project/clang/test/ASTSYCL/ast-dump-sycl-kernel-call-stmt.cpp (revision 8fb42300a02c887740825cd1b60fc4fcd8d2f933)
1 // Tests without serialization:
2 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-device \
3 // RUN:   -ast-dump %s \
4 // RUN:   | FileCheck --match-full-lines %s
5 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-host \
6 // RUN:   -ast-dump %s \
7 // RUN:   | FileCheck --match-full-lines %s
8 //
9 // Tests with serialization:
10 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-device \
11 // RUN:   -emit-pch -o %t %s
12 // RUN: %clang_cc1 -x c++ -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-device \
13 // RUN:   -include-pch %t -ast-dump-all /dev/null \
14 // RUN:   | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
15 // RUN:   | FileCheck --match-full-lines %s
16 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-host \
17 // RUN:   -emit-pch -o %t %s
18 // RUN: %clang_cc1 -x c++ -std=c++17 -triple x86_64-unknown-unknown -fsycl-is-host \
19 // RUN:   -include-pch %t -ast-dump-all /dev/null \
20 // RUN:   | sed -e "s/ <undeserialized declarations>//" -e "s/ imported//" \
21 // RUN:   | FileCheck --match-full-lines %s
22 
23 // These tests validate the AST body produced for functions declared with the
24 // sycl_kernel_entry_point attribute.
25 
26 // CHECK: TranslationUnitDecl {{.*}}
27 
28 // A unique kernel name type is required for each declared kernel entry point.
29 template<int> struct KN;
30 
31 // A unique invocable type for use with each declared kernel entry point.
32 template<int> struct K {
33   template<typename... Ts>
34   void operator()(Ts...) const {}
35 };
36 
37 
38 [[clang::sycl_kernel_entry_point(KN<1>)]]
39 void skep1() {
40 }
41 // CHECK:      |-FunctionDecl {{.*}} skep1 'void ()'
42 // CHECK-NEXT: | |-SYCLKernelCallStmt {{.*}}
43 // CHECK-NEXT: | | |-CompoundStmt {{.*}}
44 // CHECK-NEXT: | | `-OutlinedFunctionDecl {{.*}}
45 // CHECK-NEXT: | |   `-CompoundStmt {{.*}}
46 // CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<1>
47 
48 template<typename KNT, typename KT>
49 [[clang::sycl_kernel_entry_point(KNT)]]
50 void skep2(KT k) {
51   k();
52 }
53 template
54 void skep2<KN<2>>(K<2>);
55 // CHECK:      |-FunctionTemplateDecl {{.*}} skep2
56 // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} KNT
57 // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} KT
58 // CHECK-NEXT: | |-FunctionDecl {{.*}} skep2 'void (KT)'
59 // CHECK-NEXT: | | |-ParmVarDecl {{.*}} k 'KT'
60 // CHECK-NEXT: | | |-CompoundStmt {{.*}}
61 // CHECK-NEXT: | | | `-CallExpr {{.*}} '<dependent type>'
62 // CHECK-NEXT: | | |   `-DeclRefExpr {{.*}} 'KT' lvalue ParmVar {{.*}} 'k' 'KT'
63 // CHECK-NEXT: | | `-SYCLKernelEntryPointAttr {{.*}} KNT
64 
65 // CHECK-NEXT: | `-FunctionDecl {{.*}} skep2 'void (K<2>)' explicit_instantiation_definition
66 // CHECK-NEXT: |   |-TemplateArgument type 'KN<2>'
67 // CHECK-NEXT: |   | `-RecordType {{.*}} 'KN<2>'
68 // CHECK-NEXT: |   |   `-ClassTemplateSpecialization {{.*}} 'KN'
69 // CHECK-NEXT: |   |-TemplateArgument type 'K<2>'
70 // CHECK-NEXT: |   | `-RecordType {{.*}} 'K<2>'
71 // CHECK-NEXT: |   |   `-ClassTemplateSpecialization {{.*}} 'K'
72 // CHECK-NEXT: |   |-ParmVarDecl {{.*}} k 'K<2>'
73 // CHECK-NEXT: |   |-SYCLKernelCallStmt {{.*}}
74 // CHECK-NEXT: |   | |-CompoundStmt {{.*}}
75 // CHECK-NEXT: |   | | `-CXXOperatorCallExpr {{.*}} 'void' '()'
76 // CHECK-NEXT: |   | |   |-ImplicitCastExpr {{.*}} 'void (*)() const' <FunctionToPointerDecay>
77 // CHECK-NEXT: |   | |   | `-DeclRefExpr {{.*}} 'void () const' lvalue CXXMethod {{.*}} 'operator()' 'void () const'
78 // CHECK-NEXT: |   | |   `-ImplicitCastExpr {{.*}} 'const K<2>' lvalue <NoOp>
79 // CHECK-NEXT: |   | |     `-DeclRefExpr {{.*}} 'K<2>' lvalue ParmVar {{.*}} 'k' 'K<2>'
80 // CHECK-NEXT: |   | `-OutlinedFunctionDecl {{.*}}
81 // CHECK-NEXT: |   |   |-ImplicitParamDecl {{.*}} implicit used k 'K<2>'
82 // CHECK-NEXT: |   |   `-CompoundStmt {{.*}}
83 // CHECK-NEXT: |   |     `-CXXOperatorCallExpr {{.*}} 'void' '()'
84 // CHECK-NEXT: |   |       |-ImplicitCastExpr {{.*}} 'void (*)() const' <FunctionToPointerDecay>
85 // CHECK-NEXT: |   |       | `-DeclRefExpr {{.*}} 'void () const' lvalue CXXMethod {{.*}} 'operator()' 'void () const'
86 // CHECK-NEXT: |   |       `-ImplicitCastExpr {{.*}} 'const K<2>' lvalue <NoOp>
87 // CHECK-NEXT: |   |         `-DeclRefExpr {{.*}} 'K<2>' lvalue ImplicitParam {{.*}} 'k' 'K<2>'
88 // CHECK-NEXT: |   `-SYCLKernelEntryPointAttr {{.*}} KN<2>
89 
90 template<typename KNT, typename KT>
91 [[clang::sycl_kernel_entry_point(KNT)]]
92 void skep3(KT k) {
93   k();
94 }
95 template<>
96 [[clang::sycl_kernel_entry_point(KN<3>)]]
97 void skep3<KN<3>>(K<3> k) {
98   k();
99 }
100 // CHECK:      |-FunctionTemplateDecl {{.*}} skep3
101 // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} KNT
102 // CHECK-NEXT: | |-TemplateTypeParmDecl {{.*}} KT
103 // CHECK-NEXT: | |-FunctionDecl {{.*}} skep3 'void (KT)'
104 // CHECK-NEXT: | | |-ParmVarDecl {{.*}} k 'KT'
105 // CHECK-NEXT: | | |-CompoundStmt {{.*}}
106 // CHECK-NEXT: | | | `-CallExpr {{.*}} '<dependent type>'
107 // CHECK-NEXT: | | |   `-DeclRefExpr {{.*}} 'KT' lvalue ParmVar {{.*}} 'k' 'KT'
108 // CHECK-NEXT: | | `-SYCLKernelEntryPointAttr {{.*}} KNT
109 
110 // CHECK-NEXT: | `-Function {{.*}} 'skep3' 'void (K<3>)'
111 // CHECK-NEXT: |-FunctionDecl {{.*}} skep3 'void (K<3>)' explicit_specialization
112 // CHECK-NEXT: | |-TemplateArgument type 'KN<3>'
113 // CHECK-NEXT: | | `-RecordType {{.*}} 'KN<3>'
114 // CHECK-NEXT: | |   `-ClassTemplateSpecialization {{.*}} 'KN'
115 // CHECK-NEXT: | |-TemplateArgument type 'K<3>'
116 // CHECK-NEXT: | | `-RecordType {{.*}} 'K<3>'
117 // CHECK-NEXT: | |   `-ClassTemplateSpecialization {{.*}} 'K'
118 // CHECK-NEXT: | |-ParmVarDecl {{.*}} k 'K<3>'
119 // CHECK-NEXT: | |-SYCLKernelCallStmt {{.*}}
120 // CHECK-NEXT: | | |-CompoundStmt {{.*}}
121 // CHECK-NEXT: | | | `-CXXOperatorCallExpr {{.*}} 'void' '()'
122 // CHECK-NEXT: | | |   |-ImplicitCastExpr {{.*}} 'void (*)() const' <FunctionToPointerDecay>
123 // CHECK-NEXT: | | |   | `-DeclRefExpr {{.*}} 'void () const' lvalue CXXMethod {{.*}} 'operator()' 'void () const'
124 // CHECK-NEXT: | | |   `-ImplicitCastExpr {{.*}} 'const K<3>' lvalue <NoOp>
125 // CHECK-NEXT: | | |     `-DeclRefExpr {{.*}} 'K<3>' lvalue ParmVar {{.*}} 'k' 'K<3>'
126 // CHECK-NEXT: | | `-OutlinedFunctionDecl {{.*}}
127 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit used k 'K<3>'
128 // CHECK-NEXT: | |   `-CompoundStmt {{.*}}
129 // CHECK-NEXT: | |     `-CXXOperatorCallExpr {{.*}} 'void' '()'
130 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'void (*)() const' <FunctionToPointerDecay>
131 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'void () const' lvalue CXXMethod {{.*}} 'operator()' 'void () const'
132 // CHECK-NEXT: | |       `-ImplicitCastExpr {{.*}} 'const K<3>' lvalue <NoOp>
133 // CHECK-NEXT: | |         `-DeclRefExpr {{.*}} 'K<3>' lvalue ImplicitParam {{.*}} 'k' 'K<3>'
134 // CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<3>
135 
136 [[clang::sycl_kernel_entry_point(KN<4>)]]
137 void skep4(K<4> k, int p1, int p2) {
138   k(p1, p2);
139 }
140 // CHECK:      |-FunctionDecl {{.*}} skep4 'void (K<4>, int, int)'
141 // CHECK-NEXT: | |-ParmVarDecl {{.*}} k 'K<4>'
142 // CHECK-NEXT: | |-ParmVarDecl {{.*}} p1 'int'
143 // CHECK-NEXT: | |-ParmVarDecl {{.*}} p2 'int'
144 // CHECK-NEXT: | |-SYCLKernelCallStmt {{.*}}
145 // CHECK-NEXT: | | |-CompoundStmt {{.*}}
146 // CHECK-NEXT: | | | `-CXXOperatorCallExpr {{.*}} 'void' '()'
147 // CHECK-NEXT: | | |   |-ImplicitCastExpr {{.*}} 'void (*)(int, int) const' <FunctionToPointerDecay>
148 // CHECK-NEXT: | | |   | `-DeclRefExpr {{.*}} 'void (int, int) const' lvalue CXXMethod {{.*}} 'operator()' 'void (int, int) const'
149 // CHECK-NEXT: | | |   |-ImplicitCastExpr {{.*}} 'const K<4>' lvalue <NoOp>
150 // CHECK-NEXT: | | |   | `-DeclRefExpr {{.*}} 'K<4>' lvalue ParmVar {{.*}} 'k' 'K<4>'
151 // CHECK-NEXT: | | |   |-ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
152 // CHECK-NEXT: | | |   | `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'p1' 'int'
153 // CHECK-NEXT: | | |   `-ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
154 // CHECK-NEXT: | | |     `-DeclRefExpr {{.*}} 'int' lvalue ParmVar {{.*}} 'p2' 'int'
155 // CHECK-NEXT: | | `-OutlinedFunctionDecl {{.*}}
156 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit used k 'K<4>'
157 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit used p1 'int'
158 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit used p2 'int'
159 // CHECK-NEXT: | |   `-CompoundStmt {{.*}}
160 // CHECK-NEXT: | |     `-CXXOperatorCallExpr {{.*}} 'void' '()'
161 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'void (*)(int, int) const' <FunctionToPointerDecay>
162 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'void (int, int) const' lvalue CXXMethod {{.*}} 'operator()' 'void (int, int) const'
163 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'const K<4>' lvalue <NoOp>
164 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'K<4>' lvalue ImplicitParam {{.*}} 'k' 'K<4>'
165 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
166 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'int' lvalue ImplicitParam {{.*}} 'p1' 'int'
167 // CHECK-NEXT: | |       `-ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
168 // CHECK-NEXT: | |         `-DeclRefExpr {{.*}} 'int' lvalue ImplicitParam {{.*}} 'p2' 'int'
169 // CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<4>
170 
171 [[clang::sycl_kernel_entry_point(KN<5>)]]
172 void skep5(int unused1, K<5> k, int unused2, int p, int unused3) {
173   static int slv = 0;
174   int lv = 4;
175   k(slv, 1, p, 3, lv, 5, []{ return 6; });
176 }
177 // CHECK:      |-FunctionDecl {{.*}} skep5 'void (int, K<5>, int, int, int)'
178 // CHECK-NEXT: | |-ParmVarDecl {{.*}} unused1 'int'
179 // CHECK-NEXT: | |-ParmVarDecl {{.*}} used k 'K<5>'
180 // CHECK-NEXT: | |-ParmVarDecl {{.*}} unused2 'int'
181 // CHECK-NEXT: | |-ParmVarDecl {{.*}} used p 'int'
182 // CHECK-NEXT: | |-ParmVarDecl {{.*}} unused3 'int'
183 // CHECK-NEXT: | |-SYCLKernelCallStmt {{.*}}
184 // CHECK-NEXT: | | |-CompoundStmt {{.*}}
185 // CHECK:      | | `-OutlinedFunctionDecl {{.*}}
186 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit unused1 'int'
187 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit used k 'K<5>'
188 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit unused2 'int'
189 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit used p 'int'
190 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit unused3 'int'
191 // CHECK-NEXT: | |   `-CompoundStmt {{.*}}
192 // CHECK-NEXT: | |     |-DeclStmt {{.*}}
193 // CHECK-NEXT: | |     | `-VarDecl {{.*}} used slv 'int' static cinit
194 // CHECK-NEXT: | |     |   `-IntegerLiteral {{.*}} 'int' 0
195 // CHECK-NEXT: | |     |-DeclStmt {{.*}}
196 // CHECK-NEXT: | |     | `-VarDecl {{.*}} used lv 'int' cinit
197 // CHECK-NEXT: | |     |   `-IntegerLiteral {{.*}} 'int' 4
198 // CHECK-NEXT: | |     `-CXXOperatorCallExpr {{.*}} 'void' '()'
199 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'void (*)(int, int, int, int, int, int, (lambda {{.*}}) const' <FunctionToPointerDecay>
200 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'void (int, int, int, int, int, int, (lambda {{.*}})) const' lvalue CXXMethod {{.*}} 'operator()' 'void (int, int, int, int, int, int, (lambda {{.*}})) const'
201 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'const K<5>' lvalue <NoOp>
202 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'K<5>' lvalue ImplicitParam {{.*}} 'k' 'K<5>'
203 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
204 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'slv' 'int'
205 // CHECK-NEXT: | |       |-IntegerLiteral {{.*}} 'int' 1
206 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
207 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'int' lvalue ImplicitParam {{.*}} 'p' 'int'
208 // CHECK-NEXT: | |       |-IntegerLiteral {{.*}} 'int' 3
209 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'int' <LValueToRValue>
210 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'int' lvalue Var {{.*}} 'lv' 'int'
211 // CHECK-NEXT: | |       |-IntegerLiteral {{.*}} 'int' 5
212 // CHECK-NEXT: | |       `-LambdaExpr {{.*}} '(lambda {{.*}})'
213 // CHECK:      | `-SYCLKernelEntryPointAttr {{.*}} KN<5>
214 
215 struct S6 {
216   void operator()() const;
217 };
218 [[clang::sycl_kernel_entry_point(KN<6>)]]
219 void skep6(const S6 &k) {
220   k();
221 }
222 // CHECK:      |-FunctionDecl {{.*}} skep6 'void (const S6 &)'
223 // CHECK-NEXT: | |-ParmVarDecl {{.*}} used k 'const S6 &'
224 // CHECK-NEXT: | |-SYCLKernelCallStmt {{.*}}
225 // CHECK-NEXT: | | |-CompoundStmt {{.*}}
226 // CHECK-NEXT: | | | `-CXXOperatorCallExpr {{.*}} 'void' '()'
227 // CHECK-NEXT: | | |   |-ImplicitCastExpr {{.*}} 'void (*)() const' <FunctionToPointerDecay>
228 // CHECK-NEXT: | | |   | `-DeclRefExpr {{.*}} 'void () const' lvalue CXXMethod {{.*}} 'operator()' 'void () const'
229 // CHECK-NEXT: | | |   `-DeclRefExpr {{.*}} 'const S6' lvalue ParmVar {{.*}} 'k' 'const S6 &'
230 // CHECK-NEXT: | | `-OutlinedFunctionDecl {{.*}}
231 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit used k 'const S6 &'
232 // CHECK-NEXT: | |   `-CompoundStmt {{.*}}
233 // CHECK-NEXT: | |     `-CXXOperatorCallExpr {{.*}} 'void' '()'
234 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'void (*)() const' <FunctionToPointerDecay>
235 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'void () const' lvalue CXXMethod {{.*}} 'operator()' 'void () const'
236 // CHECK-NEXT: | |       `-DeclRefExpr {{.*}} 'const S6' lvalue ImplicitParam {{.*}} 'k' 'const S6 &'
237 // CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<6>
238 
239 // Parameter types are not required to be complete at the point of a
240 // non-defining declaration.
241 struct S7;
242 [[clang::sycl_kernel_entry_point(KN<7>)]]
243 void skep7(S7 k);
244 struct S7 {
245   void operator()() const;
246 };
247 [[clang::sycl_kernel_entry_point(KN<7>)]]
248 void skep7(S7 k) {
249   k();
250 }
251 // CHECK:      |-FunctionDecl {{.*}} skep7 'void (S7)'
252 // CHECK-NEXT: | |-ParmVarDecl {{.*}} k 'S7'
253 // CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<7>
254 // CHECK:      |-FunctionDecl {{.*}} prev {{.*}} skep7 'void (S7)'
255 // CHECK-NEXT: | |-ParmVarDecl {{.*}} used k 'S7'
256 // CHECK-NEXT: | |-SYCLKernelCallStmt {{.*}}
257 // CHECK-NEXT: | | |-CompoundStmt {{.*}}
258 // CHECK-NEXT: | | | `-CXXOperatorCallExpr {{.*}} 'void' '()'
259 // CHECK-NEXT: | | |   |-ImplicitCastExpr {{.*}} 'void (*)() const' <FunctionToPointerDecay>
260 // CHECK-NEXT: | | |   | `-DeclRefExpr {{.*}} 'void () const' lvalue CXXMethod {{.*}} 'operator()' 'void () const'
261 // CHECK-NEXT: | | |   `-ImplicitCastExpr {{.*}} 'const S7' lvalue <NoOp>
262 // CHECK-NEXT: | | |     `-DeclRefExpr {{.*}} 'S7' lvalue ParmVar {{.*}} 'k' 'S7'
263 // CHECK-NEXT: | | `-OutlinedFunctionDecl {{.*}}
264 // CHECK-NEXT: | |   |-ImplicitParamDecl {{.*}} implicit used k 'S7'
265 // CHECK-NEXT: | |   `-CompoundStmt {{.*}}
266 // CHECK-NEXT: | |     `-CXXOperatorCallExpr {{.*}} 'void' '()'
267 // CHECK-NEXT: | |       |-ImplicitCastExpr {{.*}} 'void (*)() const' <FunctionToPointerDecay>
268 // CHECK-NEXT: | |       | `-DeclRefExpr {{.*}} 'void () const' lvalue CXXMethod {{.*}} 'operator()' 'void () const'
269 // CHECK-NEXT: | |       `-ImplicitCastExpr {{.*}} 'const S7' lvalue <NoOp>
270 // CHECK-NEXT: | |         `-DeclRefExpr {{.*}} 'S7' lvalue ImplicitParam {{.*}} 'k' 'S7'
271 // CHECK-NEXT: | `-SYCLKernelEntryPointAttr {{.*}} KN<7>
272 
273 
274 void the_end() {}
275 // CHECK:      `-FunctionDecl {{.*}} the_end 'void ()'
276