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