1 | //===--- SemaOpenACC.cpp - Semantic Analysis for OpenACC constructs -------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | /// \file |
9 | /// This file implements semantic analysis for OpenACC constructs and |
10 | /// clauses. |
11 | /// |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "clang/Sema/SemaOpenACC.h" |
15 | #include "clang/AST/StmtOpenACC.h" |
16 | #include "clang/Basic/DiagnosticSema.h" |
17 | #include "clang/Basic/OpenACCKinds.h" |
18 | #include "clang/Sema/Sema.h" |
19 | #include "llvm/ADT/StringExtras.h" |
20 | #include "llvm/Support/Casting.h" |
21 | |
22 | using namespace clang; |
23 | |
24 | namespace { |
25 | bool diagnoseConstructAppertainment(SemaOpenACC &S, OpenACCDirectiveKind K, |
26 | SourceLocation StartLoc, bool IsStmt) { |
27 | switch (K) { |
28 | default: |
29 | case OpenACCDirectiveKind::Invalid: |
30 | // Nothing to do here, both invalid and unimplemented don't really need to |
31 | // do anything. |
32 | break; |
33 | case OpenACCDirectiveKind::Parallel: |
34 | case OpenACCDirectiveKind::Serial: |
35 | case OpenACCDirectiveKind::Kernels: |
36 | case OpenACCDirectiveKind::Loop: |
37 | if (!IsStmt) |
38 | return S.Diag(Loc: StartLoc, DiagID: diag::err_acc_construct_appertainment) << K; |
39 | break; |
40 | } |
41 | return false; |
42 | } |
43 | |
44 | bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind, |
45 | OpenACCClauseKind ClauseKind) { |
46 | switch (ClauseKind) { |
47 | // FIXME: For each clause as we implement them, we can add the |
48 | // 'legalization' list here. |
49 | case OpenACCClauseKind::Default: |
50 | switch (DirectiveKind) { |
51 | case OpenACCDirectiveKind::Parallel: |
52 | case OpenACCDirectiveKind::Serial: |
53 | case OpenACCDirectiveKind::Kernels: |
54 | case OpenACCDirectiveKind::ParallelLoop: |
55 | case OpenACCDirectiveKind::SerialLoop: |
56 | case OpenACCDirectiveKind::KernelsLoop: |
57 | case OpenACCDirectiveKind::Data: |
58 | return true; |
59 | default: |
60 | return false; |
61 | } |
62 | case OpenACCClauseKind::If: |
63 | switch (DirectiveKind) { |
64 | case OpenACCDirectiveKind::Parallel: |
65 | case OpenACCDirectiveKind::Serial: |
66 | case OpenACCDirectiveKind::Kernels: |
67 | case OpenACCDirectiveKind::Data: |
68 | case OpenACCDirectiveKind::EnterData: |
69 | case OpenACCDirectiveKind::ExitData: |
70 | case OpenACCDirectiveKind::HostData: |
71 | case OpenACCDirectiveKind::Init: |
72 | case OpenACCDirectiveKind::Shutdown: |
73 | case OpenACCDirectiveKind::Set: |
74 | case OpenACCDirectiveKind::Update: |
75 | case OpenACCDirectiveKind::Wait: |
76 | case OpenACCDirectiveKind::ParallelLoop: |
77 | case OpenACCDirectiveKind::SerialLoop: |
78 | case OpenACCDirectiveKind::KernelsLoop: |
79 | return true; |
80 | default: |
81 | return false; |
82 | } |
83 | case OpenACCClauseKind::Self: |
84 | switch (DirectiveKind) { |
85 | case OpenACCDirectiveKind::Parallel: |
86 | case OpenACCDirectiveKind::Serial: |
87 | case OpenACCDirectiveKind::Kernels: |
88 | case OpenACCDirectiveKind::Update: |
89 | case OpenACCDirectiveKind::ParallelLoop: |
90 | case OpenACCDirectiveKind::SerialLoop: |
91 | case OpenACCDirectiveKind::KernelsLoop: |
92 | return true; |
93 | default: |
94 | return false; |
95 | } |
96 | case OpenACCClauseKind::NumGangs: |
97 | case OpenACCClauseKind::NumWorkers: |
98 | case OpenACCClauseKind::VectorLength: |
99 | switch (DirectiveKind) { |
100 | case OpenACCDirectiveKind::Parallel: |
101 | case OpenACCDirectiveKind::Kernels: |
102 | case OpenACCDirectiveKind::ParallelLoop: |
103 | case OpenACCDirectiveKind::KernelsLoop: |
104 | return true; |
105 | default: |
106 | return false; |
107 | } |
108 | case OpenACCClauseKind::FirstPrivate: |
109 | switch (DirectiveKind) { |
110 | case OpenACCDirectiveKind::Parallel: |
111 | case OpenACCDirectiveKind::Serial: |
112 | case OpenACCDirectiveKind::ParallelLoop: |
113 | case OpenACCDirectiveKind::SerialLoop: |
114 | return true; |
115 | default: |
116 | return false; |
117 | } |
118 | case OpenACCClauseKind::Private: |
119 | switch (DirectiveKind) { |
120 | case OpenACCDirectiveKind::Parallel: |
121 | case OpenACCDirectiveKind::Serial: |
122 | case OpenACCDirectiveKind::Loop: |
123 | case OpenACCDirectiveKind::ParallelLoop: |
124 | case OpenACCDirectiveKind::SerialLoop: |
125 | case OpenACCDirectiveKind::KernelsLoop: |
126 | return true; |
127 | default: |
128 | return false; |
129 | } |
130 | case OpenACCClauseKind::NoCreate: |
131 | switch (DirectiveKind) { |
132 | case OpenACCDirectiveKind::Parallel: |
133 | case OpenACCDirectiveKind::Serial: |
134 | case OpenACCDirectiveKind::Kernels: |
135 | case OpenACCDirectiveKind::Data: |
136 | case OpenACCDirectiveKind::ParallelLoop: |
137 | case OpenACCDirectiveKind::SerialLoop: |
138 | case OpenACCDirectiveKind::KernelsLoop: |
139 | return true; |
140 | default: |
141 | return false; |
142 | } |
143 | case OpenACCClauseKind::Present: |
144 | switch (DirectiveKind) { |
145 | case OpenACCDirectiveKind::Parallel: |
146 | case OpenACCDirectiveKind::Serial: |
147 | case OpenACCDirectiveKind::Kernels: |
148 | case OpenACCDirectiveKind::Data: |
149 | case OpenACCDirectiveKind::Declare: |
150 | case OpenACCDirectiveKind::ParallelLoop: |
151 | case OpenACCDirectiveKind::SerialLoop: |
152 | case OpenACCDirectiveKind::KernelsLoop: |
153 | return true; |
154 | default: |
155 | return false; |
156 | } |
157 | |
158 | case OpenACCClauseKind::Copy: |
159 | case OpenACCClauseKind::PCopy: |
160 | case OpenACCClauseKind::PresentOrCopy: |
161 | switch (DirectiveKind) { |
162 | case OpenACCDirectiveKind::Parallel: |
163 | case OpenACCDirectiveKind::Serial: |
164 | case OpenACCDirectiveKind::Kernels: |
165 | case OpenACCDirectiveKind::Data: |
166 | case OpenACCDirectiveKind::Declare: |
167 | case OpenACCDirectiveKind::ParallelLoop: |
168 | case OpenACCDirectiveKind::SerialLoop: |
169 | case OpenACCDirectiveKind::KernelsLoop: |
170 | return true; |
171 | default: |
172 | return false; |
173 | } |
174 | case OpenACCClauseKind::CopyIn: |
175 | case OpenACCClauseKind::PCopyIn: |
176 | case OpenACCClauseKind::PresentOrCopyIn: |
177 | switch (DirectiveKind) { |
178 | case OpenACCDirectiveKind::Parallel: |
179 | case OpenACCDirectiveKind::Serial: |
180 | case OpenACCDirectiveKind::Kernels: |
181 | case OpenACCDirectiveKind::Data: |
182 | case OpenACCDirectiveKind::EnterData: |
183 | case OpenACCDirectiveKind::Declare: |
184 | case OpenACCDirectiveKind::ParallelLoop: |
185 | case OpenACCDirectiveKind::SerialLoop: |
186 | case OpenACCDirectiveKind::KernelsLoop: |
187 | return true; |
188 | default: |
189 | return false; |
190 | } |
191 | case OpenACCClauseKind::CopyOut: |
192 | case OpenACCClauseKind::PCopyOut: |
193 | case OpenACCClauseKind::PresentOrCopyOut: |
194 | switch (DirectiveKind) { |
195 | case OpenACCDirectiveKind::Parallel: |
196 | case OpenACCDirectiveKind::Serial: |
197 | case OpenACCDirectiveKind::Kernels: |
198 | case OpenACCDirectiveKind::Data: |
199 | case OpenACCDirectiveKind::ExitData: |
200 | case OpenACCDirectiveKind::Declare: |
201 | case OpenACCDirectiveKind::ParallelLoop: |
202 | case OpenACCDirectiveKind::SerialLoop: |
203 | case OpenACCDirectiveKind::KernelsLoop: |
204 | return true; |
205 | default: |
206 | return false; |
207 | } |
208 | case OpenACCClauseKind::Create: |
209 | case OpenACCClauseKind::PCreate: |
210 | case OpenACCClauseKind::PresentOrCreate: |
211 | switch (DirectiveKind) { |
212 | case OpenACCDirectiveKind::Parallel: |
213 | case OpenACCDirectiveKind::Serial: |
214 | case OpenACCDirectiveKind::Kernels: |
215 | case OpenACCDirectiveKind::Data: |
216 | case OpenACCDirectiveKind::EnterData: |
217 | case OpenACCDirectiveKind::ParallelLoop: |
218 | case OpenACCDirectiveKind::SerialLoop: |
219 | case OpenACCDirectiveKind::KernelsLoop: |
220 | return true; |
221 | default: |
222 | return false; |
223 | } |
224 | |
225 | case OpenACCClauseKind::Attach: |
226 | switch (DirectiveKind) { |
227 | case OpenACCDirectiveKind::Parallel: |
228 | case OpenACCDirectiveKind::Serial: |
229 | case OpenACCDirectiveKind::Kernels: |
230 | case OpenACCDirectiveKind::Data: |
231 | case OpenACCDirectiveKind::EnterData: |
232 | case OpenACCDirectiveKind::ParallelLoop: |
233 | case OpenACCDirectiveKind::SerialLoop: |
234 | case OpenACCDirectiveKind::KernelsLoop: |
235 | return true; |
236 | default: |
237 | return false; |
238 | } |
239 | case OpenACCClauseKind::DevicePtr: |
240 | switch (DirectiveKind) { |
241 | case OpenACCDirectiveKind::Parallel: |
242 | case OpenACCDirectiveKind::Serial: |
243 | case OpenACCDirectiveKind::Kernels: |
244 | case OpenACCDirectiveKind::Data: |
245 | case OpenACCDirectiveKind::Declare: |
246 | case OpenACCDirectiveKind::ParallelLoop: |
247 | case OpenACCDirectiveKind::SerialLoop: |
248 | case OpenACCDirectiveKind::KernelsLoop: |
249 | return true; |
250 | default: |
251 | return false; |
252 | } |
253 | case OpenACCClauseKind::Async: |
254 | switch (DirectiveKind) { |
255 | case OpenACCDirectiveKind::Parallel: |
256 | case OpenACCDirectiveKind::Serial: |
257 | case OpenACCDirectiveKind::Kernels: |
258 | case OpenACCDirectiveKind::Data: |
259 | case OpenACCDirectiveKind::EnterData: |
260 | case OpenACCDirectiveKind::ExitData: |
261 | case OpenACCDirectiveKind::Set: |
262 | case OpenACCDirectiveKind::Update: |
263 | case OpenACCDirectiveKind::Wait: |
264 | case OpenACCDirectiveKind::ParallelLoop: |
265 | case OpenACCDirectiveKind::SerialLoop: |
266 | case OpenACCDirectiveKind::KernelsLoop: |
267 | return true; |
268 | default: |
269 | return false; |
270 | } |
271 | case OpenACCClauseKind::Wait: |
272 | switch (DirectiveKind) { |
273 | case OpenACCDirectiveKind::Parallel: |
274 | case OpenACCDirectiveKind::Serial: |
275 | case OpenACCDirectiveKind::Kernels: |
276 | case OpenACCDirectiveKind::Data: |
277 | case OpenACCDirectiveKind::EnterData: |
278 | case OpenACCDirectiveKind::ExitData: |
279 | case OpenACCDirectiveKind::Update: |
280 | case OpenACCDirectiveKind::ParallelLoop: |
281 | case OpenACCDirectiveKind::SerialLoop: |
282 | case OpenACCDirectiveKind::KernelsLoop: |
283 | return true; |
284 | default: |
285 | return false; |
286 | } |
287 | |
288 | case OpenACCClauseKind::Seq: |
289 | switch (DirectiveKind) { |
290 | case OpenACCDirectiveKind::Loop: |
291 | case OpenACCDirectiveKind::Routine: |
292 | case OpenACCDirectiveKind::ParallelLoop: |
293 | case OpenACCDirectiveKind::SerialLoop: |
294 | case OpenACCDirectiveKind::KernelsLoop: |
295 | return true; |
296 | default: |
297 | return false; |
298 | } |
299 | |
300 | case OpenACCClauseKind::Independent: |
301 | case OpenACCClauseKind::Auto: |
302 | switch (DirectiveKind) { |
303 | case OpenACCDirectiveKind::Loop: |
304 | case OpenACCDirectiveKind::ParallelLoop: |
305 | case OpenACCDirectiveKind::SerialLoop: |
306 | case OpenACCDirectiveKind::KernelsLoop: |
307 | return true; |
308 | default: |
309 | return false; |
310 | } |
311 | |
312 | case OpenACCClauseKind::Reduction: |
313 | switch (DirectiveKind) { |
314 | case OpenACCDirectiveKind::Parallel: |
315 | case OpenACCDirectiveKind::Serial: |
316 | case OpenACCDirectiveKind::Loop: |
317 | case OpenACCDirectiveKind::ParallelLoop: |
318 | case OpenACCDirectiveKind::SerialLoop: |
319 | case OpenACCDirectiveKind::KernelsLoop: |
320 | return true; |
321 | default: |
322 | return false; |
323 | } |
324 | |
325 | case OpenACCClauseKind::DeviceType: |
326 | case OpenACCClauseKind::DType: |
327 | switch (DirectiveKind) { |
328 | case OpenACCDirectiveKind::Parallel: |
329 | case OpenACCDirectiveKind::Serial: |
330 | case OpenACCDirectiveKind::Kernels: |
331 | case OpenACCDirectiveKind::Data: |
332 | case OpenACCDirectiveKind::Init: |
333 | case OpenACCDirectiveKind::Shutdown: |
334 | case OpenACCDirectiveKind::Set: |
335 | case OpenACCDirectiveKind::Update: |
336 | case OpenACCDirectiveKind::Loop: |
337 | case OpenACCDirectiveKind::Routine: |
338 | case OpenACCDirectiveKind::ParallelLoop: |
339 | case OpenACCDirectiveKind::SerialLoop: |
340 | case OpenACCDirectiveKind::KernelsLoop: |
341 | return true; |
342 | default: |
343 | return false; |
344 | } |
345 | |
346 | default: |
347 | // Do nothing so we can go to the 'unimplemented' diagnostic instead. |
348 | return true; |
349 | } |
350 | llvm_unreachable("Invalid clause kind" ); |
351 | } |
352 | |
353 | bool checkAlreadyHasClauseOfKind( |
354 | SemaOpenACC &S, ArrayRef<const OpenACCClause *> ExistingClauses, |
355 | SemaOpenACC::OpenACCParsedClause &Clause) { |
356 | const auto *Itr = llvm::find_if(Range&: ExistingClauses, P: [&](const OpenACCClause *C) { |
357 | return C->getClauseKind() == Clause.getClauseKind(); |
358 | }); |
359 | if (Itr != ExistingClauses.end()) { |
360 | S.Diag(Loc: Clause.getBeginLoc(), DiagID: diag::err_acc_duplicate_clause_disallowed) |
361 | << Clause.getDirectiveKind() << Clause.getClauseKind(); |
362 | S.Diag(Loc: (*Itr)->getBeginLoc(), DiagID: diag::note_acc_previous_clause_here); |
363 | return true; |
364 | } |
365 | return false; |
366 | } |
367 | |
368 | bool checkValidAfterDeviceType( |
369 | SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause, |
370 | const SemaOpenACC::OpenACCParsedClause &NewClause) { |
371 | // This is only a requirement on compute and loop constructs so far, so this |
372 | // is fine otherwise. |
373 | if (!isOpenACCComputeDirectiveKind(K: NewClause.getDirectiveKind()) && |
374 | NewClause.getDirectiveKind() != OpenACCDirectiveKind::Loop) |
375 | return false; |
376 | |
377 | // OpenACC3.3: Section 2.4: Clauses that precede any device_type clause are |
378 | // default clauses. Clauses that follow a device_type clause up to the end of |
379 | // the directive or up to the next device_type clause are device-specific |
380 | // clauses for the device types specified in the device_type argument. |
381 | // |
382 | // The above implies that despite what the individual text says, these are |
383 | // valid. |
384 | if (NewClause.getClauseKind() == OpenACCClauseKind::DType || |
385 | NewClause.getClauseKind() == OpenACCClauseKind::DeviceType) |
386 | return false; |
387 | |
388 | // Implement check from OpenACC3.3: section 2.5.4: |
389 | // Only the async, wait, num_gangs, num_workers, and vector_length clauses may |
390 | // follow a device_type clause. |
391 | if (isOpenACCComputeDirectiveKind(K: NewClause.getDirectiveKind())) { |
392 | switch (NewClause.getClauseKind()) { |
393 | case OpenACCClauseKind::Async: |
394 | case OpenACCClauseKind::Wait: |
395 | case OpenACCClauseKind::NumGangs: |
396 | case OpenACCClauseKind::NumWorkers: |
397 | case OpenACCClauseKind::VectorLength: |
398 | return false; |
399 | default: |
400 | break; |
401 | } |
402 | } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Loop) { |
403 | // Implement check from OpenACC3.3: section 2.9: |
404 | // Only the collapse, gang, worker, vector, seq, independent, auto, and tile |
405 | // clauses may follow a device_type clause. |
406 | switch (NewClause.getClauseKind()) { |
407 | case OpenACCClauseKind::Collapse: |
408 | case OpenACCClauseKind::Gang: |
409 | case OpenACCClauseKind::Worker: |
410 | case OpenACCClauseKind::Vector: |
411 | case OpenACCClauseKind::Seq: |
412 | case OpenACCClauseKind::Independent: |
413 | case OpenACCClauseKind::Auto: |
414 | case OpenACCClauseKind::Tile: |
415 | return false; |
416 | default: |
417 | break; |
418 | } |
419 | } |
420 | S.Diag(Loc: NewClause.getBeginLoc(), DiagID: diag::err_acc_clause_after_device_type) |
421 | << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind() |
422 | << isOpenACCComputeDirectiveKind(K: NewClause.getDirectiveKind()) |
423 | << NewClause.getDirectiveKind(); |
424 | S.Diag(Loc: DeviceTypeClause.getBeginLoc(), DiagID: diag::note_acc_previous_clause_here); |
425 | return true; |
426 | } |
427 | |
428 | class SemaOpenACCClauseVisitor { |
429 | SemaOpenACC &SemaRef; |
430 | ASTContext &Ctx; |
431 | ArrayRef<const OpenACCClause *> ExistingClauses; |
432 | bool NotImplemented = false; |
433 | |
434 | OpenACCClause *isNotImplemented() { |
435 | NotImplemented = true; |
436 | return nullptr; |
437 | } |
438 | |
439 | public: |
440 | SemaOpenACCClauseVisitor(SemaOpenACC &S, |
441 | ArrayRef<const OpenACCClause *> ExistingClauses) |
442 | : SemaRef(S), Ctx(S.getASTContext()), ExistingClauses(ExistingClauses) {} |
443 | // Once we've implemented everything, we shouldn't need this infrastructure. |
444 | // But in the meantime, we use this to help decide whether the clause was |
445 | // handled for this directive. |
446 | bool diagNotImplemented() { return NotImplemented; } |
447 | |
448 | OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) { |
449 | switch (Clause.getClauseKind()) { |
450 | case OpenACCClauseKind::Gang: |
451 | case OpenACCClauseKind::Worker: |
452 | case OpenACCClauseKind::Vector: { |
453 | // TODO OpenACC: These are only implemented enough for the 'seq' diagnostic, |
454 | // otherwise treats itself as unimplemented. When we implement these, we |
455 | // can remove them from here. |
456 | |
457 | // OpenACC 3.3 2.9: |
458 | // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause |
459 | // appears. |
460 | const auto *Itr = |
461 | llvm::find_if(Range&: ExistingClauses, P: llvm::IsaPred<OpenACCSeqClause>); |
462 | |
463 | if (Itr != ExistingClauses.end()) { |
464 | SemaRef.Diag(Loc: Clause.getBeginLoc(), DiagID: diag::err_acc_clause_cannot_combine) |
465 | << Clause.getClauseKind() << (*Itr)->getClauseKind(); |
466 | SemaRef.Diag(Loc: (*Itr)->getBeginLoc(), DiagID: diag::note_acc_previous_clause_here); |
467 | } |
468 | return isNotImplemented(); |
469 | } |
470 | |
471 | #define VISIT_CLAUSE(CLAUSE_NAME) \ |
472 | case OpenACCClauseKind::CLAUSE_NAME: \ |
473 | return Visit##CLAUSE_NAME##Clause(Clause); |
474 | #define CLAUSE_ALIAS(ALIAS, CLAUSE_NAME, DEPRECATED) \ |
475 | case OpenACCClauseKind::ALIAS: \ |
476 | if (DEPRECATED) \ |
477 | SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name) \ |
478 | << Clause.getClauseKind() << OpenACCClauseKind::CLAUSE_NAME; \ |
479 | return Visit##CLAUSE_NAME##Clause(Clause); |
480 | #include "clang/Basic/OpenACCClauses.def" |
481 | default: |
482 | return isNotImplemented(); |
483 | } |
484 | llvm_unreachable("Invalid clause kind" ); |
485 | } |
486 | |
487 | #define VISIT_CLAUSE(CLAUSE_NAME) \ |
488 | OpenACCClause *Visit##CLAUSE_NAME##Clause( \ |
489 | SemaOpenACC::OpenACCParsedClause &Clause); |
490 | #include "clang/Basic/OpenACCClauses.def" |
491 | }; |
492 | |
493 | OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause( |
494 | SemaOpenACC::OpenACCParsedClause &Clause) { |
495 | // Restrictions only properly implemented on 'compute' constructs, and |
496 | // 'compute' constructs are the only construct that can do anything with |
497 | // this yet, so skip/treat as unimplemented in this case. |
498 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
499 | return isNotImplemented(); |
500 | |
501 | // Don't add an invalid clause to the AST. |
502 | if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid) |
503 | return nullptr; |
504 | |
505 | // OpenACC 3.3, Section 2.5.4: |
506 | // At most one 'default' clause may appear, and it must have a value of |
507 | // either 'none' or 'present'. |
508 | // Second half of the sentence is diagnosed during parsing. |
509 | if (checkAlreadyHasClauseOfKind(S&: SemaRef, ExistingClauses, Clause)) |
510 | return nullptr; |
511 | |
512 | return OpenACCDefaultClause::Create( |
513 | C: Ctx, K: Clause.getDefaultClauseKind(), BeginLoc: Clause.getBeginLoc(), |
514 | LParenLoc: Clause.getLParenLoc(), EndLoc: Clause.getEndLoc()); |
515 | } |
516 | |
517 | OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause( |
518 | SemaOpenACC::OpenACCParsedClause &Clause) { |
519 | // Restrictions only properly implemented on 'compute' constructs, and |
520 | // 'compute' constructs are the only construct that can do anything with |
521 | // this yet, so skip/treat as unimplemented in this case. |
522 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
523 | return isNotImplemented(); |
524 | |
525 | // There is no prose in the standard that says duplicates aren't allowed, |
526 | // but this diagnostic is present in other compilers, as well as makes |
527 | // sense. |
528 | if (checkAlreadyHasClauseOfKind(S&: SemaRef, ExistingClauses, Clause)) |
529 | return nullptr; |
530 | |
531 | // The parser has ensured that we have a proper condition expr, so there |
532 | // isn't really much to do here. |
533 | |
534 | // If the 'if' clause is true, it makes the 'self' clause have no effect, |
535 | // diagnose that here. |
536 | // TODO OpenACC: When we add these two to other constructs, we might not |
537 | // want to warn on this (for example, 'update'). |
538 | const auto *Itr = |
539 | llvm::find_if(Range&: ExistingClauses, P: llvm::IsaPred<OpenACCSelfClause>); |
540 | if (Itr != ExistingClauses.end()) { |
541 | SemaRef.Diag(Loc: Clause.getBeginLoc(), DiagID: diag::warn_acc_if_self_conflict); |
542 | SemaRef.Diag(Loc: (*Itr)->getBeginLoc(), DiagID: diag::note_acc_previous_clause_here); |
543 | } |
544 | |
545 | return OpenACCIfClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(), |
546 | LParenLoc: Clause.getLParenLoc(), |
547 | ConditionExpr: Clause.getConditionExpr(), EndLoc: Clause.getEndLoc()); |
548 | } |
549 | |
550 | OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause( |
551 | SemaOpenACC::OpenACCParsedClause &Clause) { |
552 | // Restrictions only properly implemented on 'compute' constructs, and |
553 | // 'compute' constructs are the only construct that can do anything with |
554 | // this yet, so skip/treat as unimplemented in this case. |
555 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
556 | return isNotImplemented(); |
557 | |
558 | // TODO OpenACC: When we implement this for 'update', this takes a |
559 | // 'var-list' instead of a condition expression, so semantics/handling has |
560 | // to happen differently here. |
561 | |
562 | // There is no prose in the standard that says duplicates aren't allowed, |
563 | // but this diagnostic is present in other compilers, as well as makes |
564 | // sense. |
565 | if (checkAlreadyHasClauseOfKind(S&: SemaRef, ExistingClauses, Clause)) |
566 | return nullptr; |
567 | |
568 | // If the 'if' clause is true, it makes the 'self' clause have no effect, |
569 | // diagnose that here. |
570 | // TODO OpenACC: When we add these two to other constructs, we might not |
571 | // want to warn on this (for example, 'update'). |
572 | const auto *Itr = |
573 | llvm::find_if(Range&: ExistingClauses, P: llvm::IsaPred<OpenACCIfClause>); |
574 | if (Itr != ExistingClauses.end()) { |
575 | SemaRef.Diag(Loc: Clause.getBeginLoc(), DiagID: diag::warn_acc_if_self_conflict); |
576 | SemaRef.Diag(Loc: (*Itr)->getBeginLoc(), DiagID: diag::note_acc_previous_clause_here); |
577 | } |
578 | return OpenACCSelfClause::Create( |
579 | C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), |
580 | ConditionExpr: Clause.getConditionExpr(), EndLoc: Clause.getEndLoc()); |
581 | } |
582 | |
583 | OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause( |
584 | SemaOpenACC::OpenACCParsedClause &Clause) { |
585 | // Restrictions only properly implemented on 'compute' constructs, and |
586 | // 'compute' constructs are the only construct that can do anything with |
587 | // this yet, so skip/treat as unimplemented in this case. |
588 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
589 | return isNotImplemented(); |
590 | |
591 | // There is no prose in the standard that says duplicates aren't allowed, |
592 | // but this diagnostic is present in other compilers, as well as makes |
593 | // sense. |
594 | if (checkAlreadyHasClauseOfKind(S&: SemaRef, ExistingClauses, Clause)) |
595 | return nullptr; |
596 | |
597 | // num_gangs requires at least 1 int expr in all forms. Diagnose here, but |
598 | // allow us to continue, an empty clause might be useful for future |
599 | // diagnostics. |
600 | if (Clause.getIntExprs().empty()) |
601 | SemaRef.Diag(Loc: Clause.getBeginLoc(), DiagID: diag::err_acc_num_gangs_num_args) |
602 | << /*NoArgs=*/0; |
603 | |
604 | unsigned MaxArgs = |
605 | (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel || |
606 | Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) |
607 | ? 3 |
608 | : 1; |
609 | // The max number of args differs between parallel and other constructs. |
610 | // Again, allow us to continue for the purposes of future diagnostics. |
611 | if (Clause.getIntExprs().size() > MaxArgs) |
612 | SemaRef.Diag(Loc: Clause.getBeginLoc(), DiagID: diag::err_acc_num_gangs_num_args) |
613 | << /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs |
614 | << Clause.getIntExprs().size(); |
615 | |
616 | // OpenACC 3.3 Section 2.5.4: |
617 | // A reduction clause may not appear on a parallel construct with a |
618 | // num_gangs clause that has more than one argument. |
619 | if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel && |
620 | Clause.getIntExprs().size() > 1) { |
621 | auto *Parallel = |
622 | llvm::find_if(Range&: ExistingClauses, P: llvm::IsaPred<OpenACCReductionClause>); |
623 | |
624 | if (Parallel != ExistingClauses.end()) { |
625 | SemaRef.Diag(Loc: Clause.getBeginLoc(), |
626 | DiagID: diag::err_acc_reduction_num_gangs_conflict) |
627 | << Clause.getIntExprs().size(); |
628 | SemaRef.Diag(Loc: (*Parallel)->getBeginLoc(), |
629 | DiagID: diag::note_acc_previous_clause_here); |
630 | return nullptr; |
631 | } |
632 | } |
633 | return OpenACCNumGangsClause::Create( |
634 | C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), IntExprs: Clause.getIntExprs(), |
635 | EndLoc: Clause.getEndLoc()); |
636 | } |
637 | |
638 | OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause( |
639 | SemaOpenACC::OpenACCParsedClause &Clause) { |
640 | // Restrictions only properly implemented on 'compute' constructs, and |
641 | // 'compute' constructs are the only construct that can do anything with |
642 | // this yet, so skip/treat as unimplemented in this case. |
643 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
644 | return isNotImplemented(); |
645 | |
646 | // There is no prose in the standard that says duplicates aren't allowed, |
647 | // but this diagnostic is present in other compilers, as well as makes |
648 | // sense. |
649 | if (checkAlreadyHasClauseOfKind(S&: SemaRef, ExistingClauses, Clause)) |
650 | return nullptr; |
651 | |
652 | assert(Clause.getIntExprs().size() == 1 && |
653 | "Invalid number of expressions for NumWorkers" ); |
654 | return OpenACCNumWorkersClause::Create( |
655 | C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), IntExpr: Clause.getIntExprs()[0], |
656 | EndLoc: Clause.getEndLoc()); |
657 | } |
658 | |
659 | OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause( |
660 | SemaOpenACC::OpenACCParsedClause &Clause) { |
661 | // Restrictions only properly implemented on 'compute' constructs, and |
662 | // 'compute' constructs are the only construct that can do anything with |
663 | // this yet, so skip/treat as unimplemented in this case. |
664 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
665 | return isNotImplemented(); |
666 | |
667 | // There is no prose in the standard that says duplicates aren't allowed, |
668 | // but this diagnostic is present in other compilers, as well as makes |
669 | // sense. |
670 | if (checkAlreadyHasClauseOfKind(S&: SemaRef, ExistingClauses, Clause)) |
671 | return nullptr; |
672 | |
673 | assert(Clause.getIntExprs().size() == 1 && |
674 | "Invalid number of expressions for NumWorkers" ); |
675 | return OpenACCVectorLengthClause::Create( |
676 | C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), IntExpr: Clause.getIntExprs()[0], |
677 | EndLoc: Clause.getEndLoc()); |
678 | } |
679 | |
680 | OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause( |
681 | SemaOpenACC::OpenACCParsedClause &Clause) { |
682 | // Restrictions only properly implemented on 'compute' constructs, and |
683 | // 'compute' constructs are the only construct that can do anything with |
684 | // this yet, so skip/treat as unimplemented in this case. |
685 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
686 | return isNotImplemented(); |
687 | |
688 | // There is no prose in the standard that says duplicates aren't allowed, |
689 | // but this diagnostic is present in other compilers, as well as makes |
690 | // sense. |
691 | if (checkAlreadyHasClauseOfKind(S&: SemaRef, ExistingClauses, Clause)) |
692 | return nullptr; |
693 | |
694 | assert(Clause.getNumIntExprs() < 2 && |
695 | "Invalid number of expressions for Async" ); |
696 | return OpenACCAsyncClause::Create( |
697 | C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), |
698 | IntExpr: Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr, |
699 | EndLoc: Clause.getEndLoc()); |
700 | } |
701 | |
702 | OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause( |
703 | SemaOpenACC::OpenACCParsedClause &Clause) { |
704 | // Restrictions only properly implemented on 'compute' and 'loop' |
705 | // constructs, and 'compute'/'loop' constructs are the only construct that |
706 | // can do anything with this yet, so skip/treat as unimplemented in this |
707 | // case. |
708 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind()) && |
709 | Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) |
710 | return isNotImplemented(); |
711 | |
712 | // ActOnVar ensured that everything is a valid variable reference, so there |
713 | // really isn't anything to do here. GCC does some duplicate-finding, though |
714 | // it isn't apparent in the standard where this is justified. |
715 | |
716 | return OpenACCPrivateClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(), |
717 | LParenLoc: Clause.getLParenLoc(), |
718 | VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc()); |
719 | } |
720 | |
721 | OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause( |
722 | SemaOpenACC::OpenACCParsedClause &Clause) { |
723 | // Restrictions only properly implemented on 'compute' constructs, and |
724 | // 'compute' constructs are the only construct that can do anything with |
725 | // this yet, so skip/treat as unimplemented in this case. |
726 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
727 | return isNotImplemented(); |
728 | |
729 | // ActOnVar ensured that everything is a valid variable reference, so there |
730 | // really isn't anything to do here. GCC does some duplicate-finding, though |
731 | // it isn't apparent in the standard where this is justified. |
732 | |
733 | return OpenACCFirstPrivateClause::Create( |
734 | C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(), |
735 | EndLoc: Clause.getEndLoc()); |
736 | } |
737 | |
738 | OpenACCClause *SemaOpenACCClauseVisitor::VisitNoCreateClause( |
739 | SemaOpenACC::OpenACCParsedClause &Clause) { |
740 | // Restrictions only properly implemented on 'compute' constructs, and |
741 | // 'compute' constructs are the only construct that can do anything with |
742 | // this yet, so skip/treat as unimplemented in this case. |
743 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
744 | return isNotImplemented(); |
745 | // ActOnVar ensured that everything is a valid variable reference, so there |
746 | // really isn't anything to do here. GCC does some duplicate-finding, though |
747 | // it isn't apparent in the standard where this is justified. |
748 | |
749 | return OpenACCNoCreateClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(), |
750 | LParenLoc: Clause.getLParenLoc(), |
751 | VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc()); |
752 | } |
753 | |
754 | OpenACCClause *SemaOpenACCClauseVisitor::VisitPresentClause( |
755 | SemaOpenACC::OpenACCParsedClause &Clause) { |
756 | // Restrictions only properly implemented on 'compute' constructs, and |
757 | // 'compute' constructs are the only construct that can do anything with |
758 | // this yet, so skip/treat as unimplemented in this case. |
759 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
760 | return isNotImplemented(); |
761 | // ActOnVar ensured that everything is a valid variable reference, so there |
762 | // really isn't anything to do here. GCC does some duplicate-finding, though |
763 | // it isn't apparent in the standard where this is justified. |
764 | |
765 | return OpenACCPresentClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(), |
766 | LParenLoc: Clause.getLParenLoc(), |
767 | VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc()); |
768 | } |
769 | |
770 | OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyClause( |
771 | SemaOpenACC::OpenACCParsedClause &Clause) { |
772 | // Restrictions only properly implemented on 'compute' constructs, and |
773 | // 'compute' constructs are the only construct that can do anything with |
774 | // this yet, so skip/treat as unimplemented in this case. |
775 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
776 | return isNotImplemented(); |
777 | // ActOnVar ensured that everything is a valid variable reference, so there |
778 | // really isn't anything to do here. GCC does some duplicate-finding, though |
779 | // it isn't apparent in the standard where this is justified. |
780 | |
781 | return OpenACCCopyClause::Create( |
782 | C: Ctx, Spelling: Clause.getClauseKind(), BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), |
783 | VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc()); |
784 | } |
785 | |
786 | OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyInClause( |
787 | SemaOpenACC::OpenACCParsedClause &Clause) { |
788 | // Restrictions only properly implemented on 'compute' constructs, and |
789 | // 'compute' constructs are the only construct that can do anything with |
790 | // this yet, so skip/treat as unimplemented in this case. |
791 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
792 | return isNotImplemented(); |
793 | // ActOnVar ensured that everything is a valid variable reference, so there |
794 | // really isn't anything to do here. GCC does some duplicate-finding, though |
795 | // it isn't apparent in the standard where this is justified. |
796 | |
797 | return OpenACCCopyInClause::Create( |
798 | C: Ctx, Spelling: Clause.getClauseKind(), BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), |
799 | IsReadOnly: Clause.isReadOnly(), VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc()); |
800 | } |
801 | |
802 | OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyOutClause( |
803 | SemaOpenACC::OpenACCParsedClause &Clause) { |
804 | // Restrictions only properly implemented on 'compute' constructs, and |
805 | // 'compute' constructs are the only construct that can do anything with |
806 | // this yet, so skip/treat as unimplemented in this case. |
807 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
808 | return isNotImplemented(); |
809 | // ActOnVar ensured that everything is a valid variable reference, so there |
810 | // really isn't anything to do here. GCC does some duplicate-finding, though |
811 | // it isn't apparent in the standard where this is justified. |
812 | |
813 | return OpenACCCopyOutClause::Create( |
814 | C: Ctx, Spelling: Clause.getClauseKind(), BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), |
815 | IsZero: Clause.isZero(), VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc()); |
816 | } |
817 | |
818 | OpenACCClause *SemaOpenACCClauseVisitor::VisitCreateClause( |
819 | SemaOpenACC::OpenACCParsedClause &Clause) { |
820 | // Restrictions only properly implemented on 'compute' constructs, and |
821 | // 'compute' constructs are the only construct that can do anything with |
822 | // this yet, so skip/treat as unimplemented in this case. |
823 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
824 | return isNotImplemented(); |
825 | // ActOnVar ensured that everything is a valid variable reference, so there |
826 | // really isn't anything to do here. GCC does some duplicate-finding, though |
827 | // it isn't apparent in the standard where this is justified. |
828 | |
829 | return OpenACCCreateClause::Create( |
830 | C: Ctx, Spelling: Clause.getClauseKind(), BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), |
831 | IsZero: Clause.isZero(), VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc()); |
832 | } |
833 | |
834 | OpenACCClause *SemaOpenACCClauseVisitor::VisitAttachClause( |
835 | SemaOpenACC::OpenACCParsedClause &Clause) { |
836 | // Restrictions only properly implemented on 'compute' constructs, and |
837 | // 'compute' constructs are the only construct that can do anything with |
838 | // this yet, so skip/treat as unimplemented in this case. |
839 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
840 | return isNotImplemented(); |
841 | |
842 | // ActOnVar ensured that everything is a valid variable reference, but we |
843 | // still have to make sure it is a pointer type. |
844 | llvm::SmallVector<Expr *> VarList{Clause.getVarList()}; |
845 | llvm::erase_if(C&: VarList, P: [&](Expr *E) { |
846 | return SemaRef.CheckVarIsPointerType(ClauseKind: OpenACCClauseKind::Attach, VarExpr: E); |
847 | }); |
848 | Clause.setVarListDetails(VarList, |
849 | /*IsReadOnly=*/false, /*IsZero=*/false); |
850 | return OpenACCAttachClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(), |
851 | LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(), |
852 | EndLoc: Clause.getEndLoc()); |
853 | } |
854 | |
855 | OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause( |
856 | SemaOpenACC::OpenACCParsedClause &Clause) { |
857 | // Restrictions only properly implemented on 'compute' constructs, and |
858 | // 'compute' constructs are the only construct that can do anything with |
859 | // this yet, so skip/treat as unimplemented in this case. |
860 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
861 | return isNotImplemented(); |
862 | |
863 | // ActOnVar ensured that everything is a valid variable reference, but we |
864 | // still have to make sure it is a pointer type. |
865 | llvm::SmallVector<Expr *> VarList{Clause.getVarList()}; |
866 | llvm::erase_if(C&: VarList, P: [&](Expr *E) { |
867 | return SemaRef.CheckVarIsPointerType(ClauseKind: OpenACCClauseKind::DevicePtr, VarExpr: E); |
868 | }); |
869 | Clause.setVarListDetails(VarList, |
870 | /*IsReadOnly=*/false, /*IsZero=*/false); |
871 | |
872 | return OpenACCDevicePtrClause::Create( |
873 | C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(), |
874 | EndLoc: Clause.getEndLoc()); |
875 | } |
876 | |
877 | OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause( |
878 | SemaOpenACC::OpenACCParsedClause &Clause) { |
879 | // Restrictions only properly implemented on 'compute' constructs, and |
880 | // 'compute' constructs are the only construct that can do anything with |
881 | // this yet, so skip/treat as unimplemented in this case. |
882 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
883 | return isNotImplemented(); |
884 | |
885 | return OpenACCWaitClause::Create( |
886 | C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), DevNumExpr: Clause.getDevNumExpr(), |
887 | QueuesLoc: Clause.getQueuesLoc(), QueueIdExprs: Clause.getQueueIdExprs(), EndLoc: Clause.getEndLoc()); |
888 | } |
889 | |
890 | OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause( |
891 | SemaOpenACC::OpenACCParsedClause &Clause) { |
892 | // Restrictions only properly implemented on 'compute' and 'loop' |
893 | // constructs, and 'compute'/'loop' constructs are the only construct that |
894 | // can do anything with this yet, so skip/treat as unimplemented in this |
895 | // case. |
896 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind()) && |
897 | Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) |
898 | return isNotImplemented(); |
899 | |
900 | // TODO OpenACC: Once we get enough of the CodeGen implemented that we have |
901 | // a source for the list of valid architectures, we need to warn on unknown |
902 | // identifiers here. |
903 | |
904 | return OpenACCDeviceTypeClause::Create( |
905 | C: Ctx, K: Clause.getClauseKind(), BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), |
906 | Archs: Clause.getDeviceTypeArchitectures(), EndLoc: Clause.getEndLoc()); |
907 | } |
908 | |
909 | OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause( |
910 | SemaOpenACC::OpenACCParsedClause &Clause) { |
911 | // Restrictions only properly implemented on 'loop' constructs, and it is |
912 | // the only construct that can do anything with this, so skip/treat as |
913 | // unimplemented for the combined constructs. |
914 | if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) |
915 | return isNotImplemented(); |
916 | |
917 | // OpenACC 3.3 2.9: |
918 | // Only one of the seq, independent, and auto clauses may appear. |
919 | const auto *Itr = |
920 | llvm::find_if(Range&: ExistingClauses, |
921 | P: llvm::IsaPred<OpenACCIndependentClause, OpenACCSeqClause>); |
922 | if (Itr != ExistingClauses.end()) { |
923 | SemaRef.Diag(Loc: Clause.getBeginLoc(), DiagID: diag::err_acc_loop_spec_conflict) |
924 | << Clause.getClauseKind() << Clause.getDirectiveKind(); |
925 | SemaRef.Diag(Loc: (*Itr)->getBeginLoc(), DiagID: diag::note_acc_previous_clause_here); |
926 | return nullptr; |
927 | } |
928 | |
929 | return OpenACCAutoClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(), |
930 | EndLoc: Clause.getEndLoc()); |
931 | } |
932 | |
933 | OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause( |
934 | SemaOpenACC::OpenACCParsedClause &Clause) { |
935 | // Restrictions only properly implemented on 'loop' constructs, and it is |
936 | // the only construct that can do anything with this, so skip/treat as |
937 | // unimplemented for the combined constructs. |
938 | if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) |
939 | return isNotImplemented(); |
940 | |
941 | // OpenACC 3.3 2.9: |
942 | // Only one of the seq, independent, and auto clauses may appear. |
943 | const auto *Itr = llvm::find_if( |
944 | Range&: ExistingClauses, P: llvm::IsaPred<OpenACCAutoClause, OpenACCSeqClause>); |
945 | if (Itr != ExistingClauses.end()) { |
946 | SemaRef.Diag(Loc: Clause.getBeginLoc(), DiagID: diag::err_acc_loop_spec_conflict) |
947 | << Clause.getClauseKind() << Clause.getDirectiveKind(); |
948 | SemaRef.Diag(Loc: (*Itr)->getBeginLoc(), DiagID: diag::note_acc_previous_clause_here); |
949 | return nullptr; |
950 | } |
951 | |
952 | return OpenACCIndependentClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(), |
953 | EndLoc: Clause.getEndLoc()); |
954 | } |
955 | |
956 | OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause( |
957 | SemaOpenACC::OpenACCParsedClause &Clause) { |
958 | // Restrictions only properly implemented on 'loop' constructs, and it is |
959 | // the only construct that can do anything with this, so skip/treat as |
960 | // unimplemented for the combined constructs. |
961 | if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop) |
962 | return isNotImplemented(); |
963 | |
964 | // OpenACC 3.3 2.9: |
965 | // Only one of the seq, independent, and auto clauses may appear. |
966 | const auto *Itr = |
967 | llvm::find_if(Range&: ExistingClauses, |
968 | P: llvm::IsaPred<OpenACCAutoClause, OpenACCIndependentClause>); |
969 | if (Itr != ExistingClauses.end()) { |
970 | SemaRef.Diag(Loc: Clause.getBeginLoc(), DiagID: diag::err_acc_loop_spec_conflict) |
971 | << Clause.getClauseKind() << Clause.getDirectiveKind(); |
972 | SemaRef.Diag(Loc: (*Itr)->getBeginLoc(), DiagID: diag::note_acc_previous_clause_here); |
973 | return nullptr; |
974 | } |
975 | |
976 | // OpenACC 3.3 2.9: |
977 | // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause |
978 | // appears. |
979 | Itr = llvm::find_if(Range&: ExistingClauses, |
980 | P: llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause, |
981 | OpenACCVectorClause>); |
982 | |
983 | if (Itr != ExistingClauses.end()) { |
984 | SemaRef.Diag(Loc: Clause.getBeginLoc(), DiagID: diag::err_acc_clause_cannot_combine) |
985 | << Clause.getClauseKind() << (*Itr)->getClauseKind(); |
986 | SemaRef.Diag(Loc: (*Itr)->getBeginLoc(), DiagID: diag::note_acc_previous_clause_here); |
987 | return nullptr; |
988 | } |
989 | |
990 | // TODO OpenACC: 2.9 ~ line 2010 specifies that the associated loop has some |
991 | // restrictions when there is a 'seq' clause in place. We probably need to |
992 | // implement that. |
993 | return OpenACCSeqClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(), |
994 | EndLoc: Clause.getEndLoc()); |
995 | } |
996 | |
997 | OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause( |
998 | SemaOpenACC::OpenACCParsedClause &Clause) { |
999 | // Restrictions only properly implemented on 'compute' constructs, and |
1000 | // 'compute' constructs are the only construct that can do anything with |
1001 | // this yet, so skip/treat as unimplemented in this case. |
1002 | if (!isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind())) |
1003 | return isNotImplemented(); |
1004 | |
1005 | // OpenACC 3.3 Section 2.5.4: |
1006 | // A reduction clause may not appear on a parallel construct with a |
1007 | // num_gangs clause that has more than one argument. |
1008 | if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel) { |
1009 | auto NumGangsClauses = llvm::make_filter_range( |
1010 | Range&: ExistingClauses, Pred: llvm::IsaPred<OpenACCNumGangsClause>); |
1011 | |
1012 | for (auto *NGC : NumGangsClauses) { |
1013 | unsigned NumExprs = |
1014 | cast<OpenACCNumGangsClause>(Val: NGC)->getIntExprs().size(); |
1015 | |
1016 | if (NumExprs > 1) { |
1017 | SemaRef.Diag(Loc: Clause.getBeginLoc(), |
1018 | DiagID: diag::err_acc_reduction_num_gangs_conflict) |
1019 | << NumExprs; |
1020 | SemaRef.Diag(Loc: NGC->getBeginLoc(), DiagID: diag::note_acc_previous_clause_here); |
1021 | return nullptr; |
1022 | } |
1023 | } |
1024 | } |
1025 | |
1026 | SmallVector<Expr *> ValidVars; |
1027 | |
1028 | for (Expr *Var : Clause.getVarList()) { |
1029 | ExprResult Res = SemaRef.CheckReductionVar(VarExpr: Var); |
1030 | |
1031 | if (Res.isUsable()) |
1032 | ValidVars.push_back(Elt: Res.get()); |
1033 | } |
1034 | |
1035 | return OpenACCReductionClause::Create( |
1036 | C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), Operator: Clause.getReductionOp(), |
1037 | VarList: ValidVars, EndLoc: Clause.getEndLoc()); |
1038 | } |
1039 | |
1040 | } // namespace |
1041 | |
1042 | SemaOpenACC::SemaOpenACC(Sema &S) : SemaBase(S) {} |
1043 | |
1044 | SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(SemaOpenACC &S, |
1045 | OpenACCDirectiveKind DK) |
1046 | : SemaRef(S), WasInsideComputeConstruct(S.InsideComputeConstruct), |
1047 | DirKind(DK) { |
1048 | // Compute constructs end up taking their 'loop'. |
1049 | if (DirKind == OpenACCDirectiveKind::Parallel || |
1050 | DirKind == OpenACCDirectiveKind::Serial || |
1051 | DirKind == OpenACCDirectiveKind::Kernels) { |
1052 | SemaRef.InsideComputeConstruct = true; |
1053 | SemaRef.ParentlessLoopConstructs.swap(RHS&: ParentlessLoopConstructs); |
1054 | } |
1055 | } |
1056 | |
1057 | SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() { |
1058 | SemaRef.InsideComputeConstruct = WasInsideComputeConstruct; |
1059 | if (DirKind == OpenACCDirectiveKind::Parallel || |
1060 | DirKind == OpenACCDirectiveKind::Serial || |
1061 | DirKind == OpenACCDirectiveKind::Kernels) { |
1062 | assert(SemaRef.ParentlessLoopConstructs.empty() && |
1063 | "Didn't consume loop construct list?" ); |
1064 | SemaRef.ParentlessLoopConstructs.swap(RHS&: ParentlessLoopConstructs); |
1065 | } |
1066 | } |
1067 | |
1068 | OpenACCClause * |
1069 | SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses, |
1070 | OpenACCParsedClause &Clause) { |
1071 | if (Clause.getClauseKind() == OpenACCClauseKind::Invalid) |
1072 | return nullptr; |
1073 | |
1074 | // Diagnose that we don't support this clause on this directive. |
1075 | if (!doesClauseApplyToDirective(DirectiveKind: Clause.getDirectiveKind(), |
1076 | ClauseKind: Clause.getClauseKind())) { |
1077 | Diag(Loc: Clause.getBeginLoc(), DiagID: diag::err_acc_clause_appertainment) |
1078 | << Clause.getDirectiveKind() << Clause.getClauseKind(); |
1079 | return nullptr; |
1080 | } |
1081 | |
1082 | if (const auto *DevTypeClause = |
1083 | llvm::find_if(Range&: ExistingClauses, |
1084 | P: [&](const OpenACCClause *C) { |
1085 | return isa<OpenACCDeviceTypeClause>(Val: C); |
1086 | }); |
1087 | DevTypeClause != ExistingClauses.end()) { |
1088 | if (checkValidAfterDeviceType( |
1089 | S&: *this, DeviceTypeClause: *cast<OpenACCDeviceTypeClause>(Val: *DevTypeClause), NewClause: Clause)) |
1090 | return nullptr; |
1091 | } |
1092 | |
1093 | SemaOpenACCClauseVisitor Visitor{*this, ExistingClauses}; |
1094 | OpenACCClause *Result = Visitor.Visit(Clause); |
1095 | assert((!Result || Result->getClauseKind() == Clause.getClauseKind()) && |
1096 | "Created wrong clause?" ); |
1097 | |
1098 | if (Visitor.diagNotImplemented()) |
1099 | Diag(Loc: Clause.getBeginLoc(), DiagID: diag::warn_acc_clause_unimplemented) |
1100 | << Clause.getClauseKind(); |
1101 | |
1102 | return Result; |
1103 | |
1104 | // switch (Clause.getClauseKind()) { |
1105 | // case OpenACCClauseKind::PresentOrCopy: |
1106 | // case OpenACCClauseKind::PCopy: |
1107 | // Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name) |
1108 | // << Clause.getClauseKind() << OpenACCClauseKind::Copy; |
1109 | // LLVM_FALLTHROUGH; |
1110 | // case OpenACCClauseKind::PresentOrCreate: |
1111 | // case OpenACCClauseKind::PCreate: |
1112 | // Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name) |
1113 | // << Clause.getClauseKind() << OpenACCClauseKind::Create; |
1114 | // LLVM_FALLTHROUGH; |
1115 | // |
1116 | // |
1117 | // |
1118 | // |
1119 | // case OpenACCClauseKind::DType: |
1120 | // |
1121 | // |
1122 | // |
1123 | // |
1124 | // |
1125 | // |
1126 | // |
1127 | // |
1128 | // case OpenACCClauseKind::Gang: |
1129 | // case OpenACCClauseKind::Worker: |
1130 | // case OpenACCClauseKind::Vector: { |
1131 | // // OpenACC 3.3 2.9: |
1132 | // // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' |
1133 | // clause |
1134 | // // appears. |
1135 | // const auto *Itr = |
1136 | // llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>); |
1137 | // |
1138 | // if (Itr != ExistingClauses.end()) { |
1139 | // Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine) |
1140 | // << Clause.getClauseKind() << (*Itr)->getClauseKind(); |
1141 | // Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here); |
1142 | // } |
1143 | // // Not yet implemented, so immediately drop to the 'not yet implemented' |
1144 | // // diagnostic. |
1145 | // break; |
1146 | // } |
1147 | // */ |
1148 | |
1149 | } |
1150 | |
1151 | /// OpenACC 3.3 section 2.5.15: |
1152 | /// At a mininmum, the supported data types include ... the numerical data types |
1153 | /// in C, C++, and Fortran. |
1154 | /// |
1155 | /// If the reduction var is a composite variable, each |
1156 | /// member of the composite variable must be a supported datatype for the |
1157 | /// reduction operation. |
1158 | ExprResult SemaOpenACC::CheckReductionVar(Expr *VarExpr) { |
1159 | VarExpr = VarExpr->IgnoreParenCasts(); |
1160 | |
1161 | auto TypeIsValid = [](QualType Ty) { |
1162 | return Ty->isDependentType() || Ty->isScalarType(); |
1163 | }; |
1164 | |
1165 | if (isa<ArraySectionExpr>(Val: VarExpr)) { |
1166 | Expr *ASExpr = VarExpr; |
1167 | QualType BaseTy = ArraySectionExpr::getBaseOriginalType(Base: ASExpr); |
1168 | QualType EltTy = getASTContext().getBaseElementType(QT: BaseTy); |
1169 | |
1170 | if (!TypeIsValid(EltTy)) { |
1171 | Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_reduction_type) |
1172 | << EltTy << /*Sub array base type*/ 1; |
1173 | return ExprError(); |
1174 | } |
1175 | } else if (auto *RD = VarExpr->getType()->getAsRecordDecl()) { |
1176 | if (!RD->isStruct() && !RD->isClass()) { |
1177 | Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_reduction_composite_type) |
1178 | << /*not class or struct*/ 0 << VarExpr->getType(); |
1179 | return ExprError(); |
1180 | } |
1181 | |
1182 | if (!RD->isCompleteDefinition()) { |
1183 | Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_reduction_composite_type) |
1184 | << /*incomplete*/ 1 << VarExpr->getType(); |
1185 | return ExprError(); |
1186 | } |
1187 | if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD); |
1188 | CXXRD && !CXXRD->isAggregate()) { |
1189 | Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_reduction_composite_type) |
1190 | << /*aggregate*/ 2 << VarExpr->getType(); |
1191 | return ExprError(); |
1192 | } |
1193 | |
1194 | for (FieldDecl *FD : RD->fields()) { |
1195 | if (!TypeIsValid(FD->getType())) { |
1196 | Diag(Loc: VarExpr->getExprLoc(), |
1197 | DiagID: diag::err_acc_reduction_composite_member_type); |
1198 | Diag(Loc: FD->getLocation(), DiagID: diag::note_acc_reduction_composite_member_loc); |
1199 | return ExprError(); |
1200 | } |
1201 | } |
1202 | } else if (!TypeIsValid(VarExpr->getType())) { |
1203 | Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_reduction_type) |
1204 | << VarExpr->getType() << /*Sub array base type*/ 0; |
1205 | return ExprError(); |
1206 | } |
1207 | |
1208 | return VarExpr; |
1209 | } |
1210 | |
1211 | void SemaOpenACC::ActOnConstruct(OpenACCDirectiveKind K, |
1212 | SourceLocation DirLoc) { |
1213 | switch (K) { |
1214 | case OpenACCDirectiveKind::Invalid: |
1215 | // Nothing to do here, an invalid kind has nothing we can check here. We |
1216 | // want to continue parsing clauses as far as we can, so we will just |
1217 | // ensure that we can still work and don't check any construct-specific |
1218 | // rules anywhere. |
1219 | break; |
1220 | case OpenACCDirectiveKind::Parallel: |
1221 | case OpenACCDirectiveKind::Serial: |
1222 | case OpenACCDirectiveKind::Kernels: |
1223 | case OpenACCDirectiveKind::Loop: |
1224 | // Nothing to do here, there is no real legalization that needs to happen |
1225 | // here as these constructs do not take any arguments. |
1226 | break; |
1227 | default: |
1228 | Diag(Loc: DirLoc, DiagID: diag::warn_acc_construct_unimplemented) << K; |
1229 | break; |
1230 | } |
1231 | } |
1232 | |
1233 | ExprResult SemaOpenACC::ActOnIntExpr(OpenACCDirectiveKind DK, |
1234 | OpenACCClauseKind CK, SourceLocation Loc, |
1235 | Expr *IntExpr) { |
1236 | |
1237 | assert(((DK != OpenACCDirectiveKind::Invalid && |
1238 | CK == OpenACCClauseKind::Invalid) || |
1239 | (DK == OpenACCDirectiveKind::Invalid && |
1240 | CK != OpenACCClauseKind::Invalid) || |
1241 | (DK == OpenACCDirectiveKind::Invalid && |
1242 | CK == OpenACCClauseKind::Invalid)) && |
1243 | "Only one of directive or clause kind should be provided" ); |
1244 | |
1245 | class IntExprConverter : public Sema::ICEConvertDiagnoser { |
1246 | OpenACCDirectiveKind DirectiveKind; |
1247 | OpenACCClauseKind ClauseKind; |
1248 | Expr *IntExpr; |
1249 | |
1250 | // gets the index into the diagnostics so we can use this for clauses, |
1251 | // directives, and sub array.s |
1252 | unsigned getDiagKind() const { |
1253 | if (ClauseKind != OpenACCClauseKind::Invalid) |
1254 | return 0; |
1255 | if (DirectiveKind != OpenACCDirectiveKind::Invalid) |
1256 | return 1; |
1257 | return 2; |
1258 | } |
1259 | |
1260 | public: |
1261 | IntExprConverter(OpenACCDirectiveKind DK, OpenACCClauseKind CK, |
1262 | Expr *IntExpr) |
1263 | : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false, |
1264 | /*Suppress=*/false, |
1265 | /*SuppressConversion=*/true), |
1266 | DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {} |
1267 | |
1268 | bool match(QualType T) override { |
1269 | // OpenACC spec just calls this 'integer expression' as having an |
1270 | // 'integer type', so fall back on C99's 'integer type'. |
1271 | return T->isIntegerType(); |
1272 | } |
1273 | SemaBase::SemaDiagnosticBuilder diagnoseNotInt(Sema &S, SourceLocation Loc, |
1274 | QualType T) override { |
1275 | return S.Diag(Loc, DiagID: diag::err_acc_int_expr_requires_integer) |
1276 | << getDiagKind() << ClauseKind << DirectiveKind << T; |
1277 | } |
1278 | |
1279 | SemaBase::SemaDiagnosticBuilder |
1280 | diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) override { |
1281 | return S.Diag(Loc, DiagID: diag::err_acc_int_expr_incomplete_class_type) |
1282 | << T << IntExpr->getSourceRange(); |
1283 | } |
1284 | |
1285 | SemaBase::SemaDiagnosticBuilder |
1286 | diagnoseExplicitConv(Sema &S, SourceLocation Loc, QualType T, |
1287 | QualType ConvTy) override { |
1288 | return S.Diag(Loc, DiagID: diag::err_acc_int_expr_explicit_conversion) |
1289 | << T << ConvTy; |
1290 | } |
1291 | |
1292 | SemaBase::SemaDiagnosticBuilder noteExplicitConv(Sema &S, |
1293 | CXXConversionDecl *Conv, |
1294 | QualType ConvTy) override { |
1295 | return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_acc_int_expr_conversion) |
1296 | << ConvTy->isEnumeralType() << ConvTy; |
1297 | } |
1298 | |
1299 | SemaBase::SemaDiagnosticBuilder |
1300 | diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override { |
1301 | return S.Diag(Loc, DiagID: diag::err_acc_int_expr_multiple_conversions) << T; |
1302 | } |
1303 | |
1304 | SemaBase::SemaDiagnosticBuilder |
1305 | noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override { |
1306 | return S.Diag(Loc: Conv->getLocation(), DiagID: diag::note_acc_int_expr_conversion) |
1307 | << ConvTy->isEnumeralType() << ConvTy; |
1308 | } |
1309 | |
1310 | SemaBase::SemaDiagnosticBuilder |
1311 | diagnoseConversion(Sema &S, SourceLocation Loc, QualType T, |
1312 | QualType ConvTy) override { |
1313 | llvm_unreachable("conversion functions are permitted" ); |
1314 | } |
1315 | } IntExprDiagnoser(DK, CK, IntExpr); |
1316 | |
1317 | ExprResult IntExprResult = SemaRef.PerformContextualImplicitConversion( |
1318 | Loc, FromE: IntExpr, Converter&: IntExprDiagnoser); |
1319 | if (IntExprResult.isInvalid()) |
1320 | return ExprError(); |
1321 | |
1322 | IntExpr = IntExprResult.get(); |
1323 | if (!IntExpr->isTypeDependent() && !IntExpr->getType()->isIntegerType()) |
1324 | return ExprError(); |
1325 | |
1326 | // TODO OpenACC: Do we want to perform usual unary conversions here? When |
1327 | // doing codegen we might find that is necessary, but skip it for now. |
1328 | return IntExpr; |
1329 | } |
1330 | |
1331 | bool SemaOpenACC::CheckVarIsPointerType(OpenACCClauseKind ClauseKind, |
1332 | Expr *VarExpr) { |
1333 | // We already know that VarExpr is a proper reference to a variable, so we |
1334 | // should be able to just take the type of the expression to get the type of |
1335 | // the referenced variable. |
1336 | |
1337 | // We've already seen an error, don't diagnose anything else. |
1338 | if (!VarExpr || VarExpr->containsErrors()) |
1339 | return false; |
1340 | |
1341 | if (isa<ArraySectionExpr>(Val: VarExpr->IgnoreParenImpCasts()) || |
1342 | VarExpr->hasPlaceholderType(K: BuiltinType::ArraySection)) { |
1343 | Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_array_section_use) << /*OpenACC=*/0; |
1344 | Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::note_acc_expected_pointer_var); |
1345 | return true; |
1346 | } |
1347 | |
1348 | QualType Ty = VarExpr->getType(); |
1349 | Ty = Ty.getNonReferenceType().getUnqualifiedType(); |
1350 | |
1351 | // Nothing we can do if this is a dependent type. |
1352 | if (Ty->isDependentType()) |
1353 | return false; |
1354 | |
1355 | if (!Ty->isPointerType()) |
1356 | return Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_var_not_pointer_type) |
1357 | << ClauseKind << Ty; |
1358 | return false; |
1359 | } |
1360 | |
1361 | ExprResult SemaOpenACC::ActOnVar(OpenACCClauseKind CK, Expr *VarExpr) { |
1362 | Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts(); |
1363 | |
1364 | // Sub-arrays/subscript-exprs are fine as long as the base is a |
1365 | // VarExpr/MemberExpr. So strip all of those off. |
1366 | while (isa<ArraySectionExpr, ArraySubscriptExpr>(Val: CurVarExpr)) { |
1367 | if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(Val: CurVarExpr)) |
1368 | CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts(); |
1369 | else |
1370 | CurVarExpr = |
1371 | cast<ArraySectionExpr>(Val: CurVarExpr)->getBase()->IgnoreParenImpCasts(); |
1372 | } |
1373 | |
1374 | // References to a VarDecl are fine. |
1375 | if (const auto *DRE = dyn_cast<DeclRefExpr>(Val: CurVarExpr)) { |
1376 | if (isa<VarDecl, NonTypeTemplateParmDecl>( |
1377 | Val: DRE->getFoundDecl()->getCanonicalDecl())) |
1378 | return VarExpr; |
1379 | } |
1380 | |
1381 | // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a |
1382 | // reduction clause must be a scalar variable name, an aggregate variable |
1383 | // name, an array element, or a subarray. |
1384 | // A MemberExpr that references a Field is valid. |
1385 | if (CK != OpenACCClauseKind::Reduction) { |
1386 | if (const auto *ME = dyn_cast<MemberExpr>(Val: CurVarExpr)) { |
1387 | if (isa<FieldDecl>(Val: ME->getMemberDecl()->getCanonicalDecl())) |
1388 | return VarExpr; |
1389 | } |
1390 | } |
1391 | |
1392 | // Referring to 'this' is always OK. |
1393 | if (isa<CXXThisExpr>(Val: CurVarExpr)) |
1394 | return VarExpr; |
1395 | |
1396 | // Nothing really we can do here, as these are dependent. So just return they |
1397 | // are valid. |
1398 | if (isa<DependentScopeDeclRefExpr>(Val: CurVarExpr) || |
1399 | (CK != OpenACCClauseKind::Reduction && |
1400 | isa<CXXDependentScopeMemberExpr>(Val: CurVarExpr))) |
1401 | return VarExpr; |
1402 | |
1403 | // There isn't really anything we can do in the case of a recovery expr, so |
1404 | // skip the diagnostic rather than produce a confusing diagnostic. |
1405 | if (isa<RecoveryExpr>(Val: CurVarExpr)) |
1406 | return ExprError(); |
1407 | |
1408 | Diag(Loc: VarExpr->getExprLoc(), DiagID: diag::err_acc_not_a_var_ref) |
1409 | << (CK != OpenACCClauseKind::Reduction); |
1410 | return ExprError(); |
1411 | } |
1412 | |
1413 | ExprResult SemaOpenACC::ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc, |
1414 | Expr *LowerBound, |
1415 | SourceLocation ColonLoc, |
1416 | Expr *Length, |
1417 | SourceLocation RBLoc) { |
1418 | ASTContext &Context = getASTContext(); |
1419 | |
1420 | // Handle placeholders. |
1421 | if (Base->hasPlaceholderType() && |
1422 | !Base->hasPlaceholderType(K: BuiltinType::ArraySection)) { |
1423 | ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Base); |
1424 | if (Result.isInvalid()) |
1425 | return ExprError(); |
1426 | Base = Result.get(); |
1427 | } |
1428 | if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) { |
1429 | ExprResult Result = SemaRef.CheckPlaceholderExpr(E: LowerBound); |
1430 | if (Result.isInvalid()) |
1431 | return ExprError(); |
1432 | Result = SemaRef.DefaultLvalueConversion(E: Result.get()); |
1433 | if (Result.isInvalid()) |
1434 | return ExprError(); |
1435 | LowerBound = Result.get(); |
1436 | } |
1437 | if (Length && Length->getType()->isNonOverloadPlaceholderType()) { |
1438 | ExprResult Result = SemaRef.CheckPlaceholderExpr(E: Length); |
1439 | if (Result.isInvalid()) |
1440 | return ExprError(); |
1441 | Result = SemaRef.DefaultLvalueConversion(E: Result.get()); |
1442 | if (Result.isInvalid()) |
1443 | return ExprError(); |
1444 | Length = Result.get(); |
1445 | } |
1446 | |
1447 | // Check the 'base' value, it must be an array or pointer type, and not to/of |
1448 | // a function type. |
1449 | QualType OriginalBaseTy = ArraySectionExpr::getBaseOriginalType(Base); |
1450 | QualType ResultTy; |
1451 | if (!Base->isTypeDependent()) { |
1452 | if (OriginalBaseTy->isAnyPointerType()) { |
1453 | ResultTy = OriginalBaseTy->getPointeeType(); |
1454 | } else if (OriginalBaseTy->isArrayType()) { |
1455 | ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType(); |
1456 | } else { |
1457 | return ExprError( |
1458 | Diag(Loc: Base->getExprLoc(), DiagID: diag::err_acc_typecheck_subarray_value) |
1459 | << Base->getSourceRange()); |
1460 | } |
1461 | |
1462 | if (ResultTy->isFunctionType()) { |
1463 | Diag(Loc: Base->getExprLoc(), DiagID: diag::err_acc_subarray_function_type) |
1464 | << ResultTy << Base->getSourceRange(); |
1465 | return ExprError(); |
1466 | } |
1467 | |
1468 | if (SemaRef.RequireCompleteType(Loc: Base->getExprLoc(), T: ResultTy, |
1469 | DiagID: diag::err_acc_subarray_incomplete_type, |
1470 | Args: Base)) |
1471 | return ExprError(); |
1472 | |
1473 | if (!Base->hasPlaceholderType(K: BuiltinType::ArraySection)) { |
1474 | ExprResult Result = SemaRef.DefaultFunctionArrayLvalueConversion(E: Base); |
1475 | if (Result.isInvalid()) |
1476 | return ExprError(); |
1477 | Base = Result.get(); |
1478 | } |
1479 | } |
1480 | |
1481 | auto GetRecovery = [&](Expr *E, QualType Ty) { |
1482 | ExprResult Recovery = |
1483 | SemaRef.CreateRecoveryExpr(Begin: E->getBeginLoc(), End: E->getEndLoc(), SubExprs: E, T: Ty); |
1484 | return Recovery.isUsable() ? Recovery.get() : nullptr; |
1485 | }; |
1486 | |
1487 | // Ensure both of the expressions are int-exprs. |
1488 | if (LowerBound && !LowerBound->isTypeDependent()) { |
1489 | ExprResult LBRes = |
1490 | ActOnIntExpr(DK: OpenACCDirectiveKind::Invalid, CK: OpenACCClauseKind::Invalid, |
1491 | Loc: LowerBound->getExprLoc(), IntExpr: LowerBound); |
1492 | |
1493 | if (LBRes.isUsable()) |
1494 | LBRes = SemaRef.DefaultLvalueConversion(E: LBRes.get()); |
1495 | LowerBound = |
1496 | LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy); |
1497 | } |
1498 | |
1499 | if (Length && !Length->isTypeDependent()) { |
1500 | ExprResult LenRes = |
1501 | ActOnIntExpr(DK: OpenACCDirectiveKind::Invalid, CK: OpenACCClauseKind::Invalid, |
1502 | Loc: Length->getExprLoc(), IntExpr: Length); |
1503 | |
1504 | if (LenRes.isUsable()) |
1505 | LenRes = SemaRef.DefaultLvalueConversion(E: LenRes.get()); |
1506 | Length = |
1507 | LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy); |
1508 | } |
1509 | |
1510 | // Length is required if the base type is not an array of known bounds. |
1511 | if (!Length && (OriginalBaseTy.isNull() || |
1512 | (!OriginalBaseTy->isDependentType() && |
1513 | !OriginalBaseTy->isConstantArrayType() && |
1514 | !OriginalBaseTy->isDependentSizedArrayType()))) { |
1515 | bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType(); |
1516 | Diag(Loc: ColonLoc, DiagID: diag::err_acc_subarray_no_length) << IsArray; |
1517 | // Fill in a dummy 'length' so that when we instantiate this we don't |
1518 | // double-diagnose here. |
1519 | ExprResult Recovery = SemaRef.CreateRecoveryExpr( |
1520 | Begin: ColonLoc, End: SourceLocation(), SubExprs: ArrayRef<Expr *>{std::nullopt}, |
1521 | T: Context.IntTy); |
1522 | Length = Recovery.isUsable() ? Recovery.get() : nullptr; |
1523 | } |
1524 | |
1525 | // Check the values of each of the arguments, they cannot be negative(we |
1526 | // assume), and if the array bound is known, must be within range. As we do |
1527 | // so, do our best to continue with evaluation, we can set the |
1528 | // value/expression to nullptr/nullopt if they are invalid, and treat them as |
1529 | // not present for the rest of evaluation. |
1530 | |
1531 | // We don't have to check for dependence, because the dependent size is |
1532 | // represented as a different AST node. |
1533 | std::optional<llvm::APSInt> BaseSize; |
1534 | if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) { |
1535 | const auto *ArrayTy = Context.getAsConstantArrayType(T: OriginalBaseTy); |
1536 | BaseSize = ArrayTy->getSize(); |
1537 | } |
1538 | |
1539 | auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> { |
1540 | if (!E || E->isInstantiationDependent()) |
1541 | return std::nullopt; |
1542 | |
1543 | Expr::EvalResult Res; |
1544 | if (!E->EvaluateAsInt(Result&: Res, Ctx: Context)) |
1545 | return std::nullopt; |
1546 | return Res.Val.getInt(); |
1547 | }; |
1548 | |
1549 | std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound); |
1550 | std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length); |
1551 | |
1552 | // Check lower bound for negative or out of range. |
1553 | if (LowerBoundValue.has_value()) { |
1554 | if (LowerBoundValue->isNegative()) { |
1555 | Diag(Loc: LowerBound->getExprLoc(), DiagID: diag::err_acc_subarray_negative) |
1556 | << /*LowerBound=*/0 << toString(I: *LowerBoundValue, /*Radix=*/10); |
1557 | LowerBoundValue.reset(); |
1558 | LowerBound = GetRecovery(LowerBound, LowerBound->getType()); |
1559 | } else if (BaseSize.has_value() && |
1560 | llvm::APSInt::compareValues(I1: *LowerBoundValue, I2: *BaseSize) >= 0) { |
1561 | // Lower bound (start index) must be less than the size of the array. |
1562 | Diag(Loc: LowerBound->getExprLoc(), DiagID: diag::err_acc_subarray_out_of_range) |
1563 | << /*LowerBound=*/0 << toString(I: *LowerBoundValue, /*Radix=*/10) |
1564 | << toString(I: *BaseSize, /*Radix=*/10); |
1565 | LowerBoundValue.reset(); |
1566 | LowerBound = GetRecovery(LowerBound, LowerBound->getType()); |
1567 | } |
1568 | } |
1569 | |
1570 | // Check length for negative or out of range. |
1571 | if (LengthValue.has_value()) { |
1572 | if (LengthValue->isNegative()) { |
1573 | Diag(Loc: Length->getExprLoc(), DiagID: diag::err_acc_subarray_negative) |
1574 | << /*Length=*/1 << toString(I: *LengthValue, /*Radix=*/10); |
1575 | LengthValue.reset(); |
1576 | Length = GetRecovery(Length, Length->getType()); |
1577 | } else if (BaseSize.has_value() && |
1578 | llvm::APSInt::compareValues(I1: *LengthValue, I2: *BaseSize) > 0) { |
1579 | // Length must be lessthan or EQUAL to the size of the array. |
1580 | Diag(Loc: Length->getExprLoc(), DiagID: diag::err_acc_subarray_out_of_range) |
1581 | << /*Length=*/1 << toString(I: *LengthValue, /*Radix=*/10) |
1582 | << toString(I: *BaseSize, /*Radix=*/10); |
1583 | LengthValue.reset(); |
1584 | Length = GetRecovery(Length, Length->getType()); |
1585 | } |
1586 | } |
1587 | |
1588 | // Adding two APSInts requires matching sign, so extract that here. |
1589 | auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt { |
1590 | if (LHS.isSigned() == RHS.isSigned()) |
1591 | return LHS + RHS; |
1592 | |
1593 | unsigned Width = std::max(a: LHS.getBitWidth(), b: RHS.getBitWidth()) + 1; |
1594 | return llvm::APSInt(LHS.sext(width: Width) + RHS.sext(width: Width), /*Signed=*/true); |
1595 | }; |
1596 | |
1597 | // If we know all 3 values, we can diagnose that the total value would be out |
1598 | // of range. |
1599 | if (BaseSize.has_value() && LowerBoundValue.has_value() && |
1600 | LengthValue.has_value() && |
1601 | llvm::APSInt::compareValues(I1: AddAPSInt(*LowerBoundValue, *LengthValue), |
1602 | I2: *BaseSize) > 0) { |
1603 | Diag(Loc: Base->getExprLoc(), |
1604 | DiagID: diag::err_acc_subarray_base_plus_length_out_of_range) |
1605 | << toString(I: *LowerBoundValue, /*Radix=*/10) |
1606 | << toString(I: *LengthValue, /*Radix=*/10) |
1607 | << toString(I: *BaseSize, /*Radix=*/10); |
1608 | |
1609 | LowerBoundValue.reset(); |
1610 | LowerBound = GetRecovery(LowerBound, LowerBound->getType()); |
1611 | LengthValue.reset(); |
1612 | Length = GetRecovery(Length, Length->getType()); |
1613 | } |
1614 | |
1615 | // If any part of the expression is dependent, return a dependent sub-array. |
1616 | QualType ArrayExprTy = Context.ArraySectionTy; |
1617 | if (Base->isTypeDependent() || |
1618 | (LowerBound && LowerBound->isInstantiationDependent()) || |
1619 | (Length && Length->isInstantiationDependent())) |
1620 | ArrayExprTy = Context.DependentTy; |
1621 | |
1622 | return new (Context) |
1623 | ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue, |
1624 | OK_Ordinary, ColonLoc, RBLoc); |
1625 | } |
1626 | |
1627 | bool SemaOpenACC::ActOnStartStmtDirective(OpenACCDirectiveKind K, |
1628 | SourceLocation StartLoc) { |
1629 | return diagnoseConstructAppertainment(S&: *this, K, StartLoc, /*IsStmt=*/true); |
1630 | } |
1631 | |
1632 | StmtResult SemaOpenACC::ActOnEndStmtDirective(OpenACCDirectiveKind K, |
1633 | SourceLocation StartLoc, |
1634 | SourceLocation DirLoc, |
1635 | SourceLocation EndLoc, |
1636 | ArrayRef<OpenACCClause *> Clauses, |
1637 | StmtResult AssocStmt) { |
1638 | switch (K) { |
1639 | default: |
1640 | return StmtEmpty(); |
1641 | case OpenACCDirectiveKind::Invalid: |
1642 | return StmtError(); |
1643 | case OpenACCDirectiveKind::Parallel: |
1644 | case OpenACCDirectiveKind::Serial: |
1645 | case OpenACCDirectiveKind::Kernels: { |
1646 | auto *ComputeConstruct = OpenACCComputeConstruct::Create( |
1647 | C: getASTContext(), K, BeginLoc: StartLoc, DirectiveLoc: DirLoc, EndLoc, Clauses, |
1648 | StructuredBlock: AssocStmt.isUsable() ? AssocStmt.get() : nullptr, |
1649 | AssociatedLoopConstructs: ParentlessLoopConstructs); |
1650 | |
1651 | ParentlessLoopConstructs.clear(); |
1652 | return ComputeConstruct; |
1653 | } |
1654 | case OpenACCDirectiveKind::Loop: { |
1655 | auto *LoopConstruct = OpenACCLoopConstruct::Create( |
1656 | C: getASTContext(), BeginLoc: StartLoc, DirLoc, EndLoc, Clauses, |
1657 | Loop: AssocStmt.isUsable() ? AssocStmt.get() : nullptr); |
1658 | |
1659 | // If we are in the scope of a compute construct, add this to the list of |
1660 | // loop constructs that need assigning to the next closing compute |
1661 | // construct. |
1662 | if (InsideComputeConstruct) |
1663 | ParentlessLoopConstructs.push_back(Elt: LoopConstruct); |
1664 | |
1665 | return LoopConstruct; |
1666 | } |
1667 | } |
1668 | llvm_unreachable("Unhandled case in directive handling?" ); |
1669 | } |
1670 | |
1671 | StmtResult SemaOpenACC::ActOnAssociatedStmt(SourceLocation DirectiveLoc, |
1672 | OpenACCDirectiveKind K, |
1673 | StmtResult AssocStmt) { |
1674 | switch (K) { |
1675 | default: |
1676 | llvm_unreachable("Unimplemented associated statement application" ); |
1677 | case OpenACCDirectiveKind::Parallel: |
1678 | case OpenACCDirectiveKind::Serial: |
1679 | case OpenACCDirectiveKind::Kernels: |
1680 | // There really isn't any checking here that could happen. As long as we |
1681 | // have a statement to associate, this should be fine. |
1682 | // OpenACC 3.3 Section 6: |
1683 | // Structured Block: in C or C++, an executable statement, possibly |
1684 | // compound, with a single entry at the top and a single exit at the |
1685 | // bottom. |
1686 | // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and |
1687 | // an interpretation of it is to allow this and treat the initializer as |
1688 | // the 'structured block'. |
1689 | return AssocStmt; |
1690 | case OpenACCDirectiveKind::Loop: |
1691 | if (AssocStmt.isUsable() && |
1692 | !isa<CXXForRangeStmt, ForStmt>(Val: AssocStmt.get())) { |
1693 | Diag(Loc: AssocStmt.get()->getBeginLoc(), DiagID: diag::err_acc_loop_not_for_loop); |
1694 | Diag(Loc: DirectiveLoc, DiagID: diag::note_acc_construct_here) << K; |
1695 | return StmtError(); |
1696 | } |
1697 | // TODO OpenACC: 2.9 ~ line 2010 specifies that the associated loop has some |
1698 | // restrictions when there is a 'seq' clause in place. We probably need to |
1699 | // implement that, including piping in the clauses here. |
1700 | return AssocStmt; |
1701 | } |
1702 | llvm_unreachable("Invalid associated statement application" ); |
1703 | } |
1704 | |
1705 | bool SemaOpenACC::ActOnStartDeclDirective(OpenACCDirectiveKind K, |
1706 | SourceLocation StartLoc) { |
1707 | return diagnoseConstructAppertainment(S&: *this, K, StartLoc, /*IsStmt=*/false); |
1708 | } |
1709 | |
1710 | DeclGroupRef SemaOpenACC::ActOnEndDeclDirective() { return DeclGroupRef{}; } |
1711 | |