clang 20.0.0git
SemaOpenACC.h
Go to the documentation of this file.
1//===----- SemaOpenACC.h - Semantic Analysis for OpenACC constructs -------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8/// \file
9/// This file declares semantic analysis for OpenACC constructs and
10/// clauses.
11///
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_SEMA_SEMAOPENACC_H
15#define LLVM_CLANG_SEMA_SEMAOPENACC_H
16
17#include "clang/AST/DeclGroup.h"
19#include "clang/Basic/LLVM.h"
23#include "clang/Sema/SemaBase.h"
24#include "llvm/ADT/SmallVector.h"
25#include "llvm/Support/Compiler.h"
26#include <cassert>
27#include <optional>
28#include <utility>
29#include <variant>
30
31namespace clang {
32class IdentifierInfo;
33class OpenACCClause;
34
35class SemaOpenACC : public SemaBase {
36private:
37 struct ComputeConstructInfo {
38 /// Which type of compute construct we are inside of, which we can use to
39 /// determine whether we should add loops to the above collection. We can
40 /// also use it to diagnose loop construct clauses.
42 // If we have an active compute construct, stores the list of clauses we've
43 // prepared for it, so that we can diagnose limitations on child constructs.
45 } ActiveComputeConstructInfo;
46
47 bool isInComputeConstruct() const {
48 return ActiveComputeConstructInfo.Kind != OpenACCDirectiveKind::Invalid;
49 }
50
51 /// Certain clauses care about the same things that aren't specific to the
52 /// individual clause, but can be shared by a few, so store them here. All
53 /// require a 'no intervening constructs' rule, so we know they are all from
54 /// the same 'place'.
55 struct LoopCheckingInfo {
56 /// Records whether we've seen the top level 'for'. We already diagnose
57 /// later that the 'top level' is a for loop, so we use this to suppress the
58 /// 'collapse inner loop not a 'for' loop' diagnostic.
59 LLVM_PREFERRED_TYPE(bool)
60 unsigned TopLevelLoopSeen : 1;
61
62 /// Records whether this 'tier' of the loop has already seen a 'for' loop,
63 /// used to diagnose if there are multiple 'for' loops at any one level.
64 LLVM_PREFERRED_TYPE(bool)
65 unsigned CurLevelHasLoopAlready : 1;
66
67 } LoopInfo{/*TopLevelLoopSeen=*/false, /*CurLevelHasLoopAlready=*/false};
68
69 /// The 'collapse' clause requires quite a bit of checking while
70 /// parsing/instantiating its body, so this structure/object keeps all of the
71 /// necessary information as we do checking. This should rarely be directly
72 /// modified, and typically should be controlled by the RAII objects.
73 ///
74 /// Collapse has an 'N' count that makes it apply to a number of loops 'below'
75 /// it.
76 struct CollapseCheckingInfo {
77 OpenACCCollapseClause *ActiveCollapse = nullptr;
78
79 /// This is a value that maintains the current value of the 'N' on the
80 /// current collapse, minus the depth that has already been traversed. When
81 /// there is not an active collapse, or a collapse whose depth we don't know
82 /// (for example, if it is a dependent value), this should be `nullopt`,
83 /// else it should be 'N' minus the current depth traversed.
84 std::optional<llvm::APSInt> CurCollapseCount;
85
86 /// Records whether we've hit a CurCollapseCount of '0' on the way down,
87 /// which allows us to diagnose if the value of 'N' is too large for the
88 /// current number of 'for' loops.
89 bool CollapseDepthSatisfied = true;
90
91 /// Records the kind of the directive that this clause is attached to, which
92 /// allows us to use it in diagnostics.
94 } CollapseInfo;
95
96 /// The 'tile' clause requires a bit of additional checking as well, so like
97 /// the `CollapseCheckingInfo`, ensure we maintain information here too.
98 struct TileCheckingInfo {
99 OpenACCTileClause *ActiveTile = nullptr;
100
101 /// This is the number of expressions on a 'tile' clause. This doesn't have
102 /// to be an APSInt because it isn't the result of a constexpr, just by our
103 /// own counting of elements.
104 std::optional<unsigned> CurTileCount;
105
106 /// Records whether we've hit a 'CurTileCount' of '0' on the wya down,
107 /// which allows us to diagnose if the number of arguments is too large for
108 /// the current number of 'for' loops.
109 bool TileDepthSatisfied = true;
110
111 /// Records the kind of the directive that this clause is attached to, which
112 /// allows us to use it in diagnostics.
114 } TileInfo;
115
116 /// A list of the active reduction clauses, which allows us to check that all
117 /// vars on nested constructs for the same reduction var have the same
118 /// reduction operator. Currently this is enforced against all constructs
119 /// despite the rule being in the 'loop' section. By current reading, this
120 /// should apply to all anyway, but we may need to make this more like the
121 /// 'loop' clause enforcement, where this is 'blocked' by a compute construct.
122 llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses;
123
124 // Type to check the info about the 'for stmt'.
125 struct ForStmtBeginChecker {
126 SemaOpenACC &SemaRef;
127 SourceLocation ForLoc;
128 bool IsRangeFor = false;
129 std::optional<const CXXForRangeStmt *> RangeFor = nullptr;
130 const Stmt *Init = nullptr;
131 bool InitChanged = false;
132 std::optional<const Stmt *> Cond = nullptr;
133 std::optional<const Stmt *> Inc = nullptr;
134 // Prevent us from checking 2x, which can happen with collapse & tile.
135 bool AlreadyChecked = false;
136
137 ForStmtBeginChecker(SemaOpenACC &SemaRef, SourceLocation ForLoc,
138 std::optional<const CXXForRangeStmt *> S)
139 : SemaRef(SemaRef), ForLoc(ForLoc), IsRangeFor(true), RangeFor(S) {}
140
141 ForStmtBeginChecker(SemaOpenACC &SemaRef, SourceLocation ForLoc,
142 const Stmt *I, bool InitChanged,
143 std::optional<const Stmt *> C,
144 std::optional<const Stmt *> Inc)
145 : SemaRef(SemaRef), ForLoc(ForLoc), IsRangeFor(false), Init(I),
146 InitChanged(InitChanged), Cond(C), Inc(Inc) {}
147 // Do the checking for the For/Range-For. Currently this implements the 'not
148 // seq' restrictions only, and should be called either if we know we are a
149 // top-level 'for' (the one associated via associated-stmt), or extended via
150 // 'collapse'.
151 void check();
152
153 const ValueDecl *checkInit();
154 void checkCond();
155 void checkInc(const ValueDecl *Init);
156 };
157
158 /// Helper function for checking the 'for' and 'range for' stmts.
159 void ForStmtBeginHelper(SourceLocation ForLoc, ForStmtBeginChecker &C);
160
161public:
162 ComputeConstructInfo &getActiveComputeConstructInfo() {
163 return ActiveComputeConstructInfo;
164 }
165
166 /// If there is a current 'active' loop construct with a 'gang' clause on a
167 /// 'kernel' construct, this will have the source location for it, and the
168 /// 'kernel kind'. This permits us to implement the restriction of no further
169 /// 'gang' clauses.
174
175 /// If there is a current 'active' loop construct with a 'worker' clause on it
176 /// (on any sort of construct), this has the source location for it. This
177 /// permits us to implement the restriction of no further 'gang' or 'worker'
178 /// clauses.
180 /// If there is a current 'active' loop construct with a 'vector' clause on it
181 /// (on any sort of construct), this has the source location for it. This
182 /// permits us to implement the restriction of no further 'gang', 'vector', or
183 /// 'worker' clauses.
185 /// If there is a current 'active' loop construct that does NOT have a 'seq'
186 /// clause on it, this has that source location and loop Directive 'kind'.
187 /// This permits us to implement the 'loop' restrictions on the loop variable.
188 /// This can be extended via 'collapse', so we need to keep this around for a
189 /// while.
194
195 // Redeclaration of the version in OpenACCClause.h.
196 using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
197
198 /// A type to represent all the data for an OpenACC Clause that has been
199 /// parsed, but not yet created/semantically analyzed. This is effectively a
200 /// discriminated union on the 'Clause Kind', with all of the individual
201 /// clause details stored in a std::variant.
203 OpenACCDirectiveKind DirKind;
204 OpenACCClauseKind ClauseKind;
205 SourceRange ClauseRange;
206 SourceLocation LParenLoc;
207
208 struct DefaultDetails {
209 OpenACCDefaultClauseKind DefaultClauseKind;
210 };
211
212 struct ConditionDetails {
213 Expr *ConditionExpr;
214 };
215
216 struct IntExprDetails {
217 SmallVector<Expr *> IntExprs;
218 };
219
220 struct VarListDetails {
221 SmallVector<Expr *> VarList;
222 bool IsReadOnly;
223 bool IsZero;
224 };
225
226 struct WaitDetails {
227 Expr *DevNumExpr;
228 SourceLocation QueuesLoc;
229 SmallVector<Expr *> QueueIdExprs;
230 };
231
232 struct DeviceTypeDetails {
234 };
235 struct ReductionDetails {
237 SmallVector<Expr *> VarList;
238 };
239
240 struct CollapseDetails {
241 bool IsForce;
242 Expr *LoopCount;
243 };
244
245 struct GangDetails {
247 SmallVector<Expr *> IntExprs;
248 };
249
250 std::variant<std::monostate, DefaultDetails, ConditionDetails,
251 IntExprDetails, VarListDetails, WaitDetails, DeviceTypeDetails,
252 ReductionDetails, CollapseDetails, GangDetails>
253 Details = std::monostate{};
254
255 public:
257 OpenACCClauseKind ClauseKind, SourceLocation BeginLoc)
258 : DirKind(DirKind), ClauseKind(ClauseKind), ClauseRange(BeginLoc, {}) {}
259
260 OpenACCDirectiveKind getDirectiveKind() const { return DirKind; }
261
262 OpenACCClauseKind getClauseKind() const { return ClauseKind; }
263
264 SourceLocation getBeginLoc() const { return ClauseRange.getBegin(); }
265
266 SourceLocation getLParenLoc() const { return LParenLoc; }
267
268 SourceLocation getEndLoc() const { return ClauseRange.getEnd(); }
269
271 assert(ClauseKind == OpenACCClauseKind::Default &&
272 "Parsed clause is not a default clause");
273 return std::get<DefaultDetails>(Details).DefaultClauseKind;
274 }
275
276 const Expr *getConditionExpr() const {
277 return const_cast<OpenACCParsedClause *>(this)->getConditionExpr();
278 }
279
281 assert((ClauseKind == OpenACCClauseKind::If ||
282 (ClauseKind == OpenACCClauseKind::Self &&
283 DirKind != OpenACCDirectiveKind::Update)) &&
284 "Parsed clause kind does not have a condition expr");
285
286 // 'self' has an optional ConditionExpr, so be tolerant of that. This will
287 // assert in variant otherwise.
288 if (ClauseKind == OpenACCClauseKind::Self &&
289 std::holds_alternative<std::monostate>(Details))
290 return nullptr;
291
292 return std::get<ConditionDetails>(Details).ConditionExpr;
293 }
294
295 unsigned getNumIntExprs() const {
296 assert((ClauseKind == OpenACCClauseKind::NumGangs ||
297 ClauseKind == OpenACCClauseKind::NumWorkers ||
298 ClauseKind == OpenACCClauseKind::Async ||
299 ClauseKind == OpenACCClauseKind::DeviceNum ||
300 ClauseKind == OpenACCClauseKind::DefaultAsync ||
301 ClauseKind == OpenACCClauseKind::Tile ||
302 ClauseKind == OpenACCClauseKind::Worker ||
303 ClauseKind == OpenACCClauseKind::Vector ||
304 ClauseKind == OpenACCClauseKind::VectorLength) &&
305 "Parsed clause kind does not have a int exprs");
306
307 // 'async', 'worker', 'vector', and 'wait' have an optional IntExpr, so be
308 // tolerant of that.
309 if ((ClauseKind == OpenACCClauseKind::Async ||
310 ClauseKind == OpenACCClauseKind::Worker ||
311 ClauseKind == OpenACCClauseKind::Vector ||
312 ClauseKind == OpenACCClauseKind::Wait) &&
313 std::holds_alternative<std::monostate>(Details))
314 return 0;
315 return std::get<IntExprDetails>(Details).IntExprs.size();
316 }
317
319 assert(ClauseKind == OpenACCClauseKind::Wait &&
320 "Parsed clause kind does not have a queues location");
321
322 if (std::holds_alternative<std::monostate>(Details))
323 return SourceLocation{};
324
325 return std::get<WaitDetails>(Details).QueuesLoc;
326 }
327
329 assert(ClauseKind == OpenACCClauseKind::Wait &&
330 "Parsed clause kind does not have a device number expr");
331
332 if (std::holds_alternative<std::monostate>(Details))
333 return nullptr;
334
335 return std::get<WaitDetails>(Details).DevNumExpr;
336 }
337
339 assert(ClauseKind == OpenACCClauseKind::Wait &&
340 "Parsed clause kind does not have a queue id expr list");
341
342 if (std::holds_alternative<std::monostate>(Details))
343 return ArrayRef<Expr *>();
344
345 return std::get<WaitDetails>(Details).QueueIdExprs;
346 }
347
349 assert((ClauseKind == OpenACCClauseKind::NumGangs ||
350 ClauseKind == OpenACCClauseKind::NumWorkers ||
351 ClauseKind == OpenACCClauseKind::Async ||
352 ClauseKind == OpenACCClauseKind::DeviceNum ||
353 ClauseKind == OpenACCClauseKind::DefaultAsync ||
354 ClauseKind == OpenACCClauseKind::Tile ||
355 ClauseKind == OpenACCClauseKind::Gang ||
356 ClauseKind == OpenACCClauseKind::Worker ||
357 ClauseKind == OpenACCClauseKind::Vector ||
358 ClauseKind == OpenACCClauseKind::VectorLength) &&
359 "Parsed clause kind does not have a int exprs");
360
361 if (ClauseKind == OpenACCClauseKind::Gang) {
362 // There might not be any gang int exprs, as this is an optional
363 // argument.
364 if (std::holds_alternative<std::monostate>(Details))
365 return {};
366 return std::get<GangDetails>(Details).IntExprs;
367 }
368
369 return std::get<IntExprDetails>(Details).IntExprs;
370 }
371
373 return const_cast<OpenACCParsedClause *>(this)->getIntExprs();
374 }
375
377 return std::get<ReductionDetails>(Details).Op;
378 }
379
381 assert(ClauseKind == OpenACCClauseKind::Gang &&
382 "Parsed clause kind does not have gang kind");
383 // The args on gang are optional, so this might not actually hold
384 // anything.
385 if (std::holds_alternative<std::monostate>(Details))
386 return {};
387 return std::get<GangDetails>(Details).GangKinds;
388 }
389
391 assert((ClauseKind == OpenACCClauseKind::Private ||
392 ClauseKind == OpenACCClauseKind::NoCreate ||
393 ClauseKind == OpenACCClauseKind::Present ||
394 ClauseKind == OpenACCClauseKind::Copy ||
395 ClauseKind == OpenACCClauseKind::PCopy ||
396 ClauseKind == OpenACCClauseKind::PresentOrCopy ||
397 ClauseKind == OpenACCClauseKind::CopyIn ||
398 ClauseKind == OpenACCClauseKind::PCopyIn ||
400 ClauseKind == OpenACCClauseKind::CopyOut ||
401 ClauseKind == OpenACCClauseKind::PCopyOut ||
403 ClauseKind == OpenACCClauseKind::Create ||
404 ClauseKind == OpenACCClauseKind::PCreate ||
406 ClauseKind == OpenACCClauseKind::Attach ||
407 ClauseKind == OpenACCClauseKind::Delete ||
408 ClauseKind == OpenACCClauseKind::UseDevice ||
409 ClauseKind == OpenACCClauseKind::Detach ||
410 ClauseKind == OpenACCClauseKind::DevicePtr ||
411 ClauseKind == OpenACCClauseKind::Reduction ||
412 ClauseKind == OpenACCClauseKind::FirstPrivate) &&
413 "Parsed clause kind does not have a var-list");
414
415 if (ClauseKind == OpenACCClauseKind::Reduction)
416 return std::get<ReductionDetails>(Details).VarList;
417
418 return std::get<VarListDetails>(Details).VarList;
419 }
420
422 return const_cast<OpenACCParsedClause *>(this)->getVarList();
423 }
424
425 bool isReadOnly() const {
426 assert((ClauseKind == OpenACCClauseKind::CopyIn ||
427 ClauseKind == OpenACCClauseKind::PCopyIn ||
428 ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
429 "Only copyin accepts 'readonly:' tag");
430 return std::get<VarListDetails>(Details).IsReadOnly;
431 }
432
433 bool isZero() const {
434 assert((ClauseKind == OpenACCClauseKind::CopyOut ||
435 ClauseKind == OpenACCClauseKind::PCopyOut ||
437 ClauseKind == OpenACCClauseKind::Create ||
438 ClauseKind == OpenACCClauseKind::PCreate ||
439 ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
440 "Only copyout/create accepts 'zero' tag");
441 return std::get<VarListDetails>(Details).IsZero;
442 }
443
444 bool isForce() const {
445 assert(ClauseKind == OpenACCClauseKind::Collapse &&
446 "Only 'collapse' has a force tag");
447 return std::get<CollapseDetails>(Details).IsForce;
448 }
449
451 assert(ClauseKind == OpenACCClauseKind::Collapse &&
452 "Only 'collapse' has a loop count");
453 return std::get<CollapseDetails>(Details).LoopCount;
454 }
455
457 assert((ClauseKind == OpenACCClauseKind::DeviceType ||
458 ClauseKind == OpenACCClauseKind::DType) &&
459 "Only 'device_type'/'dtype' has a device-type-arg list");
460 return std::get<DeviceTypeDetails>(Details).Archs;
461 }
462
463 void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
464 void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }
465
467 assert(ClauseKind == OpenACCClauseKind::Default &&
468 "Parsed clause is not a default clause");
469 Details = DefaultDetails{DefKind};
470 }
471
472 void setConditionDetails(Expr *ConditionExpr) {
473 assert((ClauseKind == OpenACCClauseKind::If ||
474 (ClauseKind == OpenACCClauseKind::Self &&
475 DirKind != OpenACCDirectiveKind::Update)) &&
476 "Parsed clause kind does not have a condition expr");
477 // In C++ we can count on this being a 'bool', but in C this gets left as
478 // some sort of scalar that codegen will have to take care of converting.
479 assert((!ConditionExpr || ConditionExpr->isInstantiationDependent() ||
480 ConditionExpr->getType()->isScalarType()) &&
481 "Condition expression type not scalar/dependent");
482
483 Details = ConditionDetails{ConditionExpr};
484 }
485
487 assert((ClauseKind == OpenACCClauseKind::NumGangs ||
488 ClauseKind == OpenACCClauseKind::NumWorkers ||
489 ClauseKind == OpenACCClauseKind::Async ||
490 ClauseKind == OpenACCClauseKind::DeviceNum ||
491 ClauseKind == OpenACCClauseKind::DefaultAsync ||
492 ClauseKind == OpenACCClauseKind::Tile ||
493 ClauseKind == OpenACCClauseKind::Worker ||
494 ClauseKind == OpenACCClauseKind::Vector ||
495 ClauseKind == OpenACCClauseKind::VectorLength) &&
496 "Parsed clause kind does not have a int exprs");
497 Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}};
498 }
500 assert((ClauseKind == OpenACCClauseKind::NumGangs ||
501 ClauseKind == OpenACCClauseKind::NumWorkers ||
502 ClauseKind == OpenACCClauseKind::Async ||
503 ClauseKind == OpenACCClauseKind::DeviceNum ||
504 ClauseKind == OpenACCClauseKind::DefaultAsync ||
505 ClauseKind == OpenACCClauseKind::Tile ||
506 ClauseKind == OpenACCClauseKind::Worker ||
507 ClauseKind == OpenACCClauseKind::Vector ||
508 ClauseKind == OpenACCClauseKind::VectorLength) &&
509 "Parsed clause kind does not have a int exprs");
510 Details = IntExprDetails{std::move(IntExprs)};
511 }
512
514 ArrayRef<Expr *> IntExprs) {
515 assert(ClauseKind == OpenACCClauseKind::Gang &&
516 "Parsed Clause kind does not have gang details");
517 assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");
518
519 Details = GangDetails{{GKs.begin(), GKs.end()},
520 {IntExprs.begin(), IntExprs.end()}};
521 }
522
524 llvm::SmallVector<Expr *> &&IntExprs) {
525 assert(ClauseKind == OpenACCClauseKind::Gang &&
526 "Parsed Clause kind does not have gang details");
527 assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");
528
529 Details = GangDetails{std::move(GKs), std::move(IntExprs)};
530 }
531
532 void setVarListDetails(ArrayRef<Expr *> VarList, bool IsReadOnly,
533 bool IsZero) {
534 assert((ClauseKind == OpenACCClauseKind::Private ||
535 ClauseKind == OpenACCClauseKind::NoCreate ||
536 ClauseKind == OpenACCClauseKind::Present ||
537 ClauseKind == OpenACCClauseKind::Copy ||
538 ClauseKind == OpenACCClauseKind::PCopy ||
539 ClauseKind == OpenACCClauseKind::PresentOrCopy ||
540 ClauseKind == OpenACCClauseKind::CopyIn ||
541 ClauseKind == OpenACCClauseKind::PCopyIn ||
543 ClauseKind == OpenACCClauseKind::CopyOut ||
544 ClauseKind == OpenACCClauseKind::PCopyOut ||
546 ClauseKind == OpenACCClauseKind::Create ||
547 ClauseKind == OpenACCClauseKind::PCreate ||
549 ClauseKind == OpenACCClauseKind::Attach ||
550 ClauseKind == OpenACCClauseKind::Delete ||
551 ClauseKind == OpenACCClauseKind::UseDevice ||
552 ClauseKind == OpenACCClauseKind::Detach ||
553 ClauseKind == OpenACCClauseKind::DevicePtr ||
554 ClauseKind == OpenACCClauseKind::FirstPrivate) &&
555 "Parsed clause kind does not have a var-list");
556 assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
557 ClauseKind == OpenACCClauseKind::PCopyIn ||
558 ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
559 "readonly: tag only valid on copyin");
560 assert((!IsZero || ClauseKind == OpenACCClauseKind::CopyOut ||
561 ClauseKind == OpenACCClauseKind::PCopyOut ||
563 ClauseKind == OpenACCClauseKind::Create ||
564 ClauseKind == OpenACCClauseKind::PCreate ||
565 ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
566 "zero: tag only valid on copyout/create");
567 Details =
568 VarListDetails{{VarList.begin(), VarList.end()}, IsReadOnly, IsZero};
569 }
570
571 void setVarListDetails(llvm::SmallVector<Expr *> &&VarList, bool IsReadOnly,
572 bool IsZero) {
573 assert((ClauseKind == OpenACCClauseKind::Private ||
574 ClauseKind == OpenACCClauseKind::NoCreate ||
575 ClauseKind == OpenACCClauseKind::Present ||
576 ClauseKind == OpenACCClauseKind::Copy ||
577 ClauseKind == OpenACCClauseKind::PCopy ||
578 ClauseKind == OpenACCClauseKind::PresentOrCopy ||
579 ClauseKind == OpenACCClauseKind::CopyIn ||
580 ClauseKind == OpenACCClauseKind::PCopyIn ||
582 ClauseKind == OpenACCClauseKind::CopyOut ||
583 ClauseKind == OpenACCClauseKind::PCopyOut ||
585 ClauseKind == OpenACCClauseKind::Create ||
586 ClauseKind == OpenACCClauseKind::PCreate ||
588 ClauseKind == OpenACCClauseKind::Attach ||
589 ClauseKind == OpenACCClauseKind::Delete ||
590 ClauseKind == OpenACCClauseKind::UseDevice ||
591 ClauseKind == OpenACCClauseKind::Detach ||
592 ClauseKind == OpenACCClauseKind::DevicePtr ||
593 ClauseKind == OpenACCClauseKind::FirstPrivate) &&
594 "Parsed clause kind does not have a var-list");
595 assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
596 ClauseKind == OpenACCClauseKind::PCopyIn ||
597 ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
598 "readonly: tag only valid on copyin");
599 assert((!IsZero || ClauseKind == OpenACCClauseKind::CopyOut ||
600 ClauseKind == OpenACCClauseKind::PCopyOut ||
602 ClauseKind == OpenACCClauseKind::Create ||
603 ClauseKind == OpenACCClauseKind::PCreate ||
604 ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
605 "zero: tag only valid on copyout/create");
606 Details = VarListDetails{std::move(VarList), IsReadOnly, IsZero};
607 }
608
610 llvm::SmallVector<Expr *> &&VarList) {
611 assert(ClauseKind == OpenACCClauseKind::Reduction &&
612 "reduction details only valid on reduction");
613 Details = ReductionDetails{Op, std::move(VarList)};
614 }
615
616 void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc,
617 llvm::SmallVector<Expr *> &&IntExprs) {
618 assert(ClauseKind == OpenACCClauseKind::Wait &&
619 "Parsed clause kind does not have a wait-details");
620 Details = WaitDetails{DevNum, QueuesLoc, std::move(IntExprs)};
621 }
622
624 assert((ClauseKind == OpenACCClauseKind::DeviceType ||
625 ClauseKind == OpenACCClauseKind::DType) &&
626 "Only 'device_type'/'dtype' has a device-type-arg list");
627 Details = DeviceTypeDetails{std::move(Archs)};
628 }
629
630 void setCollapseDetails(bool IsForce, Expr *LoopCount) {
631 assert(ClauseKind == OpenACCClauseKind::Collapse &&
632 "Only 'collapse' has collapse details");
633 Details = CollapseDetails{IsForce, LoopCount};
634 }
635 };
636
637 SemaOpenACC(Sema &S);
638
639 // Called when we encounter a 'while' statement, before looking at its 'body'.
640 void ActOnWhileStmt(SourceLocation WhileLoc);
641 // Called when we encounter a 'do' statement, before looking at its 'body'.
642 void ActOnDoStmt(SourceLocation DoLoc);
643 // Called when we encounter a 'for' statement, before looking at its 'body',
644 // for the 'range-for'. 'ActOnForStmtEnd' is used after the body.
645 void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor,
646 const Stmt *RangeFor);
647 void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *RangeFor);
648 // Called when we encounter a 'for' statement, before looking at its 'body'.
649 // 'ActOnForStmtEnd' is used after the body.
650 void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First,
651 const Stmt *Second, const Stmt *Third);
652 void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *OldFirst,
653 const Stmt *First, const Stmt *OldSecond,
654 const Stmt *Second, const Stmt *OldThird,
655 const Stmt *Third);
656 // Called when we encounter a 'for' statement, after we've consumed/checked
657 // the body. This is necessary for a number of checks on the contents of the
658 // 'for' statement.
659 void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body);
660
661 /// Called after parsing an OpenACC Clause so that it can be checked.
663 OpenACCParsedClause &Clause);
664
665 /// Called after the construct has been parsed, but clauses haven't been
666 /// parsed. This allows us to diagnose not-implemented, as well as set up any
667 /// state required for parsing the clauses.
669
670 /// Called after the directive, including its clauses, have been parsed and
671 /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
672 /// happen before any associated declarations or statements have been parsed.
673 /// This function is only called when we are parsing a 'statement' context.
676
677 /// Called after the directive, including its clauses, have been parsed and
678 /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
679 /// happen before any associated declarations or statements have been parsed.
680 /// This function is only called when we are parsing a 'Decl' context.
682 /// Called when we encounter an associated statement for our construct, this
683 /// should check legality of the statement as it appertains to this Construct.
687 StmtResult AssocStmt);
688
689 /// Called after the directive has been completely parsed, including the
690 /// declaration group or associated statement.
691 /// LParenLoc: Location of the left paren, if it exists (not on all
692 /// constructs).
693 /// MiscLoc: First misc location, if necessary (not all constructs).
694 /// Exprs: List of expressions on the construct itself, if necessary (not all
695 /// constructs).
696 /// RParenLoc: Location of the right paren, if it exists (not on all
697 /// constructs).
700 SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
701 SourceLocation RParenLoc, SourceLocation EndLoc,
702 ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt);
703
704 /// Called after the directive has been completely parsed, including the
705 /// declaration group or associated statement.
707
708 /// Called when encountering an 'int-expr' for OpenACC, and manages
709 /// conversions and diagnostics to 'int'.
711 SourceLocation Loc, Expr *IntExpr);
712
713 /// Called when encountering a 'var' for OpenACC, ensures it is actually a
714 /// declaration reference to a variable of the correct type.
716
717 /// Called while semantically analyzing the reduction clause, ensuring the var
718 /// is the correct kind of reference.
720 OpenACCReductionOperator ReductionOp,
721 Expr *VarExpr);
722
723 /// Called to check the 'var' type is a variable of pointer type, necessary
724 /// for 'deviceptr' and 'attach' clauses. Returns true on success.
725 bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr);
726
727 /// Checks and creates an Array Section used in an OpenACC construct/clause.
729 Expr *LowerBound,
730 SourceLocation ColonLocFirst, Expr *Length,
731 SourceLocation RBLoc);
732 /// Checks the loop depth value for a collapse clause.
734 /// Checks a single size expr for a tile clause.
736
737 // Check a single expression on a gang clause.
740 Expr *E);
741
742 // Does the checking for a 'gang' clause that needs to be done in dependent
743 // and not dependent cases.
746 ArrayRef<const OpenACCClause *> ExistingClauses,
747 SourceLocation BeginLoc, SourceLocation LParenLoc,
749 ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
750 // Does the checking for a 'reduction ' clause that needs to be done in
751 // dependent and not dependent cases.
754 OpenACCDirectiveKind DirectiveKind,
755 SourceLocation BeginLoc, SourceLocation LParenLoc,
756 OpenACCReductionOperator ReductionOp,
757 ArrayRef<Expr *> Vars, SourceLocation EndLoc);
758
761
762 /// Helper type to restore the state of various 'loop' constructs when we run
763 /// into a loop (for, etc) inside the construct.
765 SemaOpenACC &SemaRef;
766 LoopCheckingInfo OldLoopInfo;
767 CollapseCheckingInfo OldCollapseInfo;
768 TileCheckingInfo OldTileInfo;
769 bool PreserveDepth;
770
771 public:
772 LoopInConstructRAII(SemaOpenACC &SemaRef, bool PreserveDepth = true)
773 : SemaRef(SemaRef), OldLoopInfo(SemaRef.LoopInfo),
774 OldCollapseInfo(SemaRef.CollapseInfo), OldTileInfo(SemaRef.TileInfo),
775 PreserveDepth(PreserveDepth) {}
777 // The associated-statement level of this should NOT preserve this, as it
778 // is a new construct, but other loop uses need to preserve the depth so
779 // it makes it to the 'top level' for diagnostics.
780 bool CollapseDepthSatisified =
781 PreserveDepth ? SemaRef.CollapseInfo.CollapseDepthSatisfied
782 : OldCollapseInfo.CollapseDepthSatisfied;
783 bool TileDepthSatisfied = PreserveDepth
784 ? SemaRef.TileInfo.TileDepthSatisfied
785 : OldTileInfo.TileDepthSatisfied;
786 bool CurLevelHasLoopAlready =
787 PreserveDepth ? SemaRef.LoopInfo.CurLevelHasLoopAlready
788 : OldLoopInfo.CurLevelHasLoopAlready;
789
790 SemaRef.LoopInfo = OldLoopInfo;
791 SemaRef.CollapseInfo = OldCollapseInfo;
792 SemaRef.TileInfo = OldTileInfo;
793
794 SemaRef.CollapseInfo.CollapseDepthSatisfied = CollapseDepthSatisified;
795 SemaRef.TileInfo.TileDepthSatisfied = TileDepthSatisfied;
796 SemaRef.LoopInfo.CurLevelHasLoopAlready = CurLevelHasLoopAlready;
797 }
798 };
799
800 /// Helper type for the registration/assignment of constructs that need to
801 /// 'know' about their parent constructs and hold a reference to them, such as
802 /// Loop needing its parent construct.
804 SemaOpenACC &SemaRef;
805 ComputeConstructInfo OldActiveComputeConstructInfo;
806 OpenACCDirectiveKind DirKind;
807 LoopGangOnKernelTy OldLoopGangClauseOnKernel;
808 SourceLocation OldLoopWorkerClauseLoc;
809 SourceLocation OldLoopVectorClauseLoc;
810 LoopWithoutSeqCheckingInfo OldLoopWithoutSeqInfo;
811 llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses;
812 LoopInConstructRAII LoopRAII;
813
814 public:
825 };
826};
827
828} // namespace clang
829
830#endif // LLVM_CLANG_SEMA_SEMAOPENACC_H
Expr * E
Forward-declares and imports various common LLVM datatypes that clang wants to use unqualified.
Defines some OpenACC-specific enums and functions.
SourceLocation Loc
Definition: SemaObjC.cpp:759
Defines the clang::SourceLocation class and associated facilities.
This file defines OpenACC AST classes for statement-level contructs.
This represents one expression.
Definition: Expr.h:110
bool isInstantiationDependent() const
Whether this expression is instantiation-dependent, meaning that it depends in some way on.
Definition: Expr.h:221
QualType getType() const
Definition: Expr.h:142
This is the base type for all OpenACC Clauses.
Definition: OpenACCClause.h:24
Represents a 'collapse' clause on a 'loop' construct.
Helper type for the registration/assignment of constructs that need to 'know' about their parent cons...
Definition: SemaOpenACC.h:803
void SetTileInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
void SetCollapseInfoBeforeAssociatedStmt(ArrayRef< const OpenACCClause * > UnInstClauses, ArrayRef< OpenACCClause * > Clauses)
Helper type to restore the state of various 'loop' constructs when we run into a loop (for,...
Definition: SemaOpenACC.h:764
LoopInConstructRAII(SemaOpenACC &SemaRef, bool PreserveDepth=true)
Definition: SemaOpenACC.h:772
A type to represent all the data for an OpenACC Clause that has been parsed, but not yet created/sema...
Definition: SemaOpenACC.h:202
ArrayRef< Expr * > getQueueIdExprs() const
Definition: SemaOpenACC.h:338
OpenACCDirectiveKind getDirectiveKind() const
Definition: SemaOpenACC.h:260
ArrayRef< OpenACCGangKind > getGangKinds() const
Definition: SemaOpenACC.h:380
OpenACCParsedClause(OpenACCDirectiveKind DirKind, OpenACCClauseKind ClauseKind, SourceLocation BeginLoc)
Definition: SemaOpenACC.h:256
OpenACCReductionOperator getReductionOp() const
Definition: SemaOpenACC.h:376
void setLParenLoc(SourceLocation EndLoc)
Definition: SemaOpenACC.h:463
void setConditionDetails(Expr *ConditionExpr)
Definition: SemaOpenACC.h:472
void setCollapseDetails(bool IsForce, Expr *LoopCount)
Definition: SemaOpenACC.h:630
OpenACCClauseKind getClauseKind() const
Definition: SemaOpenACC.h:262
void setGangDetails(ArrayRef< OpenACCGangKind > GKs, ArrayRef< Expr * > IntExprs)
Definition: SemaOpenACC.h:513
SourceLocation getLParenLoc() const
Definition: SemaOpenACC.h:266
ArrayRef< DeviceTypeArgument > getDeviceTypeArchitectures() const
Definition: SemaOpenACC.h:456
void setIntExprDetails(llvm::SmallVector< Expr * > &&IntExprs)
Definition: SemaOpenACC.h:499
void setReductionDetails(OpenACCReductionOperator Op, llvm::SmallVector< Expr * > &&VarList)
Definition: SemaOpenACC.h:609
ArrayRef< Expr * > getVarList() const
Definition: SemaOpenACC.h:421
SourceLocation getBeginLoc() const
Definition: SemaOpenACC.h:264
void setDefaultDetails(OpenACCDefaultClauseKind DefKind)
Definition: SemaOpenACC.h:466
SourceLocation getQueuesLoc() const
Definition: SemaOpenACC.h:318
void setVarListDetails(llvm::SmallVector< Expr * > &&VarList, bool IsReadOnly, bool IsZero)
Definition: SemaOpenACC.h:571
void setVarListDetails(ArrayRef< Expr * > VarList, bool IsReadOnly, bool IsZero)
Definition: SemaOpenACC.h:532
void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc, llvm::SmallVector< Expr * > &&IntExprs)
Definition: SemaOpenACC.h:616
void setEndLoc(SourceLocation EndLoc)
Definition: SemaOpenACC.h:464
ArrayRef< Expr * > getIntExprs() const
Definition: SemaOpenACC.h:372
void setIntExprDetails(ArrayRef< Expr * > IntExprs)
Definition: SemaOpenACC.h:486
void setDeviceTypeDetails(llvm::SmallVector< DeviceTypeArgument > &&Archs)
Definition: SemaOpenACC.h:623
void setGangDetails(llvm::SmallVector< OpenACCGangKind > &&GKs, llvm::SmallVector< Expr * > &&IntExprs)
Definition: SemaOpenACC.h:523
OpenACCDefaultClauseKind getDefaultClauseKind() const
Definition: SemaOpenACC.h:270
ExprResult ActOnVar(OpenACCClauseKind CK, Expr *VarExpr)
Called when encountering a 'var' for OpenACC, ensures it is actually a declaration reference to a var...
ComputeConstructInfo & getActiveComputeConstructInfo()
Definition: SemaOpenACC.h:162
bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, ArrayRef< const OpenACCClause * > Clauses)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK, SourceLocation Loc, Expr *IntExpr)
Called when encountering an 'int-expr' for OpenACC, and manages conversions and diagnostics to 'int'.
void ActOnWhileStmt(SourceLocation WhileLoc)
SourceLocation LoopWorkerClauseLoc
If there is a current 'active' loop construct with a 'worker' clause on it (on any sort of construct)...
Definition: SemaOpenACC.h:179
OpenACCClause * ActOnClause(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCParsedClause &Clause)
Called after parsing an OpenACC Clause so that it can be checked.
bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc)
Called after the directive, including its clauses, have been parsed and parsing has consumed the 'ann...
bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr)
Called to check the 'var' type is a variable of pointer type, necessary for 'deviceptr' and 'attach' ...
struct clang::SemaOpenACC::LoopGangOnKernelTy LoopGangClauseOnKernel
ExprResult CheckReductionVar(OpenACCDirectiveKind DirectiveKind, OpenACCReductionOperator ReductionOp, Expr *VarExpr)
Called while semantically analyzing the reduction clause, ensuring the var is the correct kind of ref...
ExprResult CheckCollapseLoopCount(Expr *LoopCount)
Checks the loop depth value for a collapse clause.
struct clang::SemaOpenACC::LoopWithoutSeqCheckingInfo LoopWithoutSeqInfo
StmtResult ActOnEndStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef< Expr * > Exprs, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef< OpenACCClause * > Clauses, StmtResult AssocStmt)
Called after the directive has been completely parsed, including the declaration group or associated ...
DeclGroupRef ActOnEndDeclDirective()
Called after the directive has been completely parsed, including the declaration group or associated ...
OpenACCClause * CheckReductionClause(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCDirectiveKind DirectiveKind, SourceLocation BeginLoc, SourceLocation LParenLoc, OpenACCReductionOperator ReductionOp, ArrayRef< Expr * > Vars, SourceLocation EndLoc)
std::pair< IdentifierInfo *, SourceLocation > DeviceTypeArgument
Definition: SemaOpenACC.h:196
SourceLocation LoopVectorClauseLoc
If there is a current 'active' loop construct with a 'vector' clause on it (on any sort of construct)...
Definition: SemaOpenACC.h:184
void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc)
Called after the construct has been parsed, but clauses haven't been parsed.
ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc)
ExprResult CheckGangExpr(ArrayRef< const OpenACCClause * > ExistingClauses, OpenACCDirectiveKind DK, OpenACCGangKind GK, Expr *E)
void ActOnDoStmt(SourceLocation DoLoc)
void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor, const Stmt *RangeFor)
void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body)
OpenACCClause * CheckGangClause(OpenACCDirectiveKind DirKind, ArrayRef< const OpenACCClause * > ExistingClauses, SourceLocation BeginLoc, SourceLocation LParenLoc, ArrayRef< OpenACCGangKind > GangKinds, ArrayRef< Expr * > IntExprs, SourceLocation EndLoc)
StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc, OpenACCDirectiveKind K, ArrayRef< const OpenACCClause * > Clauses, StmtResult AssocStmt)
Called when we encounter an associated statement for our construct, this should check legality of the...
void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First, const Stmt *Second, const Stmt *Third)
ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc, Expr *LowerBound, SourceLocation ColonLocFirst, Expr *Length, SourceLocation RBLoc)
Checks and creates an Array Section used in an OpenACC construct/clause.
ExprResult CheckTileSizeExpr(Expr *SizeExpr)
Checks a single size expr for a tile clause.
Sema - This implements semantic analysis and AST building for C.
Definition: Sema.h:464
Encodes a location in the source.
A trivial tuple used to represent a source range.
SourceLocation getEnd() const
SourceLocation getBegin() const
void setEnd(SourceLocation e)
Stmt - This represents one statement.
Definition: Stmt.h:84
bool isScalarType() const
Definition: Type.h:8609
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition: Decl.h:671
The JSON file list parser is used to communicate input to InstallAPI.
OpenACCDirectiveKind
Definition: OpenACCKinds.h:25
OpenACCReductionOperator
Definition: OpenACCKinds.h:509
OpenACCClauseKind
Represents the kind of an OpenACC clause.
Definition: OpenACCKinds.h:178
@ Gang
'gang' clause, allowed on 'loop' and Combined constructs.
@ Wait
'wait' clause, allowed on Compute, Data, 'update', and Combined constructs.
@ DevicePtr
'deviceptr' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ PCopyOut
'copyout' clause alias 'pcopyout'. Preserved for diagnostic purposes.
@ VectorLength
'vector_length' clause, allowed on 'parallel', 'kernels', 'parallel loop', and 'kernels loop' constru...
@ Async
'async' clause, allowed on Compute, Data, 'update', 'wait', and Combined constructs.
@ PresentOrCreate
'create' clause alias 'present_or_create'.
@ Collapse
'collapse' clause, allowed on 'loop' and Combined constructs.
@ PresentOrCopy
'copy' clause alias 'present_or_copy'. Preserved for diagnostic purposes.
@ DeviceNum
'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.
@ Private
'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel loop', and 'serial loop' constru...
@ Vector
'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Copy
'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and 'declare'.
@ Worker
'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
@ Create
'create' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ DeviceType
'device_type' clause, allowed on Compute, 'data', 'init', 'shutdown', 'set', update',...
@ DefaultAsync
'default_async' clause, allowed on 'set' construct.
@ Attach
'attach' clause, allowed on Compute and Combined constructs, plus 'data' and 'enter data'.
@ NumGangs
'num_gangs' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs.
@ If
'if' clause, allowed on all the Compute Constructs, Data Constructs, Executable Constructs,...
@ Default
'default' clause, allowed on parallel, serial, kernel (and compound) constructs.
@ UseDevice
'use_device' clause, allowed on 'host_data' construct.
@ NoCreate
'no_create' clause, allowed on allowed on Compute and Combined constructs, plus 'data'.
@ PresentOrCopyOut
'copyout' clause alias 'present_or_copyout'.
@ Reduction
'reduction' clause, allowed on Parallel, Serial, Loop, and the combined constructs.
@ Self
'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
@ CopyOut
'copyout' clause, allowed on Compute and Combined constructs, plus 'data', 'exit data',...
@ FirstPrivate
'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop', and 'serial loop' constructs...
@ PCopy
'copy' clause alias 'pcopy'. Preserved for diagnostic purposes.
@ Tile
'tile' clause, allowed on 'loop' and Combined constructs.
@ PCopyIn
'copyin' clause alias 'pcopyin'. Preserved for diagnostic purposes.
@ PCreate
'create' clause alias 'pcreate'. Preserved for diagnostic purposes.
@ Present
'present' clause, allowed on Compute and Combined constructs, plus 'data' and 'declare'.
@ DType
'dtype' clause, an alias for 'device_type', stored separately for diagnostic purposes.
@ CopyIn
'copyin' clause, allowed on Compute and Combined constructs, plus 'data', 'enter data',...
@ NumWorkers
'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop', and 'kernels loop' constructs...
@ Detach
'detach' clause, allowed on the 'exit data' construct.
@ Delete
'delete' clause, allowed on the 'exit data' construct.
@ PresentOrCopyIn
'copyin' clause alias 'present_or_copyin'.
OpenACCDefaultClauseKind
Definition: OpenACCKinds.h:476
OpenACCGangKind
Definition: OpenACCKinds.h:568
If there is a current 'active' loop construct with a 'gang' clause on a 'kernel' construct,...
Definition: SemaOpenACC.h:170
If there is a current 'active' loop construct that does NOT have a 'seq' clause on it,...
Definition: SemaOpenACC.h:190