1 //===--- OpenACCKinds.h - OpenACC Enums -------------------------*- C++ -*-===//
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 ///
9 /// \file
10 /// Defines some OpenACC-specific enums and functions.
11 ///
12 //===----------------------------------------------------------------------===//
13
14 #ifndef LLVM_CLANG_BASIC_OPENACCKINDS_H
15 #define LLVM_CLANG_BASIC_OPENACCKINDS_H
16
17 #include "clang/Basic/Diagnostic.h"
18 #include "llvm/ADT/BitmaskEnum.h"
19 #include "llvm/Support/ErrorHandling.h"
20 #include "llvm/Support/raw_ostream.h"
21
22 namespace clang {
23 LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE();
24
25 // Represents the Construct/Directive kind of a pragma directive. Note the
26 // OpenACC standard is inconsistent between calling these Construct vs
27 // Directive, but we're calling it a Directive to be consistent with OpenMP.
28 enum class OpenACCDirectiveKind : uint8_t {
29 // Compute Constructs.
30 Parallel,
31 Serial,
32 Kernels,
33
34 // Data Environment. "enter data" and "exit data" are also referred to in the
35 // Executable Directives section, but just as a back reference to the Data
36 // Environment.
37 Data,
38 EnterData,
39 ExitData,
40 HostData,
41
42 // Misc.
43 Loop,
44 Cache,
45
46 // Combined Constructs.
47 ParallelLoop,
48 SerialLoop,
49 KernelsLoop,
50
51 // Atomic Construct.
52 Atomic,
53
54 // Declare Directive.
55 Declare,
56
57 // Executable Directives. "wait" is first referred to here, but ends up being
58 // in its own section after "routine".
59 Init,
60 Shutdown,
61 Set,
62 Update,
63 Wait,
64
65 // Procedure Calls in Compute Regions.
66 Routine,
67
68 // Invalid.
69 Invalid,
70 };
71
72 template <typename StreamTy>
printOpenACCDirectiveKind(StreamTy & Out,OpenACCDirectiveKind K)73 inline StreamTy &printOpenACCDirectiveKind(StreamTy &Out,
74 OpenACCDirectiveKind K) {
75 switch (K) {
76 case OpenACCDirectiveKind::Parallel:
77 return Out << "parallel";
78
79 case OpenACCDirectiveKind::Serial:
80 return Out << "serial";
81
82 case OpenACCDirectiveKind::Kernels:
83 return Out << "kernels";
84
85 case OpenACCDirectiveKind::Data:
86 return Out << "data";
87
88 case OpenACCDirectiveKind::EnterData:
89 return Out << "enter data";
90
91 case OpenACCDirectiveKind::ExitData:
92 return Out << "exit data";
93
94 case OpenACCDirectiveKind::HostData:
95 return Out << "host_data";
96
97 case OpenACCDirectiveKind::Loop:
98 return Out << "loop";
99
100 case OpenACCDirectiveKind::Cache:
101 return Out << "cache";
102
103 case OpenACCDirectiveKind::ParallelLoop:
104 return Out << "parallel loop";
105
106 case OpenACCDirectiveKind::SerialLoop:
107 return Out << "serial loop";
108
109 case OpenACCDirectiveKind::KernelsLoop:
110 return Out << "kernels loop";
111
112 case OpenACCDirectiveKind::Atomic:
113 return Out << "atomic";
114
115 case OpenACCDirectiveKind::Declare:
116 return Out << "declare";
117
118 case OpenACCDirectiveKind::Init:
119 return Out << "init";
120
121 case OpenACCDirectiveKind::Shutdown:
122 return Out << "shutdown";
123
124 case OpenACCDirectiveKind::Set:
125 return Out << "set";
126
127 case OpenACCDirectiveKind::Update:
128 return Out << "update";
129
130 case OpenACCDirectiveKind::Wait:
131 return Out << "wait";
132
133 case OpenACCDirectiveKind::Routine:
134 return Out << "routine";
135
136 case OpenACCDirectiveKind::Invalid:
137 return Out << "<invalid>";
138 }
139 llvm_unreachable("Uncovered directive kind");
140 }
141
142 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
143 OpenACCDirectiveKind K) {
144 return printOpenACCDirectiveKind(Out, K);
145 }
146
147 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
148 OpenACCDirectiveKind K) {
149 return printOpenACCDirectiveKind(Out, K);
150 }
151
isOpenACCComputeDirectiveKind(OpenACCDirectiveKind K)152 inline bool isOpenACCComputeDirectiveKind(OpenACCDirectiveKind K) {
153 return K == OpenACCDirectiveKind::Parallel ||
154 K == OpenACCDirectiveKind::Serial ||
155 K == OpenACCDirectiveKind::Kernels;
156 }
157
isOpenACCCombinedDirectiveKind(OpenACCDirectiveKind K)158 inline bool isOpenACCCombinedDirectiveKind(OpenACCDirectiveKind K) {
159 return K == OpenACCDirectiveKind::ParallelLoop ||
160 K == OpenACCDirectiveKind::SerialLoop ||
161 K == OpenACCDirectiveKind::KernelsLoop;
162 }
163
164 // Tests 'K' to see if it is 'data', 'host_data', 'enter data', or 'exit data'.
isOpenACCDataDirectiveKind(OpenACCDirectiveKind K)165 inline bool isOpenACCDataDirectiveKind(OpenACCDirectiveKind K) {
166 return K == OpenACCDirectiveKind::Data ||
167 K == OpenACCDirectiveKind::EnterData ||
168 K == OpenACCDirectiveKind::ExitData ||
169 K == OpenACCDirectiveKind::HostData;
170 }
171
172 enum class OpenACCAtomicKind : uint8_t {
173 Read,
174 Write,
175 Update,
176 Capture,
177 None,
178 };
179
180 template <typename StreamTy>
printOpenACCAtomicKind(StreamTy & Out,OpenACCAtomicKind AK)181 inline StreamTy &printOpenACCAtomicKind(StreamTy &Out, OpenACCAtomicKind AK) {
182 switch (AK) {
183 case OpenACCAtomicKind::Read:
184 return Out << "read";
185 case OpenACCAtomicKind::Write:
186 return Out << "write";
187 case OpenACCAtomicKind::Update:
188 return Out << "update";
189 case OpenACCAtomicKind::Capture:
190 return Out << "capture";
191 case OpenACCAtomicKind::None:
192 return Out << "<none>";
193 }
194 llvm_unreachable("unknown atomic kind");
195 }
196 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
197 OpenACCAtomicKind AK) {
198 return printOpenACCAtomicKind(Out, AK);
199 }
200 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
201 OpenACCAtomicKind AK) {
202 return printOpenACCAtomicKind(Out, AK);
203 }
204
205 /// Represents the kind of an OpenACC clause. Sorted alphabetically, since this
206 /// order ends up influencing the sorting of the list diagnostic.
207 enum class OpenACCClauseKind : uint8_t {
208 /// 'async' clause, allowed on Compute, Data, 'update', 'wait', and Combined
209 /// constructs.
210 Async,
211 /// 'attach' clause, allowed on Compute and Combined constructs, plus 'data'
212 /// and 'enter data'.
213 Attach,
214 /// 'auto' clause, allowed on 'loop' directives.
215 Auto,
216 /// 'bind' clause, allowed on routine constructs.
217 Bind,
218 /// 'collapse' clause, allowed on 'loop' and Combined constructs.
219 Collapse,
220 /// 'copy' clause, allowed on Compute and Combined Constructs, plus 'data' and
221 /// 'declare'.
222 Copy,
223 /// 'copy' clause alias 'pcopy'. Preserved for diagnostic purposes.
224 PCopy,
225 /// 'copy' clause alias 'present_or_copy'. Preserved for diagnostic purposes.
226 PresentOrCopy,
227 /// 'copyin' clause, allowed on Compute and Combined constructs, plus 'data',
228 /// 'enter data', and 'declare'.
229 CopyIn,
230 /// 'copyin' clause alias 'pcopyin'. Preserved for diagnostic purposes.
231 PCopyIn,
232 /// 'copyin' clause alias 'present_or_copyin'. Preserved for diagnostic
233 /// purposes.
234 PresentOrCopyIn,
235 /// 'copyout' clause, allowed on Compute and Combined constructs, plus 'data',
236 /// 'exit data', and 'declare'.
237 CopyOut,
238 /// 'copyout' clause alias 'pcopyout'. Preserved for diagnostic purposes.
239 PCopyOut,
240 /// 'copyout' clause alias 'present_or_copyout'. Preserved for diagnostic
241 /// purposes.
242 PresentOrCopyOut,
243 /// 'create' clause, allowed on Compute and Combined constructs, plus 'data',
244 /// 'enter data', and 'declare'.
245 Create,
246 /// 'create' clause alias 'pcreate'. Preserved for diagnostic purposes.
247 PCreate,
248 /// 'create' clause alias 'present_or_create'. Preserved for diagnostic
249 /// purposes.
250 PresentOrCreate,
251 /// 'default' clause, allowed on parallel, serial, kernel (and compound)
252 /// constructs.
253 Default,
254 /// 'default_async' clause, allowed on 'set' construct.
255 DefaultAsync,
256 /// 'delete' clause, allowed on the 'exit data' construct.
257 Delete,
258 /// 'detach' clause, allowed on the 'exit data' construct.
259 Detach,
260 /// 'device' clause, allowed on the 'update' construct.
261 Device,
262 /// 'device_num' clause, allowed on 'init', 'shutdown', and 'set' constructs.
263 DeviceNum,
264 /// 'deviceptr' clause, allowed on Compute and Combined Constructs, plus
265 /// 'data' and 'declare'.
266 DevicePtr,
267 /// 'device_resident' clause, allowed on the 'declare' construct.
268 DeviceResident,
269 /// 'device_type' clause, allowed on Compute, 'data', 'init', 'shutdown',
270 /// 'set', update', 'loop', 'routine', and Combined constructs.
271 DeviceType,
272 /// 'dtype' clause, an alias for 'device_type', stored separately for
273 /// diagnostic purposes.
274 DType,
275 /// 'finalize' clause, allowed on 'exit data' directive.
276 Finalize,
277 /// 'firstprivate' clause, allowed on 'parallel', 'serial', 'parallel loop',
278 /// and 'serial loop' constructs.
279 FirstPrivate,
280 /// 'gang' clause, allowed on 'loop' and Combined constructs.
281 Gang,
282 /// 'host' clause, allowed on 'update' construct.
283 Host,
284 /// 'if' clause, allowed on all the Compute Constructs, Data Constructs,
285 /// Executable Constructs, and Combined Constructs.
286 If,
287 /// 'if_present' clause, allowed on 'host_data' and 'update' directives.
288 IfPresent,
289 /// 'independent' clause, allowed on 'loop' directives.
290 Independent,
291 /// 'link' clause, allowed on 'declare' construct.
292 Link,
293 /// 'no_create' clause, allowed on allowed on Compute and Combined constructs,
294 /// plus 'data'.
295 NoCreate,
296 /// 'nohost' clause, allowed on 'routine' directives.
297 NoHost,
298 /// 'num_gangs' clause, allowed on 'parallel', 'kernels', parallel loop', and
299 /// 'kernels loop' constructs.
300 NumGangs,
301 /// 'num_workers' clause, allowed on 'parallel', 'kernels', parallel loop',
302 /// and 'kernels loop' constructs.
303 NumWorkers,
304 /// 'present' clause, allowed on Compute and Combined constructs, plus 'data'
305 /// and 'declare'.
306 Present,
307 /// 'private' clause, allowed on 'parallel', 'serial', 'loop', 'parallel
308 /// loop', and 'serial loop' constructs.
309 Private,
310 /// 'reduction' clause, allowed on Parallel, Serial, Loop, and the combined
311 /// constructs.
312 Reduction,
313 /// 'self' clause, allowed on Compute and Combined Constructs, plus 'update'.
314 Self,
315 /// 'seq' clause, allowed on 'loop' and 'routine' directives.
316 Seq,
317 /// 'tile' clause, allowed on 'loop' and Combined constructs.
318 Tile,
319 /// 'use_device' clause, allowed on 'host_data' construct.
320 UseDevice,
321 /// 'vector' clause, allowed on 'loop', Combined, and 'routine' directives.
322 Vector,
323 /// 'vector_length' clause, allowed on 'parallel', 'kernels', 'parallel loop',
324 /// and 'kernels loop' constructs.
325 VectorLength,
326 /// 'wait' clause, allowed on Compute, Data, 'update', and Combined
327 /// constructs.
328 Wait,
329 /// 'worker' clause, allowed on 'loop', Combined, and 'routine' directives.
330 Worker,
331
332 /// 'shortloop' is represented in the ACC.td file, but isn't present in the
333 /// standard. This appears to be an old extension for the nvidia fortran
334 // compiler, but seemingly not elsewhere. Put it here as a placeholder, but it
335 // is never expected to be generated.
336 Shortloop,
337 /// Represents an invalid clause, for the purposes of parsing. Should be
338 /// 'last'.
339 Invalid,
340 };
341
342 template <typename StreamTy>
printOpenACCClauseKind(StreamTy & Out,OpenACCClauseKind K)343 inline StreamTy &printOpenACCClauseKind(StreamTy &Out, OpenACCClauseKind K) {
344 switch (K) {
345 case OpenACCClauseKind::Finalize:
346 return Out << "finalize";
347
348 case OpenACCClauseKind::IfPresent:
349 return Out << "if_present";
350
351 case OpenACCClauseKind::Seq:
352 return Out << "seq";
353
354 case OpenACCClauseKind::Independent:
355 return Out << "independent";
356
357 case OpenACCClauseKind::Auto:
358 return Out << "auto";
359
360 case OpenACCClauseKind::Worker:
361 return Out << "worker";
362
363 case OpenACCClauseKind::Vector:
364 return Out << "vector";
365
366 case OpenACCClauseKind::NoHost:
367 return Out << "nohost";
368
369 case OpenACCClauseKind::Default:
370 return Out << "default";
371
372 case OpenACCClauseKind::If:
373 return Out << "if";
374
375 case OpenACCClauseKind::Self:
376 return Out << "self";
377
378 case OpenACCClauseKind::Copy:
379 return Out << "copy";
380
381 case OpenACCClauseKind::PCopy:
382 return Out << "pcopy";
383
384 case OpenACCClauseKind::PresentOrCopy:
385 return Out << "present_or_copy";
386
387 case OpenACCClauseKind::UseDevice:
388 return Out << "use_device";
389
390 case OpenACCClauseKind::Attach:
391 return Out << "attach";
392
393 case OpenACCClauseKind::Delete:
394 return Out << "delete";
395
396 case OpenACCClauseKind::Detach:
397 return Out << "detach";
398
399 case OpenACCClauseKind::Device:
400 return Out << "device";
401
402 case OpenACCClauseKind::DevicePtr:
403 return Out << "deviceptr";
404
405 case OpenACCClauseKind::DeviceResident:
406 return Out << "device_resident";
407
408 case OpenACCClauseKind::FirstPrivate:
409 return Out << "firstprivate";
410
411 case OpenACCClauseKind::Host:
412 return Out << "host";
413
414 case OpenACCClauseKind::Link:
415 return Out << "link";
416
417 case OpenACCClauseKind::NoCreate:
418 return Out << "no_create";
419
420 case OpenACCClauseKind::Present:
421 return Out << "present";
422
423 case OpenACCClauseKind::Private:
424 return Out << "private";
425
426 case OpenACCClauseKind::CopyOut:
427 return Out << "copyout";
428
429 case OpenACCClauseKind::PCopyOut:
430 return Out << "pcopyout";
431
432 case OpenACCClauseKind::PresentOrCopyOut:
433 return Out << "present_or_copyout";
434
435 case OpenACCClauseKind::CopyIn:
436 return Out << "copyin";
437
438 case OpenACCClauseKind::PCopyIn:
439 return Out << "pcopyin";
440
441 case OpenACCClauseKind::PresentOrCopyIn:
442 return Out << "present_or_copyin";
443
444 case OpenACCClauseKind::Create:
445 return Out << "create";
446
447 case OpenACCClauseKind::PCreate:
448 return Out << "pcreate";
449
450 case OpenACCClauseKind::PresentOrCreate:
451 return Out << "present_or_create";
452
453 case OpenACCClauseKind::Reduction:
454 return Out << "reduction";
455
456 case OpenACCClauseKind::Collapse:
457 return Out << "collapse";
458
459 case OpenACCClauseKind::Bind:
460 return Out << "bind";
461
462 case OpenACCClauseKind::VectorLength:
463 return Out << "vector_length";
464
465 case OpenACCClauseKind::NumGangs:
466 return Out << "num_gangs";
467
468 case OpenACCClauseKind::NumWorkers:
469 return Out << "num_workers";
470
471 case OpenACCClauseKind::DeviceNum:
472 return Out << "device_num";
473
474 case OpenACCClauseKind::DefaultAsync:
475 return Out << "default_async";
476
477 case OpenACCClauseKind::DeviceType:
478 return Out << "device_type";
479
480 case OpenACCClauseKind::DType:
481 return Out << "dtype";
482
483 case OpenACCClauseKind::Async:
484 return Out << "async";
485
486 case OpenACCClauseKind::Tile:
487 return Out << "tile";
488
489 case OpenACCClauseKind::Gang:
490 return Out << "gang";
491
492 case OpenACCClauseKind::Wait:
493 return Out << "wait";
494
495 case OpenACCClauseKind::Shortloop:
496 llvm_unreachable("Shortloop shouldn't be generated in clang");
497 LLVM_FALLTHROUGH;
498 case OpenACCClauseKind::Invalid:
499 return Out << "<invalid>";
500 }
501 llvm_unreachable("Uncovered clause kind");
502 }
503
504 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
505 OpenACCClauseKind K) {
506 return printOpenACCClauseKind(Out, K);
507 }
508
509 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
510 OpenACCClauseKind K) {
511 return printOpenACCClauseKind(Out, K);
512 }
513
514 enum class OpenACCDefaultClauseKind : uint8_t {
515 /// 'none' option.
516 None,
517 /// 'present' option.
518 Present,
519 /// Not a valid option.
520 Invalid,
521 };
522
523 template <typename StreamTy>
printOpenACCDefaultClauseKind(StreamTy & Out,OpenACCDefaultClauseKind K)524 inline StreamTy &printOpenACCDefaultClauseKind(StreamTy &Out,
525 OpenACCDefaultClauseKind K) {
526 switch (K) {
527 case OpenACCDefaultClauseKind::None:
528 return Out << "none";
529 case OpenACCDefaultClauseKind::Present:
530 return Out << "present";
531 case OpenACCDefaultClauseKind::Invalid:
532 return Out << "<invalid>";
533 }
534 llvm_unreachable("Unknown OpenACCDefaultClauseKind enum");
535 }
536
537 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
538 OpenACCDefaultClauseKind K) {
539 return printOpenACCDefaultClauseKind(Out, K);
540 }
541
542 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
543 OpenACCDefaultClauseKind K) {
544 return printOpenACCDefaultClauseKind(Out, K);
545 }
546
547 enum class OpenACCReductionOperator : uint8_t {
548 /// '+'.
549 Addition,
550 /// '*'.
551 Multiplication,
552 /// 'max'.
553 Max,
554 /// 'min'.
555 Min,
556 /// '&'.
557 BitwiseAnd,
558 /// '|'.
559 BitwiseOr,
560 /// '^'.
561 BitwiseXOr,
562 /// '&&'.
563 And,
564 /// '||'.
565 Or,
566 /// Invalid Reduction Clause Kind.
567 Invalid,
568 };
569
570 template <typename StreamTy>
printOpenACCReductionOperator(StreamTy & Out,OpenACCReductionOperator Op)571 inline StreamTy &printOpenACCReductionOperator(StreamTy &Out,
572 OpenACCReductionOperator Op) {
573 switch (Op) {
574 case OpenACCReductionOperator::Addition:
575 return Out << "+";
576 case OpenACCReductionOperator::Multiplication:
577 return Out << "*";
578 case OpenACCReductionOperator::Max:
579 return Out << "max";
580 case OpenACCReductionOperator::Min:
581 return Out << "min";
582 case OpenACCReductionOperator::BitwiseAnd:
583 return Out << "&";
584 case OpenACCReductionOperator::BitwiseOr:
585 return Out << "|";
586 case OpenACCReductionOperator::BitwiseXOr:
587 return Out << "^";
588 case OpenACCReductionOperator::And:
589 return Out << "&&";
590 case OpenACCReductionOperator::Or:
591 return Out << "||";
592 case OpenACCReductionOperator::Invalid:
593 return Out << "<invalid>";
594 }
595 llvm_unreachable("Unknown reduction operator kind");
596 }
597 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
598 OpenACCReductionOperator Op) {
599 return printOpenACCReductionOperator(Out, Op);
600 }
601 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
602 OpenACCReductionOperator Op) {
603 return printOpenACCReductionOperator(Out, Op);
604 }
605
606 enum class OpenACCGangKind : uint8_t {
607 /// num:
608 Num,
609 /// dim:
610 Dim,
611 /// static:
612 Static
613 };
614
615 template <typename StreamTy>
printOpenACCGangKind(StreamTy & Out,OpenACCGangKind GK)616 inline StreamTy &printOpenACCGangKind(StreamTy &Out, OpenACCGangKind GK) {
617 switch (GK) {
618 case OpenACCGangKind::Num:
619 return Out << "num";
620 case OpenACCGangKind::Dim:
621 return Out << "dim";
622 case OpenACCGangKind::Static:
623 return Out << "static";
624 }
625 llvm_unreachable("unknown gang kind");
626 }
627 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
628 OpenACCGangKind Op) {
629 return printOpenACCGangKind(Out, Op);
630 }
631 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
632 OpenACCGangKind Op) {
633 return printOpenACCGangKind(Out, Op);
634 }
635
636 // Represents the 'modifier' of a 'modifier-list', as applied to copy, copyin,
637 // copyout, and create. Implemented as a 'bitmask'.
638 // Note: This attempts to synchronize with mlir::acc::DataClauseModifier,
639 // however has to store `Always` separately(whereas MLIR has it as AlwaysIn &
640 // AlwaysOut). However, we keep them in sync so that we can cast between them.
641 enum class OpenACCModifierKind : uint8_t {
642 Invalid = 0,
643 Zero = 1 << 0,
644 Readonly = 1 << 1,
645 AlwaysIn = 1 << 2,
646 AlwaysOut = 1 << 3,
647 Capture = 1 << 4,
648 Always = 1 << 5,
649 LLVM_MARK_AS_BITMASK_ENUM(Always)
650 };
651
isOpenACCModifierBitSet(OpenACCModifierKind List,OpenACCModifierKind Bit)652 inline bool isOpenACCModifierBitSet(OpenACCModifierKind List,
653 OpenACCModifierKind Bit) {
654 return (List & Bit) != OpenACCModifierKind::Invalid;
655 }
656
657 template <typename StreamTy>
printOpenACCModifierKind(StreamTy & Out,OpenACCModifierKind Mods)658 inline StreamTy &printOpenACCModifierKind(StreamTy &Out,
659 OpenACCModifierKind Mods) {
660 if (Mods == OpenACCModifierKind::Invalid)
661 return Out << "<invalid>";
662
663 bool First = true;
664
665 if (isOpenACCModifierBitSet(Mods, OpenACCModifierKind::Always)) {
666 Out << "always";
667 First = false;
668 }
669
670 if (isOpenACCModifierBitSet(Mods, OpenACCModifierKind::AlwaysIn)) {
671 if (!First)
672 Out << ", ";
673 Out << "alwaysin";
674 First = false;
675 }
676
677 if (isOpenACCModifierBitSet(Mods, OpenACCModifierKind::AlwaysOut)) {
678 if (!First)
679 Out << ", ";
680 Out << "alwaysout";
681 First = false;
682 }
683
684 if (isOpenACCModifierBitSet(Mods, OpenACCModifierKind::Readonly)) {
685 if (!First)
686 Out << ", ";
687 Out << "readonly";
688 First = false;
689 }
690
691 if (isOpenACCModifierBitSet(Mods, OpenACCModifierKind::Zero)) {
692 if (!First)
693 Out << ", ";
694 Out << "zero";
695 First = false;
696 }
697
698 if (isOpenACCModifierBitSet(Mods, OpenACCModifierKind::Capture)) {
699 if (!First)
700 Out << ", ";
701 Out << "capture";
702 First = false;
703 }
704 return Out;
705 }
706 inline const StreamingDiagnostic &operator<<(const StreamingDiagnostic &Out,
707 OpenACCModifierKind Op) {
708 return printOpenACCModifierKind(Out, Op);
709 }
710 inline llvm::raw_ostream &operator<<(llvm::raw_ostream &Out,
711 OpenACCModifierKind Op) {
712 return printOpenACCModifierKind(Out, Op);
713 }
714 } // namespace clang
715
716 #endif // LLVM_CLANG_BASIC_OPENACCKINDS_H
717