clang 20.0.0git
SemaOpenACC.cpp
Go to the documentation of this file.
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
18#include "clang/Sema/Sema.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Support/Casting.h"
21
22using namespace clang;
23
24namespace {
25bool 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::ParallelLoop:
34 case OpenACCDirectiveKind::SerialLoop:
35 case OpenACCDirectiveKind::KernelsLoop:
36 case OpenACCDirectiveKind::Parallel:
37 case OpenACCDirectiveKind::Serial:
38 case OpenACCDirectiveKind::Kernels:
39 case OpenACCDirectiveKind::Loop:
40 case OpenACCDirectiveKind::Data:
41 case OpenACCDirectiveKind::EnterData:
42 case OpenACCDirectiveKind::ExitData:
43 case OpenACCDirectiveKind::HostData:
44 case OpenACCDirectiveKind::Wait:
45 if (!IsStmt)
46 return S.Diag(StartLoc, diag::err_acc_construct_appertainment) << K;
47 break;
48 }
49 return false;
50}
51
52bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
53 OpenACCClauseKind ClauseKind) {
54 switch (ClauseKind) {
55 // FIXME: For each clause as we implement them, we can add the
56 // 'legalization' list here.
57 case OpenACCClauseKind::Default:
58 switch (DirectiveKind) {
59 case OpenACCDirectiveKind::Parallel:
60 case OpenACCDirectiveKind::Serial:
61 case OpenACCDirectiveKind::Kernels:
62 case OpenACCDirectiveKind::ParallelLoop:
63 case OpenACCDirectiveKind::SerialLoop:
64 case OpenACCDirectiveKind::KernelsLoop:
65 case OpenACCDirectiveKind::Data:
66 return true;
67 default:
68 return false;
69 }
70 case OpenACCClauseKind::If:
71 switch (DirectiveKind) {
72 case OpenACCDirectiveKind::Parallel:
73 case OpenACCDirectiveKind::Serial:
74 case OpenACCDirectiveKind::Kernels:
75 case OpenACCDirectiveKind::Data:
76 case OpenACCDirectiveKind::EnterData:
77 case OpenACCDirectiveKind::ExitData:
78 case OpenACCDirectiveKind::HostData:
79 case OpenACCDirectiveKind::Init:
80 case OpenACCDirectiveKind::Shutdown:
81 case OpenACCDirectiveKind::Set:
82 case OpenACCDirectiveKind::Update:
83 case OpenACCDirectiveKind::Wait:
84 case OpenACCDirectiveKind::ParallelLoop:
85 case OpenACCDirectiveKind::SerialLoop:
86 case OpenACCDirectiveKind::KernelsLoop:
87 return true;
88 default:
89 return false;
90 }
91 case OpenACCClauseKind::Self:
92 switch (DirectiveKind) {
93 case OpenACCDirectiveKind::Parallel:
94 case OpenACCDirectiveKind::Serial:
95 case OpenACCDirectiveKind::Kernels:
96 case OpenACCDirectiveKind::Update:
97 case OpenACCDirectiveKind::ParallelLoop:
98 case OpenACCDirectiveKind::SerialLoop:
99 case OpenACCDirectiveKind::KernelsLoop:
100 return true;
101 default:
102 return false;
103 }
104 case OpenACCClauseKind::NumGangs:
105 case OpenACCClauseKind::NumWorkers:
106 case OpenACCClauseKind::VectorLength:
107 switch (DirectiveKind) {
108 case OpenACCDirectiveKind::Parallel:
109 case OpenACCDirectiveKind::Kernels:
110 case OpenACCDirectiveKind::ParallelLoop:
111 case OpenACCDirectiveKind::KernelsLoop:
112 return true;
113 default:
114 return false;
115 }
116 case OpenACCClauseKind::FirstPrivate:
117 switch (DirectiveKind) {
118 case OpenACCDirectiveKind::Parallel:
119 case OpenACCDirectiveKind::Serial:
120 case OpenACCDirectiveKind::ParallelLoop:
121 case OpenACCDirectiveKind::SerialLoop:
122 return true;
123 default:
124 return false;
125 }
126 case OpenACCClauseKind::Private:
127 switch (DirectiveKind) {
128 case OpenACCDirectiveKind::Parallel:
129 case OpenACCDirectiveKind::Serial:
130 case OpenACCDirectiveKind::Loop:
131 case OpenACCDirectiveKind::ParallelLoop:
132 case OpenACCDirectiveKind::SerialLoop:
133 case OpenACCDirectiveKind::KernelsLoop:
134 return true;
135 default:
136 return false;
137 }
138 case OpenACCClauseKind::NoCreate:
139 switch (DirectiveKind) {
140 case OpenACCDirectiveKind::Parallel:
141 case OpenACCDirectiveKind::Serial:
142 case OpenACCDirectiveKind::Kernels:
143 case OpenACCDirectiveKind::Data:
144 case OpenACCDirectiveKind::ParallelLoop:
145 case OpenACCDirectiveKind::SerialLoop:
146 case OpenACCDirectiveKind::KernelsLoop:
147 return true;
148 default:
149 return false;
150 }
151 case OpenACCClauseKind::Present:
152 switch (DirectiveKind) {
153 case OpenACCDirectiveKind::Parallel:
154 case OpenACCDirectiveKind::Serial:
155 case OpenACCDirectiveKind::Kernels:
156 case OpenACCDirectiveKind::Data:
157 case OpenACCDirectiveKind::Declare:
158 case OpenACCDirectiveKind::ParallelLoop:
159 case OpenACCDirectiveKind::SerialLoop:
160 case OpenACCDirectiveKind::KernelsLoop:
161 return true;
162 default:
163 return false;
164 }
165
166 case OpenACCClauseKind::Copy:
167 case OpenACCClauseKind::PCopy:
168 case OpenACCClauseKind::PresentOrCopy:
169 switch (DirectiveKind) {
170 case OpenACCDirectiveKind::Parallel:
171 case OpenACCDirectiveKind::Serial:
172 case OpenACCDirectiveKind::Kernels:
173 case OpenACCDirectiveKind::Data:
174 case OpenACCDirectiveKind::Declare:
175 case OpenACCDirectiveKind::ParallelLoop:
176 case OpenACCDirectiveKind::SerialLoop:
177 case OpenACCDirectiveKind::KernelsLoop:
178 return true;
179 default:
180 return false;
181 }
182 case OpenACCClauseKind::CopyIn:
183 case OpenACCClauseKind::PCopyIn:
184 case OpenACCClauseKind::PresentOrCopyIn:
185 switch (DirectiveKind) {
186 case OpenACCDirectiveKind::Parallel:
187 case OpenACCDirectiveKind::Serial:
188 case OpenACCDirectiveKind::Kernels:
189 case OpenACCDirectiveKind::Data:
190 case OpenACCDirectiveKind::EnterData:
191 case OpenACCDirectiveKind::Declare:
192 case OpenACCDirectiveKind::ParallelLoop:
193 case OpenACCDirectiveKind::SerialLoop:
194 case OpenACCDirectiveKind::KernelsLoop:
195 return true;
196 default:
197 return false;
198 }
199 case OpenACCClauseKind::CopyOut:
200 case OpenACCClauseKind::PCopyOut:
201 case OpenACCClauseKind::PresentOrCopyOut:
202 switch (DirectiveKind) {
203 case OpenACCDirectiveKind::Parallel:
204 case OpenACCDirectiveKind::Serial:
205 case OpenACCDirectiveKind::Kernels:
206 case OpenACCDirectiveKind::Data:
207 case OpenACCDirectiveKind::ExitData:
208 case OpenACCDirectiveKind::Declare:
209 case OpenACCDirectiveKind::ParallelLoop:
210 case OpenACCDirectiveKind::SerialLoop:
211 case OpenACCDirectiveKind::KernelsLoop:
212 return true;
213 default:
214 return false;
215 }
216 case OpenACCClauseKind::Create:
217 case OpenACCClauseKind::PCreate:
218 case OpenACCClauseKind::PresentOrCreate:
219 switch (DirectiveKind) {
220 case OpenACCDirectiveKind::Parallel:
221 case OpenACCDirectiveKind::Serial:
222 case OpenACCDirectiveKind::Kernels:
223 case OpenACCDirectiveKind::Data:
224 case OpenACCDirectiveKind::EnterData:
225 case OpenACCDirectiveKind::ParallelLoop:
226 case OpenACCDirectiveKind::SerialLoop:
227 case OpenACCDirectiveKind::KernelsLoop:
228 return true;
229 default:
230 return false;
231 }
232
233 case OpenACCClauseKind::Attach:
234 switch (DirectiveKind) {
235 case OpenACCDirectiveKind::Parallel:
236 case OpenACCDirectiveKind::Serial:
237 case OpenACCDirectiveKind::Kernels:
238 case OpenACCDirectiveKind::Data:
239 case OpenACCDirectiveKind::EnterData:
240 case OpenACCDirectiveKind::ParallelLoop:
241 case OpenACCDirectiveKind::SerialLoop:
242 case OpenACCDirectiveKind::KernelsLoop:
243 return true;
244 default:
245 return false;
246 }
247 case OpenACCClauseKind::DevicePtr:
248 switch (DirectiveKind) {
249 case OpenACCDirectiveKind::Parallel:
250 case OpenACCDirectiveKind::Serial:
251 case OpenACCDirectiveKind::Kernels:
252 case OpenACCDirectiveKind::Data:
253 case OpenACCDirectiveKind::Declare:
254 case OpenACCDirectiveKind::ParallelLoop:
255 case OpenACCDirectiveKind::SerialLoop:
256 case OpenACCDirectiveKind::KernelsLoop:
257 return true;
258 default:
259 return false;
260 }
261 case OpenACCClauseKind::Async:
262 switch (DirectiveKind) {
263 case OpenACCDirectiveKind::Parallel:
264 case OpenACCDirectiveKind::Serial:
265 case OpenACCDirectiveKind::Kernels:
266 case OpenACCDirectiveKind::Data:
267 case OpenACCDirectiveKind::EnterData:
268 case OpenACCDirectiveKind::ExitData:
269 case OpenACCDirectiveKind::Set:
270 case OpenACCDirectiveKind::Update:
271 case OpenACCDirectiveKind::Wait:
272 case OpenACCDirectiveKind::ParallelLoop:
273 case OpenACCDirectiveKind::SerialLoop:
274 case OpenACCDirectiveKind::KernelsLoop:
275 return true;
276 default:
277 return false;
278 }
279 case OpenACCClauseKind::Wait:
280 switch (DirectiveKind) {
281 case OpenACCDirectiveKind::Parallel:
282 case OpenACCDirectiveKind::Serial:
283 case OpenACCDirectiveKind::Kernels:
284 case OpenACCDirectiveKind::Data:
285 case OpenACCDirectiveKind::EnterData:
286 case OpenACCDirectiveKind::ExitData:
287 case OpenACCDirectiveKind::Update:
288 case OpenACCDirectiveKind::ParallelLoop:
289 case OpenACCDirectiveKind::SerialLoop:
290 case OpenACCDirectiveKind::KernelsLoop:
291 return true;
292 default:
293 return false;
294 }
295
296 case OpenACCClauseKind::Seq:
297 switch (DirectiveKind) {
298 case OpenACCDirectiveKind::Loop:
299 case OpenACCDirectiveKind::Routine:
300 case OpenACCDirectiveKind::ParallelLoop:
301 case OpenACCDirectiveKind::SerialLoop:
302 case OpenACCDirectiveKind::KernelsLoop:
303 return true;
304 default:
305 return false;
306 }
307
308 case OpenACCClauseKind::Independent:
309 case OpenACCClauseKind::Auto:
310 switch (DirectiveKind) {
311 case OpenACCDirectiveKind::Loop:
312 case OpenACCDirectiveKind::ParallelLoop:
313 case OpenACCDirectiveKind::SerialLoop:
314 case OpenACCDirectiveKind::KernelsLoop:
315 return true;
316 default:
317 return false;
318 }
319
320 case OpenACCClauseKind::Reduction:
321 switch (DirectiveKind) {
322 case OpenACCDirectiveKind::Parallel:
323 case OpenACCDirectiveKind::Serial:
324 case OpenACCDirectiveKind::Loop:
325 case OpenACCDirectiveKind::ParallelLoop:
326 case OpenACCDirectiveKind::SerialLoop:
327 case OpenACCDirectiveKind::KernelsLoop:
328 return true;
329 default:
330 return false;
331 }
332
333 case OpenACCClauseKind::DeviceType:
334 case OpenACCClauseKind::DType:
335 switch (DirectiveKind) {
336 case OpenACCDirectiveKind::Parallel:
337 case OpenACCDirectiveKind::Serial:
338 case OpenACCDirectiveKind::Kernels:
339 case OpenACCDirectiveKind::Data:
340 case OpenACCDirectiveKind::Init:
341 case OpenACCDirectiveKind::Shutdown:
342 case OpenACCDirectiveKind::Set:
343 case OpenACCDirectiveKind::Update:
344 case OpenACCDirectiveKind::Loop:
345 case OpenACCDirectiveKind::Routine:
346 case OpenACCDirectiveKind::ParallelLoop:
347 case OpenACCDirectiveKind::SerialLoop:
348 case OpenACCDirectiveKind::KernelsLoop:
349 return true;
350 default:
351 return false;
352 }
353
354 case OpenACCClauseKind::Collapse: {
355 switch (DirectiveKind) {
356 case OpenACCDirectiveKind::Loop:
357 case OpenACCDirectiveKind::ParallelLoop:
358 case OpenACCDirectiveKind::SerialLoop:
359 case OpenACCDirectiveKind::KernelsLoop:
360 return true;
361 default:
362 return false;
363 }
364 }
365 case OpenACCClauseKind::Tile: {
366 switch (DirectiveKind) {
367 case OpenACCDirectiveKind::Loop:
368 case OpenACCDirectiveKind::ParallelLoop:
369 case OpenACCDirectiveKind::SerialLoop:
370 case OpenACCDirectiveKind::KernelsLoop:
371 return true;
372 default:
373 return false;
374 }
375 }
376
377 case OpenACCClauseKind::Gang: {
378 switch (DirectiveKind) {
379 case OpenACCDirectiveKind::Loop:
380 case OpenACCDirectiveKind::ParallelLoop:
381 case OpenACCDirectiveKind::SerialLoop:
382 case OpenACCDirectiveKind::KernelsLoop:
383 case OpenACCDirectiveKind::Routine:
384 return true;
385 default:
386 return false;
387 }
388 case OpenACCClauseKind::Worker: {
389 switch (DirectiveKind) {
390 case OpenACCDirectiveKind::Loop:
391 case OpenACCDirectiveKind::ParallelLoop:
392 case OpenACCDirectiveKind::SerialLoop:
393 case OpenACCDirectiveKind::KernelsLoop:
394 case OpenACCDirectiveKind::Routine:
395 return true;
396 default:
397 return false;
398 }
399 }
400 case OpenACCClauseKind::Vector: {
401 switch (DirectiveKind) {
402 case OpenACCDirectiveKind::Loop:
403 case OpenACCDirectiveKind::ParallelLoop:
404 case OpenACCDirectiveKind::SerialLoop:
405 case OpenACCDirectiveKind::KernelsLoop:
406 case OpenACCDirectiveKind::Routine:
407 return true;
408 default:
409 return false;
410 }
411 }
412 case OpenACCClauseKind::Finalize: {
413 switch (DirectiveKind) {
414 case OpenACCDirectiveKind::ExitData:
415 return true;
416 default:
417 return false;
418 }
419 }
420 case OpenACCClauseKind::IfPresent: {
421 switch (DirectiveKind) {
422 case OpenACCDirectiveKind::HostData:
423 case OpenACCDirectiveKind::Update:
424 return true;
425 default:
426 return false;
427 }
428 }
429 case OpenACCClauseKind::Delete: {
430 switch (DirectiveKind) {
431 case OpenACCDirectiveKind::ExitData:
432 return true;
433 default:
434 return false;
435 }
436 }
437
438 case OpenACCClauseKind::Detach: {
439 switch (DirectiveKind) {
440 case OpenACCDirectiveKind::ExitData:
441 return true;
442 default:
443 return false;
444 }
445 }
446
447 case OpenACCClauseKind::DeviceNum: {
448 switch (DirectiveKind) {
449 case OpenACCDirectiveKind::Init:
450 case OpenACCDirectiveKind::Shutdown:
451 case OpenACCDirectiveKind::Set:
452 return true;
453 default:
454 return false;
455 }
456 }
457
458 case OpenACCClauseKind::UseDevice: {
459 switch (DirectiveKind) {
460 case OpenACCDirectiveKind::HostData:
461 return true;
462 default:
463 return false;
464 }
465 }
466 case OpenACCClauseKind::DefaultAsync: {
467 switch (DirectiveKind) {
468 case OpenACCDirectiveKind::Set:
469 return true;
470 default:
471 return false;
472 }
473 }
474 }
475
476 default:
477 // Do nothing so we can go to the 'unimplemented' diagnostic instead.
478 return true;
479 }
480 llvm_unreachable("Invalid clause kind");
481}
482
483bool checkAlreadyHasClauseOfKind(
486 const auto *Itr = llvm::find_if(ExistingClauses, [&](const OpenACCClause *C) {
487 return C->getClauseKind() == Clause.getClauseKind();
488 });
489 if (Itr != ExistingClauses.end()) {
490 S.Diag(Clause.getBeginLoc(), diag::err_acc_duplicate_clause_disallowed)
491 << Clause.getDirectiveKind() << Clause.getClauseKind();
492 S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
493 return true;
494 }
495 return false;
496}
497
498bool checkValidAfterDeviceType(
499 SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause,
500 const SemaOpenACC::OpenACCParsedClause &NewClause) {
501 // This is only a requirement on compute, combined, data and loop constructs
502 // so far, so this is fine otherwise.
503 if (!isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind()) &&
504 !isOpenACCCombinedDirectiveKind(NewClause.getDirectiveKind()) &&
505 NewClause.getDirectiveKind() != OpenACCDirectiveKind::Loop &&
506 NewClause.getDirectiveKind() != OpenACCDirectiveKind::Data)
507 return false;
508
509 // OpenACC3.3: Section 2.4: Clauses that precede any device_type clause are
510 // default clauses. Clauses that follow a device_type clause up to the end of
511 // the directive or up to the next device_type clause are device-specific
512 // clauses for the device types specified in the device_type argument.
513 //
514 // The above implies that despite what the individual text says, these are
515 // valid.
516 if (NewClause.getClauseKind() == OpenACCClauseKind::DType ||
517 NewClause.getClauseKind() == OpenACCClauseKind::DeviceType)
518 return false;
519
520 // Implement check from OpenACC3.3: section 2.5.4:
521 // Only the async, wait, num_gangs, num_workers, and vector_length clauses may
522 // follow a device_type clause.
523 if (isOpenACCComputeDirectiveKind(NewClause.getDirectiveKind())) {
524 switch (NewClause.getClauseKind()) {
525 case OpenACCClauseKind::Async:
526 case OpenACCClauseKind::Wait:
527 case OpenACCClauseKind::NumGangs:
528 case OpenACCClauseKind::NumWorkers:
529 case OpenACCClauseKind::VectorLength:
530 return false;
531 default:
532 break;
533 }
534 } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
535 // Implement check from OpenACC3.3: section 2.9:
536 // Only the collapse, gang, worker, vector, seq, independent, auto, and tile
537 // clauses may follow a device_type clause.
538 switch (NewClause.getClauseKind()) {
539 case OpenACCClauseKind::Collapse:
540 case OpenACCClauseKind::Gang:
541 case OpenACCClauseKind::Worker:
542 case OpenACCClauseKind::Vector:
543 case OpenACCClauseKind::Seq:
544 case OpenACCClauseKind::Independent:
545 case OpenACCClauseKind::Auto:
546 case OpenACCClauseKind::Tile:
547 return false;
548 default:
549 break;
550 }
551 } else if (isOpenACCCombinedDirectiveKind(NewClause.getDirectiveKind())) {
552 // This seems like it should be the union of 2.9 and 2.5.4 from above.
553 switch (NewClause.getClauseKind()) {
554 case OpenACCClauseKind::Async:
555 case OpenACCClauseKind::Wait:
556 case OpenACCClauseKind::NumGangs:
557 case OpenACCClauseKind::NumWorkers:
558 case OpenACCClauseKind::VectorLength:
559 case OpenACCClauseKind::Collapse:
560 case OpenACCClauseKind::Gang:
561 case OpenACCClauseKind::Worker:
562 case OpenACCClauseKind::Vector:
563 case OpenACCClauseKind::Seq:
564 case OpenACCClauseKind::Independent:
565 case OpenACCClauseKind::Auto:
566 case OpenACCClauseKind::Tile:
567 return false;
568 default:
569 break;
570 }
571 } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Data) {
572 // OpenACC3.3 section 2.6.5: Only the async and wait clauses may follow a
573 // device_type clause.
574 switch (NewClause.getClauseKind()) {
575 case OpenACCClauseKind::Async:
576 case OpenACCClauseKind::Wait:
577 return false;
578 default:
579 break;
580 }
581 }
582 S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type)
583 << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind()
584 << NewClause.getDirectiveKind();
585 S.Diag(DeviceTypeClause.getBeginLoc(), diag::note_acc_previous_clause_here);
586 return true;
587}
588
589// A temporary function that helps implement the 'not implemented' check at the
590// top of each clause checking function. This should only be used in conjunction
591// with the one being currently implemented/only updated after the entire
592// construct has been implemented.
593bool isDirectiveKindImplemented(OpenACCDirectiveKind DK) {
596 DK == OpenACCDirectiveKind::Loop || DK == OpenACCDirectiveKind::Wait ||
597 DK == OpenACCDirectiveKind::Init ||
598 DK == OpenACCDirectiveKind::Shutdown ||
599 DK == OpenACCDirectiveKind::Set;
600}
601
602class SemaOpenACCClauseVisitor {
603 SemaOpenACC &SemaRef;
604 ASTContext &Ctx;
605 ArrayRef<const OpenACCClause *> ExistingClauses;
606 bool NotImplemented = false;
607
608 OpenACCClause *isNotImplemented() {
609 NotImplemented = true;
610 return nullptr;
611 }
612
613 // OpenACC 3.3 2.9:
614 // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
615 // appears.
616 bool DiagIfSeqClause(SemaOpenACC::OpenACCParsedClause &Clause) {
617 const auto *Itr =
618 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);
619
620 if (Itr != ExistingClauses.end()) {
621 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
622 << Clause.getClauseKind() << (*Itr)->getClauseKind()
623 << Clause.getDirectiveKind();
624 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
625
626 return true;
627 }
628 return false;
629 }
630
631public:
632 SemaOpenACCClauseVisitor(SemaOpenACC &S,
633 ArrayRef<const OpenACCClause *> ExistingClauses)
634 : SemaRef(S), Ctx(S.getASTContext()), ExistingClauses(ExistingClauses) {}
635 // Once we've implemented everything, we shouldn't need this infrastructure.
636 // But in the meantime, we use this to help decide whether the clause was
637 // handled for this directive.
638 bool diagNotImplemented() { return NotImplemented; }
639
641 switch (Clause.getClauseKind()) {
642#define VISIT_CLAUSE(CLAUSE_NAME) \
643 case OpenACCClauseKind::CLAUSE_NAME: \
644 return Visit##CLAUSE_NAME##Clause(Clause);
645#define CLAUSE_ALIAS(ALIAS, CLAUSE_NAME, DEPRECATED) \
646 case OpenACCClauseKind::ALIAS: \
647 if (DEPRECATED) \
648 SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name) \
649 << Clause.getClauseKind() << OpenACCClauseKind::CLAUSE_NAME; \
650 return Visit##CLAUSE_NAME##Clause(Clause);
651#include "clang/Basic/OpenACCClauses.def"
652 default:
653 return isNotImplemented();
654 }
655 llvm_unreachable("Invalid clause kind");
656 }
657
658#define VISIT_CLAUSE(CLAUSE_NAME) \
659 OpenACCClause *Visit##CLAUSE_NAME##Clause( \
660 SemaOpenACC::OpenACCParsedClause &Clause);
661#include "clang/Basic/OpenACCClauses.def"
662};
663
664OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause(
666 // Don't add an invalid clause to the AST.
667 if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)
668 return nullptr;
669
670 // OpenACC 3.3, Section 2.5.4:
671 // At most one 'default' clause may appear, and it must have a value of
672 // either 'none' or 'present'.
673 // Second half of the sentence is diagnosed during parsing.
674 if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
675 return nullptr;
676
678 Ctx, Clause.getDefaultClauseKind(), Clause.getBeginLoc(),
679 Clause.getLParenLoc(), Clause.getEndLoc());
680}
681
682OpenACCClause *SemaOpenACCClauseVisitor::VisitTileClause(
684
685 // Duplicates here are not really sensible. We could possible permit
686 // multiples if they all had the same value, but there isn't really a good
687 // reason to do so. Also, this simplifies the suppression of duplicates, in
688 // that we know if we 'find' one after instantiation, that it is the same
689 // clause, which simplifies instantiation/checking/etc.
690 if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
691 return nullptr;
692
693 llvm::SmallVector<Expr *> NewSizeExprs;
694
695 // Make sure these are all positive constant expressions or *.
696 for (Expr *E : Clause.getIntExprs()) {
697 ExprResult Res = SemaRef.CheckTileSizeExpr(E);
698
699 if (!Res.isUsable())
700 return nullptr;
701
702 NewSizeExprs.push_back(Res.get());
703 }
704
705 return OpenACCTileClause::Create(Ctx, Clause.getBeginLoc(),
706 Clause.getLParenLoc(), NewSizeExprs,
707 Clause.getEndLoc());
708}
709
710OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
712 // There is no prose in the standard that says duplicates aren't allowed,
713 // but this diagnostic is present in other compilers, as well as makes
714 // sense. Prose DOES exist for 'data' and 'host_data', 'set', 'enter data' and
715 // 'exit data' both don't, but other implmementations do this. OpenACC issue
716 // 519 filed for the latter two. Prose also exists for 'update'.
717 // GCC allows this on init/shutdown, presumably for good reason, so we do too.
718 if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Init &&
719 Clause.getDirectiveKind() != OpenACCDirectiveKind::Shutdown &&
720 checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
721 return nullptr;
722
723 // The parser has ensured that we have a proper condition expr, so there
724 // isn't really much to do here.
725
726 // If the 'if' clause is true, it makes the 'self' clause have no effect,
727 // diagnose that here.
728 // TODO OpenACC: When we add these two to other constructs, we might not
729 // want to warn on this (for example, 'update').
730 const auto *Itr =
731 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>);
732 if (Itr != ExistingClauses.end()) {
733 SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
734 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
735 }
736
737 return OpenACCIfClause::Create(Ctx, Clause.getBeginLoc(),
738 Clause.getLParenLoc(),
739 Clause.getConditionExpr(), Clause.getEndLoc());
740}
741
742OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
744 // Restrictions only properly implemented on 'compute' constructs, and
745 // 'compute' constructs are the only construct that can do anything with
746 // this yet, so skip/treat as unimplemented in this case.
747 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
748 return isNotImplemented();
749
750 // TODO OpenACC: When we implement this for 'update', this takes a
751 // 'var-list' instead of a condition expression, so semantics/handling has
752 // to happen differently here.
753
754 // There is no prose in the standard that says duplicates aren't allowed,
755 // but this diagnostic is present in other compilers, as well as makes
756 // sense.
757 if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
758 return nullptr;
759
760 // If the 'if' clause is true, it makes the 'self' clause have no effect,
761 // diagnose that here.
762 // TODO OpenACC: When we add these two to other constructs, we might not
763 // want to warn on this (for example, 'update').
764 const auto *Itr =
765 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCIfClause>);
766 if (Itr != ExistingClauses.end()) {
767 SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
768 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
769 }
771 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
772 Clause.getConditionExpr(), Clause.getEndLoc());
773}
774
775OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause(
777 // There is no prose in the standard that says duplicates aren't allowed,
778 // but this diagnostic is present in other compilers, as well as makes
779 // sense.
780 if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
781 return nullptr;
782
783 // num_gangs requires at least 1 int expr in all forms. Diagnose here, but
784 // allow us to continue, an empty clause might be useful for future
785 // diagnostics.
786 if (Clause.getIntExprs().empty())
787 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
788 << /*NoArgs=*/0;
789
790 unsigned MaxArgs =
791 (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
792 Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop)
793 ? 3
794 : 1;
795 // The max number of args differs between parallel and other constructs.
796 // Again, allow us to continue for the purposes of future diagnostics.
797 if (Clause.getIntExprs().size() > MaxArgs)
798 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
799 << /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs
800 << Clause.getIntExprs().size();
801
802 // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
803 // directive that has a gang clause and is within a compute construct that has
804 // a num_gangs clause with more than one explicit argument.
805 if (Clause.getIntExprs().size() > 1 &&
807 auto *GangClauseItr =
808 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
809 auto *ReductionClauseItr =
810 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
811
812 if (GangClauseItr != ExistingClauses.end() &&
813 ReductionClauseItr != ExistingClauses.end()) {
814 SemaRef.Diag(Clause.getBeginLoc(),
815 diag::err_acc_gang_reduction_numgangs_conflict)
816 << OpenACCClauseKind::Reduction << OpenACCClauseKind::Gang
817 << Clause.getDirectiveKind() << /*is on combined directive=*/1;
818 SemaRef.Diag((*ReductionClauseItr)->getBeginLoc(),
819 diag::note_acc_previous_clause_here);
820 SemaRef.Diag((*GangClauseItr)->getBeginLoc(),
821 diag::note_acc_previous_clause_here);
822 return nullptr;
823 }
824 }
825
826 // OpenACC 3.3 Section 2.5.4:
827 // A reduction clause may not appear on a parallel construct with a
828 // num_gangs clause that has more than one argument.
829 if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
830 Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) &&
831 Clause.getIntExprs().size() > 1) {
832 auto *Parallel =
833 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
834
835 if (Parallel != ExistingClauses.end()) {
836 SemaRef.Diag(Clause.getBeginLoc(),
837 diag::err_acc_reduction_num_gangs_conflict)
838 << /*>1 arg in first loc=*/1 << Clause.getClauseKind()
839 << Clause.getDirectiveKind() << OpenACCClauseKind::Reduction;
840 SemaRef.Diag((*Parallel)->getBeginLoc(),
841 diag::note_acc_previous_clause_here);
842 return nullptr;
843 }
844 }
845
846 // OpenACC 3.3 Section 2.9.2:
847 // An argument with no keyword or with the 'num' keyword is allowed only when
848 // the 'num_gangs' does not appear on the 'kernel' construct.
849 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {
850 auto GangClauses = llvm::make_filter_range(
851 ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
852
853 for (auto *GC : GangClauses) {
854 if (cast<OpenACCGangClause>(GC)->hasExprOfKind(OpenACCGangKind::Num)) {
855 SemaRef.Diag(Clause.getBeginLoc(),
856 diag::err_acc_num_arg_conflict_reverse)
857 << OpenACCClauseKind::NumGangs << OpenACCClauseKind::Gang
858 << /*Num argument*/ 1;
859 SemaRef.Diag(GC->getBeginLoc(), diag::note_acc_previous_clause_here);
860 return nullptr;
861 }
862 }
863 }
864
866 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs(),
867 Clause.getEndLoc());
868}
869
870OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause(
872 // There is no prose in the standard that says duplicates aren't allowed,
873 // but this diagnostic is present in other compilers, as well as makes
874 // sense.
875 if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
876 return nullptr;
877
878 // OpenACC 3.3 Section 2.9.2:
879 // An argument is allowed only when the 'num_workers' does not appear on the
880 // kernels construct.
881 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {
882 auto WorkerClauses = llvm::make_filter_range(
883 ExistingClauses, llvm::IsaPred<OpenACCWorkerClause>);
884
885 for (auto *WC : WorkerClauses) {
886 if (cast<OpenACCWorkerClause>(WC)->hasIntExpr()) {
887 SemaRef.Diag(Clause.getBeginLoc(),
888 diag::err_acc_num_arg_conflict_reverse)
889 << OpenACCClauseKind::NumWorkers << OpenACCClauseKind::Worker
890 << /*num argument*/ 0;
891 SemaRef.Diag(WC->getBeginLoc(), diag::note_acc_previous_clause_here);
892 return nullptr;
893 }
894 }
895 }
896
897 assert(Clause.getIntExprs().size() == 1 &&
898 "Invalid number of expressions for NumWorkers");
900 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
901 Clause.getEndLoc());
902}
903
904OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause(
906 // There is no prose in the standard that says duplicates aren't allowed,
907 // but this diagnostic is present in other compilers, as well as makes
908 // sense.
909 if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
910 return nullptr;
911
912 // OpenACC 3.3 Section 2.9.4:
913 // An argument is allowed only when the 'vector_length' does not appear on the
914 // 'kernels' construct.
915 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {
916 auto VectorClauses = llvm::make_filter_range(
917 ExistingClauses, llvm::IsaPred<OpenACCVectorClause>);
918
919 for (auto *VC : VectorClauses) {
920 if (cast<OpenACCVectorClause>(VC)->hasIntExpr()) {
921 SemaRef.Diag(Clause.getBeginLoc(),
922 diag::err_acc_num_arg_conflict_reverse)
923 << OpenACCClauseKind::VectorLength << OpenACCClauseKind::Vector
924 << /*num argument*/ 0;
925 SemaRef.Diag(VC->getBeginLoc(), diag::note_acc_previous_clause_here);
926 return nullptr;
927 }
928 }
929 }
930
931 assert(Clause.getIntExprs().size() == 1 &&
932 "Invalid number of expressions for NumWorkers");
934 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
935 Clause.getEndLoc());
936}
937
938OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause(
940 // Restrictions only properly implemented on 'compute'/'combined'/'data'
941 // constructs, and 'compute'/'combined'/'data' constructs are the only
942 // construct that can do anything with this yet, so skip/treat as
943 // unimplemented in this case.
944 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
945 return isNotImplemented();
946
947 // There is no prose in the standard that says duplicates aren't allowed,
948 // but this diagnostic is present in other compilers, as well as makes
949 // sense.
950 if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
951 return nullptr;
952
953 assert(Clause.getNumIntExprs() < 2 &&
954 "Invalid number of expressions for Async");
956 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
957 Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr,
958 Clause.getEndLoc());
959}
960
961OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause(
963 // Restrictions only properly implemented on certain constructs, so skip/treat
964 // as unimplemented in those cases.
965 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
966 return isNotImplemented();
967
968 // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the
969 // same directive.
970 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Set &&
971 checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
972 return nullptr;
973
974 assert(Clause.getNumIntExprs() == 1 &&
975 "Invalid number of expressions for device_num");
977 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
978 Clause.getEndLoc());
979}
980
981OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultAsyncClause(
983 // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the
984 // same directive.
985 if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
986 return nullptr;
987
988 assert(Clause.getNumIntExprs() == 1 &&
989 "Invalid number of expressions for default_async");
991 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
992 Clause.getEndLoc());
993}
994
995OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause(
997 // ActOnVar ensured that everything is a valid variable reference, so there
998 // really isn't anything to do here. GCC does some duplicate-finding, though
999 // it isn't apparent in the standard where this is justified.
1000
1001 return OpenACCPrivateClause::Create(Ctx, Clause.getBeginLoc(),
1002 Clause.getLParenLoc(),
1003 Clause.getVarList(), Clause.getEndLoc());
1004}
1005
1006OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(
1008 // ActOnVar ensured that everything is a valid variable reference, so there
1009 // really isn't anything to do here. GCC does some duplicate-finding, though
1010 // it isn't apparent in the standard where this is justified.
1011
1013 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
1014 Clause.getEndLoc());
1015}
1016
1017OpenACCClause *SemaOpenACCClauseVisitor::VisitNoCreateClause(
1019 // ActOnVar ensured that everything is a valid variable reference, so there
1020 // really isn't anything to do here. GCC does some duplicate-finding, though
1021 // it isn't apparent in the standard where this is justified.
1022
1023 return OpenACCNoCreateClause::Create(Ctx, Clause.getBeginLoc(),
1024 Clause.getLParenLoc(),
1025 Clause.getVarList(), Clause.getEndLoc());
1026}
1027
1028OpenACCClause *SemaOpenACCClauseVisitor::VisitPresentClause(
1030 // Restrictions only properly implemented on 'compute'/'combined'/'data'
1031 // constructs, and 'compute'/'combined'/'data' constructs are the only
1032 // construct that can do anything with this yet, so skip/treat as
1033 // unimplemented in this case.
1034 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1035 return isNotImplemented();
1036 // ActOnVar ensured that everything is a valid variable reference, so there
1037 // really isn't anything to do here. GCC does some duplicate-finding, though
1038 // it isn't apparent in the standard where this is justified.
1039
1040 return OpenACCPresentClause::Create(Ctx, Clause.getBeginLoc(),
1041 Clause.getLParenLoc(),
1042 Clause.getVarList(), Clause.getEndLoc());
1043}
1044
1045OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyClause(
1047 // Restrictions only properly implemented on 'compute'/'combined'/'data'
1048 // constructs, and 'compute'/'combined'/'data' constructs are the only
1049 // construct that can do anything with this yet, so skip/treat as
1050 // unimplemented in this case.
1051 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1052 return isNotImplemented();
1053 // ActOnVar ensured that everything is a valid variable reference, so there
1054 // really isn't anything to do here. GCC does some duplicate-finding, though
1055 // it isn't apparent in the standard where this is justified.
1056
1058 Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
1059 Clause.getVarList(), Clause.getEndLoc());
1060}
1061
1062OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyInClause(
1064 // Restrictions only properly implemented on 'compute'/'combined'/'data'
1065 // constructs, and 'compute'/'combined'/'data' constructs are the only
1066 // construct that can do anything with this yet, so skip/treat as
1067 // unimplemented in this case.
1068 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1069 return isNotImplemented();
1070 // ActOnVar ensured that everything is a valid variable reference, so there
1071 // really isn't anything to do here. GCC does some duplicate-finding, though
1072 // it isn't apparent in the standard where this is justified.
1073
1075 Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
1076 Clause.isReadOnly(), Clause.getVarList(), Clause.getEndLoc());
1077}
1078
1079OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyOutClause(
1081 // Restrictions only properly implemented on 'compute'/'combined'/'data'
1082 // constructs, and 'compute'/'combined'/'data' constructs are the only
1083 // construct that can do anything with this yet, so skip/treat as
1084 // unimplemented in this case.
1085 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1086 return isNotImplemented();
1087 // ActOnVar ensured that everything is a valid variable reference, so there
1088 // really isn't anything to do here. GCC does some duplicate-finding, though
1089 // it isn't apparent in the standard where this is justified.
1090
1092 Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
1093 Clause.isZero(), Clause.getVarList(), Clause.getEndLoc());
1094}
1095
1096OpenACCClause *SemaOpenACCClauseVisitor::VisitCreateClause(
1098 // ActOnVar ensured that everything is a valid variable reference, so there
1099 // really isn't anything to do here. GCC does some duplicate-finding, though
1100 // it isn't apparent in the standard where this is justified.
1101
1103 Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
1104 Clause.isZero(), Clause.getVarList(), Clause.getEndLoc());
1105}
1106
1107OpenACCClause *SemaOpenACCClauseVisitor::VisitAttachClause(
1109 // ActOnVar ensured that everything is a valid variable reference, but we
1110 // still have to make sure it is a pointer type.
1111 llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
1112 llvm::erase_if(VarList, [&](Expr *E) {
1113 return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::Attach, E);
1114 });
1115 Clause.setVarListDetails(VarList,
1116 /*IsReadOnly=*/false, /*IsZero=*/false);
1117 return OpenACCAttachClause::Create(Ctx, Clause.getBeginLoc(),
1118 Clause.getLParenLoc(), Clause.getVarList(),
1119 Clause.getEndLoc());
1120}
1121
1122OpenACCClause *SemaOpenACCClauseVisitor::VisitDetachClause(
1124 // ActOnVar ensured that everything is a valid variable reference, but we
1125 // still have to make sure it is a pointer type.
1126 llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
1127 llvm::erase_if(VarList, [&](Expr *E) {
1128 return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::Detach, E);
1129 });
1130 Clause.setVarListDetails(VarList,
1131 /*IsReadOnly=*/false, /*IsZero=*/false);
1132 return OpenACCDetachClause::Create(Ctx, Clause.getBeginLoc(),
1133 Clause.getLParenLoc(), Clause.getVarList(),
1134 Clause.getEndLoc());
1135}
1136
1137OpenACCClause *SemaOpenACCClauseVisitor::VisitDeleteClause(
1139 // ActOnVar ensured that everything is a valid variable reference, so there
1140 // really isn't anything to do here. GCC does some duplicate-finding, though
1141 // it isn't apparent in the standard where this is justified.
1142 return OpenACCDeleteClause::Create(Ctx, Clause.getBeginLoc(),
1143 Clause.getLParenLoc(), Clause.getVarList(),
1144 Clause.getEndLoc());
1145}
1146
1147OpenACCClause *SemaOpenACCClauseVisitor::VisitUseDeviceClause(
1149 // ActOnVar ensured that everything is a valid variable or array, so nothing
1150 // left to do here.
1152 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
1153 Clause.getEndLoc());
1154}
1155
1156OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause(
1158 // Restrictions only properly implemented on 'compute'/'combined'/'data'
1159 // constructs, and 'compute'/'combined'/'data' constructs are the only
1160 // construct that can do anything with this yet, so skip/treat as
1161 // unimplemented in this case.
1162 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1163 return isNotImplemented();
1164
1165 // ActOnVar ensured that everything is a valid variable reference, but we
1166 // still have to make sure it is a pointer type.
1167 llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
1168 llvm::erase_if(VarList, [&](Expr *E) {
1169 return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::DevicePtr, E);
1170 });
1171 Clause.setVarListDetails(VarList,
1172 /*IsReadOnly=*/false, /*IsZero=*/false);
1173
1175 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
1176 Clause.getEndLoc());
1177}
1178
1179OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause(
1181 // Restrictions only properly implemented on 'compute'/'combined'/'data'
1182 // constructs, and 'compute'/'combined'/'data' constructs are the only
1183 // construct that can do anything with this yet, so skip/treat as
1184 // unimplemented in this case.
1185 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1186 return isNotImplemented();
1187
1189 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getDevNumExpr(),
1190 Clause.getQueuesLoc(), Clause.getQueueIdExprs(), Clause.getEndLoc());
1191}
1192
1193OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
1195 // Restrictions only properly implemented on 'compute', 'combined', 'data' and
1196 // 'loop' constructs, and 'compute'/'combined'/'data'/'loop' constructs are
1197 // the only construct that can do anything with this yet, so skip/treat as
1198 // unimplemented in this case.
1199 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1200 return isNotImplemented();
1201
1202 // OpenACC 3.3 2.14.3: Two instances of the same clause may not appear on the
1203 // same directive.
1204 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Set &&
1205 checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
1206 return nullptr;
1207
1208 // TODO OpenACC: Once we get enough of the CodeGen implemented that we have
1209 // a source for the list of valid architectures, we need to warn on unknown
1210 // identifiers here.
1211
1213 Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
1214 Clause.getDeviceTypeArchitectures(), Clause.getEndLoc());
1215}
1216
1217OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause(
1219 // OpenACC 3.3 2.9:
1220 // Only one of the seq, independent, and auto clauses may appear.
1221 const auto *Itr =
1222 llvm::find_if(ExistingClauses,
1223 llvm::IsaPred<OpenACCIndependentClause, OpenACCSeqClause>);
1224 if (Itr != ExistingClauses.end()) {
1225 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
1226 << Clause.getClauseKind() << Clause.getDirectiveKind();
1227 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
1228 return nullptr;
1229 }
1230
1231 return OpenACCAutoClause::Create(Ctx, Clause.getBeginLoc(),
1232 Clause.getEndLoc());
1233}
1234
1235OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
1237 // OpenACC 3.3 2.9:
1238 // Only one of the seq, independent, and auto clauses may appear.
1239 const auto *Itr = llvm::find_if(
1240 ExistingClauses, llvm::IsaPred<OpenACCAutoClause, OpenACCSeqClause>);
1241 if (Itr != ExistingClauses.end()) {
1242 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
1243 << Clause.getClauseKind() << Clause.getDirectiveKind();
1244 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
1245 return nullptr;
1246 }
1247
1248 return OpenACCIndependentClause::Create(Ctx, Clause.getBeginLoc(),
1249 Clause.getEndLoc());
1250}
1251
1252ExprResult CheckGangStaticExpr(SemaOpenACC &S, Expr *E) {
1253 if (isa<OpenACCAsteriskSizeExpr>(E))
1254 return E;
1255 return S.ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang,
1256 E->getBeginLoc(), E);
1257}
1258
1259bool IsOrphanLoop(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) {
1260 return DK == OpenACCDirectiveKind::Loop &&
1261 AssocKind == OpenACCDirectiveKind::Invalid;
1262}
1263
1264bool HasAssocKind(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) {
1265 return DK == OpenACCDirectiveKind::Loop &&
1266 AssocKind != OpenACCDirectiveKind::Invalid;
1267}
1268
1269ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, OpenACCGangKind GK,
1271 OpenACCDirectiveKind AssocKind) {
1272 S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid)
1273 << GK << CK << IsOrphanLoop(DK, AssocKind) << DK
1274 << HasAssocKind(DK, AssocKind) << AssocKind;
1275 return ExprError();
1276}
1277ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, StringRef TagKind,
1279 OpenACCDirectiveKind AssocKind) {
1280 S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid)
1281 << TagKind << CK << IsOrphanLoop(DK, AssocKind) << DK
1282 << HasAssocKind(DK, AssocKind) << AssocKind;
1283 return ExprError();
1284}
1285
1286ExprResult CheckGangParallelExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1287 OpenACCDirectiveKind AssocKind,
1288 OpenACCGangKind GK, Expr *E) {
1289 switch (GK) {
1290 case OpenACCGangKind::Static:
1291 return CheckGangStaticExpr(S, E);
1292 case OpenACCGangKind::Num:
1293 // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel
1294 // construct, or an orphaned loop construct, the gang clause behaves as
1295 // follows. ... The num argument is not allowed.
1296 return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1297 case OpenACCGangKind::Dim: {
1298 // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel
1299 // construct, or an orphaned loop construct, the gang clause behaves as
1300 // follows. ... The dim argument must be a constant positive integer value
1301 // 1, 2, or 3.
1302 if (!E)
1303 return ExprError();
1304 ExprResult Res =
1305 S.ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang,
1306 E->getBeginLoc(), E);
1307
1308 if (!Res.isUsable())
1309 return Res;
1310
1311 if (Res.get()->isInstantiationDependent())
1312 return Res;
1313
1314 std::optional<llvm::APSInt> ICE =
1316
1317 if (!ICE || *ICE <= 0 || ICE > 3) {
1318 S.Diag(Res.get()->getBeginLoc(), diag::err_acc_gang_dim_value)
1319 << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
1320 return ExprError();
1321 }
1322
1323 return ExprResult{
1324 ConstantExpr::Create(S.getASTContext(), Res.get(), APValue{*ICE})};
1325 }
1326 }
1327 llvm_unreachable("Unknown gang kind in gang parallel check");
1328}
1329
1330ExprResult CheckGangKernelsExpr(SemaOpenACC &S,
1331 ArrayRef<const OpenACCClause *> ExistingClauses,
1333 OpenACCDirectiveKind AssocKind,
1334 OpenACCGangKind GK, Expr *E) {
1335 switch (GK) {
1336 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1337 // construct, the gang clause behaves as follows. ... The dim argument is
1338 // not allowed.
1339 case OpenACCGangKind::Dim:
1340 return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1341 case OpenACCGangKind::Num: {
1342 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1343 // construct, the gang clause behaves as follows. ... An argument with no
1344 // keyword or with num keyword is only allowed when num_gangs does not
1345 // appear on the kernels construct. ... The region of a loop with the gang
1346 // clause may not contain another loop with a gang clause unless within a
1347 // nested compute region.
1348
1349 // If this is a 'combined' construct, search the list of existing clauses.
1350 // Else we need to search the containing 'kernel'.
1351 auto Collection = isOpenACCCombinedDirectiveKind(DK)
1352 ? ExistingClauses
1353 : S.getActiveComputeConstructInfo().Clauses;
1354
1355 const auto *Itr =
1356 llvm::find_if(Collection, llvm::IsaPred<OpenACCNumGangsClause>);
1357
1358 if (Itr != Collection.end()) {
1359 S.Diag(E->getBeginLoc(), diag::err_acc_num_arg_conflict)
1360 << "num" << OpenACCClauseKind::Gang << DK
1361 << HasAssocKind(DK, AssocKind) << AssocKind
1362 << OpenACCClauseKind::NumGangs;
1363
1364 S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
1365 return ExprError();
1366 }
1367 return ExprResult{E};
1368 }
1369 case OpenACCGangKind::Static:
1370 return CheckGangStaticExpr(S, E);
1371 return ExprError();
1372 }
1373 llvm_unreachable("Unknown gang kind in gang kernels check");
1374}
1375
1376ExprResult CheckGangSerialExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1377 OpenACCDirectiveKind AssocKind,
1378 OpenACCGangKind GK, Expr *E) {
1379 switch (GK) {
1380 // 'dim' and 'num' don't really make sense on serial, and GCC rejects them
1381 // too, so we disallow them too.
1382 case OpenACCGangKind::Dim:
1383 case OpenACCGangKind::Num:
1384 return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1385 case OpenACCGangKind::Static:
1386 return CheckGangStaticExpr(S, E);
1387 }
1388 llvm_unreachable("Unknown gang kind in gang serial check");
1389}
1390
1391OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorClause(
1393 if (DiagIfSeqClause(Clause))
1394 return nullptr;
1395
1396 // Restrictions only properly implemented on 'loop'/'combined' constructs, and
1397 // it is the only construct that can do anything with this, so skip/treat as
1398 // unimplemented for the routine constructs.
1399 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1400 return isNotImplemented();
1401
1402 Expr *IntExpr =
1403 Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
1404 if (IntExpr) {
1406 switch (SemaRef.getActiveComputeConstructInfo().Kind) {
1407 case OpenACCDirectiveKind::Invalid:
1408 case OpenACCDirectiveKind::Parallel:
1409 // No restriction on when 'parallel' can contain an argument.
1410 break;
1411 case OpenACCDirectiveKind::Serial:
1412 // GCC disallows this, and there is no real good reason for us to permit
1413 // it, so disallow until we come up with a use case that makes sense.
1414 DiagIntArgInvalid(SemaRef, IntExpr, "length", OpenACCClauseKind::Vector,
1415 Clause.getDirectiveKind(),
1416 SemaRef.getActiveComputeConstructInfo().Kind);
1417 IntExpr = nullptr;
1418 break;
1419 case OpenACCDirectiveKind::Kernels: {
1420 const auto *Itr =
1421 llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
1422 llvm::IsaPred<OpenACCVectorLengthClause>);
1423 if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
1424 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1425 << "length" << OpenACCClauseKind::Vector
1426 << Clause.getDirectiveKind()
1427 << HasAssocKind(Clause.getDirectiveKind(),
1428 SemaRef.getActiveComputeConstructInfo().Kind)
1429 << SemaRef.getActiveComputeConstructInfo().Kind
1430 << OpenACCClauseKind::VectorLength;
1431 SemaRef.Diag((*Itr)->getBeginLoc(),
1432 diag::note_acc_previous_clause_here);
1433
1434 IntExpr = nullptr;
1435 }
1436 break;
1437 }
1438 default:
1439 llvm_unreachable("Non compute construct in active compute construct");
1440 }
1441 } else {
1442 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::SerialLoop) {
1443 DiagIntArgInvalid(SemaRef, IntExpr, "length", OpenACCClauseKind::Vector,
1444 Clause.getDirectiveKind(),
1445 SemaRef.getActiveComputeConstructInfo().Kind);
1446 IntExpr = nullptr;
1447 } else if (Clause.getDirectiveKind() ==
1448 OpenACCDirectiveKind::KernelsLoop) {
1449 const auto *Itr = llvm::find_if(
1450 ExistingClauses, llvm::IsaPred<OpenACCVectorLengthClause>);
1451 if (Itr != ExistingClauses.end()) {
1452 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1453 << "length" << OpenACCClauseKind::Vector
1454 << Clause.getDirectiveKind()
1455 << HasAssocKind(Clause.getDirectiveKind(),
1456 SemaRef.getActiveComputeConstructInfo().Kind)
1457 << SemaRef.getActiveComputeConstructInfo().Kind
1458 << OpenACCClauseKind::VectorLength;
1459 SemaRef.Diag((*Itr)->getBeginLoc(),
1460 diag::note_acc_previous_clause_here);
1461
1462 IntExpr = nullptr;
1463 }
1464 }
1465 }
1466 }
1467
1469 // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1470 // contain a loop with a gang, worker, or vector clause unless within a
1471 // nested compute region.
1472 if (SemaRef.LoopVectorClauseLoc.isValid()) {
1473 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1474 // on one of these until we get to the end of the construct.
1475 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1476 << OpenACCClauseKind::Vector << OpenACCClauseKind::Vector
1477 << /*skip kernels construct info*/ 0;
1478 SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1479 diag::note_acc_previous_clause_here);
1480 return nullptr;
1481 }
1482 }
1483
1484 return OpenACCVectorClause::Create(Ctx, Clause.getBeginLoc(),
1485 Clause.getLParenLoc(), IntExpr,
1486 Clause.getEndLoc());
1487}
1488
1489OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
1491 if (DiagIfSeqClause(Clause))
1492 return nullptr;
1493
1494 // Restrictions only properly implemented on 'loop'/'combined' constructs, and
1495 // it is the only construct that can do anything with this, so skip/treat as
1496 // unimplemented for the routine constructs.
1497 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1498 return isNotImplemented();
1499
1500 Expr *IntExpr =
1501 Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
1502
1503 if (IntExpr) {
1505 switch (SemaRef.getActiveComputeConstructInfo().Kind) {
1506 case OpenACCDirectiveKind::Invalid:
1507 case OpenACCDirectiveKind::ParallelLoop:
1508 case OpenACCDirectiveKind::SerialLoop:
1509 case OpenACCDirectiveKind::Parallel:
1510 case OpenACCDirectiveKind::Serial:
1511 DiagIntArgInvalid(SemaRef, IntExpr, OpenACCGangKind::Num,
1512 OpenACCClauseKind::Worker, Clause.getDirectiveKind(),
1513 SemaRef.getActiveComputeConstructInfo().Kind);
1514 IntExpr = nullptr;
1515 break;
1516 case OpenACCDirectiveKind::KernelsLoop:
1517 case OpenACCDirectiveKind::Kernels: {
1518 const auto *Itr =
1519 llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
1520 llvm::IsaPred<OpenACCNumWorkersClause>);
1521 if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
1522 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1523 << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind()
1524 << HasAssocKind(Clause.getDirectiveKind(),
1525 SemaRef.getActiveComputeConstructInfo().Kind)
1526 << SemaRef.getActiveComputeConstructInfo().Kind
1527 << OpenACCClauseKind::NumWorkers;
1528 SemaRef.Diag((*Itr)->getBeginLoc(),
1529 diag::note_acc_previous_clause_here);
1530
1531 IntExpr = nullptr;
1532 }
1533 break;
1534 }
1535 default:
1536 llvm_unreachable("Non compute construct in active compute construct");
1537 }
1538 } else {
1539 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop ||
1540 Clause.getDirectiveKind() == OpenACCDirectiveKind::SerialLoop) {
1541 DiagIntArgInvalid(SemaRef, IntExpr, OpenACCGangKind::Num,
1542 OpenACCClauseKind::Worker, Clause.getDirectiveKind(),
1543 SemaRef.getActiveComputeConstructInfo().Kind);
1544 IntExpr = nullptr;
1545 } else {
1546 assert(Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop &&
1547 "Unknown combined directive kind?");
1548 const auto *Itr = llvm::find_if(ExistingClauses,
1549 llvm::IsaPred<OpenACCNumWorkersClause>);
1550 if (Itr != ExistingClauses.end()) {
1551 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1552 << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind()
1553 << HasAssocKind(Clause.getDirectiveKind(),
1554 SemaRef.getActiveComputeConstructInfo().Kind)
1555 << SemaRef.getActiveComputeConstructInfo().Kind
1556 << OpenACCClauseKind::NumWorkers;
1557 SemaRef.Diag((*Itr)->getBeginLoc(),
1558 diag::note_acc_previous_clause_here);
1559
1560 IntExpr = nullptr;
1561 }
1562 }
1563 }
1564 }
1565
1567 // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1568 // contain a loop with a gang or worker clause unless within a nested
1569 // compute region.
1570 if (SemaRef.LoopWorkerClauseLoc.isValid()) {
1571 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1572 // on one of these until we get to the end of the construct.
1573 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1574 << OpenACCClauseKind::Worker << OpenACCClauseKind::Worker
1575 << /*skip kernels construct info*/ 0;
1576 SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,
1577 diag::note_acc_previous_clause_here);
1578 return nullptr;
1579 }
1580
1581 // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1582 // contain a loop with a gang, worker, or vector clause unless within a
1583 // nested compute region.
1584 if (SemaRef.LoopVectorClauseLoc.isValid()) {
1585 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1586 // on one of these until we get to the end of the construct.
1587 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1588 << OpenACCClauseKind::Worker << OpenACCClauseKind::Vector
1589 << /*skip kernels construct info*/ 0;
1590 SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1591 diag::note_acc_previous_clause_here);
1592 return nullptr;
1593 }
1594 }
1595
1596 return OpenACCWorkerClause::Create(Ctx, Clause.getBeginLoc(),
1597 Clause.getLParenLoc(), IntExpr,
1598 Clause.getEndLoc());
1599}
1600
1601OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
1603 if (DiagIfSeqClause(Clause))
1604 return nullptr;
1605
1606 // Restrictions only properly implemented on 'loop' constructs, and it is
1607 // the only construct that can do anything with this, so skip/treat as
1608 // unimplemented for the combined constructs.
1609 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1610 return isNotImplemented();
1611
1612 // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
1613 // directive that has a gang clause and is within a compute construct that has
1614 // a num_gangs clause with more than one explicit argument.
1615 if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&
1616 SemaRef.getActiveComputeConstructInfo().Kind !=
1617 OpenACCDirectiveKind::Invalid) ||
1619 // num_gangs clause on the active compute construct.
1620 auto ActiveComputeConstructContainer =
1622 ? ExistingClauses
1623 : SemaRef.getActiveComputeConstructInfo().Clauses;
1624 auto *NumGangsClauseItr = llvm::find_if(
1625 ActiveComputeConstructContainer, llvm::IsaPred<OpenACCNumGangsClause>);
1626
1627 if (NumGangsClauseItr != ActiveComputeConstructContainer.end() &&
1628 cast<OpenACCNumGangsClause>(*NumGangsClauseItr)->getIntExprs().size() >
1629 1) {
1630 auto *ReductionClauseItr =
1631 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
1632
1633 if (ReductionClauseItr != ExistingClauses.end()) {
1634 SemaRef.Diag(Clause.getBeginLoc(),
1635 diag::err_acc_gang_reduction_numgangs_conflict)
1636 << OpenACCClauseKind::Gang << OpenACCClauseKind::Reduction
1637 << Clause.getDirectiveKind()
1639 SemaRef.Diag((*ReductionClauseItr)->getBeginLoc(),
1640 diag::note_acc_previous_clause_here);
1641 SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),
1642 diag::note_acc_previous_clause_here);
1643 return nullptr;
1644 }
1645 }
1646 }
1647
1650
1651 // Store the existing locations, so we can do duplicate checking. Index is
1652 // the int-value of the OpenACCGangKind enum.
1653 SourceLocation ExistingElemLoc[3];
1654
1655 for (unsigned I = 0; I < Clause.getIntExprs().size(); ++I) {
1656 OpenACCGangKind GK = Clause.getGangKinds()[I];
1657 ExprResult ER =
1658 SemaRef.CheckGangExpr(ExistingClauses, Clause.getDirectiveKind(), GK,
1659 Clause.getIntExprs()[I]);
1660
1661 if (!ER.isUsable())
1662 continue;
1663
1664 // OpenACC 3.3 2.9: 'gang-arg-list' may have at most one num, one dim, and
1665 // one static argument.
1666 if (ExistingElemLoc[static_cast<unsigned>(GK)].isValid()) {
1667 SemaRef.Diag(ER.get()->getBeginLoc(), diag::err_acc_gang_multiple_elt)
1668 << static_cast<unsigned>(GK);
1669 SemaRef.Diag(ExistingElemLoc[static_cast<unsigned>(GK)],
1670 diag::note_acc_previous_expr_here);
1671 continue;
1672 }
1673
1674 ExistingElemLoc[static_cast<unsigned>(GK)] = ER.get()->getBeginLoc();
1675 GangKinds.push_back(GK);
1676 IntExprs.push_back(ER.get());
1677 }
1678
1680 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1681 // construct, the gang clause behaves as follows. ... The region of a loop
1682 // with a gang clause may not contain another loop with a gang clause unless
1683 // within a nested compute region.
1684 if (SemaRef.LoopGangClauseOnKernel.Loc.isValid()) {
1685 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1686 // on one of these until we get to the end of the construct.
1687 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1688 << OpenACCClauseKind::Gang << OpenACCClauseKind::Gang
1689 << /*kernels construct info*/ 1
1691 SemaRef.Diag(SemaRef.LoopGangClauseOnKernel.Loc,
1692 diag::note_acc_previous_clause_here);
1693 return nullptr;
1694 }
1695
1696 // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1697 // contain a loop with a gang or worker clause unless within a nested
1698 // compute region.
1699 if (SemaRef.LoopWorkerClauseLoc.isValid()) {
1700 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1701 // on one of these until we get to the end of the construct.
1702 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1703 << OpenACCClauseKind::Gang << OpenACCClauseKind::Worker
1704 << /*!kernels construct info*/ 0;
1705 SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,
1706 diag::note_acc_previous_clause_here);
1707 return nullptr;
1708 }
1709
1710 // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1711 // contain a loop with a gang, worker, or vector clause unless within a
1712 // nested compute region.
1713 if (SemaRef.LoopVectorClauseLoc.isValid()) {
1714 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1715 // on one of these until we get to the end of the construct.
1716 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1717 << OpenACCClauseKind::Gang << OpenACCClauseKind::Vector
1718 << /*!kernels construct info*/ 0;
1719 SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1720 diag::note_acc_previous_clause_here);
1721 return nullptr;
1722 }
1723 }
1724
1725 return SemaRef.CheckGangClause(Clause.getDirectiveKind(), ExistingClauses,
1726 Clause.getBeginLoc(), Clause.getLParenLoc(),
1727 GangKinds, IntExprs, Clause.getEndLoc());
1728}
1729
1730OpenACCClause *SemaOpenACCClauseVisitor::VisitFinalizeClause(
1732 // There isn't anything to do here, this is only valid on one construct, and
1733 // has no associated rules.
1734 return OpenACCFinalizeClause::Create(Ctx, Clause.getBeginLoc(),
1735 Clause.getEndLoc());
1736}
1737
1738OpenACCClause *SemaOpenACCClauseVisitor::VisitIfPresentClause(
1740 // There isn't anything to do here, this is only valid on one construct, and
1741 // has no associated rules.
1742 return OpenACCIfPresentClause::Create(Ctx, Clause.getBeginLoc(),
1743 Clause.getEndLoc());
1744}
1745
1746OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
1748 // Restrictions only properly implemented on 'loop' constructs and combined ,
1749 // and it is the only construct that can do anything with this, so skip/treat
1750 // as unimplemented for the routine constructs.
1751 if (!isDirectiveKindImplemented(Clause.getDirectiveKind()))
1752 return isNotImplemented();
1753
1754 // OpenACC 3.3 2.9:
1755 // Only one of the seq, independent, and auto clauses may appear.
1756 const auto *Itr =
1757 llvm::find_if(ExistingClauses,
1758 llvm::IsaPred<OpenACCAutoClause, OpenACCIndependentClause>);
1759 if (Itr != ExistingClauses.end()) {
1760 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_loop_spec_conflict)
1761 << Clause.getClauseKind() << Clause.getDirectiveKind();
1762 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
1763 return nullptr;
1764 }
1765
1766 // OpenACC 3.3 2.9:
1767 // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
1768 // appears.
1769 Itr = llvm::find_if(ExistingClauses,
1772
1773 if (Itr != ExistingClauses.end()) {
1774 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
1775 << Clause.getClauseKind() << (*Itr)->getClauseKind()
1776 << Clause.getDirectiveKind();
1777 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
1778 return nullptr;
1779 }
1780
1781 return OpenACCSeqClause::Create(Ctx, Clause.getBeginLoc(),
1782 Clause.getEndLoc());
1783}
1784
1785OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
1787 // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
1788 // directive that has a gang clause and is within a compute construct that has
1789 // a num_gangs clause with more than one explicit argument.
1790 if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&
1791 SemaRef.getActiveComputeConstructInfo().Kind !=
1792 OpenACCDirectiveKind::Invalid) ||
1794 // num_gangs clause on the active compute construct.
1795 auto ActiveComputeConstructContainer =
1797 ? ExistingClauses
1798 : SemaRef.getActiveComputeConstructInfo().Clauses;
1799 auto *NumGangsClauseItr = llvm::find_if(
1800 ActiveComputeConstructContainer, llvm::IsaPred<OpenACCNumGangsClause>);
1801
1802 if (NumGangsClauseItr != ActiveComputeConstructContainer.end() &&
1803 cast<OpenACCNumGangsClause>(*NumGangsClauseItr)->getIntExprs().size() >
1804 1) {
1805 auto *GangClauseItr =
1806 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
1807
1808 if (GangClauseItr != ExistingClauses.end()) {
1809 SemaRef.Diag(Clause.getBeginLoc(),
1810 diag::err_acc_gang_reduction_numgangs_conflict)
1811 << OpenACCClauseKind::Reduction << OpenACCClauseKind::Gang
1812 << Clause.getDirectiveKind()
1814 SemaRef.Diag((*GangClauseItr)->getBeginLoc(),
1815 diag::note_acc_previous_clause_here);
1816 SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),
1817 diag::note_acc_previous_clause_here);
1818 return nullptr;
1819 }
1820 }
1821 }
1822
1823 // OpenACC3.3 Section 2.9.11: If a variable is involved in a reduction that
1824 // spans multiple nested loops where two or more of those loops have
1825 // associated loop directives, a reduction clause containing that variable
1826 // must appear on each of those loop directives.
1827 //
1828 // This can't really be implemented in the CFE, as this requires a level of
1829 // rechability/useage analysis that we're not really wanting to get into.
1830 // Additionally, I'm alerted that this restriction is one that the middle-end
1831 // can just 'figure out' as an extension and isn't really necessary.
1832 //
1833 // OpenACC3.3 Section 2.9.11: Every 'var' in a reduction clause appearing on
1834 // an orphaned loop construct must be private.
1835 //
1836 // This again is something we cannot really diagnose, as it requires we see
1837 // all the uses/scopes of all variables referenced. The middle end/MLIR might
1838 // be able to diagnose this.
1839
1840 // OpenACC 3.3 Section 2.5.4:
1841 // A reduction clause may not appear on a parallel construct with a
1842 // num_gangs clause that has more than one argument.
1843 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
1844 Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) {
1845 auto NumGangsClauses = llvm::make_filter_range(
1846 ExistingClauses, llvm::IsaPred<OpenACCNumGangsClause>);
1847
1848 for (auto *NGC : NumGangsClauses) {
1849 unsigned NumExprs =
1850 cast<OpenACCNumGangsClause>(NGC)->getIntExprs().size();
1851
1852 if (NumExprs > 1) {
1853 SemaRef.Diag(Clause.getBeginLoc(),
1854 diag::err_acc_reduction_num_gangs_conflict)
1855 << /*>1 arg in first loc=*/0 << Clause.getClauseKind()
1856 << Clause.getDirectiveKind() << OpenACCClauseKind::NumGangs;
1857 SemaRef.Diag(NGC->getBeginLoc(), diag::note_acc_previous_clause_here);
1858 return nullptr;
1859 }
1860 }
1861 }
1862
1863 SmallVector<Expr *> ValidVars;
1864
1865 for (Expr *Var : Clause.getVarList()) {
1866 ExprResult Res = SemaRef.CheckReductionVar(Clause.getDirectiveKind(),
1867 Clause.getReductionOp(), Var);
1868
1869 if (Res.isUsable())
1870 ValidVars.push_back(Res.get());
1871 }
1872
1873 return SemaRef.CheckReductionClause(
1874 ExistingClauses, Clause.getDirectiveKind(), Clause.getBeginLoc(),
1875 Clause.getLParenLoc(), Clause.getReductionOp(), ValidVars,
1876 Clause.getEndLoc());
1877}
1878
1879OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(
1881 // Duplicates here are not really sensible. We could possible permit
1882 // multiples if they all had the same value, but there isn't really a good
1883 // reason to do so. Also, this simplifies the suppression of duplicates, in
1884 // that we know if we 'find' one after instantiation, that it is the same
1885 // clause, which simplifies instantiation/checking/etc.
1886 if (checkAlreadyHasClauseOfKind(SemaRef, ExistingClauses, Clause))
1887 return nullptr;
1888
1889 ExprResult LoopCount = SemaRef.CheckCollapseLoopCount(Clause.getLoopCount());
1890
1891 if (!LoopCount.isUsable())
1892 return nullptr;
1893
1894 return OpenACCCollapseClause::Create(Ctx, Clause.getBeginLoc(),
1895 Clause.getLParenLoc(), Clause.isForce(),
1896 LoopCount.get(), Clause.getEndLoc());
1897}
1898
1899void CollectActiveReductionClauses(
1901 ArrayRef<OpenACCClause *> CurClauses) {
1902 for (auto *CurClause : CurClauses) {
1903 if (auto *RedClause = dyn_cast<OpenACCReductionClause>(CurClause);
1904 RedClause && !RedClause->getVarList().empty())
1905 ActiveClauses.push_back(RedClause);
1906 }
1907}
1908
1909// Depth needs to be preserved for all associated statements that aren't
1910// supposed to modify the compute/combined/loop construct information.
1911bool PreserveLoopRAIIDepthInAssociatedStmtRAII(OpenACCDirectiveKind DK) {
1912 switch (DK) {
1913 case OpenACCDirectiveKind::Parallel:
1914 case OpenACCDirectiveKind::ParallelLoop:
1915 case OpenACCDirectiveKind::Serial:
1916 case OpenACCDirectiveKind::SerialLoop:
1917 case OpenACCDirectiveKind::Kernels:
1918 case OpenACCDirectiveKind::KernelsLoop:
1919 case OpenACCDirectiveKind::Loop:
1920 return false;
1921 case OpenACCDirectiveKind::Data:
1922 case OpenACCDirectiveKind::HostData:
1923 return true;
1924 case OpenACCDirectiveKind::EnterData:
1925 case OpenACCDirectiveKind::ExitData:
1926 case OpenACCDirectiveKind::Wait:
1927 case OpenACCDirectiveKind::Init:
1928 case OpenACCDirectiveKind::Shutdown:
1929 case OpenACCDirectiveKind::Set:
1930 case OpenACCDirectiveKind::Update:
1931 llvm_unreachable("Doesn't have an associated stmt");
1932 default:
1933 case OpenACCDirectiveKind::Invalid:
1934 llvm_unreachable("Unhandled directive kind?");
1935 }
1936 llvm_unreachable("Unhandled directive kind?");
1937}
1938
1939} // namespace
1940
1942
1945 ArrayRef<const OpenACCClause *> UnInstClauses,
1947 : SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
1948 DirKind(DK), OldLoopGangClauseOnKernel(S.LoopGangClauseOnKernel),
1949 OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
1950 OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
1951 OldLoopWithoutSeqInfo(S.LoopWithoutSeqInfo),
1952 ActiveReductionClauses(S.ActiveReductionClauses),
1953 LoopRAII(SemaRef, PreserveLoopRAIIDepthInAssociatedStmtRAII(DirKind)) {
1954
1955 // Compute constructs end up taking their 'loop'.
1956 if (DirKind == OpenACCDirectiveKind::Parallel ||
1957 DirKind == OpenACCDirectiveKind::Serial ||
1958 DirKind == OpenACCDirectiveKind::Kernels) {
1959 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
1960 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
1961 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
1962
1963 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1964 // construct, the gang clause behaves as follows. ... The region of a loop
1965 // with a gang clause may not contain another loop with a gang clause unless
1966 // within a nested compute region.
1967 //
1968 // Implement the 'unless within a nested compute region' part.
1969 SemaRef.LoopGangClauseOnKernel = {};
1970 SemaRef.LoopWorkerClauseLoc = {};
1971 SemaRef.LoopVectorClauseLoc = {};
1972 SemaRef.LoopWithoutSeqInfo = {};
1973 } else if (DirKind == OpenACCDirectiveKind::ParallelLoop ||
1976 SemaRef.ActiveComputeConstructInfo.Kind = DirKind;
1977 SemaRef.ActiveComputeConstructInfo.Clauses = Clauses;
1978
1979 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
1980 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
1981 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
1982
1983 SemaRef.LoopGangClauseOnKernel = {};
1984 SemaRef.LoopWorkerClauseLoc = {};
1985 SemaRef.LoopVectorClauseLoc = {};
1986
1987 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
1988 // diagnose the for loops.
1989 SemaRef.LoopWithoutSeqInfo = {};
1990 if (Clauses.end() ==
1991 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
1992 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
1993
1994 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1995 // construct, the gang clause behaves as follows. ... The region of a loop
1996 // with a gang clause may not contain another loop with a gang clause unless
1997 // within a nested compute region.
1998 //
1999 // We don't bother doing this when this is a template instantiation, as
2000 // there is no reason to do these checks: the existance of a
2001 // gang/kernels/etc cannot be dependent.
2002 if (DirKind == OpenACCDirectiveKind::KernelsLoop && UnInstClauses.empty()) {
2003 // This handles the 'outer loop' part of this.
2004 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
2005 if (Itr != Clauses.end())
2006 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(), DirKind};
2007 }
2008
2009 if (UnInstClauses.empty()) {
2010 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
2011 if (Itr != Clauses.end())
2012 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
2013
2014 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
2015 if (Itr2 != Clauses.end())
2016 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
2017 }
2018 } else if (DirKind == OpenACCDirectiveKind::Loop) {
2019 CollectActiveReductionClauses(S.ActiveReductionClauses, Clauses);
2020 SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
2021 SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
2022
2023 // Set the active 'loop' location if there isn't a 'seq' on it, so we can
2024 // diagnose the for loops.
2025 SemaRef.LoopWithoutSeqInfo = {};
2026 if (Clauses.end() ==
2027 llvm::find_if(Clauses, llvm::IsaPred<OpenACCSeqClause>))
2028 SemaRef.LoopWithoutSeqInfo = {DirKind, DirLoc};
2029
2030 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
2031 // construct, the gang clause behaves as follows. ... The region of a loop
2032 // with a gang clause may not contain another loop with a gang clause unless
2033 // within a nested compute region.
2034 //
2035 // We don't bother doing this when this is a template instantiation, as
2036 // there is no reason to do these checks: the existance of a
2037 // gang/kernels/etc cannot be dependent.
2038 if (SemaRef.getActiveComputeConstructInfo().Kind ==
2040 UnInstClauses.empty()) {
2041 // This handles the 'outer loop' part of this.
2042 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCGangClause>);
2043 if (Itr != Clauses.end())
2044 SemaRef.LoopGangClauseOnKernel = {(*Itr)->getBeginLoc(),
2046 }
2047
2048 if (UnInstClauses.empty()) {
2049 auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
2050 if (Itr != Clauses.end())
2051 SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
2052
2053 auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
2054 if (Itr2 != Clauses.end())
2055 SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
2056 }
2057 }
2058}
2059
2061 ArrayRef<const OpenACCClause *> UnInstClauses,
2062 ArrayRef<OpenACCClause *> Clauses) {
2063
2064 // Reset this checking for loops that aren't covered in a RAII object.
2065 SemaRef.LoopInfo.CurLevelHasLoopAlready = false;
2066 SemaRef.CollapseInfo.CollapseDepthSatisfied = true;
2067 SemaRef.TileInfo.TileDepthSatisfied = true;
2068
2069 // We make sure to take an optional list of uninstantiated clauses, so that
2070 // we can check to make sure we don't 'double diagnose' in the event that
2071 // the value of 'N' was not dependent in a template. We also ensure during
2072 // Sema that there is only 1 collapse on each construct, so we can count on
2073 // the fact that if both find a 'collapse', that they are the same one.
2074 auto *CollapseClauseItr =
2075 llvm::find_if(Clauses, llvm::IsaPred<OpenACCCollapseClause>);
2076 auto *UnInstCollapseClauseItr =
2077 llvm::find_if(UnInstClauses, llvm::IsaPred<OpenACCCollapseClause>);
2078
2079 if (Clauses.end() == CollapseClauseItr)
2080 return;
2081
2082 OpenACCCollapseClause *CollapseClause =
2083 cast<OpenACCCollapseClause>(*CollapseClauseItr);
2084
2085 SemaRef.CollapseInfo.ActiveCollapse = CollapseClause;
2086 Expr *LoopCount = CollapseClause->getLoopCount();
2087
2088 // If the loop count is still instantiation dependent, setting the depth
2089 // counter isn't necessary, so return here.
2090 if (!LoopCount || LoopCount->isInstantiationDependent())
2091 return;
2092
2093 // Suppress diagnostics if we've done a 'transform' where the previous version
2094 // wasn't dependent, meaning we already diagnosed it.
2095 if (UnInstCollapseClauseItr != UnInstClauses.end() &&
2096 !cast<OpenACCCollapseClause>(*UnInstCollapseClauseItr)
2097 ->getLoopCount()
2098 ->isInstantiationDependent())
2099 return;
2100
2101 SemaRef.CollapseInfo.CollapseDepthSatisfied = false;
2102 SemaRef.CollapseInfo.CurCollapseCount =
2103 cast<ConstantExpr>(LoopCount)->getResultAsAPSInt();
2104 SemaRef.CollapseInfo.DirectiveKind = DirKind;
2105}
2106
2108 ArrayRef<const OpenACCClause *> UnInstClauses,
2109 ArrayRef<OpenACCClause *> Clauses) {
2110 // We don't diagnose if this is during instantiation, since the only thing we
2111 // care about is the number of arguments, which we can figure out without
2112 // instantiation, so we don't want to double-diagnose.
2113 if (UnInstClauses.size() > 0)
2114 return;
2115 auto *TileClauseItr =
2116 llvm::find_if(Clauses, llvm::IsaPred<OpenACCTileClause>);
2117
2118 if (Clauses.end() == TileClauseItr)
2119 return;
2120
2121 OpenACCTileClause *TileClause = cast<OpenACCTileClause>(*TileClauseItr);
2122 SemaRef.TileInfo.ActiveTile = TileClause;
2123 SemaRef.TileInfo.TileDepthSatisfied = false;
2124 SemaRef.TileInfo.CurTileCount = TileClause->getSizeExprs().size();
2125 SemaRef.TileInfo.DirectiveKind = DirKind;
2126}
2127
2129 if (DirKind == OpenACCDirectiveKind::Parallel ||
2130 DirKind == OpenACCDirectiveKind::Serial ||
2131 DirKind == OpenACCDirectiveKind::Kernels ||
2132 DirKind == OpenACCDirectiveKind::Loop ||
2136 SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
2137 SemaRef.LoopGangClauseOnKernel = OldLoopGangClauseOnKernel;
2138 SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
2139 SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;
2140 SemaRef.LoopWithoutSeqInfo = OldLoopWithoutSeqInfo;
2141 SemaRef.ActiveReductionClauses.swap(ActiveReductionClauses);
2142 } else if (DirKind == OpenACCDirectiveKind::Data ||
2143 DirKind == OpenACCDirectiveKind::HostData) {
2144 // Intentionally doesn't reset the Loop, Compute Construct, or reduction
2145 // effects.
2146 }
2147}
2148
2151 OpenACCParsedClause &Clause) {
2153 return nullptr;
2154
2155 // Diagnose that we don't support this clause on this directive.
2156 if (!doesClauseApplyToDirective(Clause.getDirectiveKind(),
2157 Clause.getClauseKind())) {
2158 Diag(Clause.getBeginLoc(), diag::err_acc_clause_appertainment)
2159 << Clause.getDirectiveKind() << Clause.getClauseKind();
2160 return nullptr;
2161 }
2162
2163 if (const auto *DevTypeClause =
2164 llvm::find_if(ExistingClauses,
2165 [&](const OpenACCClause *C) {
2166 return isa<OpenACCDeviceTypeClause>(C);
2167 });
2168 DevTypeClause != ExistingClauses.end()) {
2169 if (checkValidAfterDeviceType(
2170 *this, *cast<OpenACCDeviceTypeClause>(*DevTypeClause), Clause))
2171 return nullptr;
2172 }
2173
2174 SemaOpenACCClauseVisitor Visitor{*this, ExistingClauses};
2175 OpenACCClause *Result = Visitor.Visit(Clause);
2176 assert((!Result || Result->getClauseKind() == Clause.getClauseKind()) &&
2177 "Created wrong clause?");
2178
2179 if (Visitor.diagNotImplemented())
2180 Diag(Clause.getBeginLoc(), diag::warn_acc_clause_unimplemented)
2181 << Clause.getClauseKind();
2182
2183 return Result;
2184
2185}
2186
2187namespace {
2188// Return true if the two vars refer to the same variable, for the purposes of
2189// equality checking.
2190bool areVarsEqual(Expr *VarExpr1, Expr *VarExpr2) {
2191 if (VarExpr1->isInstantiationDependent() ||
2192 VarExpr2->isInstantiationDependent())
2193 return false;
2194
2195 VarExpr1 = VarExpr1->IgnoreParenCasts();
2196 VarExpr2 = VarExpr2->IgnoreParenCasts();
2197
2198 // Legal expressions can be: Scalar variable reference, sub-array, array
2199 // element, or composite variable member.
2200
2201 // Sub-array.
2202 if (isa<ArraySectionExpr>(VarExpr1)) {
2203 auto *Expr2AS = dyn_cast<ArraySectionExpr>(VarExpr2);
2204 if (!Expr2AS)
2205 return false;
2206
2207 auto *Expr1AS = cast<ArraySectionExpr>(VarExpr1);
2208
2209 if (!areVarsEqual(Expr1AS->getBase(), Expr2AS->getBase()))
2210 return false;
2211 // We could possibly check to see if the ranges aren't overlapping, but it
2212 // isn't clear that the rules allow this.
2213 return true;
2214 }
2215
2216 // Array-element.
2217 if (isa<ArraySubscriptExpr>(VarExpr1)) {
2218 auto *Expr2AS = dyn_cast<ArraySubscriptExpr>(VarExpr2);
2219 if (!Expr2AS)
2220 return false;
2221
2222 auto *Expr1AS = cast<ArraySubscriptExpr>(VarExpr1);
2223
2224 if (!areVarsEqual(Expr1AS->getBase(), Expr2AS->getBase()))
2225 return false;
2226
2227 // We could possibly check to see if the elements referenced aren't the
2228 // same, but it isn't clear by reading of the standard that this is allowed
2229 // (and that the 'var' refered to isn't the array).
2230 return true;
2231 }
2232
2233 // Scalar variable reference, or composite variable.
2234 if (isa<DeclRefExpr>(VarExpr1)) {
2235 auto *Expr2DRE = dyn_cast<DeclRefExpr>(VarExpr2);
2236 if (!Expr2DRE)
2237 return false;
2238
2239 auto *Expr1DRE = cast<DeclRefExpr>(VarExpr1);
2240
2241 return Expr1DRE->getDecl()->getMostRecentDecl() ==
2242 Expr2DRE->getDecl()->getMostRecentDecl();
2243 }
2244
2245 llvm_unreachable("Unknown variable type encountered");
2246}
2247} // namespace
2248
2249/// OpenACC 3.3 section 2.5.15:
2250/// At a mininmum, the supported data types include ... the numerical data types
2251/// in C, C++, and Fortran.
2252///
2253/// If the reduction var is a composite variable, each
2254/// member of the composite variable must be a supported datatype for the
2255/// reduction operation.
2257 OpenACCReductionOperator ReductionOp,
2258 Expr *VarExpr) {
2259 VarExpr = VarExpr->IgnoreParenCasts();
2260
2261 auto TypeIsValid = [](QualType Ty) {
2262 return Ty->isDependentType() || Ty->isScalarType();
2263 };
2264
2265 if (isa<ArraySectionExpr>(VarExpr)) {
2266 Expr *ASExpr = VarExpr;
2268 QualType EltTy = getASTContext().getBaseElementType(BaseTy);
2269
2270 if (!TypeIsValid(EltTy)) {
2271 Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type)
2272 << EltTy << /*Sub array base type*/ 1;
2273 return ExprError();
2274 }
2275 } else if (auto *RD = VarExpr->getType()->getAsRecordDecl()) {
2276 if (!RD->isStruct() && !RD->isClass()) {
2277 Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
2278 << /*not class or struct*/ 0 << VarExpr->getType();
2279 return ExprError();
2280 }
2281
2282 if (!RD->isCompleteDefinition()) {
2283 Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
2284 << /*incomplete*/ 1 << VarExpr->getType();
2285 return ExprError();
2286 }
2287 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
2288 CXXRD && !CXXRD->isAggregate()) {
2289 Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
2290 << /*aggregate*/ 2 << VarExpr->getType();
2291 return ExprError();
2292 }
2293
2294 for (FieldDecl *FD : RD->fields()) {
2295 if (!TypeIsValid(FD->getType())) {
2296 Diag(VarExpr->getExprLoc(),
2297 diag::err_acc_reduction_composite_member_type);
2298 Diag(FD->getLocation(), diag::note_acc_reduction_composite_member_loc);
2299 return ExprError();
2300 }
2301 }
2302 } else if (!TypeIsValid(VarExpr->getType())) {
2303 Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type)
2304 << VarExpr->getType() << /*Sub array base type*/ 0;
2305 return ExprError();
2306 }
2307
2308 // OpenACC3.3: 2.9.11: Reduction clauses on nested constructs for the same
2309 // reduction 'var' must have the same reduction operator.
2310 if (!VarExpr->isInstantiationDependent()) {
2311
2312 for (const OpenACCReductionClause *RClause : ActiveReductionClauses) {
2313 if (RClause->getReductionOp() == ReductionOp)
2314 break;
2315
2316 for (Expr *OldVarExpr : RClause->getVarList()) {
2317 if (OldVarExpr->isInstantiationDependent())
2318 continue;
2319
2320 if (areVarsEqual(VarExpr, OldVarExpr)) {
2321 Diag(VarExpr->getExprLoc(), diag::err_reduction_op_mismatch)
2322 << ReductionOp << RClause->getReductionOp();
2323 Diag(OldVarExpr->getExprLoc(), diag::note_acc_previous_clause_here);
2324 return ExprError();
2325 }
2326 }
2327 }
2328 }
2329
2330 return VarExpr;
2331}
2332
2334 SourceLocation DirLoc) {
2335 // Start an evaluation context to parse the clause arguments on.
2338
2339 switch (K) {
2341 // Nothing to do here, an invalid kind has nothing we can check here. We
2342 // want to continue parsing clauses as far as we can, so we will just
2343 // ensure that we can still work and don't check any construct-specific
2344 // rules anywhere.
2345 break;
2361 // Nothing to do here, there is no real legalization that needs to happen
2362 // here as these constructs do not take any arguments.
2363 break;
2365 // Nothing really to do here, the arguments to the 'wait' should have
2366 // already been handled by the time we get here.
2367 break;
2368 default:
2369 Diag(DirLoc, diag::warn_acc_construct_unimplemented) << K;
2370 break;
2371 }
2372}
2373
2376 Expr *IntExpr) {
2377
2378 assert(((DK != OpenACCDirectiveKind::Invalid &&
2384 "Only one of directive or clause kind should be provided");
2385
2386 class IntExprConverter : public Sema::ICEConvertDiagnoser {
2387 OpenACCDirectiveKind DirectiveKind;
2388 OpenACCClauseKind ClauseKind;
2389 Expr *IntExpr;
2390
2391 // gets the index into the diagnostics so we can use this for clauses,
2392 // directives, and sub array.s
2393 unsigned getDiagKind() const {
2394 if (ClauseKind != OpenACCClauseKind::Invalid)
2395 return 0;
2396 if (DirectiveKind != OpenACCDirectiveKind::Invalid)
2397 return 1;
2398 return 2;
2399 }
2400
2401 public:
2402 IntExprConverter(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
2403 Expr *IntExpr)
2404 : ICEConvertDiagnoser(/*AllowScopedEnumerations=*/false,
2405 /*Suppress=*/false,
2406 /*SuppressConversion=*/true),
2407 DirectiveKind(DK), ClauseKind(CK), IntExpr(IntExpr) {}
2408
2409 bool match(QualType T) override {
2410 // OpenACC spec just calls this 'integer expression' as having an
2411 // 'integer type', so fall back on C99's 'integer type'.
2412 return T->isIntegerType();
2413 }
2415 QualType T) override {
2416 return S.Diag(Loc, diag::err_acc_int_expr_requires_integer)
2417 << getDiagKind() << ClauseKind << DirectiveKind << T;
2418 }
2419
2421 diagnoseIncomplete(Sema &S, SourceLocation Loc, QualType T) override {
2422 return S.Diag(Loc, diag::err_acc_int_expr_incomplete_class_type)
2423 << T << IntExpr->getSourceRange();
2424 }
2425
2427 diagnoseExplicitConv(Sema &S, SourceLocation Loc, QualType T,
2428 QualType ConvTy) override {
2429 return S.Diag(Loc, diag::err_acc_int_expr_explicit_conversion)
2430 << T << ConvTy;
2431 }
2432
2433 SemaBase::SemaDiagnosticBuilder noteExplicitConv(Sema &S,
2434 CXXConversionDecl *Conv,
2435 QualType ConvTy) override {
2436 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
2437 << ConvTy->isEnumeralType() << ConvTy;
2438 }
2439
2441 diagnoseAmbiguous(Sema &S, SourceLocation Loc, QualType T) override {
2442 return S.Diag(Loc, diag::err_acc_int_expr_multiple_conversions) << T;
2443 }
2444
2446 noteAmbiguous(Sema &S, CXXConversionDecl *Conv, QualType ConvTy) override {
2447 return S.Diag(Conv->getLocation(), diag::note_acc_int_expr_conversion)
2448 << ConvTy->isEnumeralType() << ConvTy;
2449 }
2450
2452 diagnoseConversion(Sema &S, SourceLocation Loc, QualType T,
2453 QualType ConvTy) override {
2454 llvm_unreachable("conversion functions are permitted");
2455 }
2456 } IntExprDiagnoser(DK, CK, IntExpr);
2457
2458 if (!IntExpr)
2459 return ExprError();
2460
2462 Loc, IntExpr, IntExprDiagnoser);
2463 if (IntExprResult.isInvalid())
2464 return ExprError();
2465
2466 IntExpr = IntExprResult.get();
2467 if (!IntExpr->isTypeDependent() && !IntExpr->getType()->isIntegerType())
2468 return ExprError();
2469
2470 // TODO OpenACC: Do we want to perform usual unary conversions here? When
2471 // doing codegen we might find that is necessary, but skip it for now.
2472 return IntExpr;
2473}
2474
2476 Expr *VarExpr) {
2477 // We already know that VarExpr is a proper reference to a variable, so we
2478 // should be able to just take the type of the expression to get the type of
2479 // the referenced variable.
2480
2481 // We've already seen an error, don't diagnose anything else.
2482 if (!VarExpr || VarExpr->containsErrors())
2483 return false;
2484
2485 if (isa<ArraySectionExpr>(VarExpr->IgnoreParenImpCasts()) ||
2486 VarExpr->hasPlaceholderType(BuiltinType::ArraySection)) {
2487 Diag(VarExpr->getExprLoc(), diag::err_array_section_use) << /*OpenACC=*/0;
2488 Diag(VarExpr->getExprLoc(), diag::note_acc_expected_pointer_var);
2489 return true;
2490 }
2491
2492 QualType Ty = VarExpr->getType();
2494
2495 // Nothing we can do if this is a dependent type.
2496 if (Ty->isDependentType())
2497 return false;
2498
2499 if (!Ty->isPointerType())
2500 return Diag(VarExpr->getExprLoc(), diag::err_acc_var_not_pointer_type)
2501 << ClauseKind << Ty;
2502 return false;
2503}
2504
2506 Expr *CurVarExpr = VarExpr->IgnoreParenImpCasts();
2507
2508 // 'use_device' doesn't allow array subscript or array sections.
2509 // OpenACC3.3 2.8:
2510 // A 'var' in a 'use_device' clause must be the name of a variable or array.
2511 if (CK == OpenACCClauseKind::UseDevice &&
2512 isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
2513 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
2514 return ExprError();
2515 }
2516
2517 // Sub-arrays/subscript-exprs are fine as long as the base is a
2518 // VarExpr/MemberExpr. So strip all of those off.
2519 while (isa<ArraySectionExpr, ArraySubscriptExpr>(CurVarExpr)) {
2520 if (auto *SubScrpt = dyn_cast<ArraySubscriptExpr>(CurVarExpr))
2521 CurVarExpr = SubScrpt->getBase()->IgnoreParenImpCasts();
2522 else
2523 CurVarExpr =
2524 cast<ArraySectionExpr>(CurVarExpr)->getBase()->IgnoreParenImpCasts();
2525 }
2526
2527 // References to a VarDecl are fine.
2528 if (const auto *DRE = dyn_cast<DeclRefExpr>(CurVarExpr)) {
2529 if (isa<VarDecl, NonTypeTemplateParmDecl>(
2530 DRE->getFoundDecl()->getCanonicalDecl()))
2531 return VarExpr;
2532 }
2533
2534 // If CK is a Reduction, this special cases for OpenACC3.3 2.5.15: "A var in a
2535 // reduction clause must be a scalar variable name, an aggregate variable
2536 // name, an array element, or a subarray.
2537 // If CK is a 'use_device', this also isn't valid, as it isn' the name of a
2538 // variable or array.
2539 // A MemberExpr that references a Field is valid for other clauses.
2540 if (CK != OpenACCClauseKind::Reduction &&
2542 if (const auto *ME = dyn_cast<MemberExpr>(CurVarExpr)) {
2543 if (isa<FieldDecl>(ME->getMemberDecl()->getCanonicalDecl()))
2544 return VarExpr;
2545 }
2546 }
2547
2548 // Referring to 'this' is ok for the most part, but for 'use_device' doesn't
2549 // fall into 'variable or array name'
2550 if (CK != OpenACCClauseKind::UseDevice && isa<CXXThisExpr>(CurVarExpr))
2551 return VarExpr;
2552
2553 // Nothing really we can do here, as these are dependent. So just return they
2554 // are valid.
2555 if (isa<DependentScopeDeclRefExpr>(CurVarExpr) ||
2557 isa<CXXDependentScopeMemberExpr>(CurVarExpr)))
2558 return VarExpr;
2559
2560 // There isn't really anything we can do in the case of a recovery expr, so
2561 // skip the diagnostic rather than produce a confusing diagnostic.
2562 if (isa<RecoveryExpr>(CurVarExpr))
2563 return ExprError();
2564
2566 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref_use_device);
2567 else
2568 Diag(VarExpr->getExprLoc(), diag::err_acc_not_a_var_ref)
2570 return ExprError();
2571}
2572
2574 Expr *LowerBound,
2575 SourceLocation ColonLoc,
2576 Expr *Length,
2577 SourceLocation RBLoc) {
2578 ASTContext &Context = getASTContext();
2579
2580 // Handle placeholders.
2581 if (Base->hasPlaceholderType() &&
2582 !Base->hasPlaceholderType(BuiltinType::ArraySection)) {
2584 if (Result.isInvalid())
2585 return ExprError();
2586 Base = Result.get();
2587 }
2588 if (LowerBound && LowerBound->getType()->isNonOverloadPlaceholderType()) {
2590 if (Result.isInvalid())
2591 return ExprError();
2593 if (Result.isInvalid())
2594 return ExprError();
2595 LowerBound = Result.get();
2596 }
2597 if (Length && Length->getType()->isNonOverloadPlaceholderType()) {
2599 if (Result.isInvalid())
2600 return ExprError();
2602 if (Result.isInvalid())
2603 return ExprError();
2604 Length = Result.get();
2605 }
2606
2607 // Check the 'base' value, it must be an array or pointer type, and not to/of
2608 // a function type.
2610 QualType ResultTy;
2611 if (!Base->isTypeDependent()) {
2612 if (OriginalBaseTy->isAnyPointerType()) {
2613 ResultTy = OriginalBaseTy->getPointeeType();
2614 } else if (OriginalBaseTy->isArrayType()) {
2615 ResultTy = OriginalBaseTy->getAsArrayTypeUnsafe()->getElementType();
2616 } else {
2617 return ExprError(
2618 Diag(Base->getExprLoc(), diag::err_acc_typecheck_subarray_value)
2619 << Base->getSourceRange());
2620 }
2621
2622 if (ResultTy->isFunctionType()) {
2623 Diag(Base->getExprLoc(), diag::err_acc_subarray_function_type)
2624 << ResultTy << Base->getSourceRange();
2625 return ExprError();
2626 }
2627
2628 if (SemaRef.RequireCompleteType(Base->getExprLoc(), ResultTy,
2629 diag::err_acc_subarray_incomplete_type,
2630 Base))
2631 return ExprError();
2632
2633 if (!Base->hasPlaceholderType(BuiltinType::ArraySection)) {
2635 if (Result.isInvalid())
2636 return ExprError();
2637 Base = Result.get();
2638 }
2639 }
2640
2641 auto GetRecovery = [&](Expr *E, QualType Ty) {
2642 ExprResult Recovery =
2644 return Recovery.isUsable() ? Recovery.get() : nullptr;
2645 };
2646
2647 // Ensure both of the expressions are int-exprs.
2648 if (LowerBound && !LowerBound->isTypeDependent()) {
2649 ExprResult LBRes =
2651 LowerBound->getExprLoc(), LowerBound);
2652
2653 if (LBRes.isUsable())
2654 LBRes = SemaRef.DefaultLvalueConversion(LBRes.get());
2655 LowerBound =
2656 LBRes.isUsable() ? LBRes.get() : GetRecovery(LowerBound, Context.IntTy);
2657 }
2658
2659 if (Length && !Length->isTypeDependent()) {
2660 ExprResult LenRes =
2662 Length->getExprLoc(), Length);
2663
2664 if (LenRes.isUsable())
2665 LenRes = SemaRef.DefaultLvalueConversion(LenRes.get());
2666 Length =
2667 LenRes.isUsable() ? LenRes.get() : GetRecovery(Length, Context.IntTy);
2668 }
2669
2670 // Length is required if the base type is not an array of known bounds.
2671 if (!Length && (OriginalBaseTy.isNull() ||
2672 (!OriginalBaseTy->isDependentType() &&
2673 !OriginalBaseTy->isConstantArrayType() &&
2674 !OriginalBaseTy->isDependentSizedArrayType()))) {
2675 bool IsArray = !OriginalBaseTy.isNull() && OriginalBaseTy->isArrayType();
2676 Diag(ColonLoc, diag::err_acc_subarray_no_length) << IsArray;
2677 // Fill in a dummy 'length' so that when we instantiate this we don't
2678 // double-diagnose here.
2680 ColonLoc, SourceLocation(), ArrayRef<Expr *>(), Context.IntTy);
2681 Length = Recovery.isUsable() ? Recovery.get() : nullptr;
2682 }
2683
2684 // Check the values of each of the arguments, they cannot be negative(we
2685 // assume), and if the array bound is known, must be within range. As we do
2686 // so, do our best to continue with evaluation, we can set the
2687 // value/expression to nullptr/nullopt if they are invalid, and treat them as
2688 // not present for the rest of evaluation.
2689
2690 // We don't have to check for dependence, because the dependent size is
2691 // represented as a different AST node.
2692 std::optional<llvm::APSInt> BaseSize;
2693 if (!OriginalBaseTy.isNull() && OriginalBaseTy->isConstantArrayType()) {
2694 const auto *ArrayTy = Context.getAsConstantArrayType(OriginalBaseTy);
2695 BaseSize = ArrayTy->getSize();
2696 }
2697
2698 auto GetBoundValue = [&](Expr *E) -> std::optional<llvm::APSInt> {
2699 if (!E || E->isInstantiationDependent())
2700 return std::nullopt;
2701
2702 Expr::EvalResult Res;
2703 if (!E->EvaluateAsInt(Res, Context))
2704 return std::nullopt;
2705 return Res.Val.getInt();
2706 };
2707
2708 std::optional<llvm::APSInt> LowerBoundValue = GetBoundValue(LowerBound);
2709 std::optional<llvm::APSInt> LengthValue = GetBoundValue(Length);
2710
2711 // Check lower bound for negative or out of range.
2712 if (LowerBoundValue.has_value()) {
2713 if (LowerBoundValue->isNegative()) {
2714 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_negative)
2715 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10);
2716 LowerBoundValue.reset();
2717 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
2718 } else if (BaseSize.has_value() &&
2719 llvm::APSInt::compareValues(*LowerBoundValue, *BaseSize) >= 0) {
2720 // Lower bound (start index) must be less than the size of the array.
2721 Diag(LowerBound->getExprLoc(), diag::err_acc_subarray_out_of_range)
2722 << /*LowerBound=*/0 << toString(*LowerBoundValue, /*Radix=*/10)
2723 << toString(*BaseSize, /*Radix=*/10);
2724 LowerBoundValue.reset();
2725 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
2726 }
2727 }
2728
2729 // Check length for negative or out of range.
2730 if (LengthValue.has_value()) {
2731 if (LengthValue->isNegative()) {
2732 Diag(Length->getExprLoc(), diag::err_acc_subarray_negative)
2733 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10);
2734 LengthValue.reset();
2735 Length = GetRecovery(Length, Length->getType());
2736 } else if (BaseSize.has_value() &&
2737 llvm::APSInt::compareValues(*LengthValue, *BaseSize) > 0) {
2738 // Length must be lessthan or EQUAL to the size of the array.
2739 Diag(Length->getExprLoc(), diag::err_acc_subarray_out_of_range)
2740 << /*Length=*/1 << toString(*LengthValue, /*Radix=*/10)
2741 << toString(*BaseSize, /*Radix=*/10);
2742 LengthValue.reset();
2743 Length = GetRecovery(Length, Length->getType());
2744 }
2745 }
2746
2747 // Adding two APSInts requires matching sign, so extract that here.
2748 auto AddAPSInt = [](llvm::APSInt LHS, llvm::APSInt RHS) -> llvm::APSInt {
2749 if (LHS.isSigned() == RHS.isSigned())
2750 return LHS + RHS;
2751
2752 unsigned Width = std::max(LHS.getBitWidth(), RHS.getBitWidth()) + 1;
2753 return llvm::APSInt(LHS.sext(Width) + RHS.sext(Width), /*Signed=*/true);
2754 };
2755
2756 // If we know all 3 values, we can diagnose that the total value would be out
2757 // of range.
2758 if (BaseSize.has_value() && LowerBoundValue.has_value() &&
2759 LengthValue.has_value() &&
2760 llvm::APSInt::compareValues(AddAPSInt(*LowerBoundValue, *LengthValue),
2761 *BaseSize) > 0) {
2762 Diag(Base->getExprLoc(),
2763 diag::err_acc_subarray_base_plus_length_out_of_range)
2764 << toString(*LowerBoundValue, /*Radix=*/10)
2765 << toString(*LengthValue, /*Radix=*/10)
2766 << toString(*BaseSize, /*Radix=*/10);
2767
2768 LowerBoundValue.reset();
2769 LowerBound = GetRecovery(LowerBound, LowerBound->getType());
2770 LengthValue.reset();
2771 Length = GetRecovery(Length, Length->getType());
2772 }
2773
2774 // If any part of the expression is dependent, return a dependent sub-array.
2775 QualType ArrayExprTy = Context.ArraySectionTy;
2776 if (Base->isTypeDependent() ||
2777 (LowerBound && LowerBound->isInstantiationDependent()) ||
2778 (Length && Length->isInstantiationDependent()))
2779 ArrayExprTy = Context.DependentTy;
2780
2781 return new (Context)
2782 ArraySectionExpr(Base, LowerBound, Length, ArrayExprTy, VK_LValue,
2783 OK_Ordinary, ColonLoc, RBLoc);
2784}
2785
2787 if (!LoopCount)
2788 return ExprError();
2789
2790 assert((LoopCount->isInstantiationDependent() ||
2791 LoopCount->getType()->isIntegerType()) &&
2792 "Loop argument non integer?");
2793
2794 // If this is dependent, there really isn't anything we can check.
2795 if (LoopCount->isInstantiationDependent())
2796 return ExprResult{LoopCount};
2797
2798 std::optional<llvm::APSInt> ICE =
2800
2801 // OpenACC 3.3: 2.9.1
2802 // The argument to the collapse clause must be a constant positive integer
2803 // expression.
2804 if (!ICE || *ICE <= 0) {
2805 Diag(LoopCount->getBeginLoc(), diag::err_acc_collapse_loop_count)
2806 << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
2807 return ExprError();
2808 }
2809
2810 return ExprResult{
2811 ConstantExpr::Create(getASTContext(), LoopCount, APValue{*ICE})};
2812}
2813
2817 Expr *E) {
2818 // There are two cases for the enforcement here: the 'current' directive is a
2819 // 'loop', where we need to check the active compute construct kind, or the
2820 // current directive is a 'combined' construct, where we have to check the
2821 // current one.
2822 switch (DK) {
2824 return CheckGangParallelExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2825 E);
2827 return CheckGangSerialExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2828 E);
2830 return CheckGangKernelsExpr(*this, ExistingClauses, DK,
2831 ActiveComputeConstructInfo.Kind, GK, E);
2833 switch (ActiveComputeConstructInfo.Kind) {
2837 return CheckGangParallelExpr(*this, DK, ActiveComputeConstructInfo.Kind,
2838 GK, E);
2841 return CheckGangSerialExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2842 E);
2845 return CheckGangKernelsExpr(*this, ExistingClauses, DK,
2846 ActiveComputeConstructInfo.Kind, GK, E);
2847 default:
2848 llvm_unreachable("Non compute construct in active compute construct?");
2849 }
2850 default:
2851 // TODO: OpenACC: when we implement this on 'routine', we'll have to
2852 // implement its checking here.
2853 llvm_unreachable("Invalid directive kind for a Gang clause");
2854 }
2855 llvm_unreachable("Compute construct directive not handled?");
2856}
2857
2860 ArrayRef<const OpenACCClause *> ExistingClauses,
2861 SourceLocation BeginLoc, SourceLocation LParenLoc,
2862 ArrayRef<OpenACCGangKind> GangKinds,
2863 ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) {
2864 // OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
2865 // that has a gang clause with a dim: argument whose value is greater than 1.
2866
2867 const auto *ReductionItr =
2868 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
2869
2870 if (ReductionItr != ExistingClauses.end()) {
2871 const auto GangZip = llvm::zip_equal(GangKinds, IntExprs);
2872 const auto GangItr = llvm::find_if(GangZip, [](const auto &Tuple) {
2873 return std::get<0>(Tuple) == OpenACCGangKind::Dim;
2874 });
2875
2876 if (GangItr != GangZip.end()) {
2877 const Expr *DimExpr = std::get<1>(*GangItr);
2878
2879 assert(
2880 (DimExpr->isInstantiationDependent() || isa<ConstantExpr>(DimExpr)) &&
2881 "Improperly formed gang argument");
2882 if (const auto *DimVal = dyn_cast<ConstantExpr>(DimExpr);
2883 DimVal && DimVal->getResultAsAPSInt() > 1) {
2884 Diag(DimVal->getBeginLoc(), diag::err_acc_gang_reduction_conflict)
2885 << /*gang/reduction=*/0 << DirKind;
2886 Diag((*ReductionItr)->getBeginLoc(),
2887 diag::note_acc_previous_clause_here);
2888 return nullptr;
2889 }
2890 }
2891 }
2892
2893 return OpenACCGangClause::Create(getASTContext(), BeginLoc, LParenLoc,
2894 GangKinds, IntExprs, EndLoc);
2895}
2896
2898 ArrayRef<const OpenACCClause *> ExistingClauses,
2899 OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc,
2900 SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp,
2901 ArrayRef<Expr *> Vars, SourceLocation EndLoc) {
2902 if (DirectiveKind == OpenACCDirectiveKind::Loop ||
2903 isOpenACCCombinedDirectiveKind(DirectiveKind)) {
2904 // OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
2905 // that has a gang clause with a dim: argument whose value is greater
2906 // than 1.
2907 const auto GangClauses = llvm::make_filter_range(
2908 ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
2909
2910 for (auto *GC : GangClauses) {
2911 const auto *GangClause = cast<OpenACCGangClause>(GC);
2912 for (unsigned I = 0; I < GangClause->getNumExprs(); ++I) {
2913 std::pair<OpenACCGangKind, const Expr *> EPair = GangClause->getExpr(I);
2914 if (EPair.first != OpenACCGangKind::Dim)
2915 continue;
2916
2917 if (const auto *DimVal = dyn_cast<ConstantExpr>(EPair.second);
2918 DimVal && DimVal->getResultAsAPSInt() > 1) {
2919 Diag(BeginLoc, diag::err_acc_gang_reduction_conflict)
2920 << /*reduction/gang=*/1 << DirectiveKind;
2921 Diag(GangClause->getBeginLoc(), diag::note_acc_previous_clause_here);
2922 return nullptr;
2923 }
2924 }
2925 }
2926 }
2927
2929 getASTContext(), BeginLoc, LParenLoc, ReductionOp, Vars, EndLoc);
2930 return Ret;
2931}
2932
2934 if (!SizeExpr)
2935 return ExprError();
2936
2937 assert((SizeExpr->isInstantiationDependent() ||
2938 SizeExpr->getType()->isIntegerType()) &&
2939 "size argument non integer?");
2940
2941 // If dependent, or an asterisk, the expression is fine.
2942 if (SizeExpr->isInstantiationDependent() ||
2943 isa<OpenACCAsteriskSizeExpr>(SizeExpr))
2944 return ExprResult{SizeExpr};
2945
2946 std::optional<llvm::APSInt> ICE =
2948
2949 // OpenACC 3.3 2.9.8
2950 // where each tile size is a constant positive integer expression or asterisk.
2951 if (!ICE || *ICE <= 0) {
2952 Diag(SizeExpr->getBeginLoc(), diag::err_acc_size_expr_value)
2953 << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
2954 return ExprError();
2955 }
2956
2957 return ExprResult{
2958 ConstantExpr::Create(getASTContext(), SizeExpr, APValue{*ICE})};
2959}
2960
2962 if (!getLangOpts().OpenACC)
2963 return;
2964
2965 if (!LoopInfo.TopLevelLoopSeen)
2966 return;
2967
2968 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
2969 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
2970 << /*while loop*/ 1 << CollapseInfo.DirectiveKind
2972 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
2973 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
2974 diag::note_acc_active_clause_here)
2976
2977 // Remove the value so that we don't get cascading errors in the body. The
2978 // caller RAII object will restore this.
2979 CollapseInfo.CurCollapseCount = std::nullopt;
2980 }
2981
2982 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
2983 Diag(WhileLoc, diag::err_acc_invalid_in_loop)
2984 << /*while loop*/ 1 << TileInfo.DirectiveKind
2986 assert(TileInfo.ActiveTile && "tile count without object?");
2987 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
2989
2990 // Remove the value so that we don't get cascading errors in the body. The
2991 // caller RAII object will restore this.
2992 TileInfo.CurTileCount = std::nullopt;
2993 }
2994}
2995
2997 if (!getLangOpts().OpenACC)
2998 return;
2999
3000 if (!LoopInfo.TopLevelLoopSeen)
3001 return;
3002
3003 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
3004 Diag(DoLoc, diag::err_acc_invalid_in_loop)
3005 << /*do loop*/ 2 << CollapseInfo.DirectiveKind
3007 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
3008 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
3009 diag::note_acc_active_clause_here)
3011
3012 // Remove the value so that we don't get cascading errors in the body. The
3013 // caller RAII object will restore this.
3014 CollapseInfo.CurCollapseCount = std::nullopt;
3015 }
3016
3017 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
3018 Diag(DoLoc, diag::err_acc_invalid_in_loop)
3019 << /*do loop*/ 2 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
3020 assert(TileInfo.ActiveTile && "tile count without object?");
3021 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
3023
3024 // Remove the value so that we don't get cascading errors in the body. The
3025 // caller RAII object will restore this.
3026 TileInfo.CurTileCount = std::nullopt;
3027 }
3028}
3029
3030void SemaOpenACC::ForStmtBeginHelper(SourceLocation ForLoc,
3031 ForStmtBeginChecker &C) {
3032 assert(getLangOpts().OpenACC && "Check enabled when not OpenACC?");
3033
3034 // Enable the while/do-while checking.
3035 LoopInfo.TopLevelLoopSeen = true;
3036
3037 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
3038 C.check();
3039
3040 // OpenACC 3.3 2.9.1:
3041 // Each associated loop, except the innermost, must contain exactly one loop
3042 // or loop nest.
3043 // This checks for more than 1 loop at the current level, the
3044 // 'depth'-satisifed checking manages the 'not zero' case.
3045 if (LoopInfo.CurLevelHasLoopAlready) {
3046 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
3047 << CollapseInfo.DirectiveKind << OpenACCClauseKind::Collapse;
3048 assert(CollapseInfo.ActiveCollapse && "No collapse object?");
3049 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
3050 diag::note_acc_active_clause_here)
3052 } else {
3053 --(*CollapseInfo.CurCollapseCount);
3054
3055 // Once we've hit zero here, we know we have deep enough 'for' loops to
3056 // get to the bottom.
3057 if (*CollapseInfo.CurCollapseCount == 0)
3058 CollapseInfo.CollapseDepthSatisfied = true;
3059 }
3060 }
3061
3062 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
3063 C.check();
3064
3065 if (LoopInfo.CurLevelHasLoopAlready) {
3066 Diag(ForLoc, diag::err_acc_clause_multiple_loops)
3067 << TileInfo.DirectiveKind << OpenACCClauseKind::Tile;
3068 assert(TileInfo.ActiveTile && "No tile object?");
3069 Diag(TileInfo.ActiveTile->getBeginLoc(),
3070 diag::note_acc_active_clause_here)
3072 } else {
3073 --(*TileInfo.CurTileCount);
3074 // Once we've hit zero here, we know we have deep enough 'for' loops to
3075 // get to the bottom.
3076 if (*TileInfo.CurTileCount == 0)
3077 TileInfo.TileDepthSatisfied = true;
3078 }
3079 }
3080
3081 // Set this to 'false' for the body of this loop, so that the next level
3082 // checks independently.
3083 LoopInfo.CurLevelHasLoopAlready = false;
3084}
3085
3086namespace {
3087bool isValidLoopVariableType(QualType LoopVarTy) {
3088 // Just skip if it is dependent, it could be any of the below.
3089 if (LoopVarTy->isDependentType())
3090 return true;
3091
3092 // The loop variable must be of integer,
3093 if (LoopVarTy->isIntegerType())
3094 return true;
3095
3096 // C/C++ pointer,
3097 if (LoopVarTy->isPointerType())
3098 return true;
3099
3100 // or C++ random-access iterator type.
3101 if (const auto *RD = LoopVarTy->getAsCXXRecordDecl()) {
3102 // Note: Only do CXXRecordDecl because RecordDecl can't be a random access
3103 // iterator type!
3104
3105 // We could either do a lot of work to see if this matches
3106 // random-access-iterator, but it seems that just checking that the
3107 // 'iterator_category' typedef is more than sufficient. If programmers are
3108 // willing to lie about this, we can let them.
3109
3110 for (const auto *TD :
3111 llvm::make_filter_range(RD->decls(), llvm::IsaPred<TypedefNameDecl>)) {
3112 const auto *TDND = cast<TypedefNameDecl>(TD)->getCanonicalDecl();
3113
3114 if (TDND->getName() != "iterator_category")
3115 continue;
3116
3117 // If there is no type for this decl, return false.
3118 if (TDND->getUnderlyingType().isNull())
3119 return false;
3120
3121 const CXXRecordDecl *ItrCategoryDecl =
3122 TDND->getUnderlyingType()->getAsCXXRecordDecl();
3123
3124 // If the category isn't a record decl, it isn't the tag type.
3125 if (!ItrCategoryDecl)
3126 return false;
3127
3128 auto IsRandomAccessIteratorTag = [](const CXXRecordDecl *RD) {
3129 if (RD->getName() != "random_access_iterator_tag")
3130 return false;
3131 // Checks just for std::random_access_iterator_tag.
3133 };
3134
3135 if (IsRandomAccessIteratorTag(ItrCategoryDecl))
3136 return true;
3137
3138 // We can also support types inherited from the
3139 // random_access_iterator_tag.
3140 for (CXXBaseSpecifier BS : ItrCategoryDecl->bases()) {
3141
3142 if (IsRandomAccessIteratorTag(BS.getType()->getAsCXXRecordDecl()))
3143 return true;
3144 }
3145
3146 return false;
3147 }
3148 }
3149
3150 return false;
3151}
3152
3153} // namespace
3154
3155void SemaOpenACC::ForStmtBeginChecker::check() {
3156 if (SemaRef.LoopWithoutSeqInfo.Kind == OpenACCDirectiveKind::Invalid)
3157 return;
3158
3159 if (AlreadyChecked)
3160 return;
3161 AlreadyChecked = true;
3162
3163 // OpenACC3.3 2.1:
3164 // A loop associated with a loop construct that does not have a seq clause
3165 // must be written to meet all the following conditions:
3166 // - The loop variable must be of integer, C/C++ pointer, or C++ random-access
3167 // iterator type.
3168 // - The loop variable must monotonically increase or decrease in the
3169 // direction of its termination condition.
3170 // - The loop trip count must be computable in constant time when entering the
3171 // loop construct.
3172 //
3173 // For a C++ range-based for loop, the loop variable
3174 // identified by the above conditions is the internal iterator, such as a
3175 // pointer, that the compiler generates to iterate the range. it is not the
3176 // variable declared by the for loop.
3177
3178 if (IsRangeFor) {
3179 // If the range-for is being instantiated and didn't change, don't
3180 // re-diagnose.
3181 if (!RangeFor.has_value())
3182 return;
3183 // For a range-for, we can assume everything is 'corect' other than the type
3184 // of the iterator, so check that.
3185 const DeclStmt *RangeStmt = (*RangeFor)->getBeginStmt();
3186
3187 // In some dependent contexts, the autogenerated range statement doesn't get
3188 // included until instantiation, so skip for now.
3189 if (!RangeStmt)
3190 return;
3191
3192 const ValueDecl *InitVar = cast<ValueDecl>(RangeStmt->getSingleDecl());
3193 QualType VarType = InitVar->getType().getNonReferenceType();
3194 if (!isValidLoopVariableType(VarType)) {
3195 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
3196 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
3197 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
3198 diag::note_acc_construct_here)
3199 << SemaRef.LoopWithoutSeqInfo.Kind;
3200 }
3201 return;
3202 }
3203
3204 // Else we are in normal 'ForStmt', so we can diagnose everything.
3205 // We only have to check cond/inc if they have changed, but 'init' needs to
3206 // just suppress its diagnostics if it hasn't changed.
3207 const ValueDecl *InitVar = checkInit();
3208 if (Cond.has_value())
3209 checkCond();
3210 if (Inc.has_value())
3211 checkInc(InitVar);
3212}
3213const ValueDecl *SemaOpenACC::ForStmtBeginChecker::checkInit() {
3214 if (!Init) {
3215 if (InitChanged) {
3216 SemaRef.Diag(ForLoc, diag::err_acc_loop_variable)
3217 << SemaRef.LoopWithoutSeqInfo.Kind;
3218 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
3219 diag::note_acc_construct_here)
3220 << SemaRef.LoopWithoutSeqInfo.Kind;
3221 }
3222 return nullptr;
3223 }
3224
3225 auto DiagLoopVar = [&]() {
3226 if (InitChanged) {
3227 SemaRef.Diag(Init->getBeginLoc(), diag::err_acc_loop_variable)
3228 << SemaRef.LoopWithoutSeqInfo.Kind;
3229 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
3230 diag::note_acc_construct_here)
3231 << SemaRef.LoopWithoutSeqInfo.Kind;
3232 }
3233 return nullptr;
3234 };
3235
3236 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(Init))
3237 Init = ExprTemp->getSubExpr();
3238 if (const auto *E = dyn_cast<Expr>(Init))
3240
3241 const ValueDecl *InitVar = nullptr;
3242
3243 if (const auto *BO = dyn_cast<BinaryOperator>(Init)) {
3244 // Allow assignment operator here.
3245
3246 if (!BO->isAssignmentOp())
3247 return DiagLoopVar();
3248
3249 const Expr *LHS = BO->getLHS()->IgnoreParenImpCasts();
3250
3251 if (const auto *DRE = dyn_cast<DeclRefExpr>(LHS))
3252 InitVar = DRE->getDecl();
3253 } else if (const auto *DS = dyn_cast<DeclStmt>(Init)) {
3254 // Allow T t = <whatever>
3255 if (!DS->isSingleDecl())
3256 return DiagLoopVar();
3257
3258 InitVar = dyn_cast<ValueDecl>(DS->getSingleDecl());
3259
3260 // Ensure we have an initializer, unless this is a record/dependent type.
3261
3262 if (InitVar) {
3263 if (!isa<VarDecl>(InitVar))
3264 return DiagLoopVar();
3265
3266 if (!InitVar->getType()->isRecordType() &&
3267 !InitVar->getType()->isDependentType() &&
3268 !cast<VarDecl>(InitVar)->hasInit())
3269 return DiagLoopVar();
3270 }
3271 } else if (auto *CE = dyn_cast<CXXOperatorCallExpr>(Init)) {
3272 // Allow assignment operator call.
3273 if (CE->getOperator() != OO_Equal)
3274 return DiagLoopVar();
3275
3276 const Expr *LHS = CE->getArg(0)->IgnoreParenImpCasts();
3277
3278 if (auto *DRE = dyn_cast<DeclRefExpr>(LHS)) {
3279 InitVar = DRE->getDecl();
3280 } else if (auto *ME = dyn_cast<MemberExpr>(LHS)) {
3281 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
3282 InitVar = ME->getMemberDecl();
3283 }
3284 }
3285
3286 if (!InitVar)
3287 return DiagLoopVar();
3288
3289 InitVar = cast<ValueDecl>(InitVar->getCanonicalDecl());
3290 QualType VarType = InitVar->getType().getNonReferenceType();
3291
3292 // Since we have one, all we need to do is ensure it is the right type.
3293 if (!isValidLoopVariableType(VarType)) {
3294 if (InitChanged) {
3295 SemaRef.Diag(InitVar->getBeginLoc(), diag::err_acc_loop_variable_type)
3296 << SemaRef.LoopWithoutSeqInfo.Kind << VarType;
3297 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc,
3298 diag::note_acc_construct_here)
3299 << SemaRef.LoopWithoutSeqInfo.Kind;
3300 }
3301 return nullptr;
3302 }
3303
3304 return InitVar;
3305}
3306void SemaOpenACC::ForStmtBeginChecker::checkCond() {
3307 if (!*Cond) {
3308 SemaRef.Diag(ForLoc, diag::err_acc_loop_terminating_condition)
3309 << SemaRef.LoopWithoutSeqInfo.Kind;
3310 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
3311 << SemaRef.LoopWithoutSeqInfo.Kind;
3312 }
3313 // Nothing else to do here. we could probably do some additional work to look
3314 // into the termination condition, but that error-prone. For now, we don't
3315 // implement anything other than 'there is a termination condition', and if
3316 // codegen/MLIR comes up with some necessary restrictions, we can implement
3317 // them here.
3318}
3319
3320void SemaOpenACC::ForStmtBeginChecker::checkInc(const ValueDecl *Init) {
3321
3322 if (!*Inc) {
3323 SemaRef.Diag(ForLoc, diag::err_acc_loop_not_monotonic)
3324 << SemaRef.LoopWithoutSeqInfo.Kind;
3325 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
3326 << SemaRef.LoopWithoutSeqInfo.Kind;
3327 return;
3328 }
3329 auto DiagIncVar = [this] {
3330 SemaRef.Diag((*Inc)->getBeginLoc(), diag::err_acc_loop_not_monotonic)
3331 << SemaRef.LoopWithoutSeqInfo.Kind;
3332 SemaRef.Diag(SemaRef.LoopWithoutSeqInfo.Loc, diag::note_acc_construct_here)
3333 << SemaRef.LoopWithoutSeqInfo.Kind;
3334 return;
3335 };
3336
3337 if (const auto *ExprTemp = dyn_cast<ExprWithCleanups>(*Inc))
3338 Inc = ExprTemp->getSubExpr();
3339 if (const auto *E = dyn_cast<Expr>(*Inc))
3341
3342 auto getDeclFromExpr = [](const Expr *E) -> const ValueDecl * {
3343 E = E->IgnoreParenImpCasts();
3344 if (const auto *FE = dyn_cast<FullExpr>(E))
3345 E = FE->getSubExpr();
3346
3347 E = E->IgnoreParenImpCasts();
3348
3349 if (!E)
3350 return nullptr;
3351 if (const auto *DRE = dyn_cast<DeclRefExpr>(E))
3352 return dyn_cast<ValueDecl>(DRE->getDecl());
3353
3354 if (const auto *ME = dyn_cast<MemberExpr>(E))
3355 if (isa<CXXThisExpr>(ME->getBase()->IgnoreParenImpCasts()))
3356 return ME->getMemberDecl();
3357
3358 return nullptr;
3359 };
3360
3361 const ValueDecl *IncVar = nullptr;
3362
3363 // Here we enforce the monotonically increase/decrease:
3364 if (const auto *UO = dyn_cast<UnaryOperator>(*Inc)) {
3365 // Allow increment/decrement ops.
3366 if (!UO->isIncrementDecrementOp())
3367 return DiagIncVar();
3368 IncVar = getDeclFromExpr(UO->getSubExpr());
3369 } else if (const auto *BO = dyn_cast<BinaryOperator>(*Inc)) {
3370 switch (BO->getOpcode()) {
3371 default:
3372 return DiagIncVar();
3373 case BO_AddAssign:
3374 case BO_SubAssign:
3375 case BO_MulAssign:
3376 case BO_DivAssign:
3377 case BO_Assign:
3378 // += -= *= /= should all be fine here, this should be all of the
3379 // 'monotonical' compound-assign ops.
3380 // Assignment we just give up on, we could do better, and ensure that it
3381 // is a binary/operator expr doing more work, but that seems like a lot
3382 // of work for an error prone check.
3383 break;
3384 }
3385 IncVar = getDeclFromExpr(BO->getLHS());
3386 } else if (const auto *CE = dyn_cast<CXXOperatorCallExpr>(*Inc)) {
3387 switch (CE->getOperator()) {
3388 default:
3389 return DiagIncVar();
3390 case OO_PlusPlus:
3391 case OO_MinusMinus:
3392 case OO_PlusEqual:
3393 case OO_MinusEqual:
3394 case OO_StarEqual:
3395 case OO_SlashEqual:
3396 case OO_Equal:
3397 // += -= *= /= should all be fine here, this should be all of the
3398 // 'monotonical' compound-assign ops.
3399 // Assignment we just give up on, we could do better, and ensure that it
3400 // is a binary/operator expr doing more work, but that seems like a lot
3401 // of work for an error prone check.
3402 break;
3403 }
3404
3405 IncVar = getDeclFromExpr(CE->getArg(0));
3406
3407 } else if (const auto *ME = dyn_cast<CXXMemberCallExpr>(*Inc)) {
3408 IncVar = getDeclFromExpr(ME->getImplicitObjectArgument());
3409 // We can't really do much for member expressions, other than hope they are
3410 // doing the right thing, so give up here.
3411 }
3412
3413 if (!IncVar)
3414 return DiagIncVar();
3415
3416 // InitVar shouldn't be null unless there was an error, so don't diagnose if
3417 // that is the case. Else we should ensure that it refers to the loop
3418 // value.
3419 if (Init && IncVar->getCanonicalDecl() != Init->getCanonicalDecl())
3420 return DiagIncVar();
3421
3422 return;
3423}
3424
3426 const Stmt *First, const Stmt *OldSecond,
3427 const Stmt *Second, const Stmt *OldThird,
3428 const Stmt *Third) {
3429 if (!getLangOpts().OpenACC)
3430 return;
3431
3432 std::optional<const Stmt *> S;
3433 if (OldSecond == Second)
3434 S = std::nullopt;
3435 else
3436 S = Second;
3437 std::optional<const Stmt *> T;
3438 if (OldThird == Third)
3439 S = std::nullopt;
3440 else
3441 S = Third;
3442
3443 bool InitChanged = false;
3444 if (OldFirst != First) {
3445 InitChanged = true;
3446
3447 // VarDecls are always rebuild because they are dependent, so we can do a
3448 // little work to suppress some of the double checking based on whether the
3449 // type is instantiation dependent.
3450 QualType OldVDTy;
3451 QualType NewVDTy;
3452 if (const auto *DS = dyn_cast<DeclStmt>(OldFirst))
3453 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
3454 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
3455 OldVDTy = VD->getType();
3456 if (const auto *DS = dyn_cast<DeclStmt>(First))
3457 if (const VarDecl *VD = dyn_cast_if_present<VarDecl>(
3458 DS->isSingleDecl() ? DS->getSingleDecl() : nullptr))
3459 NewVDTy = VD->getType();
3460
3461 if (!OldVDTy.isNull() && !NewVDTy.isNull())
3462 InitChanged = OldVDTy->isInstantiationDependentType() !=
3464 }
3465
3466 ForStmtBeginChecker FSBC{*this, ForLoc, First, InitChanged, S, T};
3467 if (!LoopInfo.TopLevelLoopSeen) {
3468 FSBC.check();
3469 }
3470
3471 ForStmtBeginHelper(ForLoc, FSBC);
3472}
3473
3475 const Stmt *Second, const Stmt *Third) {
3476 if (!getLangOpts().OpenACC)
3477 return;
3478
3479 ForStmtBeginChecker FSBC{*this, ForLoc, First, /*InitChanged=*/true,
3480 Second, Third};
3481 if (!LoopInfo.TopLevelLoopSeen) {
3482 FSBC.check();
3483 }
3484
3485 ForStmtBeginHelper(ForLoc, FSBC);
3486}
3487
3489 const Stmt *OldRangeFor,
3490 const Stmt *RangeFor) {
3491 if (!getLangOpts().OpenACC)
3492 return;
3493
3494 std::optional<const CXXForRangeStmt *> RF;
3495
3496 if (OldRangeFor == RangeFor)
3497 RF = std::nullopt;
3498 else
3499 RF = cast<CXXForRangeStmt>(RangeFor);
3500
3501 ForStmtBeginChecker FSBC{*this, ForLoc, RF};
3502 if (!LoopInfo.TopLevelLoopSeen) {
3503 FSBC.check();
3504 }
3505 ForStmtBeginHelper(ForLoc, FSBC);
3506}
3507
3509 const Stmt *RangeFor) {
3510 if (!getLangOpts().OpenACC)
3511 return;
3512
3513 ForStmtBeginChecker FSBC{*this, ForLoc, cast<CXXForRangeStmt>(RangeFor)};
3514 if (!LoopInfo.TopLevelLoopSeen) {
3515 FSBC.check();
3516 }
3517 ForStmtBeginHelper(ForLoc, FSBC);
3518}
3519
3520namespace {
3521SourceLocation FindInterveningCodeInLoop(const Stmt *CurStmt) {
3522 // We should diagnose on anything except `CompoundStmt`, `NullStmt`,
3523 // `ForStmt`, `CXXForRangeStmt`, since those are legal, and `WhileStmt` and
3524 // `DoStmt`, as those are caught as a violation elsewhere.
3525 // For `CompoundStmt` we need to search inside of it.
3526 if (!CurStmt ||
3527 isa<ForStmt, NullStmt, ForStmt, CXXForRangeStmt, WhileStmt, DoStmt>(
3528 CurStmt))
3529 return SourceLocation{};
3530
3531 // Any other construct is an error anyway, so it has already been diagnosed.
3532 if (isa<OpenACCConstructStmt>(CurStmt))
3533 return SourceLocation{};
3534
3535 // Search inside the compound statement, this allows for arbitrary nesting
3536 // of compound statements, as long as there isn't any code inside.
3537 if (const auto *CS = dyn_cast<CompoundStmt>(CurStmt)) {
3538 for (const auto *ChildStmt : CS->children()) {
3539 SourceLocation ChildStmtLoc = FindInterveningCodeInLoop(ChildStmt);
3540 if (ChildStmtLoc.isValid())
3541 return ChildStmtLoc;
3542 }
3543 // Empty/not invalid compound statements are legal.
3544 return SourceLocation{};
3545 }
3546 return CurStmt->getBeginLoc();
3547}
3548} // namespace
3549
3551 if (!getLangOpts().OpenACC)
3552 return;
3553
3554 // Set this to 'true' so if we find another one at this level we can diagnose.
3555 LoopInfo.CurLevelHasLoopAlready = true;
3556
3557 if (!Body.isUsable())
3558 return;
3559
3560 bool IsActiveCollapse = CollapseInfo.CurCollapseCount &&
3561 *CollapseInfo.CurCollapseCount > 0 &&
3562 !CollapseInfo.ActiveCollapse->hasForce();
3563 bool IsActiveTile = TileInfo.CurTileCount && *TileInfo.CurTileCount > 0;
3564
3565 if (IsActiveCollapse || IsActiveTile) {
3566 SourceLocation OtherStmtLoc = FindInterveningCodeInLoop(Body.get());
3567
3568 if (OtherStmtLoc.isValid() && IsActiveCollapse) {
3569 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
3570 << OpenACCClauseKind::Collapse << CollapseInfo.DirectiveKind;
3571 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
3572 diag::note_acc_active_clause_here)
3574 }
3575
3576 if (OtherStmtLoc.isValid() && IsActiveTile) {
3577 Diag(OtherStmtLoc, diag::err_acc_intervening_code)
3578 << OpenACCClauseKind::Tile << TileInfo.DirectiveKind;
3579 Diag(TileInfo.ActiveTile->getBeginLoc(),
3580 diag::note_acc_active_clause_here)
3582 }
3583 }
3584}
3585
3586namespace {
3587// Get a list of clause Kinds for diagnosing a list, joined by a commas and an
3588// 'or'.
3589std::string GetListOfClauses(llvm::ArrayRef<OpenACCClauseKind> Clauses) {
3590 assert(!Clauses.empty() && "empty clause list not supported");
3591
3592 std::string Output;
3593 llvm::raw_string_ostream OS{Output};
3594
3595 if (Clauses.size() == 1) {
3596 OS << '\'' << Clauses[0] << '\'';
3597 return Output;
3598 }
3599
3600 llvm::ArrayRef<OpenACCClauseKind> AllButLast{Clauses.begin(),
3601 Clauses.end() - 1};
3602
3603 llvm::interleave(
3604 AllButLast, [&](OpenACCClauseKind K) { OS << '\'' << K << '\''; },
3605 [&] { OS << ", "; });
3606
3607 OS << " or \'" << Clauses.back() << '\'';
3608 return Output;
3609}
3610} // namespace
3611
3617
3618 // OpenACC 3.3 2.9.1:
3619 // Intervening code must not contain other OpenACC directives or calls to API
3620 // routines.
3621 //
3622 // ALL constructs are ill-formed if there is an active 'collapse'
3623 if (CollapseInfo.CurCollapseCount && *CollapseInfo.CurCollapseCount > 0) {
3624 Diag(StartLoc, diag::err_acc_invalid_in_loop)
3625 << /*OpenACC Construct*/ 0 << CollapseInfo.DirectiveKind
3627 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
3628 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
3629 diag::note_acc_active_clause_here)
3631 }
3632 if (TileInfo.CurTileCount && *TileInfo.CurTileCount > 0) {
3633 Diag(StartLoc, diag::err_acc_invalid_in_loop)
3634 << /*OpenACC Construct*/ 0 << TileInfo.DirectiveKind
3636 assert(TileInfo.ActiveTile && "Tile count without object?");
3637 Diag(TileInfo.ActiveTile->getBeginLoc(), diag::note_acc_active_clause_here)
3639 }
3640
3641 // OpenACC3.3 2.6.5: At least one copy, copyin, copyout, create, no_create,
3642 // present, deviceptr, attach, or default clause must appear on a 'data'
3643 // construct.
3644 if (K == OpenACCDirectiveKind::Data &&
3645 llvm::find_if(Clauses,
3650 OpenACCDefaultClause>) == Clauses.end())
3651 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
3652 << K
3653 << GetListOfClauses(
3659
3660 // OpenACC3.3 2.6.6: At least one copyin, create, or attach clause must appear
3661 // on an enter data directive.
3663 llvm::find_if(Clauses,
3665 OpenACCAttachClause>) == Clauses.end())
3666 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
3667 << K
3668 << GetListOfClauses({
3672 });
3673 // OpenACC3.3 2.6.6: At least one copyout, delete, or detach clause must
3674 // appear on an exit data directive.
3676 llvm::find_if(Clauses,
3678 OpenACCDetachClause>) == Clauses.end())
3679 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
3680 << K
3681 << GetListOfClauses({
3685 });
3686
3687 // OpenACC3.3 2.8: At least 'one use_device' clause must appear.
3689 llvm::find_if(Clauses, llvm::IsaPred<OpenACCUseDeviceClause>) ==
3690 Clauses.end())
3691 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
3692 << K << GetListOfClauses({OpenACCClauseKind::UseDevice});
3693
3694 // OpenACC3.3 2.14.3: At least one default_async, device_num, or device_type
3695 // clause must appear.
3696 if (K == OpenACCDirectiveKind::Set &&
3697 llvm::find_if(
3698 Clauses,
3701 Clauses.end())
3702 return Diag(StartLoc, diag::err_acc_construct_one_clause_of)
3703 << K
3704 << GetListOfClauses({OpenACCClauseKind::DefaultAsync,
3708
3709 // TODO: OpenACC: 'Update' construct needs to have one of 'self', 'host', or
3710 // 'device'. Implement here.
3711
3712 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/true);
3713}
3714
3717 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
3718 SourceLocation RParenLoc, SourceLocation EndLoc,
3719 ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt) {
3720 switch (K) {
3721 default:
3722 return StmtEmpty();
3724 return StmtError();
3729 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
3730 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
3731 }
3736 getASTContext(), K, StartLoc, DirLoc, EndLoc, Clauses,
3737 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
3738 }
3741 getASTContext(), ActiveComputeConstructInfo.Kind, StartLoc, DirLoc,
3742 EndLoc, Clauses, AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
3743 }
3746 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
3747 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
3748 }
3750 return OpenACCEnterDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
3751 EndLoc, Clauses);
3752 }
3754 return OpenACCExitDataConstruct::Create(getASTContext(), StartLoc, DirLoc,
3755 EndLoc, Clauses);
3756 }
3759 getASTContext(), StartLoc, DirLoc, EndLoc, Clauses,
3760 AssocStmt.isUsable() ? AssocStmt.get() : nullptr);
3761 }
3764 getASTContext(), StartLoc, DirLoc, LParenLoc, Exprs.front(), MiscLoc,
3765 Exprs.drop_front(), RParenLoc, EndLoc, Clauses);
3766 }
3768 return OpenACCInitConstruct::Create(getASTContext(), StartLoc, DirLoc,
3769 EndLoc, Clauses);
3770 }
3772 return OpenACCShutdownConstruct::Create(getASTContext(), StartLoc, DirLoc,
3773 EndLoc, Clauses);
3774 }
3776 return OpenACCSetConstruct::Create(getASTContext(), StartLoc, DirLoc,
3777 EndLoc, Clauses);
3778 }
3780 return OpenACCUpdateConstruct::Create(getASTContext(), StartLoc, DirLoc,
3781 EndLoc, Clauses);
3782 }
3783 }
3784 llvm_unreachable("Unhandled case in directive handling?");
3785}
3786
3788 SourceLocation DirectiveLoc, OpenACCDirectiveKind K,
3789 ArrayRef<const OpenACCClause *> Clauses, StmtResult AssocStmt) {
3790 switch (K) {
3791 default:
3792 llvm_unreachable("Unimplemented associated statement application");
3799 llvm_unreachable(
3800 "these don't have associated statements, so shouldn't get here");
3806 // There really isn't any checking here that could happen. As long as we
3807 // have a statement to associate, this should be fine.
3808 // OpenACC 3.3 Section 6:
3809 // Structured Block: in C or C++, an executable statement, possibly
3810 // compound, with a single entry at the top and a single exit at the
3811 // bottom.
3812 // FIXME: Should we reject DeclStmt's here? The standard isn't clear, and
3813 // an interpretation of it is to allow this and treat the initializer as
3814 // the 'structured block'.
3815 return AssocStmt;
3820 if (!AssocStmt.isUsable())
3821 return StmtError();
3822
3823 if (!isa<CXXForRangeStmt, ForStmt>(AssocStmt.get())) {
3824 Diag(AssocStmt.get()->getBeginLoc(), diag::err_acc_loop_not_for_loop)
3825 << K;
3826 Diag(DirectiveLoc, diag::note_acc_construct_here) << K;
3827 return StmtError();
3828 }
3829
3830 if (!CollapseInfo.CollapseDepthSatisfied || !TileInfo.TileDepthSatisfied) {
3831 if (!CollapseInfo.CollapseDepthSatisfied) {
3832 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
3834 assert(CollapseInfo.ActiveCollapse && "Collapse count without object?");
3835 Diag(CollapseInfo.ActiveCollapse->getBeginLoc(),
3836 diag::note_acc_active_clause_here)
3838 }
3839
3840 if (!TileInfo.TileDepthSatisfied) {
3841 Diag(DirectiveLoc, diag::err_acc_insufficient_loops)
3843 assert(TileInfo.ActiveTile && "Collapse count without object?");
3844 Diag(TileInfo.ActiveTile->getBeginLoc(),
3845 diag::note_acc_active_clause_here)
3847 }
3848 return StmtError();
3849 }
3850
3851 return AssocStmt.get();
3852 }
3853 llvm_unreachable("Invalid associated statement application");
3854}
3855
3857 SourceLocation StartLoc) {
3858 // OpenCC3.3 2.1 (line 889)
3859 // A program must not depend on the order of evaluation of expressions in
3860 // clause arguments or on any side effects of the evaluations.
3863 return diagnoseConstructAppertainment(*this, K, StartLoc, /*IsStmt=*/false);
3864}
3865
3867
3870 return OpenACCAsteriskSizeExpr::Create(getASTContext(), AsteriskLoc);
3871}
3872
3875 return BuildOpenACCAsteriskSizeExpr(AsteriskLoc);
3876}
Expr * E
Defines some OpenACC-specific enums and functions.
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static NamedDecl * getDeclFromExpr(Expr *E)
Definition: SemaExpr.cpp:14673
SourceLocation Loc
Definition: SemaObjC.cpp:759
This file declares semantic analysis for OpenACC constructs and clauses.
This file defines OpenACC AST classes for statement-level contructs.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
APSInt & getInt()
Definition: APValue.h:465
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition: ASTContext.h:188
const ConstantArrayType * getAsConstantArrayType(QualType T) const
Definition: ASTContext.h:2915
CanQualType DependentTy
Definition: ASTContext.h:1188
QualType getBaseElementType(const ArrayType *VAT) const
Return the innermost element type of an array type.
CanQualType ArraySectionTy
Definition: ASTContext.h:1200
CanQualType IntTy
Definition: ASTContext.h:1169
PtrTy get() const
Definition: Ownership.h:170
bool isInvalid() const
Definition: Ownership.h:166
bool isUsable() const
Definition: Ownership.h:168
This class represents BOTH the OpenMP Array Section and OpenACC 'subarray', with a boolean differenti...
Definition: Expr.h:6986
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition: Expr.cpp:5177
QualType getElementType() const
Definition: Type.h:3589
Represents a base class of a C++ class.
Definition: DeclCXX.h:146
Represents a C++ conversion function within a class.
Definition: DeclCXX.h:2880
Represents a C++ struct/union/class.
Definition: DeclCXX.h:258
base_class_range bases()
Definition: DeclCXX.h:620
llvm::APInt getSize() const
Return the constant array size as an APInt.
Definition: Type.h:3671
static ConstantExpr * Create(const ASTContext &Context, Expr *E, const APValue &Result)
Definition: Expr.cpp:350
bool isStdNamespace() const
Definition: DeclBase.cpp:1318
DeclContext * getEnclosingNamespaceContext()
Retrieve the nearest enclosing namespace context.
Definition: DeclBase.cpp:2008
DeclStmt - Adaptor class for mixing declarations with statements and expressions.
Definition: Stmt.h:1519
const Decl * getSingleDecl() const
Definition: Stmt.h:1534
SourceLocation getLocation() const
Definition: DeclBase.h:442
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: DeclBase.h:434
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition: DeclBase.h:967
This represents one expression.
Definition: Expr.h:110
bool EvaluateAsInt(EvalResult &Result, const ASTContext &Ctx, SideEffectsKind AllowSideEffects=SE_NoSideEffects, bool InConstantContext=false) const
EvaluateAsInt - Return true if this is a constant which we can fold and convert to an integer,...
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition: Expr.cpp:3095
bool isTypeDependent() const
Determines whether the type of this expression depends on.
Definition: Expr.h:192
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition: Expr.cpp:3090
bool containsErrors() const
Whether this expression contains subexpressions which had errors, e.g.
Definition: Expr.h:245
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx, SourceLocation *Loc=nullptr) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
QualType getType() const
Definition: Expr.h:142
bool hasPlaceholderType() const
Returns whether this expression has a placeholder type.
Definition: Expr.h:516
Represents a member of a struct/union/class.
Definition: Decl.h:3033
static OpenACCAsteriskSizeExpr * Create(const ASTContext &C, SourceLocation Loc)
Definition: Expr.cpp:5424
static OpenACCAsyncClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc)
static OpenACCAttachClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCAutoClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc)
This is the base type for all OpenACC Clauses.
Definition: OpenACCClause.h:24
OpenACCClauseKind getClauseKind() const
Definition: OpenACCClause.h:37
SourceLocation getBeginLoc() const
Definition: OpenACCClause.h:38
Represents a 'collapse' clause on a 'loop' construct.
static OpenACCCollapseClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, bool HasForce, Expr *LoopCount, SourceLocation EndLoc)
const Expr * getLoopCount() const
static OpenACCCombinedConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCComputeConstruct * Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, SourceLocation DirectiveLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
Definition: StmtOpenACC.cpp:27
static OpenACCCopyClause * Create(const ASTContext &C, OpenACCClauseKind Spelling, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCCopyInClause * Create(const ASTContext &C, OpenACCClauseKind Spelling, SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsReadOnly, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCCopyOutClause * Create(const ASTContext &C, OpenACCClauseKind Spelling, SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsZero, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCCreateClause * Create(const ASTContext &C, OpenACCClauseKind Spelling, SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsZero, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
static OpenACCDefaultAsyncClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc)
A 'default' clause, has the optional 'none' or 'present' argument.
static OpenACCDefaultClause * Create(const ASTContext &C, OpenACCDefaultClauseKind K, SourceLocation BeginLoc, SourceLocation LParenLoc, SourceLocation EndLoc)
static OpenACCDeleteClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCDetachClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCDeviceNumClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc)
static OpenACCDevicePtrClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or an identifier.
static OpenACCDeviceTypeClause * Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< DeviceTypeArgument > Archs, SourceLocation EndLoc)
static OpenACCEnterDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCExitDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCFinalizeClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc)
static OpenACCFirstPrivateClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCGangClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< OpenACCGangKind > GangKinds, ArrayRef< Expr * > IntExprs, SourceLocation EndLoc)
static OpenACCHostDataConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses, Stmt *StructuredBlock)
An 'if' clause, which has a required condition expression.
static OpenACCIfClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *ConditionExpr, SourceLocation EndLoc)
static OpenACCIfPresentClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc)
static OpenACCIndependentClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc)
static OpenACCInitConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCLoopConstruct * Create(const ASTContext &C, OpenACCDirectiveKind ParentKind, SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef< const OpenACCClause * > Clauses, Stmt *Loop)
Definition: StmtOpenACC.cpp:80
static OpenACCNoCreateClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCNumGangsClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > IntExprs, SourceLocation EndLoc)
static OpenACCNumWorkersClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc)
static OpenACCPresentClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCPrivateClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCReductionClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCReductionOperator Operator, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCSelfClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *ConditionExpr, SourceLocation EndLoc)
static OpenACCSeqClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc)
static OpenACCSetConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCShutdownConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCTileClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > SizeExprs, SourceLocation EndLoc)
llvm::ArrayRef< Expr * > getSizeExprs()
static OpenACCUpdateConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCUseDeviceClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCVectorClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc)
static OpenACCVectorLengthClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc)
static OpenACCWaitClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef< Expr * > QueueIdExprs, SourceLocation EndLoc)
static OpenACCWaitConstruct * Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, ArrayRef< Expr * > QueueIdExprs, SourceLocation RParenLoc, SourceLocation End, ArrayRef< const OpenACCClause * > Clauses)
static OpenACCWorkerClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc)
A (possibly-)qualified type.
Definition: Type.h:929
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition: Type.h:996
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: Type.h:8134
QualType getUnqualifiedType() const
Retrieve the unqualified variant of the given type, removing as little sugar as possible.
Definition: Type.h:8025
A generic diagnostic builder for errors which may or may not be deferred.
Definition: SemaBase.h:110
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
ASTContext & getASTContext() const
Definition: SemaBase.cpp:9
Sema & SemaRef
Definition: SemaBase.h:40
const LangOptions & getLangOpts() const
Definition: SemaBase.cpp:11
AssociatedStmtRAII(SemaOpenACC &, OpenACCDirectiveKind, SourceLocation, ArrayRef< const OpenACCClause * >, ArrayRef< OpenACCClause * >)
void SetTileInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
void SetCollapseInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
A type to represent all the data for an OpenACC Clause that has been parsed, but not yet created/sema...
Definition: SemaOpenACC.h:202
ArrayRef< Expr * > getQueueIdExprs() const
Definition: SemaOpenACC.h:338
OpenACCDirectiveKind getDirectiveKind() const
Definition: SemaOpenACC.h:260
ArrayRef< OpenACCGangKind > getGangKinds() const
Definition: SemaOpenACC.h:380
OpenACCReductionOperator getReductionOp() const
Definition: SemaOpenACC.h:376
OpenACCClauseKind getClauseKind() const
Definition: SemaOpenACC.h:262
SourceLocation getLParenLoc() const
Definition: SemaOpenACC.h:266
ArrayRef< DeviceTypeArgument > getDeviceTypeArchitectures() const
Definition: SemaOpenACC.h:456
SourceLocation getBeginLoc() const
Definition: SemaOpenACC.h:264
SourceLocation getQueuesLoc() const
Definition: SemaOpenACC.h:318
void setVarListDetails(ArrayRef< Expr * > VarList, bool IsReadOnly, bool IsZero)
Definition: SemaOpenACC.h:532
OpenACCDefaultClauseKind getDefaultClauseKind() const
Definition: SemaOpenACC.h:270
ExprResult ActOnVar(OpenACCClauseKind CK, Expr *VarExpr)
Called when encountering a 'var' for OpenACC, ensures it is actually a declaration reference to a var...
ComputeConstructInfo & getActiveComputeConstructInfo()
Definition: SemaOpenACC.h:162
bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, ArrayRef< const OpenACCClause * > Clauses)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, SourceLocation Loc, Expr *IntExpr)
Called when encountering an 'int-expr' for OpenACC, and manages conversions and diagnostics to 'int'.
void ActOnWhileStmt(SourceLocation WhileLoc)
SourceLocation LoopWorkerClauseLoc
If there is a current 'active' loop construct with a 'worker' clause on it (on any sort of construct)...
Definition: SemaOpenACC.h:179
OpenACCClause * ActOnClause(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCParsedClause &Clause)
Called after parsing an OpenACC Clause so that it can be checked.
bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr)
Called to check the 'var' type is a variable of pointer type, necessary for 'deviceptr' and 'attach' ...
struct clang::SemaOpenACC::LoopGangOnKernelTy LoopGangClauseOnKernel
ExprResult CheckReductionVar(OpenACCDirectiveKind DirectiveKind, OpenACCReductionOperator ReductionOp, Expr *VarExpr)
Called while semantically analyzing the reduction clause, ensuring the var is the correct kind of ref...
ExprResult CheckCollapseLoopCount(Expr *LoopCount)
Checks the loop depth value for a collapse clause.
struct clang::SemaOpenACC::LoopWithoutSeqCheckingInfo LoopWithoutSeqInfo
StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef< Expr * > Exprs, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses, StmtResult AssocStmt)
Called after the directive has been completely parsed, including the declaration group or associated ...
DeclGroupRef ActOnEndDeclDirective()
Called after the directive has been completely parsed, including the declaration group or associated ...
OpenACCClause * CheckReductionClause(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp, ArrayRef< Expr * > Vars, SourceLocation EndLoc)
SourceLocation LoopVectorClauseLoc
If there is a current 'active' loop construct with a 'vector' clause on it (on any sort of construct)...
Definition: SemaOpenACC.h:184
void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc)
Called after the construct has been parsed, but clauses haven't been parsed.
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
ExprResult CheckGangExpr(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCDirectiveKind DK, OpenACCGangKind GK, Expr *E)
void ActOnDoStmt(SourceLocation DoLoc)
void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor, const Stmt *RangeFor)
void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body)
OpenACCClause * CheckGangClause(OpenACCDirectiveKind DirKind, ArrayRef< const OpenACCClause * > ExistingClauses, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< OpenACCGangKind > GangKinds, ArrayRef< Expr * > IntExprs, SourceLocation EndLoc)
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, OpenACCDirectiveKind K, ArrayRef< const OpenACCClause * > Clauses, StmtResult AssocStmt)
Called when we encounter an associated statement for our construct, this should check legality of the...
void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First, const Stmt *Second, const Stmt *Third)
ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, Expr *Length, SourceLocation RBLoc)
Checks and creates an Array Section used in an OpenACC construct/clause.
ExprResult CheckTileSizeExpr(Expr *SizeExpr)
Checks a single size expr for a tile clause.
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:464
void PushExpressionEvaluationContext(ExpressionEvaluationContext NewContext, Decl *LambdaContextDecl=nullptr, ExpressionEvaluationContextRecord::ExpressionKind Type=ExpressionEvaluationContextRecord::EK_Other)
Definition: SemaExpr.cpp:17394
ExprResult PerformContextualImplicitConversion(SourceLocation Loc, Expr *FromE, ContextualImplicitConverter &Converter)
Perform a contextual implicit conversion.
ExprResult DefaultFunctionArrayLvalueConversion(Expr *E, bool Diagnose=true)
Definition: SemaExpr.cpp:752
ASTContext & getASTContext() const
Definition: Sema.h:532
void PopExpressionEvaluationContext()
Definition: SemaExpr.cpp:17827
ExprResult DefaultLvalueConversion(Expr *E)
Definition: SemaExpr.cpp:640
ExprResult CheckPlaceholderExpr(Expr *E)
Check for operands with placeholder types and complain if found.
Definition: SemaExpr.cpp:20971
@ PotentiallyEvaluated
The current expression is potentially evaluated at run time, which means that code may be generated t...
bool RequireCompleteType(SourceLocation Loc, QualType T, CompleteTypeKind Kind, TypeDiagnoser &Diagnoser)
Ensure that the type T is a complete type.
Definition: SemaType.cpp:9068
void DiscardCleanupsInEvaluationContext()
Definition: SemaExpr.cpp:17904
ExprResult CreateRecoveryExpr(SourceLocation Begin, SourceLocation End, ArrayRef< Expr * > SubExprs, QualType T=QualType())
Attempts to produce a RecoveryExpr after some AST node cannot be created.
Definition: SemaExpr.cpp:21168
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
Stmt - This represents one statement.
Definition: Stmt.h:84
SourceLocation getEndLoc() const LLVM_READONLY
Definition: Stmt.cpp:357
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:333
SourceLocation getBeginLoc() const LLVM_READONLY
Definition: Stmt.cpp:345
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition: Type.cpp:1916
bool isDependentSizedArrayType() const
Definition: Type.h:8278
bool isConstantArrayType() const
Definition: Type.h:8262
bool isArrayType() const
Definition: Type.h:8258
bool isPointerType() const
Definition: Type.h:8186
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition: Type.h:8550
bool isEnumeralType() const
Definition: Type.h:8290
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:738
bool isNonOverloadPlaceholderType() const
Test for a placeholder type other than Overload; see BuiltinType::isNonOverloadPlaceholderType.
Definition: Type.h:8504
bool isInstantiationDependentType() const
Determine whether this type is an instantiation-dependent type, meaning that the type involves a temp...
Definition: Type.h:2714
bool isDependentType() const
Whether this type is a dependent type, meaning that its definition somehow depends on a template para...
Definition: Type.h:2706
const ArrayType * getAsArrayTypeUnsafe() const
A variant of getAs<> for array types which silently discards qualifiers from the outermost type.
Definition: Type.h:8786
bool isFunctionType() const
Definition: Type.h:8182
bool isAnyPointerType() const
Definition: Type.h:8194
bool isRecordType() const
Definition: Type.h:8286
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition: Type.cpp:1920
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:671
QualType getType() const
Definition: Decl.h:682
Represents a variable declaration or definition.
Definition: Decl.h:882
SmallVector< BoundNodes, 1 > match(MatcherT Matcher, const NodeT &Node, ASTContext &Context)
Returns the results of matching Matcher on Node.
bool Inc(InterpState &S, CodePtr OpPC)
1) Pops a pointer from the stack 2) Load the value from the pointer 3) Writes the value increased by ...
Definition: Interp.h:824
The JSON file list parser is used to communicate input to InstallAPI.
OpenACCDirectiveKind
Definition: OpenACCKinds.h:25
OpenACCReductionOperator
Definition: OpenACCKinds.h:509
bool isOpenACCComputeDirectiveKind(OpenACCDirectiveKind K)
Definition: OpenACCKinds.h:149
bool isOpenACCCombinedDirectiveKind(OpenACCDirectiveKind K)
Definition: OpenACCKinds.h:155
bool isOpenACCDataDirectiveKind(OpenACCDirectiveKind K)
Definition: OpenACCKinds.h:162
@ OK_Ordinary
An ordinary object is located at an address in memory.
Definition: Specifiers.h:151
OpenACCClauseKind
Represents the kind of an OpenACC clause.
Definition: OpenACCKinds.h:178
@ DevicePtr
'deviceptr' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ Collapse
'collapse' clause, allowed on 'loop' and Combined constructs.
@ DeviceNum
'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.
@ Invalid
Represents an invalid clause, for the purposes of parsing.
@ Copy
'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ Create
'create' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ DeviceType
'device_type' clause, allowed on Compute, 'data', 'init', 'shutdown', 'set', update',...
@ DefaultAsync
'default_async' clause, allowed on 'set' construct.
@ Attach
'attach' clause, allowed on Compute and Combined constructs, plus 'data' and 'enter data'.
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ Default
'default' clause, allowed on parallel, serial, kernel (and compound) constructs.
@ UseDevice
'use_device' clause, allowed on 'host_data' construct.
@ NoCreate
'no_create' clause, allowed on allowed on Compute and Combined constructs, plus 'data'.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ CopyOut
'copyout' clause, allowed on Compute and Combined constructs, plus 'data', 'exit data',...
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
@ CopyIn
'copyin' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ Detach
'detach' clause, allowed on the 'exit data' construct.
@ Delete
'delete' clause, allowed on the 'exit data' construct.
StmtResult StmtError()
Definition: Ownership.h:265
@ Result
The result type of a method or function.
ExprResult ExprError()
Definition: Ownership.h:264
@ VK_LValue
An l-value expression is a reference to an object with independent storage.
Definition: Specifiers.h:139
const FunctionProtoType * T
OpenACCGangKind
Definition: OpenACCKinds.h:568
StmtResult StmtEmpty()
Definition: Ownership.h:272
EvalResult is a struct with detailed info about an evaluated expression.
Definition: Expr.h:642
APValue Val
Val - This is the value the expression can be folded to.
Definition: Expr.h:644