xref: /llvm-project/clang/include/clang/AST/OpenACCClause.h (revision be32621ce8cbffe674c62e87c0c51c9fc4a21e5f)
1 //===- OpenACCClause.h - Classes for OpenACC clauses ------------*- 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 // This file defines OpenACC AST classes for clauses.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H
15 #define LLVM_CLANG_AST_OPENACCCLAUSE_H
16 #include "clang/AST/ASTContext.h"
17 #include "clang/AST/StmtIterator.h"
18 #include "clang/Basic/OpenACCKinds.h"
19 
20 #include <utility>
21 
22 namespace clang {
23 /// This is the base type for all OpenACC Clauses.
24 class OpenACCClause {
25   OpenACCClauseKind Kind;
26   SourceRange Location;
27 
28 protected:
29   OpenACCClause(OpenACCClauseKind K, SourceLocation BeginLoc,
30                 SourceLocation EndLoc)
31       : Kind(K), Location(BeginLoc, EndLoc) {
32     assert(!BeginLoc.isInvalid() && !EndLoc.isInvalid() &&
33            "Begin and end location must be valid for OpenACCClause");
34       }
35 
36 public:
37   OpenACCClauseKind getClauseKind() const { return Kind; }
38   SourceLocation getBeginLoc() const { return Location.getBegin(); }
39   SourceLocation getEndLoc() const { return Location.getEnd(); }
40 
41   static bool classof(const OpenACCClause *) { return true; }
42 
43   using child_iterator = StmtIterator;
44   using const_child_iterator = ConstStmtIterator;
45   using child_range = llvm::iterator_range<child_iterator>;
46   using const_child_range = llvm::iterator_range<const_child_iterator>;
47 
48   child_range children();
49   const_child_range children() const {
50     auto Children = const_cast<OpenACCClause *>(this)->children();
51     return const_child_range(Children.begin(), Children.end());
52   }
53 
54   virtual ~OpenACCClause() = default;
55 };
56 
57 // Represents the 'auto' clause.
58 class OpenACCAutoClause : public OpenACCClause {
59 protected:
60   OpenACCAutoClause(SourceLocation BeginLoc, SourceLocation EndLoc)
61       : OpenACCClause(OpenACCClauseKind::Auto, BeginLoc, EndLoc) {}
62 
63 public:
64   static bool classof(const OpenACCClause *C) {
65     return C->getClauseKind() == OpenACCClauseKind::Auto;
66   }
67 
68   static OpenACCAutoClause *
69   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
70 
71   child_range children() {
72     return child_range(child_iterator(), child_iterator());
73   }
74   const_child_range children() const {
75     return const_child_range(const_child_iterator(), const_child_iterator());
76   }
77 };
78 
79 // Represents the 'finalize' clause.
80 class OpenACCFinalizeClause : public OpenACCClause {
81 protected:
82   OpenACCFinalizeClause(SourceLocation BeginLoc, SourceLocation EndLoc)
83       : OpenACCClause(OpenACCClauseKind::Finalize, BeginLoc, EndLoc) {}
84 
85 public:
86   static bool classof(const OpenACCClause *C) {
87     return C->getClauseKind() == OpenACCClauseKind::Finalize;
88   }
89 
90   static OpenACCFinalizeClause *
91   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
92 
93   child_range children() {
94     return child_range(child_iterator(), child_iterator());
95   }
96   const_child_range children() const {
97     return const_child_range(const_child_iterator(), const_child_iterator());
98   }
99 };
100 
101 // Represents the 'if_present' clause.
102 class OpenACCIfPresentClause : public OpenACCClause {
103 protected:
104   OpenACCIfPresentClause(SourceLocation BeginLoc, SourceLocation EndLoc)
105       : OpenACCClause(OpenACCClauseKind::IfPresent, BeginLoc, EndLoc) {}
106 
107 public:
108   static bool classof(const OpenACCClause *C) {
109     return C->getClauseKind() == OpenACCClauseKind::IfPresent;
110   }
111 
112   static OpenACCIfPresentClause *
113   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
114 
115   child_range children() {
116     return child_range(child_iterator(), child_iterator());
117   }
118   const_child_range children() const {
119     return const_child_range(const_child_iterator(), const_child_iterator());
120   }
121 };
122 
123 // Represents the 'independent' clause.
124 class OpenACCIndependentClause : public OpenACCClause {
125 protected:
126   OpenACCIndependentClause(SourceLocation BeginLoc, SourceLocation EndLoc)
127       : OpenACCClause(OpenACCClauseKind::Independent, BeginLoc, EndLoc) {}
128 
129 public:
130   static bool classof(const OpenACCClause *C) {
131     return C->getClauseKind() == OpenACCClauseKind::Independent;
132   }
133 
134   static OpenACCIndependentClause *
135   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
136 
137   child_range children() {
138     return child_range(child_iterator(), child_iterator());
139   }
140   const_child_range children() const {
141     return const_child_range(const_child_iterator(), const_child_iterator());
142   }
143 };
144 // Represents the 'seq' clause.
145 class OpenACCSeqClause : public OpenACCClause {
146 protected:
147   OpenACCSeqClause(SourceLocation BeginLoc, SourceLocation EndLoc)
148       : OpenACCClause(OpenACCClauseKind::Seq, BeginLoc, EndLoc) {}
149 
150 public:
151   static bool classof(const OpenACCClause *C) {
152     return C->getClauseKind() == OpenACCClauseKind::Seq;
153   }
154 
155   static OpenACCSeqClause *
156   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
157 
158   child_range children() {
159     return child_range(child_iterator(), child_iterator());
160   }
161   const_child_range children() const {
162     return const_child_range(const_child_iterator(), const_child_iterator());
163   }
164 };
165 
166 /// Represents a clause that has a list of parameters.
167 class OpenACCClauseWithParams : public OpenACCClause {
168   /// Location of the '('.
169   SourceLocation LParenLoc;
170 
171 protected:
172   OpenACCClauseWithParams(OpenACCClauseKind K, SourceLocation BeginLoc,
173                           SourceLocation LParenLoc, SourceLocation EndLoc)
174       : OpenACCClause(K, BeginLoc, EndLoc), LParenLoc(LParenLoc) {}
175 
176 public:
177   static bool classof(const OpenACCClause *C);
178 
179   SourceLocation getLParenLoc() const { return LParenLoc; }
180 
181   child_range children() {
182     return child_range(child_iterator(), child_iterator());
183   }
184   const_child_range children() const {
185     return const_child_range(const_child_iterator(), const_child_iterator());
186   }
187 };
188 
189 using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
190 /// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or
191 /// an identifier. The 'asterisk' means 'the rest'.
192 class OpenACCDeviceTypeClause final
193     : public OpenACCClauseWithParams,
194       private llvm::TrailingObjects<OpenACCDeviceTypeClause,
195                                    DeviceTypeArgument> {
196   friend TrailingObjects;
197   // Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A
198   // nullptr IdentifierInfo* represents an asterisk.
199   unsigned NumArchs;
200   OpenACCDeviceTypeClause(OpenACCClauseKind K, SourceLocation BeginLoc,
201                           SourceLocation LParenLoc,
202                           ArrayRef<DeviceTypeArgument> Archs,
203                           SourceLocation EndLoc)
204       : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
205         NumArchs(Archs.size()) {
206     assert(
207         (K == OpenACCClauseKind::DeviceType || K == OpenACCClauseKind::DType) &&
208         "Invalid clause kind for device-type");
209 
210     assert(!llvm::any_of(Archs, [](const DeviceTypeArgument &Arg) {
211       return Arg.second.isInvalid();
212     }) && "Invalid SourceLocation for an argument");
213 
214     assert(
215         (Archs.size() == 1 || !llvm::any_of(Archs,
216                                             [](const DeviceTypeArgument &Arg) {
217                                               return Arg.first == nullptr;
218                                             })) &&
219         "Only a single asterisk version is permitted, and must be the "
220         "only one");
221 
222     std::uninitialized_copy(Archs.begin(), Archs.end(),
223                             getTrailingObjects<DeviceTypeArgument>());
224   }
225 
226 public:
227   static bool classof(const OpenACCClause *C) {
228     return C->getClauseKind() == OpenACCClauseKind::DType ||
229            C->getClauseKind() == OpenACCClauseKind::DeviceType;
230   }
231   bool hasAsterisk() const {
232     return getArchitectures().size() > 0 &&
233            getArchitectures()[0].first == nullptr;
234   }
235 
236   ArrayRef<DeviceTypeArgument> getArchitectures() const {
237     return ArrayRef<DeviceTypeArgument>(
238         getTrailingObjects<DeviceTypeArgument>(), NumArchs);
239   }
240 
241   static OpenACCDeviceTypeClause *
242   Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc,
243          SourceLocation LParenLoc, ArrayRef<DeviceTypeArgument> Archs,
244          SourceLocation EndLoc);
245 };
246 
247 /// A 'default' clause, has the optional 'none' or 'present' argument.
248 class OpenACCDefaultClause : public OpenACCClauseWithParams {
249   friend class ASTReaderStmt;
250   friend class ASTWriterStmt;
251 
252   OpenACCDefaultClauseKind DefaultClauseKind;
253 
254 protected:
255   OpenACCDefaultClause(OpenACCDefaultClauseKind K, SourceLocation BeginLoc,
256                        SourceLocation LParenLoc, SourceLocation EndLoc)
257       : OpenACCClauseWithParams(OpenACCClauseKind::Default, BeginLoc, LParenLoc,
258                                 EndLoc),
259         DefaultClauseKind(K) {
260     assert((DefaultClauseKind == OpenACCDefaultClauseKind::None ||
261             DefaultClauseKind == OpenACCDefaultClauseKind::Present) &&
262            "Invalid Clause Kind");
263   }
264 
265 public:
266   static bool classof(const OpenACCClause *C) {
267     return C->getClauseKind() == OpenACCClauseKind::Default;
268   }
269   OpenACCDefaultClauseKind getDefaultClauseKind() const {
270     return DefaultClauseKind;
271   }
272 
273   static OpenACCDefaultClause *Create(const ASTContext &C,
274                                       OpenACCDefaultClauseKind K,
275                                       SourceLocation BeginLoc,
276                                       SourceLocation LParenLoc,
277                                       SourceLocation EndLoc);
278 };
279 
280 /// Represents one of the handful of classes that has an optional/required
281 /// 'condition' expression as an argument.
282 class OpenACCClauseWithCondition : public OpenACCClauseWithParams {
283   Expr *ConditionExpr = nullptr;
284 
285 protected:
286   OpenACCClauseWithCondition(OpenACCClauseKind K, SourceLocation BeginLoc,
287                              SourceLocation LParenLoc, Expr *ConditionExpr,
288                              SourceLocation EndLoc)
289       : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
290         ConditionExpr(ConditionExpr) {}
291 
292 public:
293   static bool classof(const OpenACCClause *C);
294 
295   bool hasConditionExpr() const { return ConditionExpr; }
296   const Expr *getConditionExpr() const { return ConditionExpr; }
297   Expr *getConditionExpr() { return ConditionExpr; }
298 
299   child_range children() {
300     if (ConditionExpr)
301       return child_range(reinterpret_cast<Stmt **>(&ConditionExpr),
302                          reinterpret_cast<Stmt **>(&ConditionExpr + 1));
303     return child_range(child_iterator(), child_iterator());
304   }
305 
306   const_child_range children() const {
307     if (ConditionExpr)
308       return const_child_range(
309           reinterpret_cast<Stmt *const *>(&ConditionExpr),
310           reinterpret_cast<Stmt *const *>(&ConditionExpr + 1));
311     return const_child_range(const_child_iterator(), const_child_iterator());
312   }
313 };
314 
315 /// An 'if' clause, which has a required condition expression.
316 class OpenACCIfClause : public OpenACCClauseWithCondition {
317 protected:
318   OpenACCIfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
319                   Expr *ConditionExpr, SourceLocation EndLoc);
320 
321 public:
322   static bool classof(const OpenACCClause *C) {
323     return C->getClauseKind() == OpenACCClauseKind::If;
324   }
325   static OpenACCIfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
326                                  SourceLocation LParenLoc, Expr *ConditionExpr,
327                                  SourceLocation EndLoc);
328 };
329 
330 /// A 'self' clause, which has an optional condition expression, or, in the
331 /// event of an 'update' directive, contains a 'VarList'.
332 class OpenACCSelfClause final
333     : public OpenACCClauseWithParams,
334       private llvm::TrailingObjects<OpenACCSelfClause, Expr *> {
335   friend TrailingObjects;
336   // Holds whether this HAS a condition expression. Lacks a value if this is NOT
337   // a condition-expr self clause.
338   std::optional<bool> HasConditionExpr;
339   // Holds the number of stored expressions.  In the case of a condition-expr
340   // self clause, this is expected to be ONE (and there to be 1 trailing
341   // object), whether or not that is null.
342   unsigned NumExprs;
343 
344   OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
345                     Expr *ConditionExpr, SourceLocation EndLoc);
346   OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
347                     ArrayRef<Expr *> VarList, SourceLocation EndLoc);
348 
349   // Intentionally internal, meant to be an implementation detail of everything
350   // else. All non-internal uses should go through getConditionExpr/getVarList.
351   llvm::ArrayRef<Expr *> getExprs() const {
352     return {getTrailingObjects<Expr *>(), NumExprs};
353   }
354 
355 public:
356   static bool classof(const OpenACCClause *C) {
357     return C->getClauseKind() == OpenACCClauseKind::Self;
358   }
359 
360   bool isConditionExprClause() const { return HasConditionExpr.has_value(); }
361 
362   bool hasConditionExpr() const {
363     assert(HasConditionExpr.has_value() &&
364            "VarList Self Clause asked about condition expression");
365     return *HasConditionExpr;
366   }
367 
368   const Expr *getConditionExpr() const {
369     assert(HasConditionExpr.has_value() &&
370            "VarList Self Clause asked about condition expression");
371     assert(getExprs().size() == 1 &&
372            "ConditionExpr Self Clause with too many Exprs");
373     return getExprs()[0];
374   }
375 
376   Expr *getConditionExpr() {
377     assert(HasConditionExpr.has_value() &&
378            "VarList Self Clause asked about condition expression");
379     assert(getExprs().size() == 1 &&
380            "ConditionExpr Self Clause with too many Exprs");
381     return getExprs()[0];
382   }
383 
384   ArrayRef<Expr *> getVarList() {
385     assert(!HasConditionExpr.has_value() &&
386            "Condition Expr self clause asked about var list");
387     return getExprs();
388   }
389   ArrayRef<Expr *> getVarList() const {
390     assert(!HasConditionExpr.has_value() &&
391            "Condition Expr self clause asked about var list");
392     return getExprs();
393   }
394 
395   child_range children() {
396     return child_range(
397         reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()),
398         reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>() + NumExprs));
399   }
400 
401   const_child_range children() const {
402     child_range Children = const_cast<OpenACCSelfClause *>(this)->children();
403     return const_child_range(Children.begin(), Children.end());
404   }
405 
406   static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
407                                    SourceLocation LParenLoc,
408                                    Expr *ConditionExpr, SourceLocation EndLoc);
409   static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
410                                    SourceLocation LParenLoc,
411                                    ArrayRef<Expr *> ConditionExpr,
412                                    SourceLocation EndLoc);
413 };
414 
415 /// Represents a clause that has one or more expressions associated with it.
416 class OpenACCClauseWithExprs : public OpenACCClauseWithParams {
417   MutableArrayRef<Expr *> Exprs;
418 
419 protected:
420   OpenACCClauseWithExprs(OpenACCClauseKind K, SourceLocation BeginLoc,
421                          SourceLocation LParenLoc, SourceLocation EndLoc)
422       : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {}
423 
424   /// Used only for initialization, the leaf class can initialize this to
425   /// trailing storage.
426   void setExprs(MutableArrayRef<Expr *> NewExprs) {
427     assert(Exprs.empty() && "Cannot change Exprs list");
428     Exprs = NewExprs;
429   }
430 
431   /// Gets the entire list of expressions, but leave it to the
432   /// individual clauses to expose this how they'd like.
433   llvm::ArrayRef<Expr *> getExprs() const { return Exprs; }
434 
435 public:
436   static bool classof(const OpenACCClause *C);
437   child_range children() {
438     return child_range(reinterpret_cast<Stmt **>(Exprs.begin()),
439                        reinterpret_cast<Stmt **>(Exprs.end()));
440   }
441 
442   const_child_range children() const {
443     child_range Children =
444         const_cast<OpenACCClauseWithExprs *>(this)->children();
445     return const_child_range(Children.begin(), Children.end());
446   }
447 };
448 
449 // Represents the 'devnum' and expressions lists for the 'wait' clause.
450 class OpenACCWaitClause final
451     : public OpenACCClauseWithExprs,
452       private llvm::TrailingObjects<OpenACCWaitClause, Expr *> {
453   friend TrailingObjects;
454   SourceLocation QueuesLoc;
455   OpenACCWaitClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
456                     Expr *DevNumExpr, SourceLocation QueuesLoc,
457                     ArrayRef<Expr *> QueueIdExprs, SourceLocation EndLoc)
458       : OpenACCClauseWithExprs(OpenACCClauseKind::Wait, BeginLoc, LParenLoc,
459                                EndLoc),
460         QueuesLoc(QueuesLoc) {
461     // The first element of the trailing storage is always the devnum expr,
462     // whether it is used or not.
463     std::uninitialized_copy(&DevNumExpr, &DevNumExpr + 1,
464                             getTrailingObjects<Expr *>());
465     std::uninitialized_copy(QueueIdExprs.begin(), QueueIdExprs.end(),
466                             getTrailingObjects<Expr *>() + 1);
467     setExprs(
468         MutableArrayRef(getTrailingObjects<Expr *>(), QueueIdExprs.size() + 1));
469   }
470 
471 public:
472   static bool classof(const OpenACCClause *C) {
473     return C->getClauseKind() == OpenACCClauseKind::Wait;
474   }
475   static OpenACCWaitClause *Create(const ASTContext &C, SourceLocation BeginLoc,
476                                    SourceLocation LParenLoc, Expr *DevNumExpr,
477                                    SourceLocation QueuesLoc,
478                                    ArrayRef<Expr *> QueueIdExprs,
479                                    SourceLocation EndLoc);
480 
481   bool hasQueuesTag() const { return !QueuesLoc.isInvalid(); }
482   SourceLocation getQueuesLoc() const { return QueuesLoc; }
483   bool hasDevNumExpr() const { return getExprs()[0]; }
484   Expr *getDevNumExpr() const { return getExprs()[0]; }
485   llvm::ArrayRef<Expr *> getQueueIdExprs() {
486     return OpenACCClauseWithExprs::getExprs().drop_front();
487   }
488   llvm::ArrayRef<Expr *> getQueueIdExprs() const {
489     return OpenACCClauseWithExprs::getExprs().drop_front();
490   }
491 };
492 
493 class OpenACCNumGangsClause final
494     : public OpenACCClauseWithExprs,
495       private llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {
496   friend TrailingObjects;
497 
498   OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
499                         ArrayRef<Expr *> IntExprs, SourceLocation EndLoc)
500       : OpenACCClauseWithExprs(OpenACCClauseKind::NumGangs, BeginLoc, LParenLoc,
501                                EndLoc) {
502     std::uninitialized_copy(IntExprs.begin(), IntExprs.end(),
503                             getTrailingObjects<Expr *>());
504     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));
505   }
506 
507 public:
508   static bool classof(const OpenACCClause *C) {
509     return C->getClauseKind() == OpenACCClauseKind::NumGangs;
510   }
511   static OpenACCNumGangsClause *
512   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
513          ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
514 
515   llvm::ArrayRef<Expr *> getIntExprs() {
516     return OpenACCClauseWithExprs::getExprs();
517   }
518 
519   llvm::ArrayRef<Expr *> getIntExprs() const {
520     return OpenACCClauseWithExprs::getExprs();
521   }
522 };
523 
524 class OpenACCTileClause final
525     : public OpenACCClauseWithExprs,
526       private llvm::TrailingObjects<OpenACCTileClause, Expr *> {
527   friend TrailingObjects;
528   OpenACCTileClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
529                     ArrayRef<Expr *> SizeExprs, SourceLocation EndLoc)
530       : OpenACCClauseWithExprs(OpenACCClauseKind::Tile, BeginLoc, LParenLoc,
531                                EndLoc) {
532     std::uninitialized_copy(SizeExprs.begin(), SizeExprs.end(),
533                             getTrailingObjects<Expr *>());
534     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), SizeExprs.size()));
535   }
536 
537 public:
538   static bool classof(const OpenACCClause *C) {
539     return C->getClauseKind() == OpenACCClauseKind::Tile;
540   }
541   static OpenACCTileClause *Create(const ASTContext &C, SourceLocation BeginLoc,
542                                    SourceLocation LParenLoc,
543                                    ArrayRef<Expr *> SizeExprs,
544                                    SourceLocation EndLoc);
545   llvm::ArrayRef<Expr *> getSizeExprs() {
546     return OpenACCClauseWithExprs::getExprs();
547   }
548 
549   llvm::ArrayRef<Expr *> getSizeExprs() const {
550     return OpenACCClauseWithExprs::getExprs();
551   }
552 };
553 
554 /// Represents one of a handful of clauses that have a single integer
555 /// expression.
556 class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithExprs {
557   Expr *IntExpr;
558 
559 protected:
560   OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc,
561                                  SourceLocation LParenLoc, Expr *IntExpr,
562                                  SourceLocation EndLoc)
563       : OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc),
564         IntExpr(IntExpr) {
565     if (IntExpr)
566       setExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1});
567   }
568 
569 public:
570   static bool classof(const OpenACCClause *C);
571   bool hasIntExpr() const { return !getExprs().empty(); }
572   const Expr *getIntExpr() const {
573     return hasIntExpr() ? getExprs()[0] : nullptr;
574   }
575 
576   Expr *getIntExpr() { return hasIntExpr() ? getExprs()[0] : nullptr; };
577 };
578 
579 class OpenACCGangClause final
580     : public OpenACCClauseWithExprs,
581       private llvm::TrailingObjects<OpenACCGangClause, Expr *, OpenACCGangKind> {
582   friend TrailingObjects;
583 protected:
584   OpenACCGangClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
585                     ArrayRef<OpenACCGangKind> GangKinds,
586                     ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
587 
588   OpenACCGangKind getGangKind(unsigned I) const {
589     return getTrailingObjects<OpenACCGangKind>()[I];
590   }
591 
592 public:
593   static bool classof(const OpenACCClause *C) {
594     return C->getClauseKind() == OpenACCClauseKind::Gang;
595   }
596 
597   size_t numTrailingObjects(OverloadToken<Expr *>) const {
598     return getNumExprs();
599   }
600 
601   unsigned getNumExprs() const { return getExprs().size(); }
602   std::pair<OpenACCGangKind, const Expr *> getExpr(unsigned I) const {
603     return {getGangKind(I), getExprs()[I]};
604   }
605 
606   bool hasExprOfKind(OpenACCGangKind GK) const {
607     for (unsigned I = 0; I < getNumExprs(); ++I) {
608       if (getGangKind(I) == GK)
609         return true;
610     }
611     return false;
612   }
613 
614   static OpenACCGangClause *
615   Create(const ASTContext &Ctx, SourceLocation BeginLoc,
616          SourceLocation LParenLoc, ArrayRef<OpenACCGangKind> GangKinds,
617          ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
618 };
619 
620 class OpenACCWorkerClause : public OpenACCClauseWithSingleIntExpr {
621 protected:
622   OpenACCWorkerClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
623                       Expr *IntExpr, SourceLocation EndLoc);
624 
625 public:
626   static bool classof(const OpenACCClause *C) {
627     return C->getClauseKind() == OpenACCClauseKind::Worker;
628   }
629 
630   static OpenACCWorkerClause *Create(const ASTContext &Ctx,
631                                      SourceLocation BeginLoc,
632                                      SourceLocation LParenLoc, Expr *IntExpr,
633                                      SourceLocation EndLoc);
634 };
635 
636 class OpenACCVectorClause : public OpenACCClauseWithSingleIntExpr {
637 protected:
638   OpenACCVectorClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
639                       Expr *IntExpr, SourceLocation EndLoc);
640 
641 public:
642   static bool classof(const OpenACCClause *C) {
643     return C->getClauseKind() == OpenACCClauseKind::Vector;
644   }
645 
646   static OpenACCVectorClause *Create(const ASTContext &Ctx,
647                                      SourceLocation BeginLoc,
648                                      SourceLocation LParenLoc, Expr *IntExpr,
649                                      SourceLocation EndLoc);
650 };
651 
652 class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
653   OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
654                           Expr *IntExpr, SourceLocation EndLoc);
655 
656 public:
657   static bool classof(const OpenACCClause *C) {
658     return C->getClauseKind() == OpenACCClauseKind::NumWorkers;
659   }
660   static OpenACCNumWorkersClause *Create(const ASTContext &C,
661                                          SourceLocation BeginLoc,
662                                          SourceLocation LParenLoc,
663                                          Expr *IntExpr, SourceLocation EndLoc);
664 };
665 
666 class OpenACCVectorLengthClause : public OpenACCClauseWithSingleIntExpr {
667   OpenACCVectorLengthClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
668                             Expr *IntExpr, SourceLocation EndLoc);
669 
670 public:
671   static bool classof(const OpenACCClause *C) {
672     return C->getClauseKind() == OpenACCClauseKind::VectorLength;
673   }
674   static OpenACCVectorLengthClause *
675   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
676          Expr *IntExpr, SourceLocation EndLoc);
677 };
678 
679 class OpenACCAsyncClause : public OpenACCClauseWithSingleIntExpr {
680   OpenACCAsyncClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
681                      Expr *IntExpr, SourceLocation EndLoc);
682 
683 public:
684   static bool classof(const OpenACCClause *C) {
685     return C->getClauseKind() == OpenACCClauseKind::Async;
686   }
687   static OpenACCAsyncClause *Create(const ASTContext &C,
688                                     SourceLocation BeginLoc,
689                                     SourceLocation LParenLoc, Expr *IntExpr,
690                                     SourceLocation EndLoc);
691 };
692 
693 class OpenACCDeviceNumClause : public OpenACCClauseWithSingleIntExpr {
694   OpenACCDeviceNumClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
695                      Expr *IntExpr, SourceLocation EndLoc);
696 
697 public:
698   static bool classof(const OpenACCClause *C) {
699     return C->getClauseKind() == OpenACCClauseKind::DeviceNum;
700   }
701   static OpenACCDeviceNumClause *Create(const ASTContext &C,
702                                         SourceLocation BeginLoc,
703                                         SourceLocation LParenLoc, Expr *IntExpr,
704                                         SourceLocation EndLoc);
705 };
706 
707 class OpenACCDefaultAsyncClause : public OpenACCClauseWithSingleIntExpr {
708   OpenACCDefaultAsyncClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
709                             Expr *IntExpr, SourceLocation EndLoc);
710 
711 public:
712   static bool classof(const OpenACCClause *C) {
713     return C->getClauseKind() == OpenACCClauseKind::DefaultAsync;
714   }
715   static OpenACCDefaultAsyncClause *
716   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
717          Expr *IntExpr, SourceLocation EndLoc);
718 };
719 
720 /// Represents a 'collapse' clause on a 'loop' construct. This clause takes an
721 /// integer constant expression 'N' that represents how deep to collapse the
722 /// construct. It also takes an optional 'force' tag that permits intervening
723 /// code in the loops.
724 class OpenACCCollapseClause : public OpenACCClauseWithSingleIntExpr {
725   bool HasForce = false;
726 
727   OpenACCCollapseClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
728                         bool HasForce, Expr *LoopCount, SourceLocation EndLoc);
729 
730 public:
731   const Expr *getLoopCount() const { return getIntExpr(); }
732   Expr *getLoopCount() { return getIntExpr(); }
733 
734   bool hasForce() const { return HasForce; }
735 
736   static bool classof(const OpenACCClause *C) {
737     return C->getClauseKind() == OpenACCClauseKind::Collapse;
738   }
739 
740   static OpenACCCollapseClause *Create(const ASTContext &C,
741                                        SourceLocation BeginLoc,
742                                        SourceLocation LParenLoc, bool HasForce,
743                                        Expr *LoopCount, SourceLocation EndLoc);
744 };
745 
746 /// Represents a clause with one or more 'var' objects, represented as an expr,
747 /// as its arguments. Var-list is expected to be stored in trailing storage.
748 /// For now, we're just storing the original expression in its entirety, unlike
749 /// OMP which has to do a bunch of work to create a private.
750 class OpenACCClauseWithVarList : public OpenACCClauseWithExprs {
751 protected:
752   OpenACCClauseWithVarList(OpenACCClauseKind K, SourceLocation BeginLoc,
753                            SourceLocation LParenLoc, SourceLocation EndLoc)
754       : OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc) {}
755 
756 public:
757   static bool classof(const OpenACCClause *C);
758   ArrayRef<Expr *> getVarList() { return getExprs(); }
759   ArrayRef<Expr *> getVarList() const { return getExprs(); }
760 };
761 
762 class OpenACCPrivateClause final
763     : public OpenACCClauseWithVarList,
764       private llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {
765   friend TrailingObjects;
766 
767   OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
768                        ArrayRef<Expr *> VarList, SourceLocation EndLoc)
769       : OpenACCClauseWithVarList(OpenACCClauseKind::Private, BeginLoc,
770                                  LParenLoc, EndLoc) {
771     std::uninitialized_copy(VarList.begin(), VarList.end(),
772                             getTrailingObjects<Expr *>());
773     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
774   }
775 
776 public:
777   static bool classof(const OpenACCClause *C) {
778     return C->getClauseKind() == OpenACCClauseKind::Private;
779   }
780   static OpenACCPrivateClause *
781   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
782          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
783 };
784 
785 class OpenACCFirstPrivateClause final
786     : public OpenACCClauseWithVarList,
787       private llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *> {
788   friend TrailingObjects;
789 
790   OpenACCFirstPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
791                             ArrayRef<Expr *> VarList, SourceLocation EndLoc)
792       : OpenACCClauseWithVarList(OpenACCClauseKind::FirstPrivate, BeginLoc,
793                                  LParenLoc, EndLoc) {
794     std::uninitialized_copy(VarList.begin(), VarList.end(),
795                             getTrailingObjects<Expr *>());
796     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
797   }
798 
799 public:
800   static bool classof(const OpenACCClause *C) {
801     return C->getClauseKind() == OpenACCClauseKind::FirstPrivate;
802   }
803   static OpenACCFirstPrivateClause *
804   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
805          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
806 };
807 
808 class OpenACCDevicePtrClause final
809     : public OpenACCClauseWithVarList,
810       private llvm::TrailingObjects<OpenACCDevicePtrClause, Expr *> {
811   friend TrailingObjects;
812 
813   OpenACCDevicePtrClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
814                          ArrayRef<Expr *> VarList, SourceLocation EndLoc)
815       : OpenACCClauseWithVarList(OpenACCClauseKind::DevicePtr, BeginLoc,
816                                  LParenLoc, EndLoc) {
817     std::uninitialized_copy(VarList.begin(), VarList.end(),
818                             getTrailingObjects<Expr *>());
819     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
820   }
821 
822 public:
823   static bool classof(const OpenACCClause *C) {
824     return C->getClauseKind() == OpenACCClauseKind::DevicePtr;
825   }
826   static OpenACCDevicePtrClause *
827   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
828          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
829 };
830 
831 class OpenACCAttachClause final
832     : public OpenACCClauseWithVarList,
833       private llvm::TrailingObjects<OpenACCAttachClause, Expr *> {
834   friend TrailingObjects;
835 
836   OpenACCAttachClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
837                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
838       : OpenACCClauseWithVarList(OpenACCClauseKind::Attach, BeginLoc, LParenLoc,
839                                  EndLoc) {
840     std::uninitialized_copy(VarList.begin(), VarList.end(),
841                             getTrailingObjects<Expr *>());
842     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
843   }
844 
845 public:
846   static bool classof(const OpenACCClause *C) {
847     return C->getClauseKind() == OpenACCClauseKind::Attach;
848   }
849   static OpenACCAttachClause *
850   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
851          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
852 };
853 
854 class OpenACCDetachClause final
855     : public OpenACCClauseWithVarList,
856       private llvm::TrailingObjects<OpenACCDetachClause, Expr *> {
857   friend TrailingObjects;
858 
859   OpenACCDetachClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
860                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
861       : OpenACCClauseWithVarList(OpenACCClauseKind::Detach, BeginLoc, LParenLoc,
862                                  EndLoc) {
863     std::uninitialized_copy(VarList.begin(), VarList.end(),
864                             getTrailingObjects<Expr *>());
865     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
866   }
867 
868 public:
869   static bool classof(const OpenACCClause *C) {
870     return C->getClauseKind() == OpenACCClauseKind::Detach;
871   }
872   static OpenACCDetachClause *
873   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
874          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
875 };
876 
877 class OpenACCDeleteClause final
878     : public OpenACCClauseWithVarList,
879       private llvm::TrailingObjects<OpenACCDeleteClause, Expr *> {
880   friend TrailingObjects;
881 
882   OpenACCDeleteClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
883                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
884       : OpenACCClauseWithVarList(OpenACCClauseKind::Delete, BeginLoc, LParenLoc,
885                                  EndLoc) {
886     std::uninitialized_copy(VarList.begin(), VarList.end(),
887                             getTrailingObjects<Expr *>());
888     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
889   }
890 
891 public:
892   static bool classof(const OpenACCClause *C) {
893     return C->getClauseKind() == OpenACCClauseKind::Delete;
894   }
895   static OpenACCDeleteClause *
896   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
897          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
898 };
899 
900 class OpenACCUseDeviceClause final
901     : public OpenACCClauseWithVarList,
902       private llvm::TrailingObjects<OpenACCUseDeviceClause, Expr *> {
903   friend TrailingObjects;
904 
905   OpenACCUseDeviceClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
906                          ArrayRef<Expr *> VarList, SourceLocation EndLoc)
907       : OpenACCClauseWithVarList(OpenACCClauseKind::UseDevice, BeginLoc,
908                                  LParenLoc, EndLoc) {
909     std::uninitialized_copy(VarList.begin(), VarList.end(),
910                             getTrailingObjects<Expr *>());
911     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
912   }
913 
914 public:
915   static bool classof(const OpenACCClause *C) {
916     return C->getClauseKind() == OpenACCClauseKind::UseDevice;
917   }
918   static OpenACCUseDeviceClause *
919   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
920          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
921 };
922 
923 class OpenACCNoCreateClause final
924     : public OpenACCClauseWithVarList,
925       private llvm::TrailingObjects<OpenACCNoCreateClause, Expr *> {
926   friend TrailingObjects;
927 
928   OpenACCNoCreateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
929                         ArrayRef<Expr *> VarList, SourceLocation EndLoc)
930       : OpenACCClauseWithVarList(OpenACCClauseKind::NoCreate, BeginLoc,
931                                  LParenLoc, EndLoc) {
932     std::uninitialized_copy(VarList.begin(), VarList.end(),
933                             getTrailingObjects<Expr *>());
934     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
935   }
936 
937 public:
938   static bool classof(const OpenACCClause *C) {
939     return C->getClauseKind() == OpenACCClauseKind::NoCreate;
940   }
941   static OpenACCNoCreateClause *
942   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
943          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
944 };
945 
946 class OpenACCPresentClause final
947     : public OpenACCClauseWithVarList,
948       private llvm::TrailingObjects<OpenACCPresentClause, Expr *> {
949   friend TrailingObjects;
950 
951   OpenACCPresentClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
952                        ArrayRef<Expr *> VarList, SourceLocation EndLoc)
953       : OpenACCClauseWithVarList(OpenACCClauseKind::Present, BeginLoc,
954                                  LParenLoc, EndLoc) {
955     std::uninitialized_copy(VarList.begin(), VarList.end(),
956                             getTrailingObjects<Expr *>());
957     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
958   }
959 
960 public:
961   static bool classof(const OpenACCClause *C) {
962     return C->getClauseKind() == OpenACCClauseKind::Present;
963   }
964   static OpenACCPresentClause *
965   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
966          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
967 };
968 class OpenACCHostClause final
969     : public OpenACCClauseWithVarList,
970       private llvm::TrailingObjects<OpenACCHostClause, Expr *> {
971   friend TrailingObjects;
972 
973   OpenACCHostClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
974                     ArrayRef<Expr *> VarList, SourceLocation EndLoc)
975       : OpenACCClauseWithVarList(OpenACCClauseKind::Host, BeginLoc, LParenLoc,
976                                  EndLoc) {
977     std::uninitialized_copy(VarList.begin(), VarList.end(),
978                             getTrailingObjects<Expr *>());
979     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
980   }
981 
982 public:
983   static bool classof(const OpenACCClause *C) {
984     return C->getClauseKind() == OpenACCClauseKind::Host;
985   }
986   static OpenACCHostClause *Create(const ASTContext &C, SourceLocation BeginLoc,
987                                    SourceLocation LParenLoc,
988                                    ArrayRef<Expr *> VarList,
989                                    SourceLocation EndLoc);
990 };
991 
992 class OpenACCDeviceClause final
993     : public OpenACCClauseWithVarList,
994       private llvm::TrailingObjects<OpenACCDeviceClause, Expr *> {
995   friend TrailingObjects;
996 
997   OpenACCDeviceClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
998                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
999       : OpenACCClauseWithVarList(OpenACCClauseKind::Device, BeginLoc, LParenLoc,
1000                                  EndLoc) {
1001     std::uninitialized_copy(VarList.begin(), VarList.end(),
1002                             getTrailingObjects<Expr *>());
1003     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1004   }
1005 
1006 public:
1007   static bool classof(const OpenACCClause *C) {
1008     return C->getClauseKind() == OpenACCClauseKind::Device;
1009   }
1010   static OpenACCDeviceClause *
1011   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
1012          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
1013 };
1014 
1015 class OpenACCCopyClause final
1016     : public OpenACCClauseWithVarList,
1017       private llvm::TrailingObjects<OpenACCCopyClause, Expr *> {
1018   friend TrailingObjects;
1019 
1020   OpenACCCopyClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
1021                     SourceLocation LParenLoc, ArrayRef<Expr *> VarList,
1022                     SourceLocation EndLoc)
1023       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc) {
1024     assert((Spelling == OpenACCClauseKind::Copy ||
1025             Spelling == OpenACCClauseKind::PCopy ||
1026             Spelling == OpenACCClauseKind::PresentOrCopy) &&
1027            "Invalid clause kind for copy-clause");
1028     std::uninitialized_copy(VarList.begin(), VarList.end(),
1029                             getTrailingObjects<Expr *>());
1030     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1031   }
1032 
1033 public:
1034   static bool classof(const OpenACCClause *C) {
1035     return C->getClauseKind() == OpenACCClauseKind::Copy ||
1036            C->getClauseKind() == OpenACCClauseKind::PCopy ||
1037            C->getClauseKind() == OpenACCClauseKind::PresentOrCopy;
1038   }
1039   static OpenACCCopyClause *
1040   Create(const ASTContext &C, OpenACCClauseKind Spelling,
1041          SourceLocation BeginLoc, SourceLocation LParenLoc,
1042          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
1043 };
1044 
1045 class OpenACCCopyInClause final
1046     : public OpenACCClauseWithVarList,
1047       private llvm::TrailingObjects<OpenACCCopyInClause, Expr *> {
1048   friend TrailingObjects;
1049   bool IsReadOnly;
1050 
1051   OpenACCCopyInClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
1052                       SourceLocation LParenLoc, bool IsReadOnly,
1053                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
1054       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
1055         IsReadOnly(IsReadOnly) {
1056     assert((Spelling == OpenACCClauseKind::CopyIn ||
1057             Spelling == OpenACCClauseKind::PCopyIn ||
1058             Spelling == OpenACCClauseKind::PresentOrCopyIn) &&
1059            "Invalid clause kind for copyin-clause");
1060     std::uninitialized_copy(VarList.begin(), VarList.end(),
1061                             getTrailingObjects<Expr *>());
1062     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1063   }
1064 
1065 public:
1066   static bool classof(const OpenACCClause *C) {
1067     return C->getClauseKind() == OpenACCClauseKind::CopyIn ||
1068            C->getClauseKind() == OpenACCClauseKind::PCopyIn ||
1069            C->getClauseKind() == OpenACCClauseKind::PresentOrCopyIn;
1070   }
1071   bool isReadOnly() const { return IsReadOnly; }
1072   static OpenACCCopyInClause *
1073   Create(const ASTContext &C, OpenACCClauseKind Spelling,
1074          SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsReadOnly,
1075          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
1076 };
1077 
1078 class OpenACCCopyOutClause final
1079     : public OpenACCClauseWithVarList,
1080       private llvm::TrailingObjects<OpenACCCopyOutClause, Expr *> {
1081   friend TrailingObjects;
1082   bool IsZero;
1083 
1084   OpenACCCopyOutClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
1085                        SourceLocation LParenLoc, bool IsZero,
1086                        ArrayRef<Expr *> VarList, SourceLocation EndLoc)
1087       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
1088         IsZero(IsZero) {
1089     assert((Spelling == OpenACCClauseKind::CopyOut ||
1090             Spelling == OpenACCClauseKind::PCopyOut ||
1091             Spelling == OpenACCClauseKind::PresentOrCopyOut) &&
1092            "Invalid clause kind for copyout-clause");
1093     std::uninitialized_copy(VarList.begin(), VarList.end(),
1094                             getTrailingObjects<Expr *>());
1095     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1096   }
1097 
1098 public:
1099   static bool classof(const OpenACCClause *C) {
1100     return C->getClauseKind() == OpenACCClauseKind::CopyOut ||
1101            C->getClauseKind() == OpenACCClauseKind::PCopyOut ||
1102            C->getClauseKind() == OpenACCClauseKind::PresentOrCopyOut;
1103   }
1104   bool isZero() const { return IsZero; }
1105   static OpenACCCopyOutClause *
1106   Create(const ASTContext &C, OpenACCClauseKind Spelling,
1107          SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsZero,
1108          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
1109 };
1110 
1111 class OpenACCCreateClause final
1112     : public OpenACCClauseWithVarList,
1113       private llvm::TrailingObjects<OpenACCCreateClause, Expr *> {
1114   friend TrailingObjects;
1115   bool IsZero;
1116 
1117   OpenACCCreateClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
1118                       SourceLocation LParenLoc, bool IsZero,
1119                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
1120       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
1121         IsZero(IsZero) {
1122     assert((Spelling == OpenACCClauseKind::Create ||
1123             Spelling == OpenACCClauseKind::PCreate ||
1124             Spelling == OpenACCClauseKind::PresentOrCreate) &&
1125            "Invalid clause kind for create-clause");
1126     std::uninitialized_copy(VarList.begin(), VarList.end(),
1127                             getTrailingObjects<Expr *>());
1128     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1129   }
1130 
1131 public:
1132   static bool classof(const OpenACCClause *C) {
1133     return C->getClauseKind() == OpenACCClauseKind::Create ||
1134            C->getClauseKind() == OpenACCClauseKind::PCreate ||
1135            C->getClauseKind() == OpenACCClauseKind::PresentOrCreate;
1136   }
1137   bool isZero() const { return IsZero; }
1138   static OpenACCCreateClause *
1139   Create(const ASTContext &C, OpenACCClauseKind Spelling,
1140          SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsZero,
1141          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
1142 };
1143 
1144 class OpenACCReductionClause final
1145     : public OpenACCClauseWithVarList,
1146       private llvm::TrailingObjects<OpenACCReductionClause, Expr *> {
1147   friend TrailingObjects;
1148   OpenACCReductionOperator Op;
1149 
1150   OpenACCReductionClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
1151                          OpenACCReductionOperator Operator,
1152                          ArrayRef<Expr *> VarList, SourceLocation EndLoc)
1153       : OpenACCClauseWithVarList(OpenACCClauseKind::Reduction, BeginLoc,
1154                                  LParenLoc, EndLoc),
1155         Op(Operator) {
1156     std::uninitialized_copy(VarList.begin(), VarList.end(),
1157                             getTrailingObjects<Expr *>());
1158     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1159   }
1160 
1161 public:
1162   static bool classof(const OpenACCClause *C) {
1163     return C->getClauseKind() == OpenACCClauseKind::Reduction;
1164   }
1165 
1166   static OpenACCReductionClause *
1167   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
1168          OpenACCReductionOperator Operator, ArrayRef<Expr *> VarList,
1169          SourceLocation EndLoc);
1170 
1171   OpenACCReductionOperator getReductionOp() const { return Op; }
1172 };
1173 
1174 template <class Impl> class OpenACCClauseVisitor {
1175   Impl &getDerived() { return static_cast<Impl &>(*this); }
1176 
1177 public:
1178   void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
1179     for (const OpenACCClause *Clause : List)
1180       Visit(Clause);
1181   }
1182 
1183   void Visit(const OpenACCClause *C) {
1184     if (!C)
1185       return;
1186 
1187     switch (C->getClauseKind()) {
1188 #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
1189   case OpenACCClauseKind::CLAUSE_NAME:                                         \
1190     Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C));        \
1191     return;
1192 #define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME, DEPRECATED)                      \
1193   case OpenACCClauseKind::ALIAS_NAME:                                          \
1194     Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C));        \
1195     return;
1196 #include "clang/Basic/OpenACCClauses.def"
1197 
1198     default:
1199       llvm_unreachable("Clause visitor not yet implemented");
1200     }
1201     llvm_unreachable("Invalid Clause kind");
1202   }
1203 
1204 #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
1205   void Visit##CLAUSE_NAME##Clause(                                             \
1206       const OpenACC##CLAUSE_NAME##Clause &Clause) {                            \
1207     return getDerived().Visit##CLAUSE_NAME##Clause(Clause);                    \
1208   }
1209 
1210 #include "clang/Basic/OpenACCClauses.def"
1211 };
1212 
1213 class OpenACCClausePrinter final
1214     : public OpenACCClauseVisitor<OpenACCClausePrinter> {
1215   raw_ostream &OS;
1216   const PrintingPolicy &Policy;
1217 
1218   void printExpr(const Expr *E);
1219 
1220 public:
1221   void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
1222     for (const OpenACCClause *Clause : List) {
1223       Visit(Clause);
1224 
1225       if (Clause != List.back())
1226         OS << ' ';
1227     }
1228   }
1229   OpenACCClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
1230       : OS(OS), Policy(Policy) {}
1231 
1232 #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
1233   void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause);
1234 #include "clang/Basic/OpenACCClauses.def"
1235 };
1236 
1237 } // namespace clang
1238 
1239 #endif // LLVM_CLANG_AST_OPENACCCLAUSE_H
1240