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"
15#include "clang/AST/OpenACCClause.h"
16#include "clang/Basic/DiagnosticSema.h"
17#include "clang/Basic/OpenACCKinds.h"
18#include "clang/Sema/SemaOpenACC.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 ||
34 NewClause.getClauseKind() == OpenACCClauseKind::DeviceType)
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.
40 if (isOpenACCComputeDirectiveKind(K: NewClause.getDirectiveKind())) {
41 switch (NewClause.getClauseKind()) {
42 case OpenACCClauseKind::Async:
43 case OpenACCClauseKind::Wait:
44 case OpenACCClauseKind::NumGangs:
45 case OpenACCClauseKind::NumWorkers:
46 case OpenACCClauseKind::VectorLength:
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()) {
56 case OpenACCClauseKind::Collapse:
57 case OpenACCClauseKind::Gang:
58 case OpenACCClauseKind::Worker:
59 case OpenACCClauseKind::Vector:
60 case OpenACCClauseKind::Seq:
61 case OpenACCClauseKind::Independent:
62 case OpenACCClauseKind::Auto:
63 case OpenACCClauseKind::Tile:
64 return false;
65 default:
66 break;
67 }
68 } else if (isOpenACCCombinedDirectiveKind(K: NewClause.getDirectiveKind())) {
69 // This seems like it should be the union of 2.9 and 2.5.4 from above.
70 switch (NewClause.getClauseKind()) {
71 case OpenACCClauseKind::Async:
72 case OpenACCClauseKind::Wait:
73 case OpenACCClauseKind::NumGangs:
74 case OpenACCClauseKind::NumWorkers:
75 case OpenACCClauseKind::VectorLength:
76 case OpenACCClauseKind::Collapse:
77 case OpenACCClauseKind::Gang:
78 case OpenACCClauseKind::Worker:
79 case OpenACCClauseKind::Vector:
80 case OpenACCClauseKind::Seq:
81 case OpenACCClauseKind::Independent:
82 case OpenACCClauseKind::Auto:
83 case OpenACCClauseKind::Tile:
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()) {
92 case OpenACCClauseKind::Async:
93 case OpenACCClauseKind::Wait:
94 return false;
95 default:
96 break;
97 }
98 } else if (NewClause.getDirectiveKind() == OpenACCDirectiveKind::Set ||
99 NewClause.getDirectiveKind() == OpenACCDirectiveKind::Init ||
100 NewClause.getDirectiveKind() == OpenACCDirectiveKind::Shutdown) {
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()) {
107 case OpenACCClauseKind::Async:
108 case OpenACCClauseKind::Wait:
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()) {
117 case OpenACCClauseKind::Gang:
118 case OpenACCClauseKind::Worker:
119 case OpenACCClauseKind::Vector:
120 case OpenACCClauseKind::Seq:
121 case OpenACCClauseKind::Bind:
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>(Val: 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 &&
157 !isOpenACCCombinedDirectiveKind(K: Clause.getDirectiveKind()))
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(Range&: ExistingClauses, P: 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
177 OpenACCModifierKind
178 CheckModifierList(SemaOpenACC::OpenACCParsedClause &Clause,
179 OpenACCModifierKind Mods) {
180 auto CheckSingle = [=](OpenACCModifierKind CurMods,
181 OpenACCModifierKind ValidKinds,
182 OpenACCModifierKind Bit) {
183 if (!isOpenACCModifierBitSet(List: CurMods, Bit) ||
184 isOpenACCModifierBitSet(List: 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 ||
209 isOpenACCComputeDirectiveKind(K: Clause.getDirectiveKind()) ||
210 isOpenACCCombinedDirectiveKind(K: Clause.getDirectiveKind());
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 | OpenACCModifierKind::AlwaysIn |
235 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(Range&: ExistingClauses, P: 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(first: ExistingClauses.rbegin(), last: ExistingClauses.rend(),
305 pred: 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(HasPredicate: 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(HasPredicate: 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(first: ExistingClauses.rbegin(), last: ExistingClauses.rend(),
372 pred: 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>(Val: **LastDeviceTypeItr);
409
410 auto PrevDeviceTypeItr = LastDeviceTypeItr;
411 auto CurDevTypeItr = LastDeviceTypeItr;
412
413 while ((CurDevTypeItr = std::find_if(
414 first: std::next(x: PrevDeviceTypeItr), last: ExistingClauses.rend(),
415 pred: 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>(Val: **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 RHS: 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 DK: Clause.getDirectiveKind(), CK: Clause.getClauseKind(),
485 ClauseLoc: Clause.getBeginLoc(), Clauses: ExistingClauses) ||
486 SemaRef.DiagnoseExclusiveClauses(DK: Clause.getDirectiveKind(),
487 CK: Clause.getClauseKind(),
488 ClauseLoc: Clause.getBeginLoc(), Clauses: 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(
520 SemaOpenACC::OpenACCParsedClause &Clause) {
521 // Don't add an invalid clause to the AST.
522 if (Clause.getDefaultClauseKind() == OpenACCDefaultClauseKind::Invalid)
523 return nullptr;
524
525 return OpenACCDefaultClause::Create(
526 C: Ctx, K: Clause.getDefaultClauseKind(), BeginLoc: Clause.getBeginLoc(),
527 LParenLoc: Clause.getLParenLoc(), EndLoc: 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(SizeExpr: E);
541
542 if (!Res.isUsable())
543 return nullptr;
544
545 NewSizeExprs.push_back(Elt: Res.get());
546 }
547
548 return OpenACCTileClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
549 LParenLoc: Clause.getLParenLoc(), SizeExprs: NewSizeExprs,
550 EndLoc: 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(Range&: ExistingClauses, P: 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(C: Ctx, BeginLoc: Clause.getBeginLoc(),
572 LParenLoc: Clause.getLParenLoc(),
573 ConditionExpr: Clause.getConditionExpr(), EndLoc: 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(C: Ctx, BeginLoc: Clause.getBeginLoc(),
583 LParenLoc: Clause.getLParenLoc(), ConditionExpr: Clause.getVarList(),
584 EndLoc: Clause.getEndLoc());
585
586 const auto *Itr =
587 llvm::find_if(Range&: ExistingClauses, P: 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 }
593 return OpenACCSelfClause::Create(
594 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(),
595 ConditionExpr: Clause.getConditionExpr(), EndLoc: 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 &&
627 isOpenACCCombinedDirectiveKind(K: Clause.getDirectiveKind())) {
628 auto *GangClauseItr =
629 llvm::find_if(Range&: ExistingClauses, P: llvm::IsaPred<OpenACCGangClause>);
630 auto *ReductionClauseItr =
631 llvm::find_if(Range&: ExistingClauses, P: 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(Range&: ExistingClauses, P: 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 Range&: ExistingClauses, Pred: llvm::IsaPred<OpenACCGangClause>);
676
677 for (auto *GC : GangClauses) {
678 if (cast<OpenACCGangClause>(Val: GC)->hasExprOfKind(GK: 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
690 return OpenACCNumGangsClause::Create(
691 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), IntExprs: Clause.getIntExprs(),
692 EndLoc: 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 Range&: ExistingClauses, Pred: llvm::IsaPred<OpenACCWorkerClause>);
707
708 for (auto *WC : WorkerClauses) {
709 if (cast<OpenACCWorkerClause>(Val: 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");
723 return OpenACCNumWorkersClause::Create(
724 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), IntExpr: Clause.getIntExprs()[0],
725 EndLoc: 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 Range&: ExistingClauses, Pred: llvm::IsaPred<OpenACCVectorClause>);
740
741 for (auto *VC : VectorClauses) {
742 if (cast<OpenACCVectorClause>(Val: 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");
756 return OpenACCVectorLengthClause::Create(
757 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), IntExpr: Clause.getIntExprs()[0],
758 EndLoc: 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");
768 return OpenACCAsyncClause::Create(
769 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(),
770 IntExpr: Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr,
771 EndLoc: Clause.getEndLoc());
772}
773
774OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceNumClause(
775 SemaOpenACC::OpenACCParsedClause &Clause) {
776 assert(Clause.getNumIntExprs() == 1 &&
777 "Invalid number of expressions for device_num");
778 return OpenACCDeviceNumClause::Create(
779 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), IntExpr: Clause.getIntExprs()[0],
780 EndLoc: Clause.getEndLoc());
781}
782
783OpenACCClause *SemaOpenACCClauseVisitor::VisitDefaultAsyncClause(
784 SemaOpenACC::OpenACCParsedClause &Clause) {
785 assert(Clause.getNumIntExprs() == 1 &&
786 "Invalid number of expressions for default_async");
787 return OpenACCDefaultAsyncClause::Create(
788 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), IntExpr: Clause.getIntExprs()[0],
789 EndLoc: 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 return OpenACCPrivateClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
799 LParenLoc: Clause.getLParenLoc(),
800 VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc());
801}
802
803OpenACCClause *SemaOpenACCClauseVisitor::VisitFirstPrivateClause(
804 SemaOpenACC::OpenACCParsedClause &Clause) {
805 // ActOnVar ensured that everything is a valid variable reference, so there
806 // really isn't anything to do here. GCC does some duplicate-finding, though
807 // it isn't apparent in the standard where this is justified.
808
809 return OpenACCFirstPrivateClause::Create(
810 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(),
811 EndLoc: Clause.getEndLoc());
812}
813
814OpenACCClause *SemaOpenACCClauseVisitor::VisitNoCreateClause(
815 SemaOpenACC::OpenACCParsedClause &Clause) {
816 // ActOnVar ensured that everything is a valid variable reference, so there
817 // really isn't anything to do here. GCC does some duplicate-finding, though
818 // it isn't apparent in the standard where this is justified.
819
820 return OpenACCNoCreateClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
821 LParenLoc: Clause.getLParenLoc(),
822 VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc());
823}
824
825OpenACCClause *SemaOpenACCClauseVisitor::VisitPresentClause(
826 SemaOpenACC::OpenACCParsedClause &Clause) {
827 // ActOnVar ensured that everything is a valid variable reference, so there
828 // really isn't anything to do here. GCC does some duplicate-finding, though
829 // it isn't apparent in the standard where this is justified.
830
831 // 'declare' has some restrictions that need to be enforced separately, so
832 // check it here.
833 if (SemaRef.CheckDeclareClause(Clause, Mods: OpenACCModifierKind::Invalid))
834 return nullptr;
835
836 return OpenACCPresentClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
837 LParenLoc: Clause.getLParenLoc(),
838 VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc());
839}
840
841OpenACCClause *SemaOpenACCClauseVisitor::VisitHostClause(
842 SemaOpenACC::OpenACCParsedClause &Clause) {
843 // ActOnVar ensured that everything is a valid variable reference, so there
844 // really isn't anything to do here. GCC does some duplicate-finding, though
845 // it isn't apparent in the standard where this is justified.
846
847 return OpenACCHostClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
848 LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(),
849 EndLoc: Clause.getEndLoc());
850}
851
852OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceClause(
853 SemaOpenACC::OpenACCParsedClause &Clause) {
854 // ActOnVar ensured that everything is a valid variable reference, so there
855 // really isn't anything to do here. GCC does some duplicate-finding, though
856 // it isn't apparent in the standard where this is justified.
857
858 return OpenACCDeviceClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
859 LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(),
860 EndLoc: Clause.getEndLoc());
861}
862
863OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyClause(
864 SemaOpenACC::OpenACCParsedClause &Clause) {
865 // ActOnVar ensured that everything is a valid variable reference, so there
866 // really isn't anything to do here. GCC does some duplicate-finding, though
867 // it isn't apparent in the standard where this is justified.
868
869 OpenACCModifierKind NewMods =
870 CheckModifierList(Clause, Mods: Clause.getModifierList());
871
872 // 'declare' has some restrictions that need to be enforced separately, so
873 // check it here.
874 if (SemaRef.CheckDeclareClause(Clause, Mods: NewMods))
875 return nullptr;
876
877 return OpenACCCopyClause::Create(
878 C: Ctx, Spelling: Clause.getClauseKind(), BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(),
879 Mods: Clause.getModifierList(), VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc());
880}
881
882OpenACCClause *SemaOpenACCClauseVisitor::VisitLinkClause(
883 SemaOpenACC::OpenACCParsedClause &Clause) {
884 // 'declare' has some restrictions that need to be enforced separately, so
885 // check it here.
886 if (SemaRef.CheckDeclareClause(Clause, Mods: OpenACCModifierKind::Invalid))
887 return nullptr;
888
889 Clause.setVarListDetails(VarList: SemaRef.CheckLinkClauseVarList(VarExpr: Clause.getVarList()),
890 ModKind: OpenACCModifierKind::Invalid);
891
892 return OpenACCLinkClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
893 LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(),
894 EndLoc: Clause.getEndLoc());
895}
896
897OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceResidentClause(
898 SemaOpenACC::OpenACCParsedClause &Clause) {
899 // 'declare' has some restrictions that need to be enforced separately, so
900 // check it here.
901 if (SemaRef.CheckDeclareClause(Clause, Mods: OpenACCModifierKind::Invalid))
902 return nullptr;
903
904 return OpenACCDeviceResidentClause::Create(
905 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(),
906 EndLoc: Clause.getEndLoc());
907}
908
909OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyInClause(
910 SemaOpenACC::OpenACCParsedClause &Clause) {
911 // ActOnVar ensured that everything is a valid variable reference, so there
912 // really isn't anything to do here. GCC does some duplicate-finding, though
913 // it isn't apparent in the standard where this is justified.
914
915 OpenACCModifierKind NewMods =
916 CheckModifierList(Clause, Mods: Clause.getModifierList());
917
918 // 'declare' has some restrictions that need to be enforced separately, so
919 // check it here.
920 if (SemaRef.CheckDeclareClause(Clause, Mods: NewMods))
921 return nullptr;
922
923 return OpenACCCopyInClause::Create(
924 C: Ctx, Spelling: Clause.getClauseKind(), BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(),
925 Mods: Clause.getModifierList(), VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc());
926}
927
928OpenACCClause *SemaOpenACCClauseVisitor::VisitCopyOutClause(
929 SemaOpenACC::OpenACCParsedClause &Clause) {
930 // ActOnVar ensured that everything is a valid variable reference, so there
931 // really isn't anything to do here. GCC does some duplicate-finding, though
932 // it isn't apparent in the standard where this is justified.
933
934 OpenACCModifierKind NewMods =
935 CheckModifierList(Clause, Mods: Clause.getModifierList());
936
937 // 'declare' has some restrictions that need to be enforced separately, so
938 // check it here.
939 if (SemaRef.CheckDeclareClause(Clause, Mods: NewMods))
940 return nullptr;
941
942 return OpenACCCopyOutClause::Create(
943 C: Ctx, Spelling: Clause.getClauseKind(), BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(),
944 Mods: Clause.getModifierList(), VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc());
945}
946
947OpenACCClause *SemaOpenACCClauseVisitor::VisitCreateClause(
948 SemaOpenACC::OpenACCParsedClause &Clause) {
949 // ActOnVar ensured that everything is a valid variable reference, so there
950 // really isn't anything to do here. GCC does some duplicate-finding, though
951 // it isn't apparent in the standard where this is justified.
952
953 OpenACCModifierKind NewMods =
954 CheckModifierList(Clause, Mods: Clause.getModifierList());
955
956 // 'declare' has some restrictions that need to be enforced separately, so
957 // check it here.
958 if (SemaRef.CheckDeclareClause(Clause, Mods: NewMods))
959 return nullptr;
960
961 return OpenACCCreateClause::Create(
962 C: Ctx, Spelling: Clause.getClauseKind(), BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(),
963 Mods: Clause.getModifierList(), VarList: Clause.getVarList(), EndLoc: Clause.getEndLoc());
964}
965
966OpenACCClause *SemaOpenACCClauseVisitor::VisitAttachClause(
967 SemaOpenACC::OpenACCParsedClause &Clause) {
968 // ActOnVar ensured that everything is a valid variable reference, but we
969 // still have to make sure it is a pointer type.
970 llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
971 llvm::erase_if(C&: VarList, P: [&](Expr *E) {
972 return SemaRef.CheckVarIsPointerType(ClauseKind: OpenACCClauseKind::Attach, VarExpr: E);
973 });
974 Clause.setVarListDetails(VarList, ModKind: OpenACCModifierKind::Invalid);
975 return OpenACCAttachClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
976 LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(),
977 EndLoc: Clause.getEndLoc());
978}
979
980OpenACCClause *SemaOpenACCClauseVisitor::VisitDetachClause(
981 SemaOpenACC::OpenACCParsedClause &Clause) {
982 // ActOnVar ensured that everything is a valid variable reference, but we
983 // still have to make sure it is a pointer type.
984 llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
985 llvm::erase_if(C&: VarList, P: [&](Expr *E) {
986 return SemaRef.CheckVarIsPointerType(ClauseKind: OpenACCClauseKind::Detach, VarExpr: E);
987 });
988 Clause.setVarListDetails(VarList, ModKind: OpenACCModifierKind::Invalid);
989 return OpenACCDetachClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
990 LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(),
991 EndLoc: Clause.getEndLoc());
992}
993
994OpenACCClause *SemaOpenACCClauseVisitor::VisitDeleteClause(
995 SemaOpenACC::OpenACCParsedClause &Clause) {
996 // ActOnVar ensured that everything is a valid variable reference, so there
997 // really isn't anything to do here. GCC does some duplicate-finding, though
998 // it isn't apparent in the standard where this is justified.
999 return OpenACCDeleteClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
1000 LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(),
1001 EndLoc: Clause.getEndLoc());
1002}
1003
1004OpenACCClause *SemaOpenACCClauseVisitor::VisitUseDeviceClause(
1005 SemaOpenACC::OpenACCParsedClause &Clause) {
1006 // ActOnVar ensured that everything is a valid variable or array, so nothing
1007 // left to do here.
1008 return OpenACCUseDeviceClause::Create(
1009 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(),
1010 EndLoc: Clause.getEndLoc());
1011}
1012
1013OpenACCClause *SemaOpenACCClauseVisitor::VisitDevicePtrClause(
1014 SemaOpenACC::OpenACCParsedClause &Clause) {
1015 // ActOnVar ensured that everything is a valid variable reference, but we
1016 // still have to make sure it is a pointer type.
1017 llvm::SmallVector<Expr *> VarList{Clause.getVarList()};
1018 llvm::erase_if(C&: VarList, P: [&](Expr *E) {
1019 return SemaRef.CheckVarIsPointerType(ClauseKind: OpenACCClauseKind::DevicePtr, VarExpr: E);
1020 });
1021 Clause.setVarListDetails(VarList, ModKind: OpenACCModifierKind::Invalid);
1022
1023 // 'declare' has some restrictions that need to be enforced separately, so
1024 // check it here.
1025 if (SemaRef.CheckDeclareClause(Clause, Mods: OpenACCModifierKind::Invalid))
1026 return nullptr;
1027
1028 return OpenACCDevicePtrClause::Create(
1029 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), VarList: Clause.getVarList(),
1030 EndLoc: Clause.getEndLoc());
1031}
1032
1033OpenACCClause *SemaOpenACCClauseVisitor::VisitWaitClause(
1034 SemaOpenACC::OpenACCParsedClause &Clause) {
1035 return OpenACCWaitClause::Create(
1036 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(), DevNumExpr: Clause.getDevNumExpr(),
1037 QueuesLoc: Clause.getQueuesLoc(), QueueIdExprs: Clause.getQueueIdExprs(), EndLoc: Clause.getEndLoc());
1038}
1039
1040OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
1041 SemaOpenACC::OpenACCParsedClause &Clause) {
1042
1043 // Based on discussions, having more than 1 'architecture' on a 'set' is
1044 // nonsensical, so we're going to fix the standard to reflect this. Implement
1045 // the limitation, since the Dialect requires this.
1046 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Set &&
1047 Clause.getDeviceTypeArchitectures().size() > 1) {
1048 SemaRef.Diag(Clause.getDeviceTypeArchitectures()[1].getLoc(),
1049 diag::err_acc_device_type_multiple_archs);
1050 return nullptr;
1051 }
1052
1053 // The list of valid device_type values. Flang also has these hardcoded in
1054 // openacc_parsers.cpp, as there does not seem to be a reliable backend
1055 // source. The list below is sourced from Flang, though NVC++ supports only
1056 // 'nvidia', 'host', 'multicore', and 'default'.
1057 const std::array<llvm::StringLiteral, 6> ValidValues{
1058 "default", "nvidia", "acc_device_nvidia", "radeon", "host", "multicore"};
1059 // As an optimization, we have a manually maintained list of valid values
1060 // below, rather than trying to calculate from above. These should be kept in
1061 // sync if/when the above list ever changes.
1062 std::string ValidValuesString =
1063 "'default', 'nvidia', 'acc_device_nvidia', 'radeon', 'host', 'multicore'";
1064
1065 llvm::SmallVector<DeviceTypeArgument> Architectures{
1066 Clause.getDeviceTypeArchitectures()};
1067
1068 // The parser has ensured that we either have a single entry of just '*'
1069 // (represented by a nullptr IdentifierInfo), or a list.
1070
1071 bool Diagnosed = false;
1072 auto FilterPred = [&](const DeviceTypeArgument &Arch) {
1073 // The '*' case.
1074 if (!Arch.getIdentifierInfo())
1075 return false;
1076 return llvm::find_if(Range: ValidValues, P: [&](StringRef RHS) {
1077 return Arch.getIdentifierInfo()->getName().equals_insensitive(RHS);
1078 }) == ValidValues.end();
1079 };
1080
1081 auto Diagnose = [&](const DeviceTypeArgument &Arch) {
1082 Diagnosed = SemaRef.Diag(Arch.getLoc(), diag::err_acc_invalid_default_type)
1083 << Arch.getIdentifierInfo() << Clause.getClauseKind()
1084 << ValidValuesString;
1085 };
1086
1087 // There aren't stable enumertor versions of 'for-each-then-erase', so do it
1088 // here. We DO keep track of whether we diagnosed something to make sure we
1089 // don't do the 'erase_if' in the event that the first list didn't find
1090 // anything.
1091 llvm::for_each(Range: llvm::make_filter_range(Range&: Architectures, Pred: FilterPred), F: Diagnose);
1092 if (Diagnosed)
1093 llvm::erase_if(C&: Architectures, P: FilterPred);
1094
1095 return OpenACCDeviceTypeClause::Create(
1096 C: Ctx, K: Clause.getClauseKind(), BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(),
1097 Archs: Architectures, EndLoc: Clause.getEndLoc());
1098}
1099
1100OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause(
1101 SemaOpenACC::OpenACCParsedClause &Clause) {
1102
1103 return OpenACCAutoClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(),
1104 EndLoc: Clause.getEndLoc());
1105}
1106
1107OpenACCClause *SemaOpenACCClauseVisitor::VisitNoHostClause(
1108 SemaOpenACC::OpenACCParsedClause &Clause) {
1109 return OpenACCNoHostClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(),
1110 EndLoc: Clause.getEndLoc());
1111}
1112
1113OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
1114 SemaOpenACC::OpenACCParsedClause &Clause) {
1115
1116 return OpenACCIndependentClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(),
1117 EndLoc: Clause.getEndLoc());
1118}
1119
1120ExprResult CheckGangStaticExpr(SemaOpenACC &S, Expr *E) {
1121 if (isa<OpenACCAsteriskSizeExpr>(Val: E))
1122 return E;
1123 return S.ActOnIntExpr(DK: OpenACCDirectiveKind::Invalid, CK: OpenACCClauseKind::Gang,
1124 Loc: E->getBeginLoc(), IntExpr: E);
1125}
1126
1127bool IsOrphanLoop(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) {
1128 return DK == OpenACCDirectiveKind::Loop &&
1129 AssocKind == OpenACCDirectiveKind::Invalid;
1130}
1131
1132bool HasAssocKind(OpenACCDirectiveKind DK, OpenACCDirectiveKind AssocKind) {
1133 return DK == OpenACCDirectiveKind::Loop &&
1134 AssocKind != OpenACCDirectiveKind::Invalid;
1135}
1136
1137ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, OpenACCGangKind GK,
1138 OpenACCClauseKind CK, OpenACCDirectiveKind DK,
1139 OpenACCDirectiveKind AssocKind) {
1140 S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid)
1141 << GK << CK << IsOrphanLoop(DK, AssocKind) << DK
1142 << HasAssocKind(DK, AssocKind) << AssocKind;
1143 return ExprError();
1144}
1145ExprResult DiagIntArgInvalid(SemaOpenACC &S, Expr *E, StringRef TagKind,
1146 OpenACCClauseKind CK, OpenACCDirectiveKind DK,
1147 OpenACCDirectiveKind AssocKind) {
1148 S.Diag(E->getBeginLoc(), diag::err_acc_int_arg_invalid)
1149 << TagKind << CK << IsOrphanLoop(DK, AssocKind) << DK
1150 << HasAssocKind(DK, AssocKind) << AssocKind;
1151 return ExprError();
1152}
1153
1154ExprResult CheckGangDimExpr(SemaOpenACC &S, Expr *E) {
1155 // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel
1156 // construct, or an orphaned loop construct, the gang clause behaves as
1157 // follows. ... The dim argument must be a constant positive integer value
1158 // 1, 2, or 3.
1159 // -also-
1160 // OpenACC 3.3 2.15: The 'dim' argument must be a constant positive integer
1161 // with value 1, 2, or 3.
1162 if (!E)
1163 return ExprError();
1164 ExprResult Res = S.ActOnIntExpr(DK: OpenACCDirectiveKind::Invalid,
1165 CK: OpenACCClauseKind::Gang, Loc: E->getBeginLoc(), IntExpr: E);
1166
1167 if (!Res.isUsable())
1168 return Res;
1169
1170 if (Res.get()->isInstantiationDependent())
1171 return Res;
1172
1173 std::optional<llvm::APSInt> ICE =
1174 Res.get()->getIntegerConstantExpr(Ctx: S.getASTContext());
1175
1176 if (!ICE || *ICE <= 0 || ICE > 3) {
1177 S.Diag(Res.get()->getBeginLoc(), diag::err_acc_gang_dim_value)
1178 << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
1179 return ExprError();
1180 }
1181
1182 return ExprResult{
1183 ConstantExpr::Create(S.getASTContext(), Res.get(), APValue{*ICE})};
1184}
1185
1186ExprResult CheckGangParallelExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1187 OpenACCDirectiveKind AssocKind,
1188 OpenACCGangKind GK, Expr *E) {
1189 switch (GK) {
1190 case OpenACCGangKind::Static:
1191 return CheckGangStaticExpr(S, E);
1192 case OpenACCGangKind::Num:
1193 // OpenACC 3.3 2.9.2: When the parent compute construct is a parallel
1194 // construct, or an orphaned loop construct, the gang clause behaves as
1195 // follows. ... The num argument is not allowed.
1196 return DiagIntArgInvalid(S, E, GK, CK: OpenACCClauseKind::Gang, DK, AssocKind);
1197 case OpenACCGangKind::Dim:
1198 return CheckGangDimExpr(S, E);
1199 }
1200 llvm_unreachable("Unknown gang kind in gang parallel check");
1201}
1202
1203ExprResult CheckGangKernelsExpr(SemaOpenACC &S,
1204 ArrayRef<const OpenACCClause *> ExistingClauses,
1205 OpenACCDirectiveKind DK,
1206 OpenACCDirectiveKind AssocKind,
1207 OpenACCGangKind GK, Expr *E) {
1208 switch (GK) {
1209 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1210 // construct, the gang clause behaves as follows. ... The dim argument is
1211 // not allowed.
1212 case OpenACCGangKind::Dim:
1213 return DiagIntArgInvalid(S, E, GK, CK: OpenACCClauseKind::Gang, DK, AssocKind);
1214 case OpenACCGangKind::Num: {
1215 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1216 // construct, the gang clause behaves as follows. ... An argument with no
1217 // keyword or with num keyword is only allowed when num_gangs does not
1218 // appear on the kernels construct. ... The region of a loop with the gang
1219 // clause may not contain another loop with a gang clause unless within a
1220 // nested compute region.
1221
1222 // If this is a 'combined' construct, search the list of existing clauses.
1223 // Else we need to search the containing 'kernel'.
1224 auto Collection = isOpenACCCombinedDirectiveKind(K: DK)
1225 ? ExistingClauses
1226 : S.getActiveComputeConstructInfo().Clauses;
1227
1228 const auto *Itr =
1229 llvm::find_if(Range&: Collection, P: llvm::IsaPred<OpenACCNumGangsClause>);
1230
1231 if (Itr != Collection.end()) {
1232 S.Diag(E->getBeginLoc(), diag::err_acc_num_arg_conflict)
1233 << "num" << OpenACCClauseKind::Gang << DK
1234 << HasAssocKind(DK, AssocKind) << AssocKind
1235 << OpenACCClauseKind::NumGangs;
1236
1237 S.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1238 << (*Itr)->getClauseKind();
1239 return ExprError();
1240 }
1241 return ExprResult{E};
1242 }
1243 case OpenACCGangKind::Static:
1244 return CheckGangStaticExpr(S, E);
1245 }
1246 llvm_unreachable("Unknown gang kind in gang kernels check");
1247}
1248
1249ExprResult CheckGangSerialExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1250 OpenACCDirectiveKind AssocKind,
1251 OpenACCGangKind GK, Expr *E) {
1252 switch (GK) {
1253 // 'dim' and 'num' don't really make sense on serial, and GCC rejects them
1254 // too, so we disallow them too.
1255 case OpenACCGangKind::Dim:
1256 case OpenACCGangKind::Num:
1257 return DiagIntArgInvalid(S, E, GK, CK: OpenACCClauseKind::Gang, DK, AssocKind);
1258 case OpenACCGangKind::Static:
1259 return CheckGangStaticExpr(S, E);
1260 }
1261 llvm_unreachable("Unknown gang kind in gang serial check");
1262}
1263
1264ExprResult CheckGangRoutineExpr(SemaOpenACC &S, OpenACCDirectiveKind DK,
1265 OpenACCDirectiveKind AssocKind,
1266 OpenACCGangKind GK, Expr *E) {
1267 switch (GK) {
1268 // Only 'dim' is allowed on a routine, so diallow num and static.
1269 case OpenACCGangKind::Num:
1270 case OpenACCGangKind::Static:
1271 return DiagIntArgInvalid(S, E, GK, CK: OpenACCClauseKind::Gang, DK, AssocKind);
1272 case OpenACCGangKind::Dim:
1273 return CheckGangDimExpr(S, E);
1274 }
1275 llvm_unreachable("Unknown gang kind in gang serial check");
1276}
1277
1278OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorClause(
1279 SemaOpenACC::OpenACCParsedClause &Clause) {
1280 if (DiagGangWorkerVectorSeqConflict(Clause))
1281 return nullptr;
1282
1283 Expr *IntExpr =
1284 Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
1285 if (IntExpr) {
1286 switch (Clause.getDirectiveKind()) {
1287 default:
1288 llvm_unreachable("Invalid directive kind for this clause");
1289 case OpenACCDirectiveKind::Loop:
1290 switch (SemaRef.getActiveComputeConstructInfo().Kind) {
1291 case OpenACCDirectiveKind::Invalid:
1292 case OpenACCDirectiveKind::Parallel:
1293 case OpenACCDirectiveKind::ParallelLoop:
1294 // No restriction on when 'parallel' can contain an argument.
1295 break;
1296 case OpenACCDirectiveKind::Serial:
1297 case OpenACCDirectiveKind::SerialLoop:
1298 // GCC disallows this, and there is no real good reason for us to permit
1299 // it, so disallow until we come up with a use case that makes sense.
1300 DiagIntArgInvalid(S&: SemaRef, E: IntExpr, TagKind: "length", CK: OpenACCClauseKind::Vector,
1301 DK: Clause.getDirectiveKind(),
1302 AssocKind: SemaRef.getActiveComputeConstructInfo().Kind);
1303 IntExpr = nullptr;
1304 break;
1305 case OpenACCDirectiveKind::Kernels:
1306 case OpenACCDirectiveKind::KernelsLoop: {
1307 const auto *Itr =
1308 llvm::find_if(Range&: SemaRef.getActiveComputeConstructInfo().Clauses,
1309 P: llvm::IsaPred<OpenACCVectorLengthClause>);
1310 if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
1311 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1312 << "length" << OpenACCClauseKind::Vector
1313 << Clause.getDirectiveKind()
1314 << HasAssocKind(Clause.getDirectiveKind(),
1315 SemaRef.getActiveComputeConstructInfo().Kind)
1316 << SemaRef.getActiveComputeConstructInfo().Kind
1317 << OpenACCClauseKind::VectorLength;
1318 SemaRef.Diag((*Itr)->getBeginLoc(),
1319 diag::note_acc_previous_clause_here)
1320 << (*Itr)->getClauseKind();
1321
1322 IntExpr = nullptr;
1323 }
1324 break;
1325 }
1326 default:
1327 llvm_unreachable("Non compute construct in active compute construct");
1328 }
1329 break;
1330 case OpenACCDirectiveKind::KernelsLoop: {
1331 const auto *Itr = llvm::find_if(Range&: ExistingClauses,
1332 P: llvm::IsaPred<OpenACCVectorLengthClause>);
1333 if (Itr != ExistingClauses.end()) {
1334 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1335 << "length" << OpenACCClauseKind::Vector
1336 << Clause.getDirectiveKind()
1337 << HasAssocKind(Clause.getDirectiveKind(),
1338 SemaRef.getActiveComputeConstructInfo().Kind)
1339 << SemaRef.getActiveComputeConstructInfo().Kind
1340 << OpenACCClauseKind::VectorLength;
1341 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1342 << (*Itr)->getClauseKind();
1343
1344 IntExpr = nullptr;
1345 }
1346 break;
1347 }
1348 case OpenACCDirectiveKind::SerialLoop:
1349 case OpenACCDirectiveKind::Routine:
1350 DiagIntArgInvalid(S&: SemaRef, E: IntExpr, TagKind: "length", CK: OpenACCClauseKind::Vector,
1351 DK: Clause.getDirectiveKind(),
1352 AssocKind: SemaRef.getActiveComputeConstructInfo().Kind);
1353 IntExpr = nullptr;
1354 break;
1355 case OpenACCDirectiveKind::ParallelLoop:
1356 break;
1357 case OpenACCDirectiveKind::Invalid:
1358 // This can happen when the directive was not recognized, but we continued
1359 // anyway. Since there is a lot of stuff that can happen (including
1360 // 'allow anything' in the parallel loop case), just skip all checking and
1361 // continue.
1362 break;
1363 }
1364 }
1365
1366 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
1367 // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1368 // contain a loop with a gang, worker, or vector clause unless within a
1369 // nested compute region.
1370 if (SemaRef.LoopVectorClauseLoc.isValid()) {
1371 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1372 // on one of these until we get to the end of the construct.
1373 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1374 << OpenACCClauseKind::Vector << OpenACCClauseKind::Vector
1375 << /*skip kernels construct info*/ 0;
1376 SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1377 diag::note_acc_previous_clause_here)
1378 << "vector";
1379 return nullptr;
1380 }
1381 }
1382
1383 return OpenACCVectorClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(),
1384 LParenLoc: Clause.getLParenLoc(), IntExpr,
1385 EndLoc: Clause.getEndLoc());
1386}
1387
1388OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
1389 SemaOpenACC::OpenACCParsedClause &Clause) {
1390 if (DiagGangWorkerVectorSeqConflict(Clause))
1391 return nullptr;
1392
1393 Expr *IntExpr =
1394 Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
1395
1396 if (IntExpr) {
1397 switch (Clause.getDirectiveKind()) {
1398 default:
1399 llvm_unreachable("Invalid directive kind for this clause");
1400 case OpenACCDirectiveKind::Invalid:
1401 // This can happen in cases where the directive was not recognized but we
1402 // continued anyway. Kernels allows kind of any integer argument, so we
1403 // can assume it is that (rather than marking the argument invalid like
1404 // with parallel/serial/routine), and just continue as if nothing
1405 // happened. We'll skip the 'kernels' checking vs num-workers, since this
1406 // MIGHT be something else.
1407 break;
1408 case OpenACCDirectiveKind::Loop:
1409 switch (SemaRef.getActiveComputeConstructInfo().Kind) {
1410 case OpenACCDirectiveKind::Invalid:
1411 case OpenACCDirectiveKind::ParallelLoop:
1412 case OpenACCDirectiveKind::SerialLoop:
1413 case OpenACCDirectiveKind::Parallel:
1414 case OpenACCDirectiveKind::Serial:
1415 DiagIntArgInvalid(S&: SemaRef, E: IntExpr, GK: OpenACCGangKind::Num,
1416 CK: OpenACCClauseKind::Worker, DK: Clause.getDirectiveKind(),
1417 AssocKind: SemaRef.getActiveComputeConstructInfo().Kind);
1418 IntExpr = nullptr;
1419 break;
1420 case OpenACCDirectiveKind::KernelsLoop:
1421 case OpenACCDirectiveKind::Kernels: {
1422 const auto *Itr =
1423 llvm::find_if(Range&: SemaRef.getActiveComputeConstructInfo().Clauses,
1424 P: llvm::IsaPred<OpenACCNumWorkersClause>);
1425 if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
1426 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1427 << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind()
1428 << HasAssocKind(Clause.getDirectiveKind(),
1429 SemaRef.getActiveComputeConstructInfo().Kind)
1430 << SemaRef.getActiveComputeConstructInfo().Kind
1431 << OpenACCClauseKind::NumWorkers;
1432 SemaRef.Diag((*Itr)->getBeginLoc(),
1433 diag::note_acc_previous_clause_here)
1434 << (*Itr)->getClauseKind();
1435
1436 IntExpr = nullptr;
1437 }
1438 break;
1439 }
1440 default:
1441 llvm_unreachable("Non compute construct in active compute construct");
1442 }
1443 break;
1444 case OpenACCDirectiveKind::ParallelLoop:
1445 case OpenACCDirectiveKind::SerialLoop:
1446 case OpenACCDirectiveKind::Routine:
1447 DiagIntArgInvalid(S&: SemaRef, E: IntExpr, GK: OpenACCGangKind::Num,
1448 CK: OpenACCClauseKind::Worker, DK: Clause.getDirectiveKind(),
1449 AssocKind: SemaRef.getActiveComputeConstructInfo().Kind);
1450 IntExpr = nullptr;
1451 break;
1452 case OpenACCDirectiveKind::KernelsLoop: {
1453 const auto *Itr = llvm::find_if(Range&: ExistingClauses,
1454 P: llvm::IsaPred<OpenACCNumWorkersClause>);
1455 if (Itr != ExistingClauses.end()) {
1456 SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1457 << "num" << OpenACCClauseKind::Worker << Clause.getDirectiveKind()
1458 << HasAssocKind(Clause.getDirectiveKind(),
1459 SemaRef.getActiveComputeConstructInfo().Kind)
1460 << SemaRef.getActiveComputeConstructInfo().Kind
1461 << OpenACCClauseKind::NumWorkers;
1462 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1463 << (*Itr)->getClauseKind();
1464
1465 IntExpr = nullptr;
1466 }
1467 }
1468 }
1469 }
1470
1471 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
1472 // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1473 // contain a loop with a gang or worker clause unless within a nested
1474 // compute region.
1475 if (SemaRef.LoopWorkerClauseLoc.isValid()) {
1476 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1477 // on one of these until we get to the end of the construct.
1478 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1479 << OpenACCClauseKind::Worker << OpenACCClauseKind::Worker
1480 << /*skip kernels construct info*/ 0;
1481 SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,
1482 diag::note_acc_previous_clause_here)
1483 << "worker";
1484 return nullptr;
1485 }
1486
1487 // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1488 // contain a loop with a gang, worker, or vector clause unless within a
1489 // nested compute region.
1490 if (SemaRef.LoopVectorClauseLoc.isValid()) {
1491 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1492 // on one of these until we get to the end of the construct.
1493 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1494 << OpenACCClauseKind::Worker << OpenACCClauseKind::Vector
1495 << /*skip kernels construct info*/ 0;
1496 SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1497 diag::note_acc_previous_clause_here)
1498 << "vector";
1499 return nullptr;
1500 }
1501 }
1502
1503 return OpenACCWorkerClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(),
1504 LParenLoc: Clause.getLParenLoc(), IntExpr,
1505 EndLoc: Clause.getEndLoc());
1506}
1507
1508OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
1509 SemaOpenACC::OpenACCParsedClause &Clause) {
1510
1511 if (DiagGangWorkerVectorSeqConflict(Clause))
1512 return nullptr;
1513
1514 // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
1515 // directive that has a gang clause and is within a compute construct that has
1516 // a num_gangs clause with more than one explicit argument.
1517 if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&
1518 SemaRef.getActiveComputeConstructInfo().Kind !=
1519 OpenACCDirectiveKind::Invalid) ||
1520 isOpenACCCombinedDirectiveKind(K: Clause.getDirectiveKind())) {
1521 // num_gangs clause on the active compute construct.
1522 auto ActiveComputeConstructContainer =
1523 isOpenACCCombinedDirectiveKind(K: Clause.getDirectiveKind())
1524 ? ExistingClauses
1525 : SemaRef.getActiveComputeConstructInfo().Clauses;
1526 auto *NumGangsClauseItr = llvm::find_if(
1527 Range&: ActiveComputeConstructContainer, P: llvm::IsaPred<OpenACCNumGangsClause>);
1528
1529 if (NumGangsClauseItr != ActiveComputeConstructContainer.end() &&
1530 cast<OpenACCNumGangsClause>(Val: *NumGangsClauseItr)->getIntExprs().size() >
1531 1) {
1532 auto *ReductionClauseItr =
1533 llvm::find_if(Range&: ExistingClauses, P: llvm::IsaPred<OpenACCReductionClause>);
1534
1535 if (ReductionClauseItr != ExistingClauses.end()) {
1536 SemaRef.Diag(Clause.getBeginLoc(),
1537 diag::err_acc_gang_reduction_numgangs_conflict)
1538 << OpenACCClauseKind::Gang << OpenACCClauseKind::Reduction
1539 << Clause.getDirectiveKind()
1540 << isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind());
1541 SemaRef.Diag((*ReductionClauseItr)->getBeginLoc(),
1542 diag::note_acc_previous_clause_here)
1543 << (*ReductionClauseItr)->getClauseKind();
1544 SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),
1545 diag::note_acc_previous_clause_here)
1546 << (*NumGangsClauseItr)->getClauseKind();
1547 return nullptr;
1548 }
1549 }
1550 }
1551
1552 llvm::SmallVector<OpenACCGangKind> GangKinds;
1553 llvm::SmallVector<Expr *> IntExprs;
1554
1555 // Store the existing locations, so we can do duplicate checking. Index is
1556 // the int-value of the OpenACCGangKind enum.
1557 SourceLocation ExistingElemLoc[3];
1558
1559 for (unsigned I = 0; I < Clause.getIntExprs().size(); ++I) {
1560 OpenACCGangKind GK = Clause.getGangKinds()[I];
1561 ExprResult ER =
1562 SemaRef.CheckGangExpr(ExistingClauses, DK: Clause.getDirectiveKind(), GK,
1563 E: Clause.getIntExprs()[I]);
1564
1565 if (!ER.isUsable())
1566 continue;
1567
1568 // OpenACC 3.3 2.9: 'gang-arg-list' may have at most one num, one dim, and
1569 // one static argument.
1570 if (ExistingElemLoc[static_cast<unsigned>(GK)].isValid()) {
1571 SemaRef.Diag(ER.get()->getBeginLoc(), diag::err_acc_gang_multiple_elt)
1572 << static_cast<unsigned>(GK);
1573 SemaRef.Diag(ExistingElemLoc[static_cast<unsigned>(GK)],
1574 diag::note_acc_previous_expr_here);
1575 continue;
1576 }
1577
1578 ExistingElemLoc[static_cast<unsigned>(GK)] = ER.get()->getBeginLoc();
1579 GangKinds.push_back(Elt: GK);
1580 IntExprs.push_back(Elt: ER.get());
1581 }
1582
1583 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop) {
1584 // OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1585 // construct, the gang clause behaves as follows. ... The region of a loop
1586 // with a gang clause may not contain another loop with a gang clause unless
1587 // within a nested compute region.
1588 if (SemaRef.LoopGangClauseOnKernel.Loc.isValid()) {
1589 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1590 // on one of these until we get to the end of the construct.
1591 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1592 << OpenACCClauseKind::Gang << OpenACCClauseKind::Gang
1593 << /*kernels construct info*/ 1
1594 << SemaRef.LoopGangClauseOnKernel.DirKind;
1595 SemaRef.Diag(SemaRef.LoopGangClauseOnKernel.Loc,
1596 diag::note_acc_previous_clause_here)
1597 << "gang";
1598 return nullptr;
1599 }
1600
1601 // OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1602 // contain a loop with a gang or worker clause unless within a nested
1603 // compute region.
1604 if (SemaRef.LoopWorkerClauseLoc.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::Worker
1609 << /*!kernels construct info*/ 0;
1610 SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,
1611 diag::note_acc_previous_clause_here)
1612 << "worker";
1613 return nullptr;
1614 }
1615
1616 // OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1617 // contain a loop with a gang, worker, or vector clause unless within a
1618 // nested compute region.
1619 if (SemaRef.LoopVectorClauseLoc.isValid()) {
1620 // This handles the 'inner loop' diagnostic, but we cannot set that we're
1621 // on one of these until we get to the end of the construct.
1622 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1623 << OpenACCClauseKind::Gang << OpenACCClauseKind::Vector
1624 << /*!kernels construct info*/ 0;
1625 SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1626 diag::note_acc_previous_clause_here)
1627 << "vector";
1628 return nullptr;
1629 }
1630 }
1631
1632 return SemaRef.CheckGangClause(DirKind: Clause.getDirectiveKind(), ExistingClauses,
1633 BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(),
1634 GangKinds, IntExprs, EndLoc: Clause.getEndLoc());
1635}
1636
1637OpenACCClause *SemaOpenACCClauseVisitor::VisitFinalizeClause(
1638 SemaOpenACC::OpenACCParsedClause &Clause) {
1639 // There isn't anything to do here, this is only valid on one construct, and
1640 // has no associated rules.
1641 return OpenACCFinalizeClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(),
1642 EndLoc: Clause.getEndLoc());
1643}
1644
1645OpenACCClause *SemaOpenACCClauseVisitor::VisitIfPresentClause(
1646 SemaOpenACC::OpenACCParsedClause &Clause) {
1647 // There isn't anything to do here, this is only valid on one construct, and
1648 // has no associated rules.
1649 return OpenACCIfPresentClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(),
1650 EndLoc: Clause.getEndLoc());
1651}
1652
1653OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
1654 SemaOpenACC::OpenACCParsedClause &Clause) {
1655 // OpenACC 3.3 2.9:
1656 // A 'gang', 'worker', or 'vector' clause may not appear if a 'seq' clause
1657 // appears.
1658 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop ||
1659 isOpenACCCombinedDirectiveKind(K: Clause.getDirectiveKind())) {
1660 const auto *Itr = llvm::find_if(
1661 Range&: ExistingClauses, P: llvm::IsaPred<OpenACCGangClause, OpenACCVectorClause,
1662 OpenACCWorkerClause>);
1663 if (Itr != ExistingClauses.end()) {
1664 SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
1665 << Clause.getClauseKind() << (*Itr)->getClauseKind()
1666 << Clause.getDirectiveKind();
1667 SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here)
1668 << (*Itr)->getClauseKind();
1669 return nullptr;
1670 }
1671 }
1672
1673 return OpenACCSeqClause::Create(Ctx, BeginLoc: Clause.getBeginLoc(),
1674 EndLoc: Clause.getEndLoc());
1675}
1676
1677OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
1678 SemaOpenACC::OpenACCParsedClause &Clause) {
1679 // OpenACC 3.3 Section 2.9.11: A reduction clause may not appear on a loop
1680 // directive that has a gang clause and is within a compute construct that has
1681 // a num_gangs clause with more than one explicit argument.
1682 if ((Clause.getDirectiveKind() == OpenACCDirectiveKind::Loop &&
1683 SemaRef.getActiveComputeConstructInfo().Kind !=
1684 OpenACCDirectiveKind::Invalid) ||
1685 isOpenACCCombinedDirectiveKind(K: Clause.getDirectiveKind())) {
1686 // num_gangs clause on the active compute construct.
1687 auto ActiveComputeConstructContainer =
1688 isOpenACCCombinedDirectiveKind(K: Clause.getDirectiveKind())
1689 ? ExistingClauses
1690 : SemaRef.getActiveComputeConstructInfo().Clauses;
1691 auto *NumGangsClauseItr = llvm::find_if(
1692 Range&: ActiveComputeConstructContainer, P: llvm::IsaPred<OpenACCNumGangsClause>);
1693
1694 if (NumGangsClauseItr != ActiveComputeConstructContainer.end() &&
1695 cast<OpenACCNumGangsClause>(Val: *NumGangsClauseItr)->getIntExprs().size() >
1696 1) {
1697 auto *GangClauseItr =
1698 llvm::find_if(Range&: ExistingClauses, P: llvm::IsaPred<OpenACCGangClause>);
1699
1700 if (GangClauseItr != ExistingClauses.end()) {
1701 SemaRef.Diag(Clause.getBeginLoc(),
1702 diag::err_acc_gang_reduction_numgangs_conflict)
1703 << OpenACCClauseKind::Reduction << OpenACCClauseKind::Gang
1704 << Clause.getDirectiveKind()
1705 << isOpenACCCombinedDirectiveKind(Clause.getDirectiveKind());
1706 SemaRef.Diag((*GangClauseItr)->getBeginLoc(),
1707 diag::note_acc_previous_clause_here)
1708 << (*GangClauseItr)->getClauseKind();
1709 SemaRef.Diag((*NumGangsClauseItr)->getBeginLoc(),
1710 diag::note_acc_previous_clause_here)
1711 << (*NumGangsClauseItr)->getClauseKind();
1712 return nullptr;
1713 }
1714 }
1715 }
1716
1717 // OpenACC3.3 Section 2.9.11: If a variable is involved in a reduction that
1718 // spans multiple nested loops where two or more of those loops have
1719 // associated loop directives, a reduction clause containing that variable
1720 // must appear on each of those loop directives.
1721 //
1722 // This can't really be implemented in the CFE, as this requires a level of
1723 // rechability/useage analysis that we're not really wanting to get into.
1724 // Additionally, I'm alerted that this restriction is one that the middle-end
1725 // can just 'figure out' as an extension and isn't really necessary.
1726 //
1727 // OpenACC3.3 Section 2.9.11: Every 'var' in a reduction clause appearing on
1728 // an orphaned loop construct must be private.
1729 //
1730 // This again is something we cannot really diagnose, as it requires we see
1731 // all the uses/scopes of all variables referenced. The middle end/MLIR might
1732 // be able to diagnose this.
1733
1734 // OpenACC 3.3 Section 2.5.4:
1735 // A reduction clause may not appear on a parallel construct with a
1736 // num_gangs clause that has more than one argument.
1737 if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Parallel ||
1738 Clause.getDirectiveKind() == OpenACCDirectiveKind::ParallelLoop) {
1739 auto NumGangsClauses = llvm::make_filter_range(
1740 Range&: ExistingClauses, Pred: llvm::IsaPred<OpenACCNumGangsClause>);
1741
1742 for (auto *NGC : NumGangsClauses) {
1743 unsigned NumExprs =
1744 cast<OpenACCNumGangsClause>(Val: NGC)->getIntExprs().size();
1745
1746 if (NumExprs > 1) {
1747 SemaRef.Diag(Clause.getBeginLoc(),
1748 diag::err_acc_reduction_num_gangs_conflict)
1749 << /*>1 arg in first loc=*/0 << Clause.getClauseKind()
1750 << Clause.getDirectiveKind() << OpenACCClauseKind::NumGangs;
1751 SemaRef.Diag(NGC->getBeginLoc(), diag::note_acc_previous_clause_here)
1752 << NGC->getClauseKind();
1753 return nullptr;
1754 }
1755 }
1756 }
1757
1758 SmallVector<Expr *> ValidVars;
1759
1760 for (Expr *Var : Clause.getVarList()) {
1761 ExprResult Res = SemaRef.CheckReductionVar(DirectiveKind: Clause.getDirectiveKind(),
1762 ReductionOp: Clause.getReductionOp(), VarExpr: Var);
1763
1764 if (Res.isUsable())
1765 ValidVars.push_back(Elt: Res.get());
1766 }
1767
1768 return SemaRef.CheckReductionClause(
1769 ExistingClauses, DirectiveKind: Clause.getDirectiveKind(), BeginLoc: Clause.getBeginLoc(),
1770 LParenLoc: Clause.getLParenLoc(), ReductionOp: Clause.getReductionOp(), Vars: ValidVars,
1771 EndLoc: Clause.getEndLoc());
1772}
1773
1774OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(
1775 SemaOpenACC::OpenACCParsedClause &Clause) {
1776
1777 if (DisallowSinceLastDeviceType<OpenACCCollapseClause>(Clause))
1778 return nullptr;
1779
1780 ExprResult LoopCount = SemaRef.CheckCollapseLoopCount(LoopCount: Clause.getLoopCount());
1781
1782 if (!LoopCount.isUsable())
1783 return nullptr;
1784
1785 return OpenACCCollapseClause::Create(C: Ctx, BeginLoc: Clause.getBeginLoc(),
1786 LParenLoc: Clause.getLParenLoc(), HasForce: Clause.isForce(),
1787 LoopCount: LoopCount.get(), EndLoc: Clause.getEndLoc());
1788}
1789
1790OpenACCClause *SemaOpenACCClauseVisitor::VisitBindClause(
1791 SemaOpenACC::OpenACCParsedClause &Clause) {
1792
1793 if (std::holds_alternative<StringLiteral *>(v: Clause.getBindDetails()))
1794 return OpenACCBindClause::Create(
1795 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(),
1796 SL: std::get<StringLiteral *>(v: Clause.getBindDetails()), EndLoc: Clause.getEndLoc());
1797 return OpenACCBindClause::Create(
1798 C: Ctx, BeginLoc: Clause.getBeginLoc(), LParenLoc: Clause.getLParenLoc(),
1799 ID: std::get<IdentifierInfo *>(v: Clause.getBindDetails()), EndLoc: Clause.getEndLoc());
1800}
1801
1802// Return true if the two vars refer to the same variable, for the purposes of
1803// equality checking.
1804bool areVarsEqual(Expr *VarExpr1, Expr *VarExpr2) {
1805 if (VarExpr1->isInstantiationDependent() ||
1806 VarExpr2->isInstantiationDependent())
1807 return false;
1808
1809 VarExpr1 = VarExpr1->IgnoreParenCasts();
1810 VarExpr2 = VarExpr2->IgnoreParenCasts();
1811
1812 // Legal expressions can be: Scalar variable reference, sub-array, array
1813 // element, or composite variable member.
1814
1815 // Sub-array.
1816 if (isa<ArraySectionExpr>(Val: VarExpr1)) {
1817 auto *Expr2AS = dyn_cast<ArraySectionExpr>(Val: VarExpr2);
1818 if (!Expr2AS)
1819 return false;
1820
1821 auto *Expr1AS = cast<ArraySectionExpr>(Val: VarExpr1);
1822
1823 if (!areVarsEqual(VarExpr1: Expr1AS->getBase(), VarExpr2: Expr2AS->getBase()))
1824 return false;
1825 // We could possibly check to see if the ranges aren't overlapping, but it
1826 // isn't clear that the rules allow this.
1827 return true;
1828 }
1829
1830 // Array-element.
1831 if (isa<ArraySubscriptExpr>(Val: VarExpr1)) {
1832 auto *Expr2AS = dyn_cast<ArraySubscriptExpr>(Val: VarExpr2);
1833 if (!Expr2AS)
1834 return false;
1835
1836 auto *Expr1AS = cast<ArraySubscriptExpr>(Val: VarExpr1);
1837
1838 if (!areVarsEqual(VarExpr1: Expr1AS->getBase(), VarExpr2: Expr2AS->getBase()))
1839 return false;
1840
1841 // We could possibly check to see if the elements referenced aren't the
1842 // same, but it isn't clear by reading of the standard that this is allowed
1843 // (and that the 'var' refered to isn't the array).
1844 return true;
1845 }
1846
1847 // Scalar variable reference, or composite variable.
1848 if (isa<DeclRefExpr>(Val: VarExpr1)) {
1849 auto *Expr2DRE = dyn_cast<DeclRefExpr>(Val: VarExpr2);
1850 if (!Expr2DRE)
1851 return false;
1852
1853 auto *Expr1DRE = cast<DeclRefExpr>(Val: VarExpr1);
1854
1855 return Expr1DRE->getDecl()->getMostRecentDecl() ==
1856 Expr2DRE->getDecl()->getMostRecentDecl();
1857 }
1858
1859 llvm_unreachable("Unknown variable type encountered");
1860}
1861} // namespace
1862
1863OpenACCClause *
1864SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
1865 OpenACCParsedClause &Clause) {
1866 if (Clause.getClauseKind() == OpenACCClauseKind::Invalid)
1867 return nullptr;
1868
1869 if (DiagnoseAllowedClauses(DK: Clause.getDirectiveKind(), CK: Clause.getClauseKind(),
1870 ClauseLoc: Clause.getBeginLoc()))
1871 return nullptr;
1872 //// Diagnose that we don't support this clause on this directive.
1873 // if (!doesClauseApplyToDirective(Clause.getDirectiveKind(),
1874 // Clause.getClauseKind())) {
1875 // Diag(Clause.getBeginLoc(), diag::err_acc_clause_appertainment)
1876 // << Clause.getDirectiveKind() << Clause.getClauseKind();
1877 // return nullptr;
1878 // }
1879
1880 if (const auto *DevTypeClause = llvm::find_if(
1881 Range&: ExistingClauses, P: llvm::IsaPred<OpenACCDeviceTypeClause>);
1882 DevTypeClause != ExistingClauses.end()) {
1883 if (checkValidAfterDeviceType(
1884 S&: *this, DeviceTypeClause: *cast<OpenACCDeviceTypeClause>(Val: *DevTypeClause), NewClause: Clause))
1885 return nullptr;
1886 }
1887
1888 SemaOpenACCClauseVisitor Visitor{*this, ExistingClauses};
1889 OpenACCClause *Result = Visitor.Visit(Clause);
1890 assert((!Result || Result->getClauseKind() == Clause.getClauseKind()) &&
1891 "Created wrong clause?");
1892
1893 return Result;
1894}
1895
1896/// OpenACC 3.3 section 2.5.15:
1897/// At a mininmum, the supported data types include ... the numerical data types
1898/// in C, C++, and Fortran.
1899///
1900/// If the reduction var is a composite variable, each
1901/// member of the composite variable must be a supported datatype for the
1902/// reduction operation.
1903ExprResult SemaOpenACC::CheckReductionVar(OpenACCDirectiveKind DirectiveKind,
1904 OpenACCReductionOperator ReductionOp,
1905 Expr *VarExpr) {
1906 VarExpr = VarExpr->IgnoreParenCasts();
1907
1908 auto TypeIsValid = [](QualType Ty) {
1909 return Ty->isDependentType() || Ty->isScalarType();
1910 };
1911
1912 if (isa<ArraySectionExpr>(Val: VarExpr)) {
1913 Expr *ASExpr = VarExpr;
1914 QualType BaseTy = ArraySectionExpr::getBaseOriginalType(Base: ASExpr);
1915 QualType EltTy = getASTContext().getBaseElementType(BaseTy);
1916
1917 if (!TypeIsValid(EltTy)) {
1918 Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type)
1919 << EltTy << /*Sub array base type*/ 1;
1920 return ExprError();
1921 }
1922 } else if (auto *RD = VarExpr->getType()->getAsRecordDecl()) {
1923 if (!RD->isStruct() && !RD->isClass()) {
1924 Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1925 << /*not class or struct*/ 0 << VarExpr->getType();
1926 return ExprError();
1927 }
1928
1929 if (!RD->isCompleteDefinition()) {
1930 Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1931 << /*incomplete*/ 1 << VarExpr->getType();
1932 return ExprError();
1933 }
1934 if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(Val: RD);
1935 CXXRD && !CXXRD->isAggregate()) {
1936 Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_composite_type)
1937 << /*aggregate*/ 2 << VarExpr->getType();
1938 return ExprError();
1939 }
1940
1941 for (FieldDecl *FD : RD->fields()) {
1942 if (!TypeIsValid(FD->getType())) {
1943 Diag(VarExpr->getExprLoc(),
1944 diag::err_acc_reduction_composite_member_type);
1945 Diag(FD->getLocation(), diag::note_acc_reduction_composite_member_loc);
1946 return ExprError();
1947 }
1948 }
1949 } else if (!TypeIsValid(VarExpr->getType())) {
1950 Diag(VarExpr->getExprLoc(), diag::err_acc_reduction_type)
1951 << VarExpr->getType() << /*Sub array base type*/ 0;
1952 return ExprError();
1953 }
1954
1955 // OpenACC3.3: 2.9.11: Reduction clauses on nested constructs for the same
1956 // reduction 'var' must have the same reduction operator.
1957 if (!VarExpr->isInstantiationDependent()) {
1958
1959 for (const OpenACCReductionClause *RClause : ActiveReductionClauses) {
1960 if (RClause->getReductionOp() == ReductionOp)
1961 break;
1962
1963 for (Expr *OldVarExpr : RClause->getVarList()) {
1964 if (OldVarExpr->isInstantiationDependent())
1965 continue;
1966
1967 if (areVarsEqual(VarExpr1: VarExpr, VarExpr2: OldVarExpr)) {
1968 Diag(VarExpr->getExprLoc(), diag::err_reduction_op_mismatch)
1969 << ReductionOp << RClause->getReductionOp();
1970 Diag(OldVarExpr->getExprLoc(), diag::note_acc_previous_clause_here)
1971 << RClause->getClauseKind();
1972 return ExprError();
1973 }
1974 }
1975 }
1976 }
1977
1978 return VarExpr;
1979}
1980
1981ExprResult SemaOpenACC::CheckTileSizeExpr(Expr *SizeExpr) {
1982 if (!SizeExpr)
1983 return ExprError();
1984
1985 assert((SizeExpr->isInstantiationDependent() ||
1986 SizeExpr->getType()->isIntegerType()) &&
1987 "size argument non integer?");
1988
1989 // If dependent, or an asterisk, the expression is fine.
1990 if (SizeExpr->isInstantiationDependent() ||
1991 isa<OpenACCAsteriskSizeExpr>(Val: SizeExpr))
1992 return ExprResult{SizeExpr};
1993
1994 std::optional<llvm::APSInt> ICE =
1995 SizeExpr->getIntegerConstantExpr(Ctx: getASTContext());
1996
1997 // OpenACC 3.3 2.9.8
1998 // where each tile size is a constant positive integer expression or asterisk.
1999 if (!ICE || *ICE <= 0) {
2000 Diag(SizeExpr->getBeginLoc(), diag::err_acc_size_expr_value)
2001 << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
2002 return ExprError();
2003 }
2004
2005 return ExprResult{
2006 ConstantExpr::Create(getASTContext(), SizeExpr, APValue{*ICE})};
2007}
2008
2009ExprResult SemaOpenACC::CheckCollapseLoopCount(Expr *LoopCount) {
2010 if (!LoopCount)
2011 return ExprError();
2012
2013 assert((LoopCount->isInstantiationDependent() ||
2014 LoopCount->getType()->isIntegerType()) &&
2015 "Loop argument non integer?");
2016
2017 // If this is dependent, there really isn't anything we can check.
2018 if (LoopCount->isInstantiationDependent())
2019 return ExprResult{LoopCount};
2020
2021 std::optional<llvm::APSInt> ICE =
2022 LoopCount->getIntegerConstantExpr(Ctx: getASTContext());
2023
2024 // OpenACC 3.3: 2.9.1
2025 // The argument to the collapse clause must be a constant positive integer
2026 // expression.
2027 if (!ICE || *ICE <= 0) {
2028 Diag(LoopCount->getBeginLoc(), diag::err_acc_collapse_loop_count)
2029 << ICE.has_value() << ICE.value_or(llvm::APSInt{}).getExtValue();
2030 return ExprError();
2031 }
2032
2033 return ExprResult{
2034 ConstantExpr::Create(getASTContext(), LoopCount, APValue{*ICE})};
2035}
2036
2037ExprResult
2038SemaOpenACC::CheckGangExpr(ArrayRef<const OpenACCClause *> ExistingClauses,
2039 OpenACCDirectiveKind DK, OpenACCGangKind GK,
2040 Expr *E) {
2041 // There are two cases for the enforcement here: the 'current' directive is a
2042 // 'loop', where we need to check the active compute construct kind, or the
2043 // current directive is a 'combined' construct, where we have to check the
2044 // current one.
2045 switch (DK) {
2046 case OpenACCDirectiveKind::ParallelLoop:
2047 return CheckGangParallelExpr(S&: *this, DK, AssocKind: ActiveComputeConstructInfo.Kind, GK,
2048 E);
2049 case OpenACCDirectiveKind::SerialLoop:
2050 return CheckGangSerialExpr(S&: *this, DK, AssocKind: ActiveComputeConstructInfo.Kind, GK,
2051 E);
2052 case OpenACCDirectiveKind::KernelsLoop:
2053 return CheckGangKernelsExpr(S&: *this, ExistingClauses, DK,
2054 AssocKind: ActiveComputeConstructInfo.Kind, GK, E);
2055 case OpenACCDirectiveKind::Routine:
2056 return CheckGangRoutineExpr(S&: *this, DK, AssocKind: ActiveComputeConstructInfo.Kind, GK,
2057 E);
2058 case OpenACCDirectiveKind::Loop:
2059 switch (ActiveComputeConstructInfo.Kind) {
2060 case OpenACCDirectiveKind::Invalid:
2061 case OpenACCDirectiveKind::Parallel:
2062 case OpenACCDirectiveKind::ParallelLoop:
2063 return CheckGangParallelExpr(S&: *this, DK, AssocKind: ActiveComputeConstructInfo.Kind,
2064 GK, E);
2065 case OpenACCDirectiveKind::SerialLoop:
2066 case OpenACCDirectiveKind::Serial:
2067 return CheckGangSerialExpr(S&: *this, DK, AssocKind: ActiveComputeConstructInfo.Kind, GK,
2068 E);
2069 case OpenACCDirectiveKind::KernelsLoop:
2070 case OpenACCDirectiveKind::Kernels:
2071 return CheckGangKernelsExpr(S&: *this, ExistingClauses, DK,
2072 AssocKind: ActiveComputeConstructInfo.Kind, GK, E);
2073 default:
2074 llvm_unreachable("Non compute construct in active compute construct?");
2075 }
2076 case OpenACCDirectiveKind::Invalid:
2077 // This can happen in cases where the the directive was not recognized but
2078 // we continued anyway. Since the validity checking is all-over the place
2079 // (it can be a star/integer, or a constant expr depending on the tag), we
2080 // just give up and return an ExprError here.
2081 return ExprError();
2082 default:
2083 llvm_unreachable("Invalid directive kind for a Gang clause");
2084 }
2085 llvm_unreachable("Compute construct directive not handled?");
2086}
2087
2088OpenACCClause *
2089SemaOpenACC::CheckGangClause(OpenACCDirectiveKind DirKind,
2090 ArrayRef<const OpenACCClause *> ExistingClauses,
2091 SourceLocation BeginLoc, SourceLocation LParenLoc,
2092 ArrayRef<OpenACCGangKind> GangKinds,
2093 ArrayRef<Expr *> IntExprs, SourceLocation EndLoc) {
2094 // Reduction isn't possible on 'routine' so we don't bother checking it here.
2095 if (DirKind != OpenACCDirectiveKind::Routine) {
2096 // OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
2097 // that has a gang clause with a dim: argument whose value is greater
2098 // than 1.
2099 const auto *ReductionItr =
2100 llvm::find_if(Range&: ExistingClauses, P: llvm::IsaPred<OpenACCReductionClause>);
2101
2102 if (ReductionItr != ExistingClauses.end()) {
2103 const auto GangZip = llvm::zip_equal(t&: GangKinds, u&: IntExprs);
2104 const auto GangItr = llvm::find_if(Range: GangZip, P: [](const auto &Tuple) {
2105 return std::get<0>(Tuple) == OpenACCGangKind::Dim;
2106 });
2107
2108 if (GangItr != GangZip.end()) {
2109 const Expr *DimExpr = std::get<1>(t: *GangItr);
2110
2111 assert((DimExpr->isInstantiationDependent() ||
2112 isa<ConstantExpr>(DimExpr)) &&
2113 "Improperly formed gang argument");
2114 if (const auto *DimVal = dyn_cast<ConstantExpr>(Val: DimExpr);
2115 DimVal && DimVal->getResultAsAPSInt() > 1) {
2116 Diag(DimVal->getBeginLoc(), diag::err_acc_gang_reduction_conflict)
2117 << /*gang/reduction=*/0 << DirKind;
2118 Diag((*ReductionItr)->getBeginLoc(),
2119 diag::note_acc_previous_clause_here)
2120 << (*ReductionItr)->getClauseKind();
2121 return nullptr;
2122 }
2123 }
2124 }
2125 }
2126
2127 return OpenACCGangClause::Create(Ctx: getASTContext(), BeginLoc, LParenLoc,
2128 GangKinds, IntExprs, EndLoc);
2129}
2130
2131OpenACCClause *SemaOpenACC::CheckReductionClause(
2132 ArrayRef<const OpenACCClause *> ExistingClauses,
2133 OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc,
2134 SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp,
2135 ArrayRef<Expr *> Vars, SourceLocation EndLoc) {
2136 if (DirectiveKind == OpenACCDirectiveKind::Loop ||
2137 isOpenACCCombinedDirectiveKind(K: DirectiveKind)) {
2138 // OpenACC 3.3 2.9.11: A reduction clause may not appear on a loop directive
2139 // that has a gang clause with a dim: argument whose value is greater
2140 // than 1.
2141 const auto GangClauses = llvm::make_filter_range(
2142 Range&: ExistingClauses, Pred: llvm::IsaPred<OpenACCGangClause>);
2143
2144 for (auto *GC : GangClauses) {
2145 const auto *GangClause = cast<OpenACCGangClause>(Val: GC);
2146 for (unsigned I = 0; I < GangClause->getNumExprs(); ++I) {
2147 std::pair<OpenACCGangKind, const Expr *> EPair = GangClause->getExpr(I);
2148 if (EPair.first != OpenACCGangKind::Dim)
2149 continue;
2150
2151 if (const auto *DimVal = dyn_cast<ConstantExpr>(Val: EPair.second);
2152 DimVal && DimVal->getResultAsAPSInt() > 1) {
2153 Diag(BeginLoc, diag::err_acc_gang_reduction_conflict)
2154 << /*reduction/gang=*/1 << DirectiveKind;
2155 Diag(GangClause->getBeginLoc(), diag::note_acc_previous_clause_here)
2156 << GangClause->getClauseKind();
2157 return nullptr;
2158 }
2159 }
2160 }
2161 }
2162
2163 auto *Ret = OpenACCReductionClause::Create(
2164 C: getASTContext(), BeginLoc, LParenLoc, Operator: ReductionOp, VarList: Vars, EndLoc);
2165 return Ret;
2166}
2167
2168llvm::SmallVector<Expr *>
2169SemaOpenACC::CheckLinkClauseVarList(ArrayRef<Expr *> VarExprs) {
2170 const DeclContext *DC = removeLinkageSpecDC(getCurContext());
2171
2172 // Link has no special restrictions on its var list unless it is not at NS/TU
2173 // scope.
2174 if (isa<NamespaceDecl, TranslationUnitDecl>(Val: DC))
2175 return llvm::SmallVector<Expr *>(VarExprs);
2176
2177 llvm::SmallVector<Expr *> NewVarList;
2178
2179 for (Expr *VarExpr : VarExprs) {
2180 if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(Val: VarExpr)) {
2181 NewVarList.push_back(Elt: VarExpr);
2182 continue;
2183 }
2184
2185 // Field decls can't be global, nor extern, and declare can't refer to
2186 // non-static fields in class-scope, so this always fails the scope check.
2187 // BUT for now we add this so it gets diagnosed by the general 'declare'
2188 // rules.
2189 if (isa<MemberExpr>(Val: VarExpr)) {
2190 NewVarList.push_back(Elt: VarExpr);
2191 continue;
2192 }
2193
2194 const auto *DRE = cast<DeclRefExpr>(Val: VarExpr);
2195 const VarDecl *Var = dyn_cast<VarDecl>(Val: DRE->getDecl());
2196
2197 if (!Var || !Var->hasExternalStorage())
2198 Diag(VarExpr->getBeginLoc(), diag::err_acc_link_not_extern);
2199 else
2200 NewVarList.push_back(Elt: VarExpr);
2201 }
2202
2203 return NewVarList;
2204}
2205bool SemaOpenACC::CheckDeclareClause(SemaOpenACC::OpenACCParsedClause &Clause,
2206 OpenACCModifierKind Mods) {
2207
2208 if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Declare)
2209 return false;
2210
2211 const DeclContext *DC = removeLinkageSpecDC(getCurContext());
2212
2213 // Whether this is 'create', 'copyin', 'deviceptr', 'device_resident', or
2214 // 'link', which have 2 special rules.
2215 bool IsSpecialClause =
2216 Clause.getClauseKind() == OpenACCClauseKind::Create ||
2217 Clause.getClauseKind() == OpenACCClauseKind::CopyIn ||
2218 Clause.getClauseKind() == OpenACCClauseKind::DevicePtr ||
2219 Clause.getClauseKind() == OpenACCClauseKind::DeviceResident ||
2220 Clause.getClauseKind() == OpenACCClauseKind::Link;
2221
2222 // OpenACC 3.3 2.13:
2223 // In C or C++ global or namespace scope, only 'create',
2224 // 'copyin', 'deviceptr', 'device_resident', or 'link' clauses are
2225 // allowed.
2226 if (!IsSpecialClause && isa<NamespaceDecl, TranslationUnitDecl>(Val: DC)) {
2227 return Diag(Clause.getBeginLoc(), diag::err_acc_declare_clause_at_global)
2228 << Clause.getClauseKind();
2229 }
2230
2231 llvm::SmallVector<Expr *> FilteredVarList;
2232 const DeclaratorDecl *CurDecl = nullptr;
2233 for (Expr *VarExpr : Clause.getVarList()) {
2234 if (isa<DependentScopeDeclRefExpr, CXXDependentScopeMemberExpr>(Val: VarExpr)) {
2235 // There isn't really anything we can do here, so we add them anyway and
2236 // we can check them again when we instantiate this.
2237 } else if (const auto *MemExpr = dyn_cast<MemberExpr>(Val: VarExpr)) {
2238 FieldDecl *FD =
2239 cast<FieldDecl>(MemExpr->getMemberDecl()->getCanonicalDecl());
2240 CurDecl = FD;
2241
2242 if (removeLinkageSpecDC(
2243 FD->getLexicalDeclContext()->getPrimaryContext()) != DC) {
2244 Diag(MemExpr->getBeginLoc(), diag::err_acc_declare_same_scope)
2245 << Clause.getClauseKind();
2246 continue;
2247 }
2248 } else {
2249 const auto *DRE = cast<DeclRefExpr>(Val: VarExpr);
2250 if (const auto *Var = dyn_cast<VarDecl>(Val: DRE->getDecl())) {
2251 CurDecl = Var->getCanonicalDecl();
2252
2253 // OpenACC3.3 2.13:
2254 // A 'declare' directive must be in the same scope as the declaration of
2255 // any var that appears in the clauses of the directive or any scope
2256 // within a C/C++ function.
2257 // We can't really check 'scope' here, so we check declaration context,
2258 // which is a reasonable approximation, but misses scopes inside of
2259 // functions.
2260 if (removeLinkageSpecDC(
2261 Var->getLexicalDeclContext()->getPrimaryContext()) != DC) {
2262 Diag(VarExpr->getBeginLoc(), diag::err_acc_declare_same_scope)
2263 << Clause.getClauseKind();
2264 continue;
2265 }
2266 // OpenACC3.3 2.13:
2267 // C and C++ extern variables may only appear in 'create',
2268 // 'copyin', 'deviceptr', 'device_resident', or 'link' clauses on a
2269 // 'declare' directive.
2270 if (!IsSpecialClause && Var->hasExternalStorage()) {
2271 Diag(VarExpr->getBeginLoc(), diag::err_acc_declare_extern)
2272 << Clause.getClauseKind();
2273 continue;
2274 }
2275 }
2276
2277 // OpenACC3.3 2.13:
2278 // A var may appear at most once in all the clauses of declare
2279 // directives for a function, subroutine, program, or module.
2280
2281 if (CurDecl) {
2282 auto [Itr, Inserted] = DeclareVarReferences.try_emplace(Key: CurDecl);
2283 if (!Inserted) {
2284 Diag(VarExpr->getBeginLoc(), diag::err_acc_multiple_references)
2285 << Clause.getClauseKind();
2286 Diag(Itr->second, diag::note_acc_previous_reference);
2287 continue;
2288 } else {
2289 Itr->second = VarExpr->getBeginLoc();
2290 }
2291 }
2292 }
2293 FilteredVarList.push_back(Elt: VarExpr);
2294 }
2295
2296 Clause.setVarListDetails(VarList: FilteredVarList, ModKind: Mods);
2297 return false;
2298}
2299

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of clang/lib/Sema/SemaOpenACCClause.cpp