xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/OpenACCClause.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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:
OpenACCClause(OpenACCClauseKind K,SourceLocation BeginLoc,SourceLocation EndLoc)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:
getClauseKind()37   OpenACCClauseKind getClauseKind() const { return Kind; }
getBeginLoc()38   SourceLocation getBeginLoc() const { return Location.getBegin(); }
getEndLoc()39   SourceLocation getEndLoc() const { return Location.getEnd(); }
40 
classof(const OpenACCClause *)41   static bool classof(const OpenACCClause *) { return false; }
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();
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:
OpenACCAutoClause(SourceLocation BeginLoc,SourceLocation EndLoc)60   OpenACCAutoClause(SourceLocation BeginLoc, SourceLocation EndLoc)
61       : OpenACCClause(OpenACCClauseKind::Auto, BeginLoc, EndLoc) {}
62 
63 public:
classof(const OpenACCClause * C)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 
children()71   child_range children() {
72     return child_range(child_iterator(), child_iterator());
73   }
children()74   const_child_range children() const {
75     return const_child_range(const_child_iterator(), const_child_iterator());
76   }
77 };
78 
79 // Represents the 'independent' clause.
80 class OpenACCIndependentClause : public OpenACCClause {
81 protected:
OpenACCIndependentClause(SourceLocation BeginLoc,SourceLocation EndLoc)82   OpenACCIndependentClause(SourceLocation BeginLoc, SourceLocation EndLoc)
83       : OpenACCClause(OpenACCClauseKind::Independent, BeginLoc, EndLoc) {}
84 
85 public:
classof(const OpenACCClause * C)86   static bool classof(const OpenACCClause *C) {
87     return C->getClauseKind() == OpenACCClauseKind::Independent;
88   }
89 
90   static OpenACCIndependentClause *
91   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
92 
children()93   child_range children() {
94     return child_range(child_iterator(), child_iterator());
95   }
children()96   const_child_range children() const {
97     return const_child_range(const_child_iterator(), const_child_iterator());
98   }
99 };
100 // Represents the 'seq' clause.
101 class OpenACCSeqClause : public OpenACCClause {
102 protected:
OpenACCSeqClause(SourceLocation BeginLoc,SourceLocation EndLoc)103   OpenACCSeqClause(SourceLocation BeginLoc, SourceLocation EndLoc)
104       : OpenACCClause(OpenACCClauseKind::Seq, BeginLoc, EndLoc) {}
105 
106 public:
classof(const OpenACCClause * C)107   static bool classof(const OpenACCClause *C) {
108     return C->getClauseKind() == OpenACCClauseKind::Seq;
109   }
110 
111   static OpenACCSeqClause *
112   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
113 
children()114   child_range children() {
115     return child_range(child_iterator(), child_iterator());
116   }
children()117   const_child_range children() const {
118     return const_child_range(const_child_iterator(), const_child_iterator());
119   }
120 };
121 
122 // Not yet implemented, but the type name is necessary for 'seq' diagnostics, so
123 // this provides a basic, do-nothing implementation. We still need to add this
124 // type to the visitors/etc, as well as get it to take its proper arguments.
125 class OpenACCGangClause : public OpenACCClause {
126 protected:
OpenACCGangClause(SourceLocation BeginLoc,SourceLocation EndLoc)127   OpenACCGangClause(SourceLocation BeginLoc, SourceLocation EndLoc)
128       : OpenACCClause(OpenACCClauseKind::Gang, BeginLoc, EndLoc) {
129     llvm_unreachable("Not yet implemented");
130   }
131 
132 public:
classof(const OpenACCClause * C)133   static bool classof(const OpenACCClause *C) {
134     return C->getClauseKind() == OpenACCClauseKind::Gang;
135   }
136 
137   static OpenACCGangClause *
138   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
139 
children()140   child_range children() {
141     return child_range(child_iterator(), child_iterator());
142   }
children()143   const_child_range children() const {
144     return const_child_range(const_child_iterator(), const_child_iterator());
145   }
146 };
147 
148 // Not yet implemented, but the type name is necessary for 'seq' diagnostics, so
149 // this provides a basic, do-nothing implementation. We still need to add this
150 // type to the visitors/etc, as well as get it to take its proper arguments.
151 class OpenACCVectorClause : public OpenACCClause {
152 protected:
OpenACCVectorClause(SourceLocation BeginLoc,SourceLocation EndLoc)153   OpenACCVectorClause(SourceLocation BeginLoc, SourceLocation EndLoc)
154       : OpenACCClause(OpenACCClauseKind::Vector, BeginLoc, EndLoc) {
155     llvm_unreachable("Not yet implemented");
156   }
157 
158 public:
classof(const OpenACCClause * C)159   static bool classof(const OpenACCClause *C) {
160     return C->getClauseKind() == OpenACCClauseKind::Gang;
161   }
162 
163   static OpenACCVectorClause *
164   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
165 
children()166   child_range children() {
167     return child_range(child_iterator(), child_iterator());
168   }
children()169   const_child_range children() const {
170     return const_child_range(const_child_iterator(), const_child_iterator());
171   }
172 };
173 
174 // Not yet implemented, but the type name is necessary for 'seq' diagnostics, so
175 // this provides a basic, do-nothing implementation. We still need to add this
176 // type to the visitors/etc, as well as get it to take its proper arguments.
177 class OpenACCWorkerClause : public OpenACCClause {
178 protected:
OpenACCWorkerClause(SourceLocation BeginLoc,SourceLocation EndLoc)179   OpenACCWorkerClause(SourceLocation BeginLoc, SourceLocation EndLoc)
180       : OpenACCClause(OpenACCClauseKind::Gang, BeginLoc, EndLoc) {
181     llvm_unreachable("Not yet implemented");
182   }
183 
184 public:
classof(const OpenACCClause * C)185   static bool classof(const OpenACCClause *C) {
186     return C->getClauseKind() == OpenACCClauseKind::Gang;
187   }
188 
189   static OpenACCWorkerClause *
190   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
191 
children()192   child_range children() {
193     return child_range(child_iterator(), child_iterator());
194   }
children()195   const_child_range children() const {
196     return const_child_range(const_child_iterator(), const_child_iterator());
197   }
198 };
199 
200 /// Represents a clause that has a list of parameters.
201 class OpenACCClauseWithParams : public OpenACCClause {
202   /// Location of the '('.
203   SourceLocation LParenLoc;
204 
205 protected:
OpenACCClauseWithParams(OpenACCClauseKind K,SourceLocation BeginLoc,SourceLocation LParenLoc,SourceLocation EndLoc)206   OpenACCClauseWithParams(OpenACCClauseKind K, SourceLocation BeginLoc,
207                           SourceLocation LParenLoc, SourceLocation EndLoc)
208       : OpenACCClause(K, BeginLoc, EndLoc), LParenLoc(LParenLoc) {}
209 
210 public:
211   static bool classof(const OpenACCClause *C);
212 
getLParenLoc()213   SourceLocation getLParenLoc() const { return LParenLoc; }
214 
children()215   child_range children() {
216     return child_range(child_iterator(), child_iterator());
217   }
children()218   const_child_range children() const {
219     return const_child_range(const_child_iterator(), const_child_iterator());
220   }
221 };
222 
223 using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
224 /// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or
225 /// an identifier. The 'asterisk' means 'the rest'.
226 class OpenACCDeviceTypeClause final
227     : public OpenACCClauseWithParams,
228       public llvm::TrailingObjects<OpenACCDeviceTypeClause,
229                                    DeviceTypeArgument> {
230   // Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A
231   // nullptr IdentifierInfo* represents an asterisk.
232   unsigned NumArchs;
OpenACCDeviceTypeClause(OpenACCClauseKind K,SourceLocation BeginLoc,SourceLocation LParenLoc,ArrayRef<DeviceTypeArgument> Archs,SourceLocation EndLoc)233   OpenACCDeviceTypeClause(OpenACCClauseKind K, SourceLocation BeginLoc,
234                           SourceLocation LParenLoc,
235                           ArrayRef<DeviceTypeArgument> Archs,
236                           SourceLocation EndLoc)
237       : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
238         NumArchs(Archs.size()) {
239     assert(
240         (K == OpenACCClauseKind::DeviceType || K == OpenACCClauseKind::DType) &&
241         "Invalid clause kind for device-type");
242 
243     assert(!llvm::any_of(Archs, [](const DeviceTypeArgument &Arg) {
244       return Arg.second.isInvalid();
245     }) && "Invalid SourceLocation for an argument");
246 
247     assert(
248         (Archs.size() == 1 || !llvm::any_of(Archs,
249                                             [](const DeviceTypeArgument &Arg) {
250                                               return Arg.first == nullptr;
251                                             })) &&
252         "Only a single asterisk version is permitted, and must be the "
253         "only one");
254 
255     std::uninitialized_copy(Archs.begin(), Archs.end(),
256                             getTrailingObjects<DeviceTypeArgument>());
257   }
258 
259 public:
classof(const OpenACCClause * C)260   static bool classof(const OpenACCClause *C) {
261     return C->getClauseKind() == OpenACCClauseKind::DType ||
262            C->getClauseKind() == OpenACCClauseKind::DeviceType;
263   }
hasAsterisk()264   bool hasAsterisk() const {
265     return getArchitectures().size() > 0 &&
266            getArchitectures()[0].first == nullptr;
267   }
268 
getArchitectures()269   ArrayRef<DeviceTypeArgument> getArchitectures() const {
270     return ArrayRef<DeviceTypeArgument>(
271         getTrailingObjects<DeviceTypeArgument>(), NumArchs);
272   }
273 
274   static OpenACCDeviceTypeClause *
275   Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc,
276          SourceLocation LParenLoc, ArrayRef<DeviceTypeArgument> Archs,
277          SourceLocation EndLoc);
278 };
279 
280 /// A 'default' clause, has the optional 'none' or 'present' argument.
281 class OpenACCDefaultClause : public OpenACCClauseWithParams {
282   friend class ASTReaderStmt;
283   friend class ASTWriterStmt;
284 
285   OpenACCDefaultClauseKind DefaultClauseKind;
286 
287 protected:
OpenACCDefaultClause(OpenACCDefaultClauseKind K,SourceLocation BeginLoc,SourceLocation LParenLoc,SourceLocation EndLoc)288   OpenACCDefaultClause(OpenACCDefaultClauseKind K, SourceLocation BeginLoc,
289                        SourceLocation LParenLoc, SourceLocation EndLoc)
290       : OpenACCClauseWithParams(OpenACCClauseKind::Default, BeginLoc, LParenLoc,
291                                 EndLoc),
292         DefaultClauseKind(K) {
293     assert((DefaultClauseKind == OpenACCDefaultClauseKind::None ||
294             DefaultClauseKind == OpenACCDefaultClauseKind::Present) &&
295            "Invalid Clause Kind");
296   }
297 
298 public:
classof(const OpenACCClause * C)299   static bool classof(const OpenACCClause *C) {
300     return C->getClauseKind() == OpenACCClauseKind::Default;
301   }
getDefaultClauseKind()302   OpenACCDefaultClauseKind getDefaultClauseKind() const {
303     return DefaultClauseKind;
304   }
305 
306   static OpenACCDefaultClause *Create(const ASTContext &C,
307                                       OpenACCDefaultClauseKind K,
308                                       SourceLocation BeginLoc,
309                                       SourceLocation LParenLoc,
310                                       SourceLocation EndLoc);
311 };
312 
313 /// Represents one of the handful of classes that has an optional/required
314 /// 'condition' expression as an argument.
315 class OpenACCClauseWithCondition : public OpenACCClauseWithParams {
316   Expr *ConditionExpr = nullptr;
317 
318 protected:
OpenACCClauseWithCondition(OpenACCClauseKind K,SourceLocation BeginLoc,SourceLocation LParenLoc,Expr * ConditionExpr,SourceLocation EndLoc)319   OpenACCClauseWithCondition(OpenACCClauseKind K, SourceLocation BeginLoc,
320                              SourceLocation LParenLoc, Expr *ConditionExpr,
321                              SourceLocation EndLoc)
322       : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
323         ConditionExpr(ConditionExpr) {}
324 
325 public:
326   static bool classof(const OpenACCClause *C);
327 
hasConditionExpr()328   bool hasConditionExpr() const { return ConditionExpr; }
getConditionExpr()329   const Expr *getConditionExpr() const { return ConditionExpr; }
getConditionExpr()330   Expr *getConditionExpr() { return ConditionExpr; }
331 
children()332   child_range children() {
333     if (ConditionExpr)
334       return child_range(reinterpret_cast<Stmt **>(&ConditionExpr),
335                          reinterpret_cast<Stmt **>(&ConditionExpr + 1));
336     return child_range(child_iterator(), child_iterator());
337   }
338 
children()339   const_child_range children() const {
340     if (ConditionExpr)
341       return const_child_range(
342           reinterpret_cast<Stmt *const *>(&ConditionExpr),
343           reinterpret_cast<Stmt *const *>(&ConditionExpr + 1));
344     return const_child_range(const_child_iterator(), const_child_iterator());
345   }
346 };
347 
348 /// An 'if' clause, which has a required condition expression.
349 class OpenACCIfClause : public OpenACCClauseWithCondition {
350 protected:
351   OpenACCIfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
352                   Expr *ConditionExpr, SourceLocation EndLoc);
353 
354 public:
classof(const OpenACCClause * C)355   static bool classof(const OpenACCClause *C) {
356     return C->getClauseKind() == OpenACCClauseKind::If;
357   }
358   static OpenACCIfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
359                                  SourceLocation LParenLoc, Expr *ConditionExpr,
360                                  SourceLocation EndLoc);
361 };
362 
363 /// A 'self' clause, which has an optional condition expression.
364 class OpenACCSelfClause : public OpenACCClauseWithCondition {
365   OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
366                     Expr *ConditionExpr, SourceLocation EndLoc);
367 
368 public:
classof(const OpenACCClause * C)369   static bool classof(const OpenACCClause *C) {
370     return C->getClauseKind() == OpenACCClauseKind::Self;
371   }
372   static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
373                                    SourceLocation LParenLoc,
374                                    Expr *ConditionExpr, SourceLocation EndLoc);
375 };
376 
377 /// Represents a clause that has one or more expressions associated with it.
378 class OpenACCClauseWithExprs : public OpenACCClauseWithParams {
379   MutableArrayRef<Expr *> Exprs;
380 
381 protected:
OpenACCClauseWithExprs(OpenACCClauseKind K,SourceLocation BeginLoc,SourceLocation LParenLoc,SourceLocation EndLoc)382   OpenACCClauseWithExprs(OpenACCClauseKind K, SourceLocation BeginLoc,
383                          SourceLocation LParenLoc, SourceLocation EndLoc)
384       : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {}
385 
386   /// Used only for initialization, the leaf class can initialize this to
387   /// trailing storage.
setExprs(MutableArrayRef<Expr * > NewExprs)388   void setExprs(MutableArrayRef<Expr *> NewExprs) {
389     assert(Exprs.empty() && "Cannot change Exprs list");
390     Exprs = NewExprs;
391   }
392 
393   /// Gets the entire list of expressions, but leave it to the
394   /// individual clauses to expose this how they'd like.
getExprs()395   llvm::ArrayRef<Expr *> getExprs() const { return Exprs; }
396 
397 public:
398   static bool classof(const OpenACCClause *C);
children()399   child_range children() {
400     return child_range(reinterpret_cast<Stmt **>(Exprs.begin()),
401                        reinterpret_cast<Stmt **>(Exprs.end()));
402   }
403 
children()404   const_child_range children() const {
405     child_range Children =
406         const_cast<OpenACCClauseWithExprs *>(this)->children();
407     return const_child_range(Children.begin(), Children.end());
408   }
409 };
410 
411 // Represents the 'devnum' and expressions lists for the 'wait' clause.
412 class OpenACCWaitClause final
413     : public OpenACCClauseWithExprs,
414       public llvm::TrailingObjects<OpenACCWaitClause, Expr *> {
415   SourceLocation QueuesLoc;
OpenACCWaitClause(SourceLocation BeginLoc,SourceLocation LParenLoc,Expr * DevNumExpr,SourceLocation QueuesLoc,ArrayRef<Expr * > QueueIdExprs,SourceLocation EndLoc)416   OpenACCWaitClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
417                     Expr *DevNumExpr, SourceLocation QueuesLoc,
418                     ArrayRef<Expr *> QueueIdExprs, SourceLocation EndLoc)
419       : OpenACCClauseWithExprs(OpenACCClauseKind::Wait, BeginLoc, LParenLoc,
420                                EndLoc),
421         QueuesLoc(QueuesLoc) {
422     // The first element of the trailing storage is always the devnum expr,
423     // whether it is used or not.
424     std::uninitialized_copy(&DevNumExpr, &DevNumExpr + 1,
425                             getTrailingObjects<Expr *>());
426     std::uninitialized_copy(QueueIdExprs.begin(), QueueIdExprs.end(),
427                             getTrailingObjects<Expr *>() + 1);
428     setExprs(
429         MutableArrayRef(getTrailingObjects<Expr *>(), QueueIdExprs.size() + 1));
430   }
431 
432 public:
classof(const OpenACCClause * C)433   static bool classof(const OpenACCClause *C) {
434     return C->getClauseKind() == OpenACCClauseKind::Wait;
435   }
436   static OpenACCWaitClause *Create(const ASTContext &C, SourceLocation BeginLoc,
437                                    SourceLocation LParenLoc, Expr *DevNumExpr,
438                                    SourceLocation QueuesLoc,
439                                    ArrayRef<Expr *> QueueIdExprs,
440                                    SourceLocation EndLoc);
441 
hasQueuesTag()442   bool hasQueuesTag() const { return !QueuesLoc.isInvalid(); }
getQueuesLoc()443   SourceLocation getQueuesLoc() const { return QueuesLoc; }
hasDevNumExpr()444   bool hasDevNumExpr() const { return getExprs()[0]; }
getDevNumExpr()445   Expr *getDevNumExpr() const { return getExprs()[0]; }
getQueueIdExprs()446   llvm::ArrayRef<Expr *> getQueueIdExprs() {
447     return OpenACCClauseWithExprs::getExprs().drop_front();
448   }
getQueueIdExprs()449   llvm::ArrayRef<Expr *> getQueueIdExprs() const {
450     return OpenACCClauseWithExprs::getExprs().drop_front();
451   }
452 };
453 
454 class OpenACCNumGangsClause final
455     : public OpenACCClauseWithExprs,
456       public llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {
457 
OpenACCNumGangsClause(SourceLocation BeginLoc,SourceLocation LParenLoc,ArrayRef<Expr * > IntExprs,SourceLocation EndLoc)458   OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
459                         ArrayRef<Expr *> IntExprs, SourceLocation EndLoc)
460       : OpenACCClauseWithExprs(OpenACCClauseKind::NumGangs, BeginLoc, LParenLoc,
461                                EndLoc) {
462     std::uninitialized_copy(IntExprs.begin(), IntExprs.end(),
463                             getTrailingObjects<Expr *>());
464     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));
465   }
466 
467 public:
classof(const OpenACCClause * C)468   static bool classof(const OpenACCClause *C) {
469     return C->getClauseKind() == OpenACCClauseKind::NumGangs;
470   }
471   static OpenACCNumGangsClause *
472   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
473          ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
474 
getIntExprs()475   llvm::ArrayRef<Expr *> getIntExprs() {
476     return OpenACCClauseWithExprs::getExprs();
477   }
478 
getIntExprs()479   llvm::ArrayRef<Expr *> getIntExprs() const {
480     return OpenACCClauseWithExprs::getExprs();
481   }
482 };
483 
484 /// Represents one of a handful of clauses that have a single integer
485 /// expression.
486 class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithExprs {
487   Expr *IntExpr;
488 
489 protected:
OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K,SourceLocation BeginLoc,SourceLocation LParenLoc,Expr * IntExpr,SourceLocation EndLoc)490   OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc,
491                                  SourceLocation LParenLoc, Expr *IntExpr,
492                                  SourceLocation EndLoc)
493       : OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc),
494         IntExpr(IntExpr) {
495     if (IntExpr)
496       setExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1});
497   }
498 
499 public:
500   static bool classof(const OpenACCClause *C);
hasIntExpr()501   bool hasIntExpr() const { return !getExprs().empty(); }
getIntExpr()502   const Expr *getIntExpr() const {
503     return hasIntExpr() ? getExprs()[0] : nullptr;
504   }
505 
getIntExpr()506   Expr *getIntExpr() { return hasIntExpr() ? getExprs()[0] : nullptr; };
507 };
508 
509 class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
510   OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
511                           Expr *IntExpr, SourceLocation EndLoc);
512 
513 public:
classof(const OpenACCClause * C)514   static bool classof(const OpenACCClause *C) {
515     return C->getClauseKind() == OpenACCClauseKind::NumWorkers;
516   }
517   static OpenACCNumWorkersClause *Create(const ASTContext &C,
518                                          SourceLocation BeginLoc,
519                                          SourceLocation LParenLoc,
520                                          Expr *IntExpr, SourceLocation EndLoc);
521 };
522 
523 class OpenACCVectorLengthClause : public OpenACCClauseWithSingleIntExpr {
524   OpenACCVectorLengthClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
525                             Expr *IntExpr, SourceLocation EndLoc);
526 
527 public:
classof(const OpenACCClause * C)528   static bool classof(const OpenACCClause *C) {
529     return C->getClauseKind() == OpenACCClauseKind::VectorLength;
530   }
531   static OpenACCVectorLengthClause *
532   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
533          Expr *IntExpr, SourceLocation EndLoc);
534 };
535 
536 class OpenACCAsyncClause : public OpenACCClauseWithSingleIntExpr {
537   OpenACCAsyncClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
538                      Expr *IntExpr, SourceLocation EndLoc);
539 
540 public:
classof(const OpenACCClause * C)541   static bool classof(const OpenACCClause *C) {
542     return C->getClauseKind() == OpenACCClauseKind::Async;
543   }
544   static OpenACCAsyncClause *Create(const ASTContext &C,
545                                     SourceLocation BeginLoc,
546                                     SourceLocation LParenLoc, Expr *IntExpr,
547                                     SourceLocation EndLoc);
548 };
549 
550 /// Represents a clause with one or more 'var' objects, represented as an expr,
551 /// as its arguments. Var-list is expected to be stored in trailing storage.
552 /// For now, we're just storing the original expression in its entirety, unlike
553 /// OMP which has to do a bunch of work to create a private.
554 class OpenACCClauseWithVarList : public OpenACCClauseWithExprs {
555 protected:
OpenACCClauseWithVarList(OpenACCClauseKind K,SourceLocation BeginLoc,SourceLocation LParenLoc,SourceLocation EndLoc)556   OpenACCClauseWithVarList(OpenACCClauseKind K, SourceLocation BeginLoc,
557                            SourceLocation LParenLoc, SourceLocation EndLoc)
558       : OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc) {}
559 
560 public:
561   static bool classof(const OpenACCClause *C);
getVarList()562   ArrayRef<Expr *> getVarList() { return getExprs(); }
getVarList()563   ArrayRef<Expr *> getVarList() const { return getExprs(); }
564 };
565 
566 class OpenACCPrivateClause final
567     : public OpenACCClauseWithVarList,
568       public llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {
569 
OpenACCPrivateClause(SourceLocation BeginLoc,SourceLocation LParenLoc,ArrayRef<Expr * > VarList,SourceLocation EndLoc)570   OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
571                        ArrayRef<Expr *> VarList, SourceLocation EndLoc)
572       : OpenACCClauseWithVarList(OpenACCClauseKind::Private, BeginLoc,
573                                  LParenLoc, EndLoc) {
574     std::uninitialized_copy(VarList.begin(), VarList.end(),
575                             getTrailingObjects<Expr *>());
576     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
577   }
578 
579 public:
classof(const OpenACCClause * C)580   static bool classof(const OpenACCClause *C) {
581     return C->getClauseKind() == OpenACCClauseKind::Private;
582   }
583   static OpenACCPrivateClause *
584   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
585          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
586 };
587 
588 class OpenACCFirstPrivateClause final
589     : public OpenACCClauseWithVarList,
590       public llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *> {
591 
OpenACCFirstPrivateClause(SourceLocation BeginLoc,SourceLocation LParenLoc,ArrayRef<Expr * > VarList,SourceLocation EndLoc)592   OpenACCFirstPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
593                             ArrayRef<Expr *> VarList, SourceLocation EndLoc)
594       : OpenACCClauseWithVarList(OpenACCClauseKind::FirstPrivate, BeginLoc,
595                                  LParenLoc, EndLoc) {
596     std::uninitialized_copy(VarList.begin(), VarList.end(),
597                             getTrailingObjects<Expr *>());
598     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
599   }
600 
601 public:
classof(const OpenACCClause * C)602   static bool classof(const OpenACCClause *C) {
603     return C->getClauseKind() == OpenACCClauseKind::FirstPrivate;
604   }
605   static OpenACCFirstPrivateClause *
606   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
607          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
608 };
609 
610 class OpenACCDevicePtrClause final
611     : public OpenACCClauseWithVarList,
612       public llvm::TrailingObjects<OpenACCDevicePtrClause, Expr *> {
613 
OpenACCDevicePtrClause(SourceLocation BeginLoc,SourceLocation LParenLoc,ArrayRef<Expr * > VarList,SourceLocation EndLoc)614   OpenACCDevicePtrClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
615                          ArrayRef<Expr *> VarList, SourceLocation EndLoc)
616       : OpenACCClauseWithVarList(OpenACCClauseKind::DevicePtr, BeginLoc,
617                                  LParenLoc, EndLoc) {
618     std::uninitialized_copy(VarList.begin(), VarList.end(),
619                             getTrailingObjects<Expr *>());
620     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
621   }
622 
623 public:
classof(const OpenACCClause * C)624   static bool classof(const OpenACCClause *C) {
625     return C->getClauseKind() == OpenACCClauseKind::DevicePtr;
626   }
627   static OpenACCDevicePtrClause *
628   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
629          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
630 };
631 
632 class OpenACCAttachClause final
633     : public OpenACCClauseWithVarList,
634       public llvm::TrailingObjects<OpenACCAttachClause, Expr *> {
635 
OpenACCAttachClause(SourceLocation BeginLoc,SourceLocation LParenLoc,ArrayRef<Expr * > VarList,SourceLocation EndLoc)636   OpenACCAttachClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
637                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
638       : OpenACCClauseWithVarList(OpenACCClauseKind::Attach, BeginLoc, LParenLoc,
639                                  EndLoc) {
640     std::uninitialized_copy(VarList.begin(), VarList.end(),
641                             getTrailingObjects<Expr *>());
642     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
643   }
644 
645 public:
classof(const OpenACCClause * C)646   static bool classof(const OpenACCClause *C) {
647     return C->getClauseKind() == OpenACCClauseKind::Attach;
648   }
649   static OpenACCAttachClause *
650   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
651          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
652 };
653 
654 class OpenACCNoCreateClause final
655     : public OpenACCClauseWithVarList,
656       public llvm::TrailingObjects<OpenACCNoCreateClause, Expr *> {
657 
OpenACCNoCreateClause(SourceLocation BeginLoc,SourceLocation LParenLoc,ArrayRef<Expr * > VarList,SourceLocation EndLoc)658   OpenACCNoCreateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
659                         ArrayRef<Expr *> VarList, SourceLocation EndLoc)
660       : OpenACCClauseWithVarList(OpenACCClauseKind::NoCreate, BeginLoc,
661                                  LParenLoc, EndLoc) {
662     std::uninitialized_copy(VarList.begin(), VarList.end(),
663                             getTrailingObjects<Expr *>());
664     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
665   }
666 
667 public:
classof(const OpenACCClause * C)668   static bool classof(const OpenACCClause *C) {
669     return C->getClauseKind() == OpenACCClauseKind::NoCreate;
670   }
671   static OpenACCNoCreateClause *
672   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
673          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
674 };
675 
676 class OpenACCPresentClause final
677     : public OpenACCClauseWithVarList,
678       public llvm::TrailingObjects<OpenACCPresentClause, Expr *> {
679 
OpenACCPresentClause(SourceLocation BeginLoc,SourceLocation LParenLoc,ArrayRef<Expr * > VarList,SourceLocation EndLoc)680   OpenACCPresentClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
681                        ArrayRef<Expr *> VarList, SourceLocation EndLoc)
682       : OpenACCClauseWithVarList(OpenACCClauseKind::Present, BeginLoc,
683                                  LParenLoc, EndLoc) {
684     std::uninitialized_copy(VarList.begin(), VarList.end(),
685                             getTrailingObjects<Expr *>());
686     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
687   }
688 
689 public:
classof(const OpenACCClause * C)690   static bool classof(const OpenACCClause *C) {
691     return C->getClauseKind() == OpenACCClauseKind::Present;
692   }
693   static OpenACCPresentClause *
694   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
695          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
696 };
697 
698 class OpenACCCopyClause final
699     : public OpenACCClauseWithVarList,
700       public llvm::TrailingObjects<OpenACCCopyClause, Expr *> {
701 
OpenACCCopyClause(OpenACCClauseKind Spelling,SourceLocation BeginLoc,SourceLocation LParenLoc,ArrayRef<Expr * > VarList,SourceLocation EndLoc)702   OpenACCCopyClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
703                     SourceLocation LParenLoc, ArrayRef<Expr *> VarList,
704                     SourceLocation EndLoc)
705       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc) {
706     assert((Spelling == OpenACCClauseKind::Copy ||
707             Spelling == OpenACCClauseKind::PCopy ||
708             Spelling == OpenACCClauseKind::PresentOrCopy) &&
709            "Invalid clause kind for copy-clause");
710     std::uninitialized_copy(VarList.begin(), VarList.end(),
711                             getTrailingObjects<Expr *>());
712     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
713   }
714 
715 public:
classof(const OpenACCClause * C)716   static bool classof(const OpenACCClause *C) {
717     return C->getClauseKind() == OpenACCClauseKind::Copy ||
718            C->getClauseKind() == OpenACCClauseKind::PCopy ||
719            C->getClauseKind() == OpenACCClauseKind::PresentOrCopy;
720   }
721   static OpenACCCopyClause *
722   Create(const ASTContext &C, OpenACCClauseKind Spelling,
723          SourceLocation BeginLoc, SourceLocation LParenLoc,
724          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
725 };
726 
727 class OpenACCCopyInClause final
728     : public OpenACCClauseWithVarList,
729       public llvm::TrailingObjects<OpenACCCopyInClause, Expr *> {
730   bool IsReadOnly;
731 
OpenACCCopyInClause(OpenACCClauseKind Spelling,SourceLocation BeginLoc,SourceLocation LParenLoc,bool IsReadOnly,ArrayRef<Expr * > VarList,SourceLocation EndLoc)732   OpenACCCopyInClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
733                       SourceLocation LParenLoc, bool IsReadOnly,
734                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
735       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
736         IsReadOnly(IsReadOnly) {
737     assert((Spelling == OpenACCClauseKind::CopyIn ||
738             Spelling == OpenACCClauseKind::PCopyIn ||
739             Spelling == OpenACCClauseKind::PresentOrCopyIn) &&
740            "Invalid clause kind for copyin-clause");
741     std::uninitialized_copy(VarList.begin(), VarList.end(),
742                             getTrailingObjects<Expr *>());
743     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
744   }
745 
746 public:
classof(const OpenACCClause * C)747   static bool classof(const OpenACCClause *C) {
748     return C->getClauseKind() == OpenACCClauseKind::CopyIn ||
749            C->getClauseKind() == OpenACCClauseKind::PCopyIn ||
750            C->getClauseKind() == OpenACCClauseKind::PresentOrCopyIn;
751   }
isReadOnly()752   bool isReadOnly() const { return IsReadOnly; }
753   static OpenACCCopyInClause *
754   Create(const ASTContext &C, OpenACCClauseKind Spelling,
755          SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsReadOnly,
756          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
757 };
758 
759 class OpenACCCopyOutClause final
760     : public OpenACCClauseWithVarList,
761       public llvm::TrailingObjects<OpenACCCopyOutClause, Expr *> {
762   bool IsZero;
763 
OpenACCCopyOutClause(OpenACCClauseKind Spelling,SourceLocation BeginLoc,SourceLocation LParenLoc,bool IsZero,ArrayRef<Expr * > VarList,SourceLocation EndLoc)764   OpenACCCopyOutClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
765                        SourceLocation LParenLoc, bool IsZero,
766                        ArrayRef<Expr *> VarList, SourceLocation EndLoc)
767       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
768         IsZero(IsZero) {
769     assert((Spelling == OpenACCClauseKind::CopyOut ||
770             Spelling == OpenACCClauseKind::PCopyOut ||
771             Spelling == OpenACCClauseKind::PresentOrCopyOut) &&
772            "Invalid clause kind for copyout-clause");
773     std::uninitialized_copy(VarList.begin(), VarList.end(),
774                             getTrailingObjects<Expr *>());
775     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
776   }
777 
778 public:
classof(const OpenACCClause * C)779   static bool classof(const OpenACCClause *C) {
780     return C->getClauseKind() == OpenACCClauseKind::CopyOut ||
781            C->getClauseKind() == OpenACCClauseKind::PCopyOut ||
782            C->getClauseKind() == OpenACCClauseKind::PresentOrCopyOut;
783   }
isZero()784   bool isZero() const { return IsZero; }
785   static OpenACCCopyOutClause *
786   Create(const ASTContext &C, OpenACCClauseKind Spelling,
787          SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsZero,
788          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
789 };
790 
791 class OpenACCCreateClause final
792     : public OpenACCClauseWithVarList,
793       public llvm::TrailingObjects<OpenACCCreateClause, Expr *> {
794   bool IsZero;
795 
OpenACCCreateClause(OpenACCClauseKind Spelling,SourceLocation BeginLoc,SourceLocation LParenLoc,bool IsZero,ArrayRef<Expr * > VarList,SourceLocation EndLoc)796   OpenACCCreateClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
797                       SourceLocation LParenLoc, bool IsZero,
798                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
799       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
800         IsZero(IsZero) {
801     assert((Spelling == OpenACCClauseKind::Create ||
802             Spelling == OpenACCClauseKind::PCreate ||
803             Spelling == OpenACCClauseKind::PresentOrCreate) &&
804            "Invalid clause kind for create-clause");
805     std::uninitialized_copy(VarList.begin(), VarList.end(),
806                             getTrailingObjects<Expr *>());
807     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
808   }
809 
810 public:
classof(const OpenACCClause * C)811   static bool classof(const OpenACCClause *C) {
812     return C->getClauseKind() == OpenACCClauseKind::Create ||
813            C->getClauseKind() == OpenACCClauseKind::PCreate ||
814            C->getClauseKind() == OpenACCClauseKind::PresentOrCreate;
815   }
isZero()816   bool isZero() const { return IsZero; }
817   static OpenACCCreateClause *
818   Create(const ASTContext &C, OpenACCClauseKind Spelling,
819          SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsZero,
820          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
821 };
822 
823 class OpenACCReductionClause final
824     : public OpenACCClauseWithVarList,
825       public llvm::TrailingObjects<OpenACCReductionClause, Expr *> {
826   OpenACCReductionOperator Op;
827 
OpenACCReductionClause(SourceLocation BeginLoc,SourceLocation LParenLoc,OpenACCReductionOperator Operator,ArrayRef<Expr * > VarList,SourceLocation EndLoc)828   OpenACCReductionClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
829                          OpenACCReductionOperator Operator,
830                          ArrayRef<Expr *> VarList, SourceLocation EndLoc)
831       : OpenACCClauseWithVarList(OpenACCClauseKind::Reduction, BeginLoc,
832                                  LParenLoc, EndLoc),
833         Op(Operator) {
834     std::uninitialized_copy(VarList.begin(), VarList.end(),
835                             getTrailingObjects<Expr *>());
836     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
837   }
838 
839 public:
classof(const OpenACCClause * C)840   static bool classof(const OpenACCClause *C) {
841     return C->getClauseKind() == OpenACCClauseKind::Reduction;
842   }
843 
844   static OpenACCReductionClause *
845   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
846          OpenACCReductionOperator Operator, ArrayRef<Expr *> VarList,
847          SourceLocation EndLoc);
848 
getReductionOp()849   OpenACCReductionOperator getReductionOp() const { return Op; }
850 };
851 
852 template <class Impl> class OpenACCClauseVisitor {
getDerived()853   Impl &getDerived() { return static_cast<Impl &>(*this); }
854 
855 public:
VisitClauseList(ArrayRef<const OpenACCClause * > List)856   void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
857     for (const OpenACCClause *Clause : List)
858       Visit(Clause);
859   }
860 
Visit(const OpenACCClause * C)861   void Visit(const OpenACCClause *C) {
862     if (!C)
863       return;
864 
865     switch (C->getClauseKind()) {
866 #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
867   case OpenACCClauseKind::CLAUSE_NAME:                                         \
868     Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C));        \
869     return;
870 #define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME, DEPRECATED)                      \
871   case OpenACCClauseKind::ALIAS_NAME:                                          \
872     Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C));        \
873     return;
874 #include "clang/Basic/OpenACCClauses.def"
875 
876     default:
877       llvm_unreachable("Clause visitor not yet implemented");
878     }
879     llvm_unreachable("Invalid Clause kind");
880   }
881 
882 #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
883   void Visit##CLAUSE_NAME##Clause(                                             \
884       const OpenACC##CLAUSE_NAME##Clause &Clause) {                            \
885     return getDerived().Visit##CLAUSE_NAME##Clause(Clause);                    \
886   }
887 
888 #include "clang/Basic/OpenACCClauses.def"
889 };
890 
891 class OpenACCClausePrinter final
892     : public OpenACCClauseVisitor<OpenACCClausePrinter> {
893   raw_ostream &OS;
894   const PrintingPolicy &Policy;
895 
896   void printExpr(const Expr *E);
897 
898 public:
VisitClauseList(ArrayRef<const OpenACCClause * > List)899   void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
900     for (const OpenACCClause *Clause : List) {
901       Visit(Clause);
902 
903       if (Clause != List.back())
904         OS << ' ';
905     }
906   }
OpenACCClausePrinter(raw_ostream & OS,const PrintingPolicy & Policy)907   OpenACCClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
908       : OS(OS), Policy(Policy) {}
909 
910 #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
911   void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause);
912 #include "clang/Basic/OpenACCClauses.def"
913 };
914 
915 } // namespace clang
916 
917 #endif // LLVM_CLANG_AST_OPENACCCLAUSE_H
918