clang 22.0.0git
SemaOpenACCClause.cpp
Go to the documentation of this file.
1//===--- SemaOpenACCClause.cpp - Semantic Analysis for OpenACC clause -----===//
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 clauses.
10///
11//===----------------------------------------------------------------------===//
12
13#include "clang/AST/DeclCXX.h"
14#include "clang/AST/ExprCXX.h"
19
20using namespace clang;
21
22namespace {
23bool checkValidAfterDeviceType(
24 SemaOpenACC &S, const OpenACCDeviceTypeClause &DeviceTypeClause,
25 const SemaOpenACC::OpenACCParsedClause &NewClause) {
26 // OpenACC3.3: Section 2.4: Clauses that precede any device_type clause are
27 // default clauses. Clauses that follow a device_type clause up to the end of
28 // the directive or up to the next device_type clause are device-specific
29 // clauses for the device types specified in the device_type argument.
30 //
31 // The above implies that despite what the individual text says, these are
32 // valid.
33 if (NewClause.getClauseKind() == OpenACCClauseKind::DType ||
35 return false;
36
37 // Implement check from OpenACC3.3: section 2.5.4:
38 // Only the async, wait, num_gangs, num_workers, and vector_length clauses may
39 // follow a device_type clause.
41 switch (NewClause.getClauseKind()) {
47 return false;
48 default:
49 break;
50 }
51 } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
52 // Implement check from OpenACC3.3: section 2.9:
53 // Only the collapse, gang, worker, vector, seq, independent, auto, and tile
54 // clauses may follow a device_type clause.
55 switch (NewClause.getClauseKind()) {
64 return false;
65 default:
66 break;
67 }
68 } else if (isOpenACCCombinedDirectiveKind(NewClause.getDirectiveKind())) {
69 // This seems like it should be the union of 2.9 and 2.5.4 from above.
70 switch (NewClause.getClauseKind()) {
84 return false;
85 default:
86 break;
87 }
88 } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Data) {
89 // OpenACC3.3 section 2.6.5: Only the async and wait clauses may follow a
90 // device_type clause.
91 switch (NewClause.getClauseKind()) {
94 return false;
95 default:
96 break;
97 }
98 } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Set ||
101 // There are no restrictions on 'set', 'init', or 'shutdown'.
102 return false;
103 } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Update) {
104 // OpenACC3.3 section 2.14.4: Only the async and wait clauses may follow a
105 // device_type clause.
106 switch (NewClause.getClauseKind()) {
109 return false;
110 default:
111 break;
112 }
113 } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Routine) {
114 // OpenACC 3.3 section 2.15: Only the 'gang', 'worker', 'vector', 'seq', and
115 // 'bind' clauses may follow a device_type clause.
116 switch (NewClause.getClauseKind()) {
122 return false;
123 default:
124 break;
125 }
126 }
127 S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type)
128 << NewClause.getClauseKind() << DeviceTypeClause.getClauseKind()
129 << NewClause.getDirectiveKind();
130 S.Diag(DeviceTypeClause.getBeginLoc(),
131 diag::note_acc_active_applies_clause_here)
132 << diag::ACCDeviceTypeApp::Active << DeviceTypeClause.getClauseKind();
133 return true;
134}
135
136// GCC looks through linkage specs, but not the other transparent declaration
137// contexts for 'declare' restrictions, so this helper function helps get us
138// through that.
139const DeclContext *removeLinkageSpecDC(const DeclContext *DC) {
140 while (isa<LinkageSpecDecl>(DC))
141 DC = DC->getParent();
142
143 return DC;
144}
145
146class SemaOpenACCClauseVisitor {
147 SemaOpenACC &SemaRef;
148 ASTContext &Ctx;
149 ArrayRef<const OpenACCClause *> ExistingClauses;
150
151 // OpenACC 3.3 2.9:
152 // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
153 // appears.
154 bool
155 DiagGangWorkerVectorSeqConflict(SemaOpenACC::OpenACCParsedClause &Clause) {
156 if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop &&
158 return false;
159 assert(Clause.getClauseKind() == OpenACCClauseKind::Gang ||
160 Clause.getClauseKind() == OpenACCClauseKind::Worker ||
161 Clause.getClauseKind() == OpenACCClauseKind::Vector);
162 const auto *Itr =
163 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSeqClause>);
164
165 if (Itr != ExistingClauses.end()) {
166 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
167 << Clause.getClauseKind() << (*Itr)->getClauseKind()
168 << Clause.getDirectiveKind();
169 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
170 << (*Itr)->getClauseKind();
171
172 return true;
173 }
174 return false;
175 }
176
178 CheckModifierList(SemaOpenACC::OpenACCParsedClause &Clause,
179 OpenACCModifierKind Mods) {
180 auto CheckSingle = [=](OpenACCModifierKind CurMods,
181 OpenACCModifierKind ValidKinds,
183 if (!isOpenACCModifierBitSet(CurMods, Bit) ||
184 isOpenACCModifierBitSet(ValidKinds, Bit))
185 return CurMods;
186
187 SemaRef.Diag(Clause.getLParenLoc(), diag::err_acc_invalid_modifier)
188 << Bit << Clause.getClauseKind();
189
190 return CurMods ^ Bit;
191 };
192 auto Check = [&](OpenACCModifierKind ValidKinds) {
193 if ((Mods | ValidKinds) == ValidKinds)
194 return Mods;
195
196 Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Always);
197 Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::AlwaysIn);
198 Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::AlwaysOut);
199 Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Readonly);
200 Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Zero);
201 Mods = CheckSingle(Mods, ValidKinds, OpenACCModifierKind::Capture);
202 return Mods;
203 };
204
205 // The 'capture' modifier is only valid on copyin, copyout, and create on
206 // structured data or compute constructs (which also includes combined).
207 bool IsStructuredDataOrCompute =
208 Clause.getDirectiveKind() == OpenACCDirectiveKind::Data ||
211
212 switch (Clause.getClauseKind()) {
213 default:
214 llvm_unreachable("Only for copy, copyin, copyout, create");
215 case OpenACCClauseKind::Copy:
216 case OpenACCClauseKind::PCopy:
217 case OpenACCClauseKind::PresentOrCopy:
218 // COPY: Capture always
219 return Check(OpenACCModifierKind::Always | OpenACCModifierKind::AlwaysIn |
220 OpenACCModifierKind::AlwaysOut |
221 OpenACCModifierKind::Capture);
222 case OpenACCClauseKind::CopyIn:
223 case OpenACCClauseKind::PCopyIn:
224 case OpenACCClauseKind::PresentOrCopyIn:
225 // COPYIN: Capture only struct.data & compute
226 return Check(OpenACCModifierKind::Always | OpenACCModifierKind::AlwaysIn |
227 OpenACCModifierKind::Readonly |
228 (IsStructuredDataOrCompute ? OpenACCModifierKind::Capture
229 : OpenACCModifierKind::Invalid));
230 case OpenACCClauseKind::CopyOut:
231 case OpenACCClauseKind::PCopyOut:
232 case OpenACCClauseKind::PresentOrCopyOut:
233 // COPYOUT: Capture only struct.data & compute
234 return Check(OpenACCModifierKind::Always |
235 OpenACCModifierKind::AlwaysOut | OpenACCModifierKind::Zero |
236 (IsStructuredDataOrCompute ? OpenACCModifierKind::Capture
237 : OpenACCModifierKind::Invalid));
238 case OpenACCClauseKind::Create:
239 case OpenACCClauseKind::PCreate:
240 case OpenACCClauseKind::PresentOrCreate:
241 // CREATE: Capture only struct.data & compute
242 return Check(OpenACCModifierKind::Zero |
243 (IsStructuredDataOrCompute ? OpenACCModifierKind::Capture
244 : OpenACCModifierKind::Invalid));
245 }
246 llvm_unreachable("didn't return from switch above?");
247 }
248
249 // Helper for the 'routine' checks during 'new' clause addition. Precondition
250 // is that we already know the new clause is one of the prohbiited ones.
251 template <typename Pred>
252 bool
253 CheckValidRoutineNewClauseHelper(Pred HasPredicate,
254 SemaOpenACC::OpenACCParsedClause &Clause) {
255 if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Routine)
256 return false;
257
258 auto *FirstDeviceType =
259 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCDeviceTypeClause>);
260
261 if (FirstDeviceType == ExistingClauses.end()) {
262 // If there isn't a device type yet, ANY duplicate is wrong.
263
264 auto *ExistingProhibitedClause =
265 llvm::find_if(ExistingClauses, HasPredicate);
266
267 if (ExistingProhibitedClause == ExistingClauses.end())
268 return false;
269
270 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
271 << Clause.getClauseKind()
272 << (*ExistingProhibitedClause)->getClauseKind()
273 << Clause.getDirectiveKind();
274 SemaRef.Diag((*ExistingProhibitedClause)->getBeginLoc(),
275 diag::note_acc_previous_clause_here)
276 << (*ExistingProhibitedClause)->getClauseKind();
277 return true;
278 }
279
280 // At this point we know that this is 'after' a device type. So this is an
281 // error if: 1- there is one BEFORE the 'device_type' 2- there is one
282 // between this and the previous 'device_type'.
283
284 auto *BeforeDeviceType =
285 std::find_if(ExistingClauses.begin(), FirstDeviceType, HasPredicate);
286 // If there is one before the device_type (and we know we are after a
287 // device_type), than this is ill-formed.
288 if (BeforeDeviceType != FirstDeviceType) {
289 SemaRef.Diag(
290 Clause.getBeginLoc(),
291 diag::err_acc_clause_routine_cannot_combine_before_device_type)
292 << Clause.getClauseKind() << (*BeforeDeviceType)->getClauseKind();
293 SemaRef.Diag((*BeforeDeviceType)->getBeginLoc(),
294 diag::note_acc_previous_clause_here)
295 << (*BeforeDeviceType)->getClauseKind();
296 SemaRef.Diag((*FirstDeviceType)->getBeginLoc(),
297 diag::note_acc_active_applies_clause_here)
298 << diag::ACCDeviceTypeApp::Active
299 << (*FirstDeviceType)->getClauseKind();
300 return true;
301 }
302
303 auto LastDeviceTypeItr =
304 std::find_if(ExistingClauses.rbegin(), ExistingClauses.rend(),
305 llvm::IsaPred<OpenACCDeviceTypeClause>);
306
307 // We already know there is one in the list, so it is nonsensical to not
308 // have one.
309 assert(LastDeviceTypeItr != ExistingClauses.rend());
310
311 // Get the device-type from-the-front (not reverse) iterator from the
312 // reverse iterator.
313 auto *LastDeviceType = LastDeviceTypeItr.base() - 1;
314
315 auto *ExistingProhibitedSinceLastDevice =
316 std::find_if(LastDeviceType, ExistingClauses.end(), HasPredicate);
317
318 // No prohibited ones since the last device-type.
319 if (ExistingProhibitedSinceLastDevice == ExistingClauses.end())
320 return false;
321
322 SemaRef.Diag(Clause.getBeginLoc(),
323 diag::err_acc_clause_routine_cannot_combine_same_device_type)
324 << Clause.getClauseKind()
325 << (*ExistingProhibitedSinceLastDevice)->getClauseKind();
326 SemaRef.Diag((*ExistingProhibitedSinceLastDevice)->getBeginLoc(),
327 diag::note_acc_previous_clause_here)
328 << (*ExistingProhibitedSinceLastDevice)->getClauseKind();
329 SemaRef.Diag((*LastDeviceType)->getBeginLoc(),
330 diag::note_acc_active_applies_clause_here)
331 << diag::ACCDeviceTypeApp::Active << (*LastDeviceType)->getClauseKind();
332 return true;
333 }
334
335 // Routine has a pretty complicated set of rules for how device_type and the
336 // gang, worker, vector, and seq clauses work. So diagnose some of it here.
337 bool CheckValidRoutineGangWorkerVectorSeqNewClause(
338 SemaOpenACC::OpenACCParsedClause &Clause) {
339
340 if (Clause.getClauseKind() != OpenACCClauseKind::Gang &&
341 Clause.getClauseKind() != OpenACCClauseKind::Vector &&
342 Clause.getClauseKind() != OpenACCClauseKind::Worker &&
343 Clause.getClauseKind() != OpenACCClauseKind::Seq)
344 return false;
345 auto ProhibitedPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
346 OpenACCVectorClause, OpenACCSeqClause>;
347
348 return CheckValidRoutineNewClauseHelper(ProhibitedPred, Clause);
349 }
350
351 // Bind should have similar rules on a routine as gang/worker/vector/seq,
352 // except there is no 'must have 1' rule, so we can get all the checking done
353 // here.
354 bool
355 CheckValidRoutineBindNewClause(SemaOpenACC::OpenACCParsedClause &Clause) {
356
357 if (Clause.getClauseKind() != OpenACCClauseKind::Bind)
358 return false;
359
360 auto HasBindPred = llvm::IsaPred<OpenACCBindClause>;
361 return CheckValidRoutineNewClauseHelper(HasBindPred, Clause);
362 }
363
364 // For 'tile' and 'collapse', only allow 1 per 'device_type'.
365 // Also applies to num_worker, num_gangs, vector_length, and async.
366 // This does introspection into the actual device-types to prevent duplicates
367 // across device types as well.
368 template <typename TheClauseTy>
369 bool DisallowSinceLastDeviceType(SemaOpenACC::OpenACCParsedClause &Clause) {
370 auto LastDeviceTypeItr =
371 std::find_if(ExistingClauses.rbegin(), ExistingClauses.rend(),
372 llvm::IsaPred<OpenACCDeviceTypeClause>);
373
374 auto LastSinceDevTy =
375 std::find_if(ExistingClauses.rbegin(), LastDeviceTypeItr,
376 llvm::IsaPred<TheClauseTy>);
377
378 // In this case there is a duplicate since the last device_type/lack of a
379 // device_type. Diagnose these as duplicates.
380 if (LastSinceDevTy != LastDeviceTypeItr) {
381 SemaRef.Diag(Clause.getBeginLoc(),
382 diag::err_acc_clause_since_last_device_type)
383 << Clause.getClauseKind() << Clause.getDirectiveKind()
384 << (LastDeviceTypeItr != ExistingClauses.rend());
385
386 SemaRef.Diag((*LastSinceDevTy)->getBeginLoc(),
387 diag::note_acc_previous_clause_here)
388 << (*LastSinceDevTy)->getClauseKind();
389
390 // Mention the last device_type as well.
391 if (LastDeviceTypeItr != ExistingClauses.rend())
392 SemaRef.Diag((*LastDeviceTypeItr)->getBeginLoc(),
393 diag::note_acc_active_applies_clause_here)
394 << diag::ACCDeviceTypeApp::Active
395 << (*LastDeviceTypeItr)->getClauseKind();
396 return true;
397 }
398
399 // If this isn't in a device_type, and we didn't diagnose that there are
400 // dupes above, just give up, no sense in searching for previous device_type
401 // regions as they don't exist.
402 if (LastDeviceTypeItr == ExistingClauses.rend())
403 return false;
404
405 // The device-type that is active for us, so we can compare to the previous
406 // ones.
407 const auto &ActiveDeviceTypeClause =
408 cast<OpenACCDeviceTypeClause>(**LastDeviceTypeItr);
409
410 auto PrevDeviceTypeItr = LastDeviceTypeItr;
411 auto CurDevTypeItr = LastDeviceTypeItr;
412
413 while ((CurDevTypeItr = std::find_if(
414 std::next(PrevDeviceTypeItr), ExistingClauses.rend(),
415 llvm::IsaPred<OpenACCDeviceTypeClause>)) !=
416 ExistingClauses.rend()) {
417 // At this point, we know that we have a region between two device_types,
418 // as specified by CurDevTypeItr and PrevDeviceTypeItr.
419
420 auto CurClauseKindItr = std::find_if(PrevDeviceTypeItr, CurDevTypeItr,
421 llvm::IsaPred<TheClauseTy>);
422
423 // There are no clauses of the current kind between these device_types, so
424 // continue.
425 if (CurClauseKindItr == CurDevTypeItr) {
426 PrevDeviceTypeItr = CurDevTypeItr;
427 continue;
428 }
429
430 // At this point, we know that this device_type region has a collapse. So
431 // diagnose if the two device_types have any overlap in their
432 // architectures.
433 const auto &CurDeviceTypeClause =
434 cast<OpenACCDeviceTypeClause>(**CurDevTypeItr);
435
436 for (const DeviceTypeArgument &arg :
437 ActiveDeviceTypeClause.getArchitectures()) {
438 for (const DeviceTypeArgument &prevArg :
439 CurDeviceTypeClause.getArchitectures()) {
440
441 // This should catch duplicates * regions, duplicate same-text (thanks
442 // to identifier equiv.) and case insensitive dupes.
443 if (arg.getIdentifierInfo() == prevArg.getIdentifierInfo() ||
444 (arg.getIdentifierInfo() && prevArg.getIdentifierInfo() &&
445 StringRef{arg.getIdentifierInfo()->getName()}.equals_insensitive(
446 prevArg.getIdentifierInfo()->getName()))) {
447 SemaRef.Diag(Clause.getBeginLoc(),
448 diag::err_acc_clause_conflicts_prev_dev_type)
449 << Clause.getClauseKind()
450 << (arg.getIdentifierInfo() ? arg.getIdentifierInfo()->getName()
451 : "*");
452 // mention the active device type.
453 SemaRef.Diag(ActiveDeviceTypeClause.getBeginLoc(),
454 diag::note_acc_active_applies_clause_here)
455 << diag::ACCDeviceTypeApp::Active
456 << ActiveDeviceTypeClause.getClauseKind();
457 // mention the previous clause.
458 SemaRef.Diag((*CurClauseKindItr)->getBeginLoc(),
459 diag::note_acc_previous_clause_here)
460 << (*CurClauseKindItr)->getClauseKind();
461 // mention the previous device type.
462 SemaRef.Diag(CurDeviceTypeClause.getBeginLoc(),
463 diag::note_acc_active_applies_clause_here)
464 << diag::ACCDeviceTypeApp::Applies
465 << CurDeviceTypeClause.getClauseKind();
466 return true;
467 }
468 }
469 }
470
471 PrevDeviceTypeItr = CurDevTypeItr;
472 }
473 return false;
474 }
475
476public:
477 SemaOpenACCClauseVisitor(SemaOpenACC &S,
478 ArrayRef<const OpenACCClause *> ExistingClauses)
479 : SemaRef(S), Ctx(S.getASTContext()), ExistingClauses(ExistingClauses) {}
480
481 OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) {
482
483 if (SemaRef.DiagnoseAllowedOnceClauses(
484 Clause.getDirectiveKind(), Clause.getClauseKind(),
485 Clause.getBeginLoc(), ExistingClauses) ||
486 SemaRef.DiagnoseExclusiveClauses(Clause.getDirectiveKind(),
487 Clause.getClauseKind(),
488 Clause.getBeginLoc(), ExistingClauses))
489 return nullptr;
490 if (CheckValidRoutineGangWorkerVectorSeqNewClause(Clause) ||
491 CheckValidRoutineBindNewClause(Clause))
492 return nullptr;
493
494 switch (Clause.getClauseKind()) {
495 case OpenACCClauseKind::Shortloop:
496 llvm_unreachable("Shortloop shouldn't be generated in clang");
497 case OpenACCClauseKind::Invalid:
498 return nullptr;
499#define VISIT_CLAUSE(CLAUSE_NAME) \
500 case OpenACCClauseKind::CLAUSE_NAME: \
501 return Visit##CLAUSE_NAME##Clause(Clause);
502#define CLAUSE_ALIAS(ALIAS, CLAUSE_NAME, DEPRECATED) \
503 case OpenACCClauseKind::ALIAS: \
504 if (DEPRECATED) \
505 SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_deprecated_alias_name) \
506 << Clause.getClauseKind() << OpenACCClauseKind::CLAUSE_NAME; \
507 return Visit##CLAUSE_NAME##Clause(Clause);
508#include "clang/Basic/OpenACCClauses.def"
509 }
510 llvm_unreachable("Invalid clause kind");
511 }
512
513#define VISIT_CLAUSE(CLAUSE_NAME) \
514 OpenACCClause *Visit##CLAUSE_NAME##Clause( \
515 SemaOpenACC::OpenACCParsedClause &Clause);
516#include "clang/Basic/OpenACCClauses.def"
517};
518
519OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultClause(
521 // Don't add an invalid clause to the AST.
522 if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)
523 return nullptr;
524
526 Ctx, Clause.getDefaultClauseKind(), Clause.getBeginLoc(),
527 Clause.getLParenLoc(), Clause.getEndLoc());
528}
529
530OpenACCClause *SemaOpenACCClauseVisitor::VisitTileClause(
531 SemaOpenACC::OpenACCParsedClause &Clause) {
532
533 if (DisallowSinceLastDeviceType<OpenACCTileClause>(Clause))
534 return nullptr;
535
536 llvm::SmallVector<Expr *> NewSizeExprs;
537
538 // Make sure these are all positive constant expressions or *.
539 for (Expr *E : Clause.getIntExprs()) {
540 ExprResult Res = SemaRef.CheckTileSizeExpr(E);
541
542 if (!Res.isUsable())
543 return nullptr;
544
545 NewSizeExprs.push_back(Res.get());
546 }
547
548 return OpenACCTileClause::Create(Ctx, Clause.getBeginLoc(),
549 Clause.getLParenLoc(), NewSizeExprs,
550 Clause.getEndLoc());
551}
552
553OpenACCClause *SemaOpenACCClauseVisitor::VisitIfClause(
554 SemaOpenACC::OpenACCParsedClause &Clause) {
555
556 // The parser has ensured that we have a proper condition expr, so there
557 // isn't really much to do here.
558
559 // If the 'if' clause is true, it makes the 'self' clause have no effect,
560 // diagnose that here. This only applies on compute/combined constructs.
561 if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Update) {
562 const auto *Itr =
563 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCSelfClause>);
564 if (Itr != ExistingClauses.end()) {
565 SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
566 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
567 << (*Itr)->getClauseKind();
568 }
569 }
570
571 return OpenACCIfClause::Create(Ctx, Clause.getBeginLoc(),
572 Clause.getLParenLoc(),
573 Clause.getConditionExpr(), Clause.getEndLoc());
574}
575
576OpenACCClause *SemaOpenACCClauseVisitor::VisitSelfClause(
577 SemaOpenACC::OpenACCParsedClause &Clause) {
578
579 // If the 'if' clause is true, it makes the 'self' clause have no effect,
580 // diagnose that here. This only applies on compute/combined constructs.
581 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Update)
582 return OpenACCSelfClause::Create(Ctx, Clause.getBeginLoc(),
583 Clause.getLParenLoc(), Clause.getVarList(),
584 Clause.getEndLoc());
585
586 const auto *Itr =
587 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCIfClause>);
588 if (Itr != ExistingClauses.end()) {
589 SemaRef.Diag(Clause.getBeginLoc(), diag::warn_acc_if_self_conflict);
590 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
591 << (*Itr)->getClauseKind();
592 }
594 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
595 Clause.getConditionExpr(), Clause.getEndLoc());
596}
597
598OpenACCClause *SemaOpenACCClauseVisitor::VisitNumGangsClause(
599 SemaOpenACC::OpenACCParsedClause &Clause) {
600
601 if (DisallowSinceLastDeviceType<OpenACCNumGangsClause>(Clause))
602 return nullptr;
603
604 // num_gangs requires at least 1 int expr in all forms. Diagnose here, but
605 // allow us to continue, an empty clause might be useful for future
606 // diagnostics.
607 if (Clause.getIntExprs().empty())
608 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
609 << /*NoArgs=*/0;
610
611 unsigned MaxArgs =
612 (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
613 Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop)
614 ? 3
615 : 1;
616 // The max number of args differs between parallel and other constructs.
617 // Again, allow us to continue for the purposes of future diagnostics.
618 if (Clause.getIntExprs().size() > MaxArgs)
619 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_num_gangs_num_args)
620 << /*NoArgs=*/1 << Clause.getDirectiveKind() << MaxArgs
621 << Clause.getIntExprs().size();
622
623 // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
624 // directive that has a gang clause and is within a compute construct that has
625 // a num_gangs clause with more than one explicit argument.
626 if (Clause.getIntExprs().size() > 1 &&
628 auto *GangClauseItr =
629 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
630 auto *ReductionClauseItr =
631 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
632
633 if (GangClauseItr != ExistingClauses.end() &&
634 ReductionClauseItr != ExistingClauses.end()) {
635 SemaRef.Diag(Clause.getBeginLoc(),
636 diag::err_acc_gang_reduction_numgangs_conflict)
637 << OpenACCClauseKind::Reduction << OpenACCClauseKind::Gang
638 << Clause.getDirectiveKind() << /*is on combined directive=*/1;
639 SemaRef.Diag((*ReductionClauseItr)->getBeginLoc(),
640 diag::note_acc_previous_clause_here)
641 << (*ReductionClauseItr)->getClauseKind();
642 SemaRef.Diag((*GangClauseItr)->getBeginLoc(),
643 diag::note_acc_previous_clause_here)
644 << (*GangClauseItr)->getClauseKind();
645 return nullptr;
646 }
647 }
648
649 // OpenACC 3.3 Section 2.5.4:
650 // A reduction clause may not appear on a parallel construct with a
651 // num_gangs clause that has more than one argument.
652 if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
653 Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) &&
654 Clause.getIntExprs().size() > 1) {
655 auto *Parallel =
656 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
657
658 if (Parallel != ExistingClauses.end()) {
659 SemaRef.Diag(Clause.getBeginLoc(),
660 diag::err_acc_reduction_num_gangs_conflict)
661 << /*>1 arg in first loc=*/1 << Clause.getClauseKind()
662 << Clause.getDirectiveKind() << OpenACCClauseKind::Reduction;
663 SemaRef.Diag((*Parallel)->getBeginLoc(),
664 diag::note_acc_previous_clause_here)
665 << (*Parallel)->getClauseKind();
666 return nullptr;
667 }
668 }
669
670 // OpenACC 3.3 Section 2.9.2:
671 // An argument with no keyword or with the 'num' keyword is allowed only when
672 // the 'num_gangs' does not appear on the 'kernel' construct.
673 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {
674 auto GangClauses = llvm::make_filter_range(
675 ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
676
677 for (auto *GC : GangClauses) {
678 if (cast<OpenACCGangClause>(GC)->hasExprOfKind(OpenACCGangKind::Num)) {
679 SemaRef.Diag(Clause.getBeginLoc(),
680 diag::err_acc_num_arg_conflict_reverse)
681 << OpenACCClauseKind::NumGangs << OpenACCClauseKind::Gang
682 << /*Num argument*/ 1;
683 SemaRef.Diag(GC->getBeginLoc(), diag::note_acc_previous_clause_here)
684 << GC->getClauseKind();
685 return nullptr;
686 }
687 }
688 }
689
691 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs(),
692 Clause.getEndLoc());
693}
694
695OpenACCClause *SemaOpenACCClauseVisitor::VisitNumWorkersClause(
696 SemaOpenACC::OpenACCParsedClause &Clause) {
697
698 if (DisallowSinceLastDeviceType<OpenACCNumWorkersClause>(Clause))
699 return nullptr;
700
701 // OpenACC 3.3 Section 2.9.2:
702 // An argument is allowed only when the 'num_workers' does not appear on the
703 // kernels construct.
704 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {
705 auto WorkerClauses = llvm::make_filter_range(
706 ExistingClauses, llvm::IsaPred<OpenACCWorkerClause>);
707
708 for (auto *WC : WorkerClauses) {
709 if (cast<OpenACCWorkerClause>(WC)->hasIntExpr()) {
710 SemaRef.Diag(Clause.getBeginLoc(),
711 diag::err_acc_num_arg_conflict_reverse)
712 << OpenACCClauseKind::NumWorkers << OpenACCClauseKind::Worker
713 << /*num argument*/ 0;
714 SemaRef.Diag(WC->getBeginLoc(), diag::note_acc_previous_clause_here)
715 << WC->getClauseKind();
716 return nullptr;
717 }
718 }
719 }
720
721 assert(Clause.getIntExprs().size() == 1 &&
722 "Invalid number of expressions for NumWorkers");
724 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
725 Clause.getEndLoc());
726}
727
728OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorLengthClause(
729 SemaOpenACC::OpenACCParsedClause &Clause) {
730
731 if (DisallowSinceLastDeviceType<OpenACCVectorLengthClause>(Clause))
732 return nullptr;
733
734 // OpenACC 3.3 Section 2.9.4:
735 // An argument is allowed only when the 'vector_length' does not appear on the
736 // 'kernels' construct.
737 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::KernelsLoop) {
738 auto VectorClauses = llvm::make_filter_range(
739 ExistingClauses, llvm::IsaPred<OpenACCVectorClause>);
740
741 for (auto *VC : VectorClauses) {
742 if (cast<OpenACCVectorClause>(VC)->hasIntExpr()) {
743 SemaRef.Diag(Clause.getBeginLoc(),
744 diag::err_acc_num_arg_conflict_reverse)
745 << OpenACCClauseKind::VectorLength << OpenACCClauseKind::Vector
746 << /*num argument*/ 0;
747 SemaRef.Diag(VC->getBeginLoc(), diag::note_acc_previous_clause_here)
748 << VC->getClauseKind();
749 return nullptr;
750 }
751 }
752 }
753
754 assert(Clause.getIntExprs().size() == 1 &&
755 "Invalid number of expressions for NumWorkers");
757 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
758 Clause.getEndLoc());
759}
760
761OpenACCClause *SemaOpenACCClauseVisitor::VisitAsyncClause(
762 SemaOpenACC::OpenACCParsedClause &Clause) {
763 if (DisallowSinceLastDeviceType<OpenACCAsyncClause>(Clause))
764 return nullptr;
765
766 assert(Clause.getNumIntExprs() < 2 &&
767 "Invalid number of expressions for Async");
769 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
770 Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr,
771 Clause.getEndLoc());
772}
773
774OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause(
775 SemaOpenACC::OpenACCParsedClause &Clause) {
776 assert(Clause.getNumIntExprs() == 1 &&
777 "Invalid number of expressions for device_num");
779 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
780 Clause.getEndLoc());
781}
782
783OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultAsyncClause(
784 SemaOpenACC::OpenACCParsedClause &Clause) {
785 assert(Clause.getNumIntExprs() == 1 &&
786 "Invalid number of expressions for default_async");
788 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getIntExprs()[0],
789 Clause.getEndLoc());
790}
791
792OpenACCClause *SemaOpenACCClauseVisitor::VisitPrivateClause(
793 SemaOpenACC::OpenACCParsedClause &Clause) {
794 // ActOnVar ensured that everything is a valid variable reference, so there
795 // really isn't anything to do here. GCC does some duplicate-finding, though
796 // it isn't apparent in the standard where this is justified.
797
798 llvm::SmallVector<OpenACCPrivateRecipe> InitRecipes;
799
800 // Assemble the recipes list.
801 for (const Expr *VarExpr : Clause.getVarList())
802 InitRecipes.push_back(SemaRef.CreatePrivateInitRecipe(VarExpr));
803
805 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
806 InitRecipes, Clause.getEndLoc());
807}
808
809OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(
810 SemaOpenACC::OpenACCParsedClause &Clause) {
811 // ActOnVar ensured that everything is a valid variable reference, so there
812 // really isn't anything to do here. GCC does some duplicate-finding, though
813 // it isn't apparent in the standard where this is justified.
814
815 llvm::SmallVector<OpenACCFirstPrivateRecipe> InitRecipes;
816
817 // Assemble the recipes list.
818 for (const Expr *VarExpr : Clause.getVarList())
819 InitRecipes.push_back(SemaRef.CreateFirstPrivateInitRecipe(VarExpr));
820
822 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
823 InitRecipes, Clause.getEndLoc());
824}
825
826OpenACCClause *SemaOpenACCClauseVisitor::VisitNoCreateClause(
827 SemaOpenACC::OpenACCParsedClause &Clause) {
828 // ActOnVar ensured that everything is a valid variable reference, so there
829 // really isn't anything to do here. GCC does some duplicate-finding, though
830 // it isn't apparent in the standard where this is justified.
831
832 return OpenACCNoCreateClause::Create(Ctx, Clause.getBeginLoc(),
833 Clause.getLParenLoc(),
834 Clause.getVarList(), Clause.getEndLoc());
835}
836
837OpenACCClause *SemaOpenACCClauseVisitor::VisitPresentClause(
838 SemaOpenACC::OpenACCParsedClause &Clause) {
839 // ActOnVar ensured that everything is a valid variable reference, so there
840 // really isn't anything to do here. GCC does some duplicate-finding, though
841 // it isn't apparent in the standard where this is justified.
842
843 // 'declare' has some restrictions that need to be enforced separately, so
844 // check it here.
845 if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))
846 return nullptr;
847
848 return OpenACCPresentClause::Create(Ctx, Clause.getBeginLoc(),
849 Clause.getLParenLoc(),
850 Clause.getVarList(), Clause.getEndLoc());
851}
852
853OpenACCClause *SemaOpenACCClauseVisitor::VisitHostClause(
854 SemaOpenACC::OpenACCParsedClause &Clause) {
855 // ActOnVar ensured that everything is a valid variable reference, so there
856 // really isn't anything to do here. GCC does some duplicate-finding, though
857 // it isn't apparent in the standard where this is justified.
858
859 return OpenACCHostClause::Create(Ctx, Clause.getBeginLoc(),
860 Clause.getLParenLoc(), Clause.getVarList(),
861 Clause.getEndLoc());
862}
863
864OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceClause(
865 SemaOpenACC::OpenACCParsedClause &Clause) {
866 // ActOnVar ensured that everything is a valid variable reference, so there
867 // really isn't anything to do here. GCC does some duplicate-finding, though
868 // it isn't apparent in the standard where this is justified.
869
870 return OpenACCDeviceClause::Create(Ctx, Clause.getBeginLoc(),
871 Clause.getLParenLoc(), Clause.getVarList(),
872 Clause.getEndLoc());
873}
874
875OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyClause(
876 SemaOpenACC::OpenACCParsedClause &Clause) {
877 // ActOnVar ensured that everything is a valid variable reference, so there
878 // really isn't anything to do here. GCC does some duplicate-finding, though
879 // it isn't apparent in the standard where this is justified.
880
881 OpenACCModifierKind NewMods =
882 CheckModifierList(Clause, Clause.getModifierList());
883
884 // 'declare' has some restrictions that need to be enforced separately, so
885 // check it here.
886 if (SemaRef.CheckDeclareClause(Clause, NewMods))
887 return nullptr;
888
890 Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
891 Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());
892}
893
894OpenACCClause *SemaOpenACCClauseVisitor::VisitLinkClause(
895 SemaOpenACC::OpenACCParsedClause &Clause) {
896 // 'declare' has some restrictions that need to be enforced separately, so
897 // check it here.
898 if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))
899 return nullptr;
900
901 Clause.setVarListDetails(SemaRef.CheckLinkClauseVarList(Clause.getVarList()),
902 OpenACCModifierKind::Invalid);
903
904 return OpenACCLinkClause::Create(Ctx, Clause.getBeginLoc(),
905 Clause.getLParenLoc(), Clause.getVarList(),
906 Clause.getEndLoc());
907}
908
909OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceResidentClause(
910 SemaOpenACC::OpenACCParsedClause &Clause) {
911 // 'declare' has some restrictions that need to be enforced separately, so
912 // check it here.
913 if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))
914 return nullptr;
915
917 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
918 Clause.getEndLoc());
919}
920
921OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyInClause(
922 SemaOpenACC::OpenACCParsedClause &Clause) {
923 // ActOnVar ensured that everything is a valid variable reference, so there
924 // really isn't anything to do here. GCC does some duplicate-finding, though
925 // it isn't apparent in the standard where this is justified.
926
927 OpenACCModifierKind NewMods =
928 CheckModifierList(Clause, Clause.getModifierList());
929
930 // 'declare' has some restrictions that need to be enforced separately, so
931 // check it here.
932 if (SemaRef.CheckDeclareClause(Clause, NewMods))
933 return nullptr;
934
936 Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
937 Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());
938}
939
940OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyOutClause(
941 SemaOpenACC::OpenACCParsedClause &Clause) {
942 // ActOnVar ensured that everything is a valid variable reference, so there
943 // really isn't anything to do here. GCC does some duplicate-finding, though
944 // it isn't apparent in the standard where this is justified.
945
946 OpenACCModifierKind NewMods =
947 CheckModifierList(Clause, Clause.getModifierList());
948
949 // 'declare' has some restrictions that need to be enforced separately, so
950 // check it here.
951 if (SemaRef.CheckDeclareClause(Clause, NewMods))
952 return nullptr;
953
955 Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
956 Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());
957}
958
959OpenACCClause *SemaOpenACCClauseVisitor::VisitCreateClause(
960 SemaOpenACC::OpenACCParsedClause &Clause) {
961 // ActOnVar ensured that everything is a valid variable reference, so there
962 // really isn't anything to do here. GCC does some duplicate-finding, though
963 // it isn't apparent in the standard where this is justified.
964
965 OpenACCModifierKind NewMods =
966 CheckModifierList(Clause, Clause.getModifierList());
967
968 // 'declare' has some restrictions that need to be enforced separately, so
969 // check it here.
970 if (SemaRef.CheckDeclareClause(Clause, NewMods))
971 return nullptr;
972
974 Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
975 Clause.getModifierList(), Clause.getVarList(), Clause.getEndLoc());
976}
977
978OpenACCClause *SemaOpenACCClauseVisitor::VisitAttachClause(
979 SemaOpenACC::OpenACCParsedClause &Clause) {
980 // ActOnVar ensured that everything is a valid variable reference, but we
981 // still have to make sure it is a pointer type.
982 llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
983 llvm::erase_if(VarList, [&](Expr *E) {
984 return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::Attach, E);
985 });
986 Clause.setVarListDetails(VarList, OpenACCModifierKind::Invalid);
987 return OpenACCAttachClause::Create(Ctx, Clause.getBeginLoc(),
988 Clause.getLParenLoc(), Clause.getVarList(),
989 Clause.getEndLoc());
990}
991
992OpenACCClause *SemaOpenACCClauseVisitor::VisitDetachClause(
993 SemaOpenACC::OpenACCParsedClause &Clause) {
994 // ActOnVar ensured that everything is a valid variable reference, but we
995 // still have to make sure it is a pointer type.
996 llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
997 llvm::erase_if(VarList, [&](Expr *E) {
998 return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::Detach, E);
999 });
1000 Clause.setVarListDetails(VarList, OpenACCModifierKind::Invalid);
1001 return OpenACCDetachClause::Create(Ctx, Clause.getBeginLoc(),
1002 Clause.getLParenLoc(), Clause.getVarList(),
1003 Clause.getEndLoc());
1004}
1005
1006OpenACCClause *SemaOpenACCClauseVisitor::VisitDeleteClause(
1007 SemaOpenACC::OpenACCParsedClause &Clause) {
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 return OpenACCDeleteClause::Create(Ctx, Clause.getBeginLoc(),
1012 Clause.getLParenLoc(), Clause.getVarList(),
1013 Clause.getEndLoc());
1014}
1015
1016OpenACCClause *SemaOpenACCClauseVisitor::VisitUseDeviceClause(
1017 SemaOpenACC::OpenACCParsedClause &Clause) {
1018 // ActOnVar ensured that everything is a valid variable or array, so nothing
1019 // left to do here.
1021 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
1022 Clause.getEndLoc());
1023}
1024
1025OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause(
1026 SemaOpenACC::OpenACCParsedClause &Clause) {
1027 // ActOnVar ensured that everything is a valid variable reference, but we
1028 // still have to make sure it is a pointer type.
1029 llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
1030 llvm::erase_if(VarList, [&](Expr *E) {
1031 return SemaRef.CheckVarIsPointerType(OpenACCClauseKind::DevicePtr, E);
1032 });
1033 Clause.setVarListDetails(VarList, OpenACCModifierKind::Invalid);
1034
1035 // 'declare' has some restrictions that need to be enforced separately, so
1036 // check it here.
1037 if (SemaRef.CheckDeclareClause(Clause, OpenACCModifierKind::Invalid))
1038 return nullptr;
1039
1041 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getVarList(),
1042 Clause.getEndLoc());
1043}
1044
1045OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause(
1046 SemaOpenACC::OpenACCParsedClause &Clause) {
1048 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(), Clause.getDevNumExpr(),
1049 Clause.getQueuesLoc(), Clause.getQueueIdExprs(), Clause.getEndLoc());
1050}
1051
1052OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
1053 SemaOpenACC::OpenACCParsedClause &Clause) {
1054
1055 // OpenACC Pull #550 (https://github.com/OpenACC/openacc-spec/pull/550)
1056 // clarified that Init, Shutdown, and Set only support a single architecture.
1057 // Though the dialect only requires it for 'set' as far as we know, we'll just
1058 // implement all 3 here.
1059 if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Init ||
1060 Clause.getDirectiveKind() == OpenACCDirectiveKind::Shutdown ||
1061 Clause.getDirectiveKind() == OpenACCDirectiveKind::Set) &&
1062 Clause.getDeviceTypeArchitectures().size() > 1) {
1063 SemaRef.Diag(Clause.getDeviceTypeArchitectures()[1].getLoc(),
1064 diag::err_acc_device_type_multiple_archs)
1065 << Clause.getDirectiveKind();
1066 return nullptr;
1067 }
1068
1069 // The list of valid device_type values. Flang also has these hardcoded in
1070 // openacc_parsers.cpp, as there does not seem to be a reliable backend
1071 // source. The list below is sourced from Flang, though NVC++ supports only
1072 // 'nvidia', 'host', 'multicore', and 'default'.
1073 const std::array<llvm::StringLiteral, 6> ValidValues{
1074 "default", "nvidia", "acc_device_nvidia", "radeon", "host", "multicore"};
1075 // As an optimization, we have a manually maintained list of valid values
1076 // below, rather than trying to calculate from above. These should be kept in
1077 // sync if/when the above list ever changes.
1078 std::string ValidValuesString =
1079 "'default', 'nvidia', 'acc_device_nvidia', 'radeon', 'host', 'multicore'";
1080
1081 llvm::SmallVector<DeviceTypeArgument> Architectures{
1083
1084 // The parser has ensured that we either have a single entry of just '*'
1085 // (represented by a nullptr IdentifierInfo), or a list.
1086
1087 bool Diagnosed = false;
1088 auto FilterPred = [&](const DeviceTypeArgument &Arch) {
1089 // The '*' case.
1090 if (!Arch.getIdentifierInfo())
1091 return false;
1092 return llvm::find_if(ValidValues, [&](StringRef RHS) {
1093 return Arch.getIdentifierInfo()->getName().equals_insensitive(RHS);
1094 }) == ValidValues.end();
1095 };
1096
1097 auto Diagnose = [&](const DeviceTypeArgument &Arch) {
1098 Diagnosed = SemaRef.Diag(Arch.getLoc(), diag::err_acc_invalid_default_type)
1099 << Arch.getIdentifierInfo() << Clause.getClauseKind()
1100 << ValidValuesString;
1101 };
1102
1103 // There aren't stable enumertor versions of 'for-each-then-erase', so do it
1104 // here. We DO keep track of whether we diagnosed something to make sure we
1105 // don't do the 'erase_if' in the event that the first list didn't find
1106 // anything.
1107 llvm::for_each(llvm::make_filter_range(Architectures, FilterPred), Diagnose);
1108 if (Diagnosed)
1109 llvm::erase_if(Architectures, FilterPred);
1110
1112 Ctx, Clause.getClauseKind(), Clause.getBeginLoc(), Clause.getLParenLoc(),
1113 Architectures, Clause.getEndLoc());
1114}
1115
1116OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause(
1117 SemaOpenACC::OpenACCParsedClause &Clause) {
1118
1119 return OpenACCAutoClause::Create(Ctx, Clause.getBeginLoc(),
1120 Clause.getEndLoc());
1121}
1122
1123OpenACCClause *SemaOpenACCClauseVisitor::VisitNoHostClause(
1124 SemaOpenACC::OpenACCParsedClause &Clause) {
1125 return OpenACCNoHostClause::Create(Ctx, Clause.getBeginLoc(),
1126 Clause.getEndLoc());
1127}
1128
1129OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
1130 SemaOpenACC::OpenACCParsedClause &Clause) {
1131
1132 return OpenACCIndependentClause::Create(Ctx, Clause.getBeginLoc(),
1133 Clause.getEndLoc());
1134}
1135
1136ExprResult CheckGangStaticExpr(SemaOpenACC &S, Expr *E) {
1138 return E;
1139 return S.ActOnIntExpr(OpenACCDirectiveKind::Invalid, OpenACCClauseKind::Gang,
1140 E->getBeginLoc(), E);
1141}
1142
1143bool IsOrphanLoop(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) {
1144 return DK == OpenACCDirectiveKind::Loop &&
1145 AssocKind == OpenACCDirectiveKind::Invalid;
1146}
1147
1148bool HasAssocKind(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) {
1149 return DK == OpenACCDirectiveKind::Loop &&
1150 AssocKind != OpenACCDirectiveKind::Invalid;
1151}
1152
1153ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, OpenACCGangKind GK,
1155 OpenACCDirectiveKind AssocKind) {
1156 S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid)
1157 << GK << CK << IsOrphanLoop(DK, AssocKind) << DK
1158 << HasAssocKind(DK, AssocKind) << AssocKind;
1159 return ExprError();
1160}
1161ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, StringRef TagKind,
1163 OpenACCDirectiveKind AssocKind) {
1164 S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid)
1165 << TagKind << CK << IsOrphanLoop(DK, AssocKind) << DK
1166 << HasAssocKind(DK, AssocKind) << AssocKind;
1167 return ExprError();
1168}
1169
1170ExprResult CheckGangDimExpr(SemaOpenACC &S, Expr *E) {
1171 // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel
1172 // construct, or an orphaned loop construct, the gang clause behaves as
1173 // follows. ... The dim argument must be a constant positive integer value
1174 // 1, 2, or 3.
1175 // -also-
1176 // OpenACC 3.3 2.15: The 'dim' argument must be a constant positive integer
1177 // with value 1, 2, or 3.
1178 if (!E)
1179 return ExprError();
1180 ExprResult Res = S.ActOnIntExpr(OpenACCDirectiveKind::Invalid,
1181 OpenACCClauseKind::Gang, E->getBeginLoc(), E);
1182
1183 if (!Res.isUsable())
1184 return Res;
1185
1186 if (Res.get()->isInstantiationDependent())
1187 return Res;
1188
1189 std::optional<llvm::APSInt> ICE =
1191
1192 if (!ICE || *ICE <= 0 || ICE > 3) {
1193 S.Diag(Res.get()->getBeginLoc(), diag::err_acc_gang_dim_value)
1194 << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
1195 return ExprError();
1196 }
1197
1198 return ExprResult{
1199 ConstantExpr::Create(S.getASTContext(), Res.get(), APValue{*ICE})};
1200}
1201
1202ExprResult CheckGangParallelExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1203 OpenACCDirectiveKind AssocKind,
1204 OpenACCGangKind GK, Expr *E) {
1205 switch (GK) {
1206 case OpenACCGangKind::Static:
1207 return CheckGangStaticExpr(S, E);
1208 case OpenACCGangKind::Num:
1209 // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel
1210 // construct, or an orphaned loop construct, the gang clause behaves as
1211 // follows. ... The num argument is not allowed.
1212 return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1213 case OpenACCGangKind::Dim:
1214 return CheckGangDimExpr(S, E);
1215 }
1216 llvm_unreachable("Unknown gang kind in gang parallel check");
1217}
1218
1219ExprResult CheckGangKernelsExpr(SemaOpenACC &S,
1220 ArrayRef<const OpenACCClause *> ExistingClauses,
1222 OpenACCDirectiveKind AssocKind,
1223 OpenACCGangKind GK, Expr *E) {
1224 switch (GK) {
1225 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1226 // construct, the gang clause behaves as follows. ... The dim argument is
1227 // not allowed.
1228 case OpenACCGangKind::Dim:
1229 return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1230 case OpenACCGangKind::Num: {
1231 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1232 // construct, the gang clause behaves as follows. ... An argument with no
1233 // keyword or with num keyword is only allowed when num_gangs does not
1234 // appear on the kernels construct. ... The region of a loop with the gang
1235 // clause may not contain another loop with a gang clause unless within a
1236 // nested compute region.
1237
1238 // If this is a 'combined' construct, search the list of existing clauses.
1239 // Else we need to search the containing 'kernel'.
1240 auto Collection = isOpenACCCombinedDirectiveKind(DK)
1241 ? ExistingClauses
1242 : S.getActiveComputeConstructInfo().Clauses;
1243
1244 const auto *Itr =
1245 llvm::find_if(Collection, llvm::IsaPred<OpenACCNumGangsClause>);
1246
1247 if (Itr != Collection.end()) {
1248 S.Diag(E->getBeginLoc(), diag::err_acc_num_arg_conflict)
1249 << "num" << OpenACCClauseKind::Gang << DK
1250 << HasAssocKind(DK, AssocKind) << AssocKind
1251 << OpenACCClauseKind::NumGangs;
1252
1253 S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1254 << (*Itr)->getClauseKind();
1255 return ExprError();
1256 }
1257 return ExprResult{E};
1258 }
1259 case OpenACCGangKind::Static:
1260 return CheckGangStaticExpr(S, E);
1261 }
1262 llvm_unreachable("Unknown gang kind in gang kernels check");
1263}
1264
1265ExprResult CheckGangSerialExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1266 OpenACCDirectiveKind AssocKind,
1267 OpenACCGangKind GK, Expr *E) {
1268 switch (GK) {
1269 // 'dim' and 'num' don't really make sense on serial, and GCC rejects them
1270 // too, so we disallow them too.
1271 case OpenACCGangKind::Dim:
1272 case OpenACCGangKind::Num:
1273 return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1274 case OpenACCGangKind::Static:
1275 return CheckGangStaticExpr(S, E);
1276 }
1277 llvm_unreachable("Unknown gang kind in gang serial check");
1278}
1279
1280ExprResult CheckGangRoutineExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1281 OpenACCDirectiveKind AssocKind,
1282 OpenACCGangKind GK, Expr *E) {
1283 switch (GK) {
1284 // Only 'dim' is allowed on a routine, so diallow num and static.
1285 case OpenACCGangKind::Num:
1286 case OpenACCGangKind::Static:
1287 return DiagIntArgInvalid(S, E, GK, OpenACCClauseKind::Gang, DK, AssocKind);
1288 case OpenACCGangKind::Dim:
1289 return CheckGangDimExpr(S, E);
1290 }
1291 llvm_unreachable("Unknown gang kind in gang serial check");
1292}
1293
1294OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorClause(
1295 SemaOpenACC::OpenACCParsedClause &Clause) {
1296 if (DiagGangWorkerVectorSeqConflict(Clause))
1297 return nullptr;
1298
1299 Expr *IntExpr =
1300 Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
1301 if (IntExpr) {
1302 switch (Clause.getDirectiveKind()) {
1303 default:
1304 llvm_unreachable("Invalid directive kind for this clause");
1305 case OpenACCDirectiveKind::Loop:
1306 switch (SemaRef.getActiveComputeConstructInfo().Kind) {
1307 case OpenACCDirectiveKind::Invalid:
1308 case OpenACCDirectiveKind::Parallel:
1309 case OpenACCDirectiveKind::ParallelLoop:
1310 // No restriction on when 'parallel' can contain an argument.
1311 break;
1312 case OpenACCDirectiveKind::Serial:
1313 case OpenACCDirectiveKind::SerialLoop:
1314 // GCC disallows this, and there is no real good reason for us to permit
1315 // it, so disallow until we come up with a use case that makes sense.
1316 DiagIntArgInvalid(SemaRef, IntExpr, "length", OpenACCClauseKind::Vector,
1317 Clause.getDirectiveKind(),
1318 SemaRef.getActiveComputeConstructInfo().Kind);
1319 IntExpr = nullptr;
1320 break;
1321 case OpenACCDirectiveKind::Kernels:
1322 case OpenACCDirectiveKind::KernelsLoop: {
1323 const auto *Itr =
1324 llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
1325 llvm::IsaPred<OpenACCVectorLengthClause>);
1326 if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
1327 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1328 << "length" << OpenACCClauseKind::Vector
1329 << Clause.getDirectiveKind()
1330 << HasAssocKind(Clause.getDirectiveKind(),
1331 SemaRef.getActiveComputeConstructInfo().Kind)
1332 << SemaRef.getActiveComputeConstructInfo().Kind
1333 << OpenACCClauseKind::VectorLength;
1334 SemaRef.Diag((*Itr)->getBeginLoc(),
1335 diag::note_acc_previous_clause_here)
1336 << (*Itr)->getClauseKind();
1337
1338 IntExpr = nullptr;
1339 }
1340 break;
1341 }
1342 default:
1343 llvm_unreachable("Non compute construct in active compute construct");
1344 }
1345 break;
1346 case OpenACCDirectiveKind::KernelsLoop: {
1347 const auto *Itr = llvm::find_if(ExistingClauses,
1348 llvm::IsaPred<OpenACCVectorLengthClause>);
1349 if (Itr != ExistingClauses.end()) {
1350 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1351 << "length" << OpenACCClauseKind::Vector
1352 << Clause.getDirectiveKind()
1353 << HasAssocKind(Clause.getDirectiveKind(),
1354 SemaRef.getActiveComputeConstructInfo().Kind)
1355 << SemaRef.getActiveComputeConstructInfo().Kind
1356 << OpenACCClauseKind::VectorLength;
1357 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1358 << (*Itr)->getClauseKind();
1359
1360 IntExpr = nullptr;
1361 }
1362 break;
1363 }
1364 case OpenACCDirectiveKind::SerialLoop:
1365 case OpenACCDirectiveKind::Routine:
1366 DiagIntArgInvalid(SemaRef, IntExpr, "length", OpenACCClauseKind::Vector,
1367 Clause.getDirectiveKind(),
1368 SemaRef.getActiveComputeConstructInfo().Kind);
1369 IntExpr = nullptr;
1370 break;
1371 case OpenACCDirectiveKind::ParallelLoop:
1372 break;
1373 case OpenACCDirectiveKind::Invalid:
1374 // This can happen when the directive was not recognized, but we continued
1375 // anyway. Since there is a lot of stuff that can happen (including
1376 // 'allow anything' in the parallel loop case), just skip all checking and
1377 // continue.
1378 break;
1379 }
1380 }
1381
1382 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
1383 // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1384 // contain a loop with a gang, worker, or vector clause unless within a
1385 // nested compute region.
1386 if (SemaRef.LoopVectorClauseLoc.isValid()) {
1387 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1388 // on one of these until we get to the end of the construct.
1389 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1390 << OpenACCClauseKind::Vector << OpenACCClauseKind::Vector
1391 << /*skip kernels construct info*/ 0;
1392 SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1393 diag::note_acc_previous_clause_here)
1394 << "vector";
1395 return nullptr;
1396 }
1397 }
1398
1399 return OpenACCVectorClause::Create(Ctx, Clause.getBeginLoc(),
1400 Clause.getLParenLoc(), IntExpr,
1401 Clause.getEndLoc());
1402}
1403
1404OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
1405 SemaOpenACC::OpenACCParsedClause &Clause) {
1406 if (DiagGangWorkerVectorSeqConflict(Clause))
1407 return nullptr;
1408
1409 Expr *IntExpr =
1410 Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
1411
1412 if (IntExpr) {
1413 switch (Clause.getDirectiveKind()) {
1414 default:
1415 llvm_unreachable("Invalid directive kind for this clause");
1416 case OpenACCDirectiveKind::Invalid:
1417 // This can happen in cases where the directive was not recognized but we
1418 // continued anyway. Kernels allows kind of any integer argument, so we
1419 // can assume it is that (rather than marking the argument invalid like
1420 // with parallel/serial/routine), and just continue as if nothing
1421 // happened. We'll skip the 'kernels' checking vs num-workers, since this
1422 // MIGHT be something else.
1423 break;
1424 case OpenACCDirectiveKind::Loop:
1425 switch (SemaRef.getActiveComputeConstructInfo().Kind) {
1426 case OpenACCDirectiveKind::Invalid:
1427 case OpenACCDirectiveKind::ParallelLoop:
1428 case OpenACCDirectiveKind::SerialLoop:
1429 case OpenACCDirectiveKind::Parallel:
1430 case OpenACCDirectiveKind::Serial:
1431 DiagIntArgInvalid(SemaRef, IntExpr, OpenACCGangKind::Num,
1432 OpenACCClauseKind::Worker, Clause.getDirectiveKind(),
1433 SemaRef.getActiveComputeConstructInfo().Kind);
1434 IntExpr = nullptr;
1435 break;
1436 case OpenACCDirectiveKind::KernelsLoop:
1437 case OpenACCDirectiveKind::Kernels: {
1438 const auto *Itr =
1439 llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
1440 llvm::IsaPred<OpenACCNumWorkersClause>);
1441 if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
1442 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1443 << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind()
1444 << HasAssocKind(Clause.getDirectiveKind(),
1445 SemaRef.getActiveComputeConstructInfo().Kind)
1446 << SemaRef.getActiveComputeConstructInfo().Kind
1447 << OpenACCClauseKind::NumWorkers;
1448 SemaRef.Diag((*Itr)->getBeginLoc(),
1449 diag::note_acc_previous_clause_here)
1450 << (*Itr)->getClauseKind();
1451
1452 IntExpr = nullptr;
1453 }
1454 break;
1455 }
1456 default:
1457 llvm_unreachable("Non compute construct in active compute construct");
1458 }
1459 break;
1460 case OpenACCDirectiveKind::ParallelLoop:
1461 case OpenACCDirectiveKind::SerialLoop:
1462 case OpenACCDirectiveKind::Routine:
1463 DiagIntArgInvalid(SemaRef, IntExpr, OpenACCGangKind::Num,
1464 OpenACCClauseKind::Worker, Clause.getDirectiveKind(),
1465 SemaRef.getActiveComputeConstructInfo().Kind);
1466 IntExpr = nullptr;
1467 break;
1468 case OpenACCDirectiveKind::KernelsLoop: {
1469 const auto *Itr = llvm::find_if(ExistingClauses,
1470 llvm::IsaPred<OpenACCNumWorkersClause>);
1471 if (Itr != ExistingClauses.end()) {
1472 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1473 << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind()
1474 << HasAssocKind(Clause.getDirectiveKind(),
1475 SemaRef.getActiveComputeConstructInfo().Kind)
1476 << SemaRef.getActiveComputeConstructInfo().Kind
1477 << OpenACCClauseKind::NumWorkers;
1478 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1479 << (*Itr)->getClauseKind();
1480
1481 IntExpr = nullptr;
1482 }
1483 }
1484 }
1485 }
1486
1487 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
1488 // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1489 // contain a loop with a gang or worker clause unless within a nested
1490 // compute region.
1491 if (SemaRef.LoopWorkerClauseLoc.isValid()) {
1492 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1493 // on one of these until we get to the end of the construct.
1494 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1495 << OpenACCClauseKind::Worker << OpenACCClauseKind::Worker
1496 << /*skip kernels construct info*/ 0;
1497 SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,
1498 diag::note_acc_previous_clause_here)
1499 << "worker";
1500 return nullptr;
1501 }
1502
1503 // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1504 // contain a loop with a gang, worker, or vector clause unless within a
1505 // nested compute region.
1506 if (SemaRef.LoopVectorClauseLoc.isValid()) {
1507 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1508 // on one of these until we get to the end of the construct.
1509 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1510 << OpenACCClauseKind::Worker << OpenACCClauseKind::Vector
1511 << /*skip kernels construct info*/ 0;
1512 SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1513 diag::note_acc_previous_clause_here)
1514 << "vector";
1515 return nullptr;
1516 }
1517 }
1518
1519 return OpenACCWorkerClause::Create(Ctx, Clause.getBeginLoc(),
1520 Clause.getLParenLoc(), IntExpr,
1521 Clause.getEndLoc());
1522}
1523
1524OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
1525 SemaOpenACC::OpenACCParsedClause &Clause) {
1526
1527 if (DiagGangWorkerVectorSeqConflict(Clause))
1528 return nullptr;
1529
1530 // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
1531 // directive that has a gang clause and is within a compute construct that has
1532 // a num_gangs clause with more than one explicit argument.
1533 if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&
1534 SemaRef.getActiveComputeConstructInfo().Kind !=
1535 OpenACCDirectiveKind::Invalid) ||
1537 // num_gangs clause on the active compute construct.
1538 auto ActiveComputeConstructContainer =
1540 ? ExistingClauses
1541 : SemaRef.getActiveComputeConstructInfo().Clauses;
1542 auto *NumGangsClauseItr = llvm::find_if(
1543 ActiveComputeConstructContainer, llvm::IsaPred<OpenACCNumGangsClause>);
1544
1545 if (NumGangsClauseItr != ActiveComputeConstructContainer.end() &&
1546 cast<OpenACCNumGangsClause>(*NumGangsClauseItr)->getIntExprs().size() >
1547 1) {
1548 auto *ReductionClauseItr =
1549 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
1550
1551 if (ReductionClauseItr != ExistingClauses.end()) {
1552 SemaRef.Diag(Clause.getBeginLoc(),
1553 diag::err_acc_gang_reduction_numgangs_conflict)
1554 << OpenACCClauseKind::Gang << OpenACCClauseKind::Reduction
1555 << Clause.getDirectiveKind()
1557 SemaRef.Diag((*ReductionClauseItr)->getBeginLoc(),
1558 diag::note_acc_previous_clause_here)
1559 << (*ReductionClauseItr)->getClauseKind();
1560 SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),
1561 diag::note_acc_previous_clause_here)
1562 << (*NumGangsClauseItr)->getClauseKind();
1563 return nullptr;
1564 }
1565 }
1566 }
1567
1568 llvm::SmallVector<OpenACCGangKind> GangKinds;
1569 llvm::SmallVector<Expr *> IntExprs;
1570
1571 // Store the existing locations, so we can do duplicate checking. Index is
1572 // the int-value of the OpenACCGangKind enum.
1573 SourceLocation ExistingElemLoc[3];
1574
1575 for (unsigned I = 0; I < Clause.getIntExprs().size(); ++I) {
1576 OpenACCGangKind GK = Clause.getGangKinds()[I];
1577 ExprResult ER =
1578 SemaRef.CheckGangExpr(ExistingClauses, Clause.getDirectiveKind(), GK,
1579 Clause.getIntExprs()[I]);
1580
1581 if (!ER.isUsable())
1582 continue;
1583
1584 // OpenACC 3.3 2.9: 'gang-arg-list' may have at most one num, one dim, and
1585 // one static argument.
1586 if (ExistingElemLoc[static_cast<unsigned>(GK)].isValid()) {
1587 SemaRef.Diag(ER.get()->getBeginLoc(), diag::err_acc_gang_multiple_elt)
1588 << static_cast<unsigned>(GK);
1589 SemaRef.Diag(ExistingElemLoc[static_cast<unsigned>(GK)],
1590 diag::note_acc_previous_expr_here);
1591 continue;
1592 }
1593
1594 ExistingElemLoc[static_cast<unsigned>(GK)] = ER.get()->getBeginLoc();
1595 GangKinds.push_back(GK);
1596 IntExprs.push_back(ER.get());
1597 }
1598
1599 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
1600 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1601 // construct, the gang clause behaves as follows. ... The region of a loop
1602 // with a gang clause may not contain another loop with a gang clause unless
1603 // within a nested compute region.
1604 if (SemaRef.LoopGangClauseOnKernel.Loc.isValid()) {
1605 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1606 // on one of these until we get to the end of the construct.
1607 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1608 << OpenACCClauseKind::Gang << OpenACCClauseKind::Gang
1609 << /*kernels construct info*/ 1
1611 SemaRef.Diag(SemaRef.LoopGangClauseOnKernel.Loc,
1612 diag::note_acc_previous_clause_here)
1613 << "gang";
1614 return nullptr;
1615 }
1616
1617 // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1618 // contain a loop with a gang or worker clause unless within a nested
1619 // compute region.
1620 if (SemaRef.LoopWorkerClauseLoc.isValid()) {
1621 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1622 // on one of these until we get to the end of the construct.
1623 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1624 << OpenACCClauseKind::Gang << OpenACCClauseKind::Worker
1625 << /*!kernels construct info*/ 0;
1626 SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,
1627 diag::note_acc_previous_clause_here)
1628 << "worker";
1629 return nullptr;
1630 }
1631
1632 // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1633 // contain a loop with a gang, worker, or vector clause unless within a
1634 // nested compute region.
1635 if (SemaRef.LoopVectorClauseLoc.isValid()) {
1636 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1637 // on one of these until we get to the end of the construct.
1638 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1639 << OpenACCClauseKind::Gang << OpenACCClauseKind::Vector
1640 << /*!kernels construct info*/ 0;
1641 SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1642 diag::note_acc_previous_clause_here)
1643 << "vector";
1644 return nullptr;
1645 }
1646 }
1647
1648 return SemaRef.CheckGangClause(Clause.getDirectiveKind(), ExistingClauses,
1649 Clause.getBeginLoc(), Clause.getLParenLoc(),
1650 GangKinds, IntExprs, Clause.getEndLoc());
1651}
1652
1653OpenACCClause *SemaOpenACCClauseVisitor::VisitFinalizeClause(
1654 SemaOpenACC::OpenACCParsedClause &Clause) {
1655 // There isn't anything to do here, this is only valid on one construct, and
1656 // has no associated rules.
1657 return OpenACCFinalizeClause::Create(Ctx, Clause.getBeginLoc(),
1658 Clause.getEndLoc());
1659}
1660
1661OpenACCClause *SemaOpenACCClauseVisitor::VisitIfPresentClause(
1662 SemaOpenACC::OpenACCParsedClause &Clause) {
1663 // There isn't anything to do here, this is only valid on one construct, and
1664 // has no associated rules.
1665 return OpenACCIfPresentClause::Create(Ctx, Clause.getBeginLoc(),
1666 Clause.getEndLoc());
1667}
1668
1669OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
1670 SemaOpenACC::OpenACCParsedClause &Clause) {
1671 // OpenACC 3.3 2.9:
1672 // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
1673 // appears.
1674 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop ||
1676 const auto *Itr = llvm::find_if(
1677 ExistingClauses, llvm::IsaPred<OpenACCGangClause, OpenACCVectorClause,
1678 OpenACCWorkerClause>);
1679 if (Itr != ExistingClauses.end()) {
1680 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
1681 << Clause.getClauseKind() << (*Itr)->getClauseKind()
1682 << Clause.getDirectiveKind();
1683 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1684 << (*Itr)->getClauseKind();
1685 return nullptr;
1686 }
1687 }
1688
1689 return OpenACCSeqClause::Create(Ctx, Clause.getBeginLoc(),
1690 Clause.getEndLoc());
1691}
1692
1693OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
1694 SemaOpenACC::OpenACCParsedClause &Clause) {
1695 // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
1696 // directive that has a gang clause and is within a compute construct that has
1697 // a num_gangs clause with more than one explicit argument.
1698 if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&
1699 SemaRef.getActiveComputeConstructInfo().Kind !=
1700 OpenACCDirectiveKind::Invalid) ||
1702 // num_gangs clause on the active compute construct.
1703 auto ActiveComputeConstructContainer =
1705 ? ExistingClauses
1706 : SemaRef.getActiveComputeConstructInfo().Clauses;
1707 auto *NumGangsClauseItr = llvm::find_if(
1708 ActiveComputeConstructContainer, llvm::IsaPred<OpenACCNumGangsClause>);
1709
1710 if (NumGangsClauseItr != ActiveComputeConstructContainer.end() &&
1711 cast<OpenACCNumGangsClause>(*NumGangsClauseItr)->getIntExprs().size() >
1712 1) {
1713 auto *GangClauseItr =
1714 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
1715
1716 if (GangClauseItr != ExistingClauses.end()) {
1717 SemaRef.Diag(Clause.getBeginLoc(),
1718 diag::err_acc_gang_reduction_numgangs_conflict)
1719 << OpenACCClauseKind::Reduction << OpenACCClauseKind::Gang
1720 << Clause.getDirectiveKind()
1722 SemaRef.Diag((*GangClauseItr)->getBeginLoc(),
1723 diag::note_acc_previous_clause_here)
1724 << (*GangClauseItr)->getClauseKind();
1725 SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),
1726 diag::note_acc_previous_clause_here)
1727 << (*NumGangsClauseItr)->getClauseKind();
1728 return nullptr;
1729 }
1730 }
1731 }
1732
1733 // OpenACC3.3 Section 2.9.11: If a variable is involved in a reduction that
1734 // spans multiple nested loops where two or more of those loops have
1735 // associated loop directives, a reduction clause containing that variable
1736 // must appear on each of those loop directives.
1737 //
1738 // This can't really be implemented in the CFE, as this requires a level of
1739 // rechability/useage analysis that we're not really wanting to get into.
1740 // Additionally, I'm alerted that this restriction is one that the middle-end
1741 // can just 'figure out' as an extension and isn't really necessary.
1742 //
1743 // OpenACC3.3 Section 2.9.11: Every 'var' in a reduction clause appearing on
1744 // an orphaned loop construct must be private.
1745 //
1746 // This again is something we cannot really diagnose, as it requires we see
1747 // all the uses/scopes of all variables referenced. The middle end/MLIR might
1748 // be able to diagnose this.
1749
1750 // OpenACC 3.3 Section 2.5.4:
1751 // A reduction clause may not appear on a parallel construct with a
1752 // num_gangs clause that has more than one argument.
1753 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
1754 Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) {
1755 auto NumGangsClauses = llvm::make_filter_range(
1756 ExistingClauses, llvm::IsaPred<OpenACCNumGangsClause>);
1757
1758 for (auto *NGC : NumGangsClauses) {
1759 unsigned NumExprs =
1760 cast<OpenACCNumGangsClause>(NGC)->getIntExprs().size();
1761
1762 if (NumExprs > 1) {
1763 SemaRef.Diag(Clause.getBeginLoc(),
1764 diag::err_acc_reduction_num_gangs_conflict)
1765 << /*>1 arg in first loc=*/0 << Clause.getClauseKind()
1766 << Clause.getDirectiveKind() << OpenACCClauseKind::NumGangs;
1767 SemaRef.Diag(NGC->getBeginLoc(), diag::note_acc_previous_clause_here)
1768 << NGC->getClauseKind();
1769 return nullptr;
1770 }
1771 }
1772 }
1773
1774 SmallVector<Expr *> ValidVars;
1775 SmallVector<OpenACCReductionRecipe> Recipes;
1776
1777 for (Expr *Var : Clause.getVarList()) {
1778 ExprResult Res = SemaRef.CheckReductionVar(Clause.getDirectiveKind(),
1779 Clause.getReductionOp(), Var);
1780
1781 if (Res.isUsable()) {
1782 ValidVars.push_back(Res.get());
1783
1784 Recipes.push_back(SemaRef.CreateReductionInitRecipe(
1785 Clause.getReductionOp(), Res.get()));
1786 }
1787 }
1788
1789 return SemaRef.CheckReductionClause(
1790 ExistingClauses, Clause.getDirectiveKind(), Clause.getBeginLoc(),
1791 Clause.getLParenLoc(), Clause.getReductionOp(), ValidVars,
1792 Recipes,
1793 Clause.getEndLoc());
1794}
1795
1796OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(
1797 SemaOpenACC::OpenACCParsedClause &Clause) {
1798
1799 if (DisallowSinceLastDeviceType<OpenACCCollapseClause>(Clause))
1800 return nullptr;
1801
1802 ExprResult LoopCount = SemaRef.CheckCollapseLoopCount(Clause.getLoopCount());
1803
1804 if (!LoopCount.isUsable())
1805 return nullptr;
1806
1807 return OpenACCCollapseClause::Create(Ctx, Clause.getBeginLoc(),
1808 Clause.getLParenLoc(), Clause.isForce(),
1809 LoopCount.get(), Clause.getEndLoc());
1810}
1811
1812OpenACCClause *SemaOpenACCClauseVisitor::VisitBindClause(
1813 SemaOpenACC::OpenACCParsedClause &Clause) {
1814
1815 if (std::holds_alternative<StringLiteral *>(Clause.getBindDetails()))
1817 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
1818 std::get<StringLiteral *>(Clause.getBindDetails()), Clause.getEndLoc());
1820 Ctx, Clause.getBeginLoc(), Clause.getLParenLoc(),
1821 std::get<IdentifierInfo *>(Clause.getBindDetails()), Clause.getEndLoc());
1822}
1823
1824// Return true if the two vars refer to the same variable, for the purposes of
1825// equality checking.
1826bool areVarsEqual(Expr *VarExpr1, Expr *VarExpr2) {
1827 if (VarExpr1->isInstantiationDependent() ||
1828 VarExpr2->isInstantiationDependent())
1829 return false;
1830
1831 VarExpr1 = VarExpr1->IgnoreParenCasts();
1832 VarExpr2 = VarExpr2->IgnoreParenCasts();
1833
1834 // Legal expressions can be: Scalar variable reference, sub-array, array
1835 // element, or composite variable member.
1836
1837 // Sub-array.
1838 if (isa<ArraySectionExpr>(VarExpr1)) {
1839 auto *Expr2AS = dyn_cast<ArraySectionExpr>(VarExpr2);
1840 if (!Expr2AS)
1841 return false;
1842
1843 auto *Expr1AS = cast<ArraySectionExpr>(VarExpr1);
1844
1845 if (!areVarsEqual(Expr1AS->getBase(), Expr2AS->getBase()))
1846 return false;
1847 // We could possibly check to see if the ranges aren't overlapping, but it
1848 // isn't clear that the rules allow this.
1849 return true;
1850 }
1851
1852 // Array-element.
1853 if (isa<ArraySubscriptExpr>(VarExpr1)) {
1854 auto *Expr2AS = dyn_cast<ArraySubscriptExpr>(VarExpr2);
1855 if (!Expr2AS)
1856 return false;
1857
1858 auto *Expr1AS = cast<ArraySubscriptExpr>(VarExpr1);
1859
1860 if (!areVarsEqual(Expr1AS->getBase(), Expr2AS->getBase()))
1861 return false;
1862
1863 // We could possibly check to see if the elements referenced aren't the
1864 // same, but it isn't clear by reading of the standard that this is allowed
1865 // (and that the 'var' refered to isn't the array).
1866 return true;
1867 }
1868
1869 // Scalar variable reference, or composite variable.
1870 if (isa<DeclRefExpr>(VarExpr1)) {
1871 auto *Expr2DRE = dyn_cast<DeclRefExpr>(VarExpr2);
1872 if (!Expr2DRE)
1873 return false;
1874
1875 auto *Expr1DRE = cast<DeclRefExpr>(VarExpr1);
1876
1877 return Expr1DRE->getDecl()->getMostRecentDecl() ==
1878 Expr2DRE->getDecl()->getMostRecentDecl();
1879 }
1880
1881 llvm_unreachable("Unknown variable type encountered");
1882}
1883} // namespace
1884
1885OpenACCClause *
1887 OpenACCParsedClause &Clause) {
1888 if (Clause.getClauseKind() == OpenACCClauseKind::Invalid)
1889 return nullptr;
1890
1891 if (DiagnoseAllowedClauses(Clause.getDirectiveKind(), Clause.getClauseKind(),
1892 Clause.getBeginLoc()))
1893 return nullptr;
1894 //// Diagnose that we don't support this clause on this directive.
1895 // if (!doesClauseApplyToDirective(Clause.getDirectiveKind(),
1896 // Clause.getClauseKind())) {
1897 // Diag(Clause.getBeginLoc(), diag::err_acc_clause_appertainment)
1898 // << Clause.getDirectiveKind() << Clause.getClauseKind();
1899 // return nullptr;
1900 // }
1901
1902 if (const auto *DevTypeClause = llvm::find_if(
1903 ExistingClauses, llvm::IsaPred<OpenACCDeviceTypeClause>);
1904 DevTypeClause != ExistingClauses.end()) {
1905 if (checkValidAfterDeviceType(
1906 *this, *cast<OpenACCDeviceTypeClause>(*DevTypeClause), Clause))
1907 return nullptr;
1908 }
1909
1910 SemaOpenACCClauseVisitor Visitor{*this, ExistingClauses};
1911 OpenACCClause *Result = Visitor.Visit(Clause);
1912 assert((!Result || Result->getClauseKind() == Clause.getClauseKind()) &&
1913 "Created wrong clause?");
1914
1915 return Result;
1916}
1917
1918/// OpenACC 3.3 section 2.5.15:
1919/// At a mininmum, the supported data types include ... the numerical data types
1920/// in C, C++, and Fortran.
1921///
1922/// If the reduction var is a composite variable, each
1923/// member of the composite variable must be a supported datatype for the
1924/// reduction operation.
1926 OpenACCReductionOperator ReductionOp,
1927 Expr *VarExpr) {
1928 // For now, we only support 'scalar' types, or composites/arrays of scalar
1929 // types.
1930 VarExpr = VarExpr->IgnoreParenCasts();
1931 SourceLocation VarLoc = VarExpr->getBeginLoc();
1932
1934 QualType CurType = VarExpr->getType();
1935
1936 // For array like things, the expression can either be an array element
1937 // (subscript expr), array section, or array type. Peel those off, and add
1938 // notes in case we find an illegal kind. We'll allow scalar or composite of
1939 // scalars inside of this.
1940 if (auto *ASE = dyn_cast<ArraySectionExpr>(VarExpr)) {
1942
1943 PartialDiagnostic PD = PDiag(diag::note_acc_reduction_array)
1944 << diag::OACCReductionArray::Section << BaseType;
1945 Notes.push_back({ASE->getBeginLoc(), PD});
1946
1947 CurType = getASTContext().getBaseElementType(BaseType);
1948 } else if (auto *SubExpr = dyn_cast<ArraySubscriptExpr>(VarExpr)) {
1949 // Array subscript already results in the type of the thing as its type, so
1950 // there is no type to change here.
1952 PDiag(diag::note_acc_reduction_array)
1953 << diag::OACCReductionArray::Subscript
1954 << SubExpr->getBase()->IgnoreParenImpCasts()->getType();
1955 Notes.push_back({SubExpr->getBeginLoc(), PD});
1956 } else if (auto *AT = getASTContext().getAsArrayType(CurType)) {
1957 // If we're already the array type, peel off the array and leave the element
1958 // type.
1959 CurType = getASTContext().getBaseElementType(AT);
1960 PartialDiagnostic PD = PDiag(diag::note_acc_reduction_array)
1961 << diag::OACCReductionArray::ArrayTy << CurType;
1962 Notes.push_back({VarLoc, PD});
1963 }
1964
1965 auto IsValidMemberOfComposite = [](QualType Ty) {
1966 return !Ty->isAnyComplexType() &&
1967 (Ty->isDependentType() ||
1968 (Ty->isScalarType() && !Ty->isPointerType()));
1969 };
1970
1971 auto EmitDiags = [&](SourceLocation Loc, PartialDiagnostic PD) {
1972 Diag(Loc, PD);
1973
1974 for (auto [Loc, PD] : Notes)
1975 Diag(Loc, PD);
1976
1977 Diag(VarLoc, diag::note_acc_reduction_type_summary);
1978 };
1979
1980 // If the type is already scalar, or is dependent, just give up.
1981 if (IsValidMemberOfComposite(CurType)) {
1982 // Nothing to do here, is valid.
1983 } else if (auto *RD = CurType->getAsRecordDecl()) {
1984 if (!RD->isStruct() && !RD->isClass()) {
1985 EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)
1986 << RD << diag::OACCReductionTy::NotClassStruct);
1987 return ExprError();
1988 }
1989
1990 if (!RD->isCompleteDefinition()) {
1991 EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)
1992 << RD << diag::OACCReductionTy::NotComplete);
1993 return ExprError();
1994 }
1995
1996 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
1997 CXXRD && !CXXRD->isAggregate()) {
1998 EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)
1999 << CXXRD << diag::OACCReductionTy::NotAgg);
2000 return ExprError();
2001 }
2002
2003 for (FieldDecl *FD : RD->fields()) {
2004 if (!IsValidMemberOfComposite(FD->getType())) {
2006 PDiag(diag::note_acc_reduction_member_of_composite)
2007 << FD->getName() << RD->getName();
2008 Notes.push_back({FD->getBeginLoc(), PD});
2009 // TODO: member here.note_acc_reduction_member_of_composite
2010 EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)
2011 << FD->getType()
2012 << diag::OACCReductionTy::MemberNotScalar);
2013 return ExprError();
2014 }
2015 }
2016 } else {
2017 EmitDiags(VarLoc, PDiag(diag::err_acc_reduction_type)
2018 << CurType << diag::OACCReductionTy::NotScalar);
2019 }
2020
2021 // OpenACC3.3: 2.9.11: Reduction clauses on nested constructs for the same
2022 // reduction 'var' must have the same reduction operator.
2023 if (!VarExpr->isInstantiationDependent()) {
2024
2025 for (const OpenACCReductionClause *RClause : ActiveReductionClauses) {
2026 if (RClause->getReductionOp() == ReductionOp)
2027 break;
2028
2029 for (Expr *OldVarExpr : RClause->getVarList()) {
2030 if (OldVarExpr->isInstantiationDependent())
2031 continue;
2032
2033 if (areVarsEqual(VarExpr, OldVarExpr)) {
2034 Diag(VarExpr->getExprLoc(), diag::err_reduction_op_mismatch)
2035 << ReductionOp << RClause->getReductionOp();
2036 Diag(OldVarExpr->getExprLoc(), diag::note_acc_previous_clause_here)
2037 << RClause->getClauseKind();
2038 return ExprError();
2039 }
2040 }
2041 }
2042 }
2043
2044 return VarExpr;
2045}
2046
2048 if (!SizeExpr)
2049 return ExprError();
2050
2051 assert((SizeExpr->isInstantiationDependent() ||
2052 SizeExpr->getType()->isIntegerType()) &&
2053 "size argument non integer?");
2054
2055 // If dependent, or an asterisk, the expression is fine.
2056 if (SizeExpr->isInstantiationDependent() ||
2058 return ExprResult{SizeExpr};
2059
2060 std::optional<llvm::APSInt> ICE =
2062
2063 // OpenACC 3.3 2.9.8
2064 // where each tile size is a constant positive integer expression or asterisk.
2065 if (!ICE || *ICE <= 0) {
2066 Diag(SizeExpr->getBeginLoc(), diag::err_acc_size_expr_value)
2067 << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
2068 return ExprError();
2069 }
2070
2071 return ExprResult{
2072 ConstantExpr::Create(getASTContext(), SizeExpr, APValue{*ICE})};
2073}
2074
2076 if (!LoopCount)
2077 return ExprError();
2078
2079 assert((LoopCount->isInstantiationDependent() ||
2080 LoopCount->getType()->isIntegerType()) &&
2081 "Loop argument non integer?");
2082
2083 // If this is dependent, there really isn't anything we can check.
2084 if (LoopCount->isInstantiationDependent())
2085 return ExprResult{LoopCount};
2086
2087 std::optional<llvm::APSInt> ICE =
2089
2090 // OpenACC 3.3: 2.9.1
2091 // The argument to the collapse clause must be a constant positive integer
2092 // expression.
2093 if (!ICE || *ICE <= 0) {
2094 Diag(LoopCount->getBeginLoc(), diag::err_acc_collapse_loop_count)
2095 << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
2096 return ExprError();
2097 }
2098
2099 return ExprResult{
2100 ConstantExpr::Create(getASTContext(), LoopCount, APValue{*ICE})};
2101}
2102
2106 Expr *E) {
2107 // There are two cases for the enforcement here: the 'current' directive is a
2108 // 'loop', where we need to check the active compute construct kind, or the
2109 // current directive is a 'combined' construct, where we have to check the
2110 // current one.
2111 switch (DK) {
2113 return CheckGangParallelExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2114 E);
2116 return CheckGangSerialExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2117 E);
2119 return CheckGangKernelsExpr(*this, ExistingClauses, DK,
2120 ActiveComputeConstructInfo.Kind, GK, E);
2122 return CheckGangRoutineExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2123 E);
2125 switch (ActiveComputeConstructInfo.Kind) {
2129 return CheckGangParallelExpr(*this, DK, ActiveComputeConstructInfo.Kind,
2130 GK, E);
2133 return CheckGangSerialExpr(*this, DK, ActiveComputeConstructInfo.Kind, GK,
2134 E);
2137 return CheckGangKernelsExpr(*this, ExistingClauses, DK,
2138 ActiveComputeConstructInfo.Kind, GK, E);
2139 default:
2140 llvm_unreachable("Non compute construct in active compute construct?");
2141 }
2143 // This can happen in cases where the the directive was not recognized but
2144 // we continued anyway. Since the validity checking is all-over the place
2145 // (it can be a star/integer, or a constant expr depending on the tag), we
2146 // just give up and return an ExprError here.
2147 return ExprError();
2148 default:
2149 llvm_unreachable("Invalid directive kind for a Gang clause");
2150 }
2151 llvm_unreachable("Compute construct directive not handled?");
2152}
2153
2156 ArrayRef<const OpenACCClause *> ExistingClauses,
2157 SourceLocation BeginLoc, SourceLocation LParenLoc,
2158 ArrayRef<OpenACCGangKind> GangKinds,
2159 ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) {
2160 // Reduction isn't possible on 'routine' so we don't bother checking it here.
2161 if (DirKind != OpenACCDirectiveKind::Routine) {
2162 // OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
2163 // that has a gang clause with a dim: argument whose value is greater
2164 // than 1.
2165 const auto *ReductionItr =
2166 llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCReductionClause>);
2167
2168 if (ReductionItr != ExistingClauses.end()) {
2169 const auto GangZip = llvm::zip_equal(GangKinds, IntExprs);
2170 const auto GangItr = llvm::find_if(GangZip, [](const auto &Tuple) {
2171 return std::get<0>(Tuple) == OpenACCGangKind::Dim;
2172 });
2173
2174 if (GangItr != GangZip.end()) {
2175 const Expr *DimExpr = std::get<1>(*GangItr);
2176
2177 assert((DimExpr->isInstantiationDependent() ||
2178 isa<ConstantExpr>(DimExpr)) &&
2179 "Improperly formed gang argument");
2180 if (const auto *DimVal = dyn_cast<ConstantExpr>(DimExpr);
2181 DimVal && DimVal->getResultAsAPSInt() > 1) {
2182 Diag(DimVal->getBeginLoc(), diag::err_acc_gang_reduction_conflict)
2183 << /*gang/reduction=*/0 << DirKind;
2184 Diag((*ReductionItr)->getBeginLoc(),
2185 diag::note_acc_previous_clause_here)
2186 << (*ReductionItr)->getClauseKind();
2187 return nullptr;
2188 }
2189 }
2190 }
2191 }
2192
2193 return OpenACCGangClause::Create(getASTContext(), BeginLoc, LParenLoc,
2194 GangKinds, IntExprs, EndLoc);
2195}
2196
2198 ArrayRef<const OpenACCClause *> ExistingClauses,
2199 OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc,
2200 SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp,
2202 SourceLocation EndLoc) {
2203 if (DirectiveKind == OpenACCDirectiveKind::Loop ||
2204 isOpenACCCombinedDirectiveKind(DirectiveKind)) {
2205 // OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
2206 // that has a gang clause with a dim: argument whose value is greater
2207 // than 1.
2208 const auto GangClauses = llvm::make_filter_range(
2209 ExistingClauses, llvm::IsaPred<OpenACCGangClause>);
2210
2211 for (auto *GC : GangClauses) {
2212 const auto *GangClause = cast<OpenACCGangClause>(GC);
2213 for (unsigned I = 0; I < GangClause->getNumExprs(); ++I) {
2214 std::pair<OpenACCGangKind, const Expr *> EPair = GangClause->getExpr(I);
2215 if (EPair.first != OpenACCGangKind::Dim)
2216 continue;
2217
2218 if (const auto *DimVal = dyn_cast<ConstantExpr>(EPair.second);
2219 DimVal && DimVal->getResultAsAPSInt() > 1) {
2220 Diag(BeginLoc, diag::err_acc_gang_reduction_conflict)
2221 << /*reduction/gang=*/1 << DirectiveKind;
2222 Diag(GangClause->getBeginLoc(), diag::note_acc_previous_clause_here)
2223 << GangClause->getClauseKind();
2224 return nullptr;
2225 }
2226 }
2227 }
2228 }
2229
2231 getASTContext(), BeginLoc, LParenLoc, ReductionOp, Vars, Recipes, EndLoc);
2232 return Ret;
2233}
2234
2237 const DeclContext *DC = removeLinkageSpecDC(getCurContext());
2238
2239 // Link has no special restrictions on its var list unless it is not at NS/TU
2240 // scope.
2242 return llvm::SmallVector<Expr *>(VarExprs);
2243
2244 llvm::SmallVector<Expr *> NewVarList;
2245
2246 for (Expr *VarExpr : VarExprs) {
2248 NewVarList.push_back(VarExpr);
2249 continue;
2250 }
2251
2252 // Field decls can't be global, nor extern, and declare can't refer to
2253 // non-static fields in class-scope, so this always fails the scope check.
2254 // BUT for now we add this so it gets diagnosed by the general 'declare'
2255 // rules.
2256 if (isa<MemberExpr>(VarExpr)) {
2257 NewVarList.push_back(VarExpr);
2258 continue;
2259 }
2260
2261 const auto *DRE = cast<DeclRefExpr>(VarExpr);
2262 const VarDecl *Var = dyn_cast<VarDecl>(DRE->getDecl());
2263
2264 if (!Var || !Var->hasExternalStorage())
2265 Diag(VarExpr->getBeginLoc(), diag::err_acc_link_not_extern);
2266 else
2267 NewVarList.push_back(VarExpr);
2268 }
2269
2270 return NewVarList;
2271}
2273 OpenACCModifierKind Mods) {
2274
2275 if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Declare)
2276 return false;
2277
2278 const DeclContext *DC = removeLinkageSpecDC(getCurContext());
2279
2280 // Whether this is 'create', 'copyin', 'deviceptr', 'device_resident', or
2281 // 'link', which have 2 special rules.
2282 bool IsSpecialClause =
2283 Clause.getClauseKind() == OpenACCClauseKind::Create ||
2284 Clause.getClauseKind() == OpenACCClauseKind::CopyIn ||
2285 Clause.getClauseKind() == OpenACCClauseKind::DevicePtr ||
2286 Clause.getClauseKind() == OpenACCClauseKind::DeviceResident ||
2287 Clause.getClauseKind() == OpenACCClauseKind::Link;
2288
2289 // OpenACC 3.3 2.13:
2290 // In C or C++ global or namespace scope, only 'create',
2291 // 'copyin', 'deviceptr', 'device_resident', or 'link' clauses are
2292 // allowed.
2293 if (!IsSpecialClause && isa<NamespaceDecl, TranslationUnitDecl>(DC)) {
2294 return Diag(Clause.getBeginLoc(), diag::err_acc_declare_clause_at_global)
2295 << Clause.getClauseKind();
2296 }
2297
2298 llvm::SmallVector<Expr *> FilteredVarList;
2299 const DeclaratorDecl *CurDecl = nullptr;
2300 for (Expr *VarExpr : Clause.getVarList()) {
2302 // There isn't really anything we can do here, so we add them anyway and
2303 // we can check them again when we instantiate this.
2304 } else if (const auto *MemExpr = dyn_cast<MemberExpr>(VarExpr)) {
2305 FieldDecl *FD =
2306 cast<FieldDecl>(MemExpr->getMemberDecl()->getCanonicalDecl());
2307 CurDecl = FD;
2308
2309 if (removeLinkageSpecDC(
2310 FD->getLexicalDeclContext()->getPrimaryContext()) != DC) {
2311 Diag(MemExpr->getBeginLoc(), diag::err_acc_declare_same_scope)
2312 << Clause.getClauseKind();
2313 continue;
2314 }
2315 } else {
2316
2317 const Expr *VarExprTemp = VarExpr;
2318
2319 while (const auto *ASE = dyn_cast<ArraySectionExpr>(VarExprTemp))
2320 VarExprTemp = ASE->getBase()->IgnoreParenImpCasts();
2321
2322 const auto *DRE = cast<DeclRefExpr>(VarExprTemp);
2323 if (const auto *Var = dyn_cast<VarDecl>(DRE->getDecl())) {
2324 CurDecl = Var->getCanonicalDecl();
2325
2326 // OpenACC3.3 2.13:
2327 // A 'declare' directive must be in the same scope as the declaration of
2328 // any var that appears in the clauses of the directive or any scope
2329 // within a C/C++ function.
2330 // We can't really check 'scope' here, so we check declaration context,
2331 // which is a reasonable approximation, but misses scopes inside of
2332 // functions.
2333 if (removeLinkageSpecDC(
2334 Var->getLexicalDeclContext()->getPrimaryContext()) != DC) {
2335 Diag(VarExpr->getBeginLoc(), diag::err_acc_declare_same_scope)
2336 << Clause.getClauseKind();
2337 continue;
2338 }
2339 // OpenACC3.3 2.13:
2340 // C and C++ extern variables may only appear in 'create',
2341 // 'copyin', 'deviceptr', 'device_resident', or 'link' clauses on a
2342 // 'declare' directive.
2343 if (!IsSpecialClause && Var->hasExternalStorage()) {
2344 Diag(VarExpr->getBeginLoc(), diag::err_acc_declare_extern)
2345 << Clause.getClauseKind();
2346 continue;
2347 }
2348 }
2349
2350 // OpenACC3.3 2.13:
2351 // A var may appear at most once in all the clauses of declare
2352 // directives for a function, subroutine, program, or module.
2353
2354 if (CurDecl) {
2355 auto [Itr, Inserted] = DeclareVarReferences.try_emplace(CurDecl);
2356 if (!Inserted) {
2357 Diag(VarExpr->getBeginLoc(), diag::err_acc_multiple_references)
2358 << Clause.getClauseKind();
2359 Diag(Itr->second, diag::note_acc_previous_reference);
2360 continue;
2361 } else {
2362 Itr->second = VarExpr->getBeginLoc();
2363 }
2364 }
2365 }
2366 FilteredVarList.push_back(VarExpr);
2367 }
2368
2369 Clause.setVarListDetails(FilteredVarList, Mods);
2370 return false;
2371}
Defines the C++ Decl subclasses, other than those for templates (found in DeclTemplate....
Defines the clang::Expr interface and subclasses for C++ expressions.
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
Defines some OpenACC-specific enums and functions.
This file declares semantic analysis for OpenACC constructs and clauses.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
PtrTy get() const
Definition Ownership.h:171
bool isUsable() const
Definition Ownership.h:169
static QualType getBaseOriginalType(const Expr *Base)
Return original type of the base expression for array section.
Definition Expr.cpp:5224
static ConstantExpr * Create(const ASTContext &Context, Expr *E, const APValue &Result)
Definition Expr.cpp:346
DeclContext - This is used only as base class of specific decl types that can act as declaration cont...
Definition DeclBase.h:1449
DeclContext * getParent()
getParent - Returns the containing DeclContext.
Definition DeclBase.h:2109
DeclContext * getPrimaryContext()
getPrimaryContext - There may be many different declarations of the same entity (including forward de...
DeclContext * getLexicalDeclContext()
getLexicalDeclContext - The declaration context where this Decl was lexically declared (LexicalDC).
Definition DeclBase.h:918
virtual Decl * getCanonicalDecl()
Retrieves the "canonical" declaration of the given declaration.
Definition DeclBase.h:978
Represents a ValueDecl that came out of a declarator.
Definition Decl.h:779
This represents one expression.
Definition Expr.h:112
Expr * IgnoreParenCasts() LLVM_READONLY
Skip past any parentheses and casts which might surround this expression until reaching a fixed point...
Definition Expr.cpp:3078
Expr * IgnoreParenImpCasts() LLVM_READONLY
Skip past any parentheses and implicit casts which might surround this expression until reaching a fi...
Definition Expr.cpp:3073
std::optional< llvm::APSInt > getIntegerConstantExpr(const ASTContext &Ctx) const
isIntegerConstantExpr - Return the value if this expression is a valid integer constant expression.
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition Expr.h:223
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:273
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3157
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)
static OpenACCBindClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, const IdentifierInfo *ID, SourceLocation EndLoc)
This is the base type for all OpenACC Clauses.
OpenACCClauseKind getClauseKind() const
SourceLocation getBeginLoc() const
static OpenACCCollapseClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, bool HasForce, Expr *LoopCount, SourceLocation EndLoc)
static OpenACCCopyClause * Create(const ASTContext &C, OpenACCClauseKind Spelling, SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCModifierKind Mods, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCCopyInClause * Create(const ASTContext &C, OpenACCClauseKind Spelling, SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCModifierKind Mods, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCCopyOutClause * Create(const ASTContext &C, OpenACCClauseKind Spelling, SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCModifierKind Mods, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCCreateClause * Create(const ASTContext &C, OpenACCClauseKind Spelling, SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCModifierKind Mods, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCDefaultAsyncClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc)
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 OpenACCDeviceClause * 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)
static OpenACCDeviceResidentClause * 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 OpenACCFinalizeClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc)
static OpenACCFirstPrivateClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, ArrayRef< OpenACCFirstPrivateRecipe > InitRecipes, SourceLocation EndLoc)
static OpenACCGangClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< OpenACCGangKind > GangKinds, ArrayRef< Expr * > IntExprs, SourceLocation EndLoc)
static OpenACCHostClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
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 OpenACCLinkClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCNoCreateClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > VarList, SourceLocation EndLoc)
static OpenACCNoHostClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, 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, ArrayRef< OpenACCPrivateRecipe > InitRecipes, SourceLocation EndLoc)
static OpenACCReductionClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCReductionOperator Operator, ArrayRef< Expr * > VarList, ArrayRef< OpenACCReductionRecipe > Recipes, 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 OpenACCTileClause * Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< Expr * > SizeExprs, SourceLocation EndLoc)
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 OpenACCWorkerClause * Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation LParenLoc, Expr *IntExpr, SourceLocation EndLoc)
A (possibly-)qualified type.
Definition TypeBase.h:937
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition SemaBase.cpp:61
PartialDiagnostic PDiag(unsigned DiagID=0)
Build a partial diagnostic.
Definition SemaBase.cpp:33
ASTContext & getASTContext() const
Definition SemaBase.cpp:9
DeclContext * getCurContext() const
Definition SemaBase.cpp:12
A type to represent all the data for an OpenACC Clause that has been parsed, but not yet created/sema...
void setVarListDetails(ArrayRef< Expr * > VarList, OpenACCModifierKind ModKind)
ArrayRef< Expr * > getQueueIdExprs() const
OpenACCDirectiveKind getDirectiveKind() const
ArrayRef< OpenACCGangKind > getGangKinds() const
OpenACCReductionOperator getReductionOp() const
OpenACCClauseKind getClauseKind() const
ArrayRef< DeviceTypeArgument > getDeviceTypeArchitectures() const
std::variant< std::monostate, clang::StringLiteral *, IdentifierInfo * > getBindDetails() const
OpenACCModifierKind getModifierList() const
OpenACCDefaultClauseKind getDefaultClauseKind() const
bool CheckDeclareClause(SemaOpenACC::OpenACCParsedClause &Clause, OpenACCModifierKind Mods)
OpenACCPrivateRecipe CreatePrivateInitRecipe(const Expr *VarExpr)
ComputeConstructInfo & getActiveComputeConstructInfo()
OpenACCReductionRecipe CreateReductionInitRecipe(OpenACCReductionOperator ReductionOperator, const Expr *VarExpr)
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'.
OpenACCClause * CheckReductionClause(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp, ArrayRef< Expr * > Vars, ArrayRef< OpenACCReductionRecipe > Recipes, SourceLocation EndLoc)
SourceLocation LoopWorkerClauseLoc
If there is a current 'active' loop construct with a 'worker' clause on it (on any sort of construct)...
OpenACCClause * ActOnClause(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCParsedClause &Clause)
Called after parsing an OpenACC Clause so that it can be checked.
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...
llvm::SmallVector< Expr * > CheckLinkClauseVarList(ArrayRef< Expr * > VarExpr)
ExprResult CheckCollapseLoopCount(Expr *LoopCount)
Checks the loop depth value for a collapse clause.
SourceLocation LoopVectorClauseLoc
If there is a current 'active' loop construct with a 'vector' clause on it (on any sort of construct)...
ExprResult CheckGangExpr(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCDirectiveKind DK, OpenACCGangKind GK, Expr *E)
OpenACCFirstPrivateRecipe CreateFirstPrivateInitRecipe(const Expr *VarExpr)
OpenACCClause * CheckGangClause(OpenACCDirectiveKind DirKind, ArrayRef< const OpenACCClause * > ExistingClauses, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< OpenACCGangKind > GangKinds, ArrayRef< Expr * > IntExprs, SourceLocation EndLoc)
ExprResult CheckTileSizeExpr(Expr *SizeExpr)
Checks a single size expr for a tile clause.
Encodes a location in the source.
bool isValid() const
Return true if this is a valid SourceLocation object.
SourceLocation getBeginLoc() const LLVM_READONLY
Definition Stmt.cpp:346
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8922
Represents a variable declaration or definition.
Definition Decl.h:925
bool hasExternalStorage() const
Returns true if a variable has extern or private_extern storage.
Definition Decl.h:1216
The JSON file list parser is used to communicate input to InstallAPI.
OpenACCDirectiveKind
OpenACCReductionOperator
bool isa(CodeGen::Address addr)
Definition Address.h:330
bool isOpenACCComputeDirectiveKind(OpenACCDirectiveKind K)
bool isOpenACCCombinedDirectiveKind(OpenACCDirectiveKind K)
OpenACCModifierKind
OpenACCClauseKind
Represents the kind of an OpenACC clause.
@ Auto
'auto' clause, allowed on 'loop' directives.
@ Bind
'bind' clause, allowed on routine constructs.
@ Gang
'gang' clause, allowed on 'loop' and Combined constructs.
@ Wait
'wait' clause, allowed on Compute, Data, 'update', and Combined constructs.
@ DevicePtr
'deviceptr' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ VectorLength
'vector_length' clause, allowed on 'parallel', 'kernels', 'parallel loop', and 'kernels loop' constru...
@ Async
'async' clause, allowed on Compute, Data, 'update', 'wait', and Combined constructs.
@ Collapse
'collapse' clause, allowed on 'loop' and Combined constructs.
@ Invalid
Represents an invalid clause, for the purposes of parsing.
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Worker
'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
@ 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',...
@ NumGangs
'num_gangs' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs.
@ Link
'link' clause, allowed on 'declare' construct.
@ Seq
'seq' clause, allowed on 'loop' and 'routine' directives.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
@ DeviceResident
'device_resident' clause, allowed on the 'declare' construct.
@ DType
'dtype' clause, an alias for 'device_type', stored separately for diagnostic purposes.
@ CopyIn
'copyin' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ Independent
'independent' clause, allowed on 'loop' directives.
@ NumWorkers
'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs...
IdentifierLoc DeviceTypeArgument
@ Result
The result type of a method or function.
Definition TypeBase.h:905
ExprResult ExprError()
Definition Ownership.h:265
bool isOpenACCModifierBitSet(OpenACCModifierKind List, OpenACCModifierKind Bit)
U cast(CodeGen::Address addr)
Definition Address.h:327
ActionResult< Expr * > ExprResult
Definition Ownership.h:249
__DEVICE__ _Tp arg(const std::complex< _Tp > &__c)