xref: /freebsd/contrib/llvm-project/clang/include/clang/Basic/OpenACCKinds.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
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