xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/StmtOpenACC.h (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===- StmtOpenACC.h - Classes for OpenACC directives  ----------*- 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 /// \file
9 /// This file defines OpenACC AST classes for statement-level contructs.
10 ///
11 //===----------------------------------------------------------------------===//
12 
13 #ifndef LLVM_CLANG_AST_STMTOPENACC_H
14 #define LLVM_CLANG_AST_STMTOPENACC_H
15 
16 #include "clang/AST/OpenACCClause.h"
17 #include "clang/AST/Stmt.h"
18 #include "clang/Basic/OpenACCKinds.h"
19 #include "clang/Basic/SourceLocation.h"
20 #include "llvm/ADT/STLExtras.h"
21 #include <memory>
22 
23 namespace clang {
24 /// This is the base class for an OpenACC statement-level construct, other
25 /// construct types are expected to inherit from this.
26 class OpenACCConstructStmt : public Stmt {
27   friend class ASTStmtWriter;
28   friend class ASTStmtReader;
29   /// The directive kind. Each implementation of this interface should handle
30   /// specific kinds.
31   OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
32   /// The location of the directive statement, from the '#' to the last token of
33   /// the directive.
34   SourceRange Range;
35   /// The location of the directive name.
36   SourceLocation DirectiveLoc;
37 
38   /// The list of clauses.  This is stored here as an ArrayRef, as this is the
39   /// most convienient place to access the list, however the list itself should
40   /// be stored in leaf nodes, likely in trailing-storage.
41   MutableArrayRef<const OpenACCClause *> Clauses;
42 
43 protected:
OpenACCConstructStmt(StmtClass SC,OpenACCDirectiveKind K,SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End)44   OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K,
45                        SourceLocation Start, SourceLocation DirectiveLoc,
46                        SourceLocation End)
47       : Stmt(SC), Kind(K), Range(Start, End), DirectiveLoc(DirectiveLoc) {}
48 
49   // Used only for initialization, the leaf class can initialize this to
50   // trailing storage.
setClauseList(MutableArrayRef<const OpenACCClause * > NewClauses)51   void setClauseList(MutableArrayRef<const OpenACCClause *> NewClauses) {
52     assert(Clauses.empty() && "Cannot change clause list");
53     Clauses = NewClauses;
54   }
55 
56 public:
getDirectiveKind()57   OpenACCDirectiveKind getDirectiveKind() const { return Kind; }
58 
classof(const Stmt * S)59   static bool classof(const Stmt *S) {
60     return S->getStmtClass() >= firstOpenACCConstructStmtConstant &&
61            S->getStmtClass() <= lastOpenACCConstructStmtConstant;
62   }
63 
getBeginLoc()64   SourceLocation getBeginLoc() const { return Range.getBegin(); }
getEndLoc()65   SourceLocation getEndLoc() const { return Range.getEnd(); }
getDirectiveLoc()66   SourceLocation getDirectiveLoc() const { return DirectiveLoc; }
clauses()67   ArrayRef<const OpenACCClause *> clauses() const { return Clauses; }
68 
children()69   child_range children() {
70     return child_range(child_iterator(), child_iterator());
71   }
72 
children()73   const_child_range children() const {
74     return const_cast<OpenACCConstructStmt *>(this)->children();
75   }
76 };
77 
78 /// This is a base class for any OpenACC statement-level constructs that have an
79 /// associated statement. This class is not intended to be instantiated, but is
80 /// a convenient place to hold the associated statement.
81 class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt {
82   friend class ASTStmtWriter;
83   friend class ASTStmtReader;
84   template <typename Derived> friend class RecursiveASTVisitor;
85   Stmt *AssociatedStmt = nullptr;
86 
87 protected:
OpenACCAssociatedStmtConstruct(StmtClass SC,OpenACCDirectiveKind K,SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,Stmt * AssocStmt)88   OpenACCAssociatedStmtConstruct(StmtClass SC, OpenACCDirectiveKind K,
89                                  SourceLocation Start,
90                                  SourceLocation DirectiveLoc,
91                                  SourceLocation End, Stmt *AssocStmt)
92       : OpenACCConstructStmt(SC, K, Start, DirectiveLoc, End),
93         AssociatedStmt(AssocStmt) {}
94 
setAssociatedStmt(Stmt * S)95   void setAssociatedStmt(Stmt *S) { AssociatedStmt = S; }
getAssociatedStmt()96   Stmt *getAssociatedStmt() { return AssociatedStmt; }
getAssociatedStmt()97   const Stmt *getAssociatedStmt() const {
98     return const_cast<OpenACCAssociatedStmtConstruct *>(this)
99         ->getAssociatedStmt();
100   }
101 
102 public:
classof(const Stmt * T)103   static bool classof(const Stmt *T) {
104     return false;
105   }
106 
children()107   child_range children() {
108     if (getAssociatedStmt())
109       return child_range(&AssociatedStmt, &AssociatedStmt + 1);
110     return child_range(child_iterator(), child_iterator());
111   }
112 
children()113   const_child_range children() const {
114     return const_cast<OpenACCAssociatedStmtConstruct *>(this)->children();
115   }
116 };
117 
118 /// This class represents a compute construct, representing a 'Kind' of
119 /// `parallel', 'serial', or 'kernel'. These constructs are associated with a
120 /// 'structured block', defined as:
121 ///
122 ///  in C or C++, an executable statement, possibly compound, with a single
123 ///  entry at the top and a single exit at the bottom
124 ///
125 /// At the moment there is no real motivation to have a different AST node for
126 /// those three, as they are semantically identical, and have only minor
127 /// differences in the permitted list of clauses, which can be differentiated by
128 /// the 'Kind'.
129 class OpenACCComputeConstruct final
130     : public OpenACCAssociatedStmtConstruct,
131       private llvm::TrailingObjects<OpenACCComputeConstruct,
132                                     const OpenACCClause *> {
133   friend class ASTStmtWriter;
134   friend class ASTStmtReader;
135   friend class ASTContext;
136   friend TrailingObjects;
OpenACCComputeConstruct(unsigned NumClauses)137   OpenACCComputeConstruct(unsigned NumClauses)
138       : OpenACCAssociatedStmtConstruct(
139             OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid,
140             SourceLocation{}, SourceLocation{}, SourceLocation{},
141             /*AssociatedStmt=*/nullptr) {
142     // We cannot send the TrailingObjects storage to the base class (which holds
143     // a reference to the data) until it is constructed, so we have to set it
144     // separately here.
145     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
146     setClauseList(getTrailingObjects(NumClauses));
147   }
148 
OpenACCComputeConstruct(OpenACCDirectiveKind K,SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses,Stmt * StructuredBlock)149   OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start,
150                           SourceLocation DirectiveLoc, SourceLocation End,
151                           ArrayRef<const OpenACCClause *> Clauses,
152                           Stmt *StructuredBlock)
153       : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start,
154                                        DirectiveLoc, End, StructuredBlock) {
155     assert(isOpenACCComputeDirectiveKind(K) &&
156            "Only parallel, serial, and kernels constructs should be "
157            "represented by this type");
158 
159     // Initialize the trailing storage.
160     llvm::uninitialized_copy(Clauses, getTrailingObjects());
161 
162     setClauseList(getTrailingObjects(Clauses.size()));
163   }
164 
setStructuredBlock(Stmt * S)165   void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
166 
167 public:
classof(const Stmt * T)168   static bool classof(const Stmt *T) {
169     return T->getStmtClass() == OpenACCComputeConstructClass;
170   }
171 
172   static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C,
173                                               unsigned NumClauses);
174   static OpenACCComputeConstruct *
175   Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc,
176          SourceLocation DirectiveLoc, SourceLocation EndLoc,
177          ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock);
178 
getStructuredBlock()179   Stmt *getStructuredBlock() { return getAssociatedStmt(); }
getStructuredBlock()180   const Stmt *getStructuredBlock() const {
181     return const_cast<OpenACCComputeConstruct *>(this)->getStructuredBlock();
182   }
183 };
184 /// This class represents a 'loop' construct.  The 'loop' construct applies to a
185 /// 'for' loop (or range-for loop), and is optionally associated with a Compute
186 /// Construct.
187 class OpenACCLoopConstruct final
188     : public OpenACCAssociatedStmtConstruct,
189       private llvm::TrailingObjects<OpenACCLoopConstruct,
190                                    const OpenACCClause *> {
191   // The compute/combined construct kind this loop is associated with, or
192   // invalid if this is an orphaned loop construct.
193   OpenACCDirectiveKind ParentComputeConstructKind =
194       OpenACCDirectiveKind::Invalid;
195 
196   friend class ASTStmtWriter;
197   friend class ASTStmtReader;
198   friend class ASTContext;
199   friend class OpenACCAssociatedStmtConstruct;
200   friend class OpenACCCombinedConstruct;
201   friend class OpenACCComputeConstruct;
202   friend TrailingObjects;
203 
204   OpenACCLoopConstruct(unsigned NumClauses);
205 
206   OpenACCLoopConstruct(OpenACCDirectiveKind ParentKind, SourceLocation Start,
207                        SourceLocation DirLoc, SourceLocation End,
208                        ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop);
209 
210 public:
classof(const Stmt * T)211   static bool classof(const Stmt *T) {
212     return T->getStmtClass() == OpenACCLoopConstructClass;
213   }
214 
215   static OpenACCLoopConstruct *CreateEmpty(const ASTContext &C,
216                                            unsigned NumClauses);
217 
218   static OpenACCLoopConstruct *
219   Create(const ASTContext &C, OpenACCDirectiveKind ParentKind,
220          SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation EndLoc,
221          ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop);
222 
getLoop()223   Stmt *getLoop() { return getAssociatedStmt(); }
getLoop()224   const Stmt *getLoop() const {
225     return const_cast<OpenACCLoopConstruct *>(this)->getLoop();
226   }
227 
228   /// OpenACC 3.3 2.9:
229   /// An orphaned loop construct is a loop construct that is not lexically
230   /// enclosed within a compute construct. The parent compute construct of a
231   /// loop construct is the nearest compute construct that lexically contains
232   /// the loop construct.
isOrphanedLoopConstruct()233   bool isOrphanedLoopConstruct() const {
234     return ParentComputeConstructKind == OpenACCDirectiveKind::Invalid;
235   }
236 
getParentComputeConstructKind()237   OpenACCDirectiveKind getParentComputeConstructKind() const {
238     return ParentComputeConstructKind;
239   }
240 };
241 
242 // This class represents a 'combined' construct, which has a bunch of rules
243 // shared with both loop and compute constructs.
244 class OpenACCCombinedConstruct final
245     : public OpenACCAssociatedStmtConstruct,
246       private llvm::TrailingObjects<OpenACCCombinedConstruct,
247                                    const OpenACCClause *> {
248   friend TrailingObjects;
OpenACCCombinedConstruct(unsigned NumClauses)249   OpenACCCombinedConstruct(unsigned NumClauses)
250       : OpenACCAssociatedStmtConstruct(
251             OpenACCCombinedConstructClass, OpenACCDirectiveKind::Invalid,
252             SourceLocation{}, SourceLocation{}, SourceLocation{},
253             /*AssociatedStmt=*/nullptr) {
254     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
255     setClauseList(getTrailingObjects(NumClauses));
256   }
257 
OpenACCCombinedConstruct(OpenACCDirectiveKind K,SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses,Stmt * StructuredBlock)258   OpenACCCombinedConstruct(OpenACCDirectiveKind K, SourceLocation Start,
259                            SourceLocation DirectiveLoc, SourceLocation End,
260                            ArrayRef<const OpenACCClause *> Clauses,
261                            Stmt *StructuredBlock)
262       : OpenACCAssociatedStmtConstruct(OpenACCCombinedConstructClass, K, Start,
263                                        DirectiveLoc, End, StructuredBlock) {
264     assert(isOpenACCCombinedDirectiveKind(K) &&
265            "Only parallel loop, serial loop, and kernels loop constructs "
266            "should be represented by this type");
267 
268     llvm::uninitialized_copy(Clauses, getTrailingObjects());
269     setClauseList(getTrailingObjects(Clauses.size()));
270   }
setStructuredBlock(Stmt * S)271   void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
272 
273 public:
classof(const Stmt * T)274   static bool classof(const Stmt *T) {
275     return T->getStmtClass() == OpenACCCombinedConstructClass;
276   }
277 
278   static OpenACCCombinedConstruct *CreateEmpty(const ASTContext &C,
279                                                unsigned NumClauses);
280   static OpenACCCombinedConstruct *
281   Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start,
282          SourceLocation DirectiveLoc, SourceLocation End,
283          ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock);
getLoop()284   Stmt *getLoop() { return getAssociatedStmt(); }
getLoop()285   const Stmt *getLoop() const {
286     return const_cast<OpenACCCombinedConstruct *>(this)->getLoop();
287   }
288 };
289 
290 // This class represents a 'data' construct, which has an associated statement
291 // and clauses, but is otherwise pretty simple.
292 class OpenACCDataConstruct final
293     : public OpenACCAssociatedStmtConstruct,
294       private llvm::TrailingObjects<OpenACCDataConstruct,
295                                    const OpenACCClause *> {
296   friend TrailingObjects;
OpenACCDataConstruct(unsigned NumClauses)297   OpenACCDataConstruct(unsigned NumClauses)
298       : OpenACCAssociatedStmtConstruct(
299             OpenACCDataConstructClass, OpenACCDirectiveKind::Data,
300             SourceLocation{}, SourceLocation{}, SourceLocation{},
301             /*AssociatedStmt=*/nullptr) {
302     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
303     setClauseList(getTrailingObjects(NumClauses));
304   }
305 
OpenACCDataConstruct(SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses,Stmt * StructuredBlock)306   OpenACCDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
307                        SourceLocation End,
308                        ArrayRef<const OpenACCClause *> Clauses,
309                        Stmt *StructuredBlock)
310       : OpenACCAssociatedStmtConstruct(OpenACCDataConstructClass,
311                                        OpenACCDirectiveKind::Data, Start,
312                                        DirectiveLoc, End, StructuredBlock) {
313     llvm::uninitialized_copy(Clauses, getTrailingObjects());
314     setClauseList(getTrailingObjects(Clauses.size()));
315   }
setStructuredBlock(Stmt * S)316   void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
317 
318 public:
classof(const Stmt * T)319   static bool classof(const Stmt *T) {
320     return T->getStmtClass() == OpenACCDataConstructClass;
321   }
322 
323   static OpenACCDataConstruct *CreateEmpty(const ASTContext &C,
324                                            unsigned NumClauses);
325   static OpenACCDataConstruct *Create(const ASTContext &C, SourceLocation Start,
326                                       SourceLocation DirectiveLoc,
327                                       SourceLocation End,
328                                       ArrayRef<const OpenACCClause *> Clauses,
329                                       Stmt *StructuredBlock);
getStructuredBlock()330   Stmt *getStructuredBlock() { return getAssociatedStmt(); }
getStructuredBlock()331   const Stmt *getStructuredBlock() const {
332     return const_cast<OpenACCDataConstruct *>(this)->getStructuredBlock();
333   }
334 };
335 // This class represents a 'enter data' construct, which JUST has clauses.
336 class OpenACCEnterDataConstruct final
337     : public OpenACCConstructStmt,
338       private llvm::TrailingObjects<OpenACCEnterDataConstruct,
339                                    const OpenACCClause *> {
340   friend TrailingObjects;
OpenACCEnterDataConstruct(unsigned NumClauses)341   OpenACCEnterDataConstruct(unsigned NumClauses)
342       : OpenACCConstructStmt(OpenACCEnterDataConstructClass,
343                              OpenACCDirectiveKind::EnterData, SourceLocation{},
344                              SourceLocation{}, SourceLocation{}) {
345     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
346     setClauseList(getTrailingObjects(NumClauses));
347   }
OpenACCEnterDataConstruct(SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses)348   OpenACCEnterDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
349                             SourceLocation End,
350                             ArrayRef<const OpenACCClause *> Clauses)
351       : OpenACCConstructStmt(OpenACCEnterDataConstructClass,
352                              OpenACCDirectiveKind::EnterData, Start,
353                              DirectiveLoc, End) {
354     llvm::uninitialized_copy(Clauses, getTrailingObjects());
355     setClauseList(getTrailingObjects(Clauses.size()));
356   }
357 
358 public:
classof(const Stmt * T)359   static bool classof(const Stmt *T) {
360     return T->getStmtClass() == OpenACCEnterDataConstructClass;
361   }
362   static OpenACCEnterDataConstruct *CreateEmpty(const ASTContext &C,
363                                                 unsigned NumClauses);
364   static OpenACCEnterDataConstruct *
365   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
366          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
367 };
368 // This class represents a 'exit data' construct, which JUST has clauses.
369 class OpenACCExitDataConstruct final
370     : public OpenACCConstructStmt,
371       private llvm::TrailingObjects<OpenACCExitDataConstruct,
372                                    const OpenACCClause *> {
373   friend TrailingObjects;
OpenACCExitDataConstruct(unsigned NumClauses)374   OpenACCExitDataConstruct(unsigned NumClauses)
375       : OpenACCConstructStmt(OpenACCExitDataConstructClass,
376                              OpenACCDirectiveKind::ExitData, SourceLocation{},
377                              SourceLocation{}, SourceLocation{}) {
378     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
379     setClauseList(getTrailingObjects(NumClauses));
380   }
OpenACCExitDataConstruct(SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses)381   OpenACCExitDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
382                            SourceLocation End,
383                            ArrayRef<const OpenACCClause *> Clauses)
384       : OpenACCConstructStmt(OpenACCExitDataConstructClass,
385                              OpenACCDirectiveKind::ExitData, Start,
386                              DirectiveLoc, End) {
387     llvm::uninitialized_copy(Clauses, getTrailingObjects());
388     setClauseList(getTrailingObjects(Clauses.size()));
389   }
390 
391 public:
classof(const Stmt * T)392   static bool classof(const Stmt *T) {
393     return T->getStmtClass() == OpenACCExitDataConstructClass;
394   }
395   static OpenACCExitDataConstruct *CreateEmpty(const ASTContext &C,
396                                                unsigned NumClauses);
397   static OpenACCExitDataConstruct *
398   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
399          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
400 };
401 // This class represents a 'host_data' construct, which has an associated
402 // statement and clauses, but is otherwise pretty simple.
403 class OpenACCHostDataConstruct final
404     : public OpenACCAssociatedStmtConstruct,
405       private llvm::TrailingObjects<OpenACCHostDataConstruct,
406                                    const OpenACCClause *> {
407   friend TrailingObjects;
OpenACCHostDataConstruct(unsigned NumClauses)408   OpenACCHostDataConstruct(unsigned NumClauses)
409       : OpenACCAssociatedStmtConstruct(
410             OpenACCHostDataConstructClass, OpenACCDirectiveKind::HostData,
411             SourceLocation{}, SourceLocation{}, SourceLocation{},
412             /*AssociatedStmt=*/nullptr) {
413     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
414     setClauseList(getTrailingObjects(NumClauses));
415   }
OpenACCHostDataConstruct(SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses,Stmt * StructuredBlock)416   OpenACCHostDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
417                            SourceLocation End,
418                            ArrayRef<const OpenACCClause *> Clauses,
419                            Stmt *StructuredBlock)
420       : OpenACCAssociatedStmtConstruct(OpenACCHostDataConstructClass,
421                                        OpenACCDirectiveKind::HostData, Start,
422                                        DirectiveLoc, End, StructuredBlock) {
423     llvm::uninitialized_copy(Clauses, getTrailingObjects());
424     setClauseList(getTrailingObjects(Clauses.size()));
425   }
setStructuredBlock(Stmt * S)426   void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
427 
428 public:
classof(const Stmt * T)429   static bool classof(const Stmt *T) {
430     return T->getStmtClass() == OpenACCHostDataConstructClass;
431   }
432   static OpenACCHostDataConstruct *CreateEmpty(const ASTContext &C,
433                                                unsigned NumClauses);
434   static OpenACCHostDataConstruct *
435   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
436          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses,
437          Stmt *StructuredBlock);
getStructuredBlock()438   Stmt *getStructuredBlock() { return getAssociatedStmt(); }
getStructuredBlock()439   const Stmt *getStructuredBlock() const {
440     return const_cast<OpenACCHostDataConstruct *>(this)->getStructuredBlock();
441   }
442 };
443 
444 // This class represents a 'wait' construct, which has some expressions plus a
445 // clause list.
446 class OpenACCWaitConstruct final
447     : public OpenACCConstructStmt,
448       private llvm::TrailingObjects<OpenACCWaitConstruct, Expr *,
449                                     OpenACCClause *> {
450   // FIXME: We should be storing a `const OpenACCClause *` to be consistent with
451   // the rest of the constructs, but TrailingObjects doesn't allow for mixing
452   // constness in its implementation of `getTrailingObjects`.
453 
454   friend TrailingObjects;
455   friend class ASTStmtWriter;
456   friend class ASTStmtReader;
457   // Locations of the left and right parens of the 'wait-argument'
458   // expression-list.
459   SourceLocation LParenLoc, RParenLoc;
460   // Location of the 'queues' keyword, if present.
461   SourceLocation QueuesLoc;
462 
463   // Number of the expressions being represented.  Index '0' is always the
464   // 'devnum' expression, even if it not present.
465   unsigned NumExprs = 0;
466 
OpenACCWaitConstruct(unsigned NumExprs,unsigned NumClauses)467   OpenACCWaitConstruct(unsigned NumExprs, unsigned NumClauses)
468       : OpenACCConstructStmt(OpenACCWaitConstructClass,
469                              OpenACCDirectiveKind::Wait, SourceLocation{},
470                              SourceLocation{}, SourceLocation{}),
471         NumExprs(NumExprs) {
472     assert(NumExprs >= 1 &&
473            "NumExprs should always be >= 1 because the 'devnum' "
474            "expr is represented by a null if necessary");
475     std::uninitialized_value_construct_n(getExprPtr(), NumExprs);
476     std::uninitialized_value_construct_n(getTrailingObjects<OpenACCClause *>(),
477                                          NumClauses);
478     setClauseList(MutableArrayRef(const_cast<const OpenACCClause **>(
479                                       getTrailingObjects<OpenACCClause *>()),
480                                   NumClauses));
481   }
482 
OpenACCWaitConstruct(SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation LParenLoc,Expr * DevNumExpr,SourceLocation QueuesLoc,ArrayRef<Expr * > QueueIdExprs,SourceLocation RParenLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses)483   OpenACCWaitConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
484                        SourceLocation LParenLoc, Expr *DevNumExpr,
485                        SourceLocation QueuesLoc, ArrayRef<Expr *> QueueIdExprs,
486                        SourceLocation RParenLoc, SourceLocation End,
487                        ArrayRef<const OpenACCClause *> Clauses)
488       : OpenACCConstructStmt(OpenACCWaitConstructClass,
489                              OpenACCDirectiveKind::Wait, Start, DirectiveLoc,
490                              End),
491         LParenLoc(LParenLoc), RParenLoc(RParenLoc), QueuesLoc(QueuesLoc),
492         NumExprs(QueueIdExprs.size() + 1) {
493     assert(NumExprs >= 1 &&
494            "NumExprs should always be >= 1 because the 'devnum' "
495            "expr is represented by a null if necessary");
496 
497     llvm::uninitialized_copy(ArrayRef(DevNumExpr), getExprPtr());
498     llvm::uninitialized_copy(QueueIdExprs, getExprPtr() + 1);
499     std::uninitialized_copy(const_cast<OpenACCClause **>(Clauses.begin()),
500                             const_cast<OpenACCClause **>(Clauses.end()),
501                             getTrailingObjects<OpenACCClause *>());
502     setClauseList(MutableArrayRef(const_cast<const OpenACCClause **>(
503                                       getTrailingObjects<OpenACCClause *>()),
504                                   Clauses.size()));
505   }
506 
numTrailingObjects(OverloadToken<Expr * >)507   size_t numTrailingObjects(OverloadToken<Expr *>) const { return NumExprs; }
numTrailingObjects(OverloadToken<const OpenACCClause * >)508   size_t numTrailingObjects(OverloadToken<const OpenACCClause *>) const {
509     return clauses().size();
510   }
511 
getExprPtr()512   Expr **getExprPtr() const {
513     return const_cast<Expr**>(getTrailingObjects<Expr *>());
514   }
515 
getExprs()516   ArrayRef<Expr *> getExprs() const { return {getExprPtr(), NumExprs}; }
517 
getExprs()518   ArrayRef<Expr *> getExprs() { return {getExprPtr(), NumExprs}; }
519 
520 public:
classof(const Stmt * T)521   static bool classof(const Stmt *T) {
522     return T->getStmtClass() == OpenACCWaitConstructClass;
523   }
524 
525   static OpenACCWaitConstruct *
526   CreateEmpty(const ASTContext &C, unsigned NumExprs, unsigned NumClauses);
527 
528   static OpenACCWaitConstruct *
529   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
530          SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc,
531          ArrayRef<Expr *> QueueIdExprs, SourceLocation RParenLoc,
532          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
533 
getLParenLoc()534   SourceLocation getLParenLoc() const { return LParenLoc; }
getRParenLoc()535   SourceLocation getRParenLoc() const { return RParenLoc; }
hasQueuesTag()536   bool hasQueuesTag() const { return !QueuesLoc.isInvalid(); }
getQueuesLoc()537   SourceLocation getQueuesLoc() const { return QueuesLoc; }
538 
hasDevNumExpr()539   bool hasDevNumExpr() const { return getExprs()[0]; }
getDevNumExpr()540   Expr *getDevNumExpr() const { return getExprs()[0]; }
getQueueIdExprs()541   ArrayRef<Expr *> getQueueIdExprs() { return getExprs().drop_front(); }
getQueueIdExprs()542   ArrayRef<Expr *> getQueueIdExprs() const { return getExprs().drop_front(); }
543 
children()544   child_range children() {
545     Stmt **Begin = reinterpret_cast<Stmt **>(getExprPtr());
546     return child_range(Begin, Begin + NumExprs);
547   }
548 
children()549   const_child_range children() const {
550     Stmt *const *Begin =
551         reinterpret_cast<Stmt *const *>(getExprPtr());
552     return const_child_range(Begin, Begin + NumExprs);
553   }
554 };
555 
556 class OpenACCCacheConstruct final
557     : public OpenACCConstructStmt,
558       private llvm::TrailingObjects<OpenACCCacheConstruct, Expr *> {
559   friend TrailingObjects;
560   friend class ASTStmtWriter;
561   friend class ASTStmtReader;
562   // Locations of the left and right parens of the 'var-list'
563   // expression-list.
564   SourceRange ParensLoc;
565   SourceLocation ReadOnlyLoc;
566 
567   unsigned NumVars = 0;
568 
OpenACCCacheConstruct(unsigned NumVars)569   OpenACCCacheConstruct(unsigned NumVars)
570       : OpenACCConstructStmt(OpenACCCacheConstructClass,
571                              OpenACCDirectiveKind::Cache, SourceLocation{},
572                              SourceLocation{}, SourceLocation{}),
573         NumVars(NumVars) {
574     std::uninitialized_value_construct_n(getTrailingObjects(), NumVars);
575   }
OpenACCCacheConstruct(SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation LParenLoc,SourceLocation ReadOnlyLoc,ArrayRef<Expr * > VarList,SourceLocation RParenLoc,SourceLocation End)576   OpenACCCacheConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
577                         SourceLocation LParenLoc, SourceLocation ReadOnlyLoc,
578                         ArrayRef<Expr *> VarList, SourceLocation RParenLoc,
579                         SourceLocation End)
580       : OpenACCConstructStmt(OpenACCCacheConstructClass,
581                              OpenACCDirectiveKind::Cache, Start, DirectiveLoc,
582                              End),
583         ParensLoc(LParenLoc, RParenLoc), ReadOnlyLoc(ReadOnlyLoc),
584         NumVars(VarList.size()) {
585 
586     llvm::uninitialized_copy(VarList, getTrailingObjects());
587   }
588 
589 public:
getVarList()590   ArrayRef<Expr *> getVarList() const { return getTrailingObjects(NumVars); }
591 
getVarList()592   MutableArrayRef<Expr *> getVarList() { return getTrailingObjects(NumVars); }
593 
classof(const Stmt * T)594   static bool classof(const Stmt *T) {
595     return T->getStmtClass() == OpenACCCacheConstructClass;
596   }
597 
598   static OpenACCCacheConstruct *CreateEmpty(const ASTContext &C,
599                                             unsigned NumVars);
600   static OpenACCCacheConstruct *
601   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
602          SourceLocation LParenLoc, SourceLocation ReadOnlyLoc,
603          ArrayRef<Expr *> VarList, SourceLocation RParenLoc,
604          SourceLocation End);
605 
getLParenLoc()606   SourceLocation getLParenLoc() const { return ParensLoc.getBegin(); }
getRParenLoc()607   SourceLocation getRParenLoc() const { return ParensLoc.getEnd(); }
hasReadOnly()608   bool hasReadOnly() const { return !ReadOnlyLoc.isInvalid(); }
getReadOnlyLoc()609   SourceLocation getReadOnlyLoc() const { return ReadOnlyLoc; }
610 
children()611   child_range children() {
612     Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects());
613     return child_range(Begin, Begin + NumVars);
614   }
615 
children()616   const_child_range children() const {
617     Stmt *const *Begin = reinterpret_cast<Stmt *const *>(getTrailingObjects());
618     return const_child_range(Begin, Begin + NumVars);
619   }
620 };
621 
622 // This class represents an 'init' construct, which has just a clause list.
623 class OpenACCInitConstruct final
624     : public OpenACCConstructStmt,
625       private llvm::TrailingObjects<OpenACCInitConstruct,
626                                     const OpenACCClause *> {
627   friend TrailingObjects;
OpenACCInitConstruct(unsigned NumClauses)628   OpenACCInitConstruct(unsigned NumClauses)
629       : OpenACCConstructStmt(OpenACCInitConstructClass,
630                              OpenACCDirectiveKind::Init, SourceLocation{},
631                              SourceLocation{}, SourceLocation{}) {
632     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
633     setClauseList(getTrailingObjects(NumClauses));
634   }
OpenACCInitConstruct(SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses)635   OpenACCInitConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
636                        SourceLocation End,
637                        ArrayRef<const OpenACCClause *> Clauses)
638       : OpenACCConstructStmt(OpenACCInitConstructClass,
639                              OpenACCDirectiveKind::Init, Start, DirectiveLoc,
640                              End) {
641     llvm::uninitialized_copy(Clauses, getTrailingObjects());
642     setClauseList(getTrailingObjects(Clauses.size()));
643   }
644 
645 public:
classof(const Stmt * T)646   static bool classof(const Stmt *T) {
647     return T->getStmtClass() == OpenACCInitConstructClass;
648   }
649   static OpenACCInitConstruct *CreateEmpty(const ASTContext &C,
650                                            unsigned NumClauses);
651   static OpenACCInitConstruct *Create(const ASTContext &C, SourceLocation Start,
652                                       SourceLocation DirectiveLoc,
653                                       SourceLocation End,
654                                       ArrayRef<const OpenACCClause *> Clauses);
655 };
656 
657 // This class represents a 'shutdown' construct, which has just a clause list.
658 class OpenACCShutdownConstruct final
659     : public OpenACCConstructStmt,
660       private llvm::TrailingObjects<OpenACCShutdownConstruct,
661                                     const OpenACCClause *> {
662   friend TrailingObjects;
OpenACCShutdownConstruct(unsigned NumClauses)663   OpenACCShutdownConstruct(unsigned NumClauses)
664       : OpenACCConstructStmt(OpenACCShutdownConstructClass,
665                              OpenACCDirectiveKind::Shutdown, SourceLocation{},
666                              SourceLocation{}, SourceLocation{}) {
667     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
668     setClauseList(getTrailingObjects(NumClauses));
669   }
OpenACCShutdownConstruct(SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses)670   OpenACCShutdownConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
671                            SourceLocation End,
672                            ArrayRef<const OpenACCClause *> Clauses)
673       : OpenACCConstructStmt(OpenACCShutdownConstructClass,
674                              OpenACCDirectiveKind::Shutdown, Start,
675                              DirectiveLoc, End) {
676     llvm::uninitialized_copy(Clauses, getTrailingObjects());
677     setClauseList(getTrailingObjects(Clauses.size()));
678   }
679 
680 public:
classof(const Stmt * T)681   static bool classof(const Stmt *T) {
682     return T->getStmtClass() == OpenACCShutdownConstructClass;
683   }
684   static OpenACCShutdownConstruct *CreateEmpty(const ASTContext &C,
685                                                unsigned NumClauses);
686   static OpenACCShutdownConstruct *
687   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
688          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
689 };
690 
691 // This class represents a 'set' construct, which has just a clause list.
692 class OpenACCSetConstruct final
693     : public OpenACCConstructStmt,
694       private llvm::TrailingObjects<OpenACCSetConstruct,
695                                     const OpenACCClause *> {
696   friend TrailingObjects;
OpenACCSetConstruct(unsigned NumClauses)697   OpenACCSetConstruct(unsigned NumClauses)
698       : OpenACCConstructStmt(OpenACCSetConstructClass,
699                              OpenACCDirectiveKind::Set, SourceLocation{},
700                              SourceLocation{}, SourceLocation{}) {
701     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
702     setClauseList(getTrailingObjects(NumClauses));
703   }
704 
OpenACCSetConstruct(SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses)705   OpenACCSetConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
706                       SourceLocation End,
707                       ArrayRef<const OpenACCClause *> Clauses)
708       : OpenACCConstructStmt(OpenACCSetConstructClass,
709                              OpenACCDirectiveKind::Set, Start, DirectiveLoc,
710                              End) {
711     llvm::uninitialized_copy(Clauses, getTrailingObjects());
712     setClauseList(getTrailingObjects(Clauses.size()));
713   }
714 
715 public:
classof(const Stmt * T)716   static bool classof(const Stmt *T) {
717     return T->getStmtClass() == OpenACCSetConstructClass;
718   }
719   static OpenACCSetConstruct *CreateEmpty(const ASTContext &C,
720                                           unsigned NumClauses);
721   static OpenACCSetConstruct *Create(const ASTContext &C, SourceLocation Start,
722                                      SourceLocation DirectiveLoc,
723                                      SourceLocation End,
724                                      ArrayRef<const OpenACCClause *> Clauses);
725 };
726 // This class represents an 'update' construct, which has just a clause list.
727 class OpenACCUpdateConstruct final
728     : public OpenACCConstructStmt,
729       private llvm::TrailingObjects<OpenACCUpdateConstruct,
730                                     const OpenACCClause *> {
731   friend TrailingObjects;
OpenACCUpdateConstruct(unsigned NumClauses)732   OpenACCUpdateConstruct(unsigned NumClauses)
733       : OpenACCConstructStmt(OpenACCUpdateConstructClass,
734                              OpenACCDirectiveKind::Update, SourceLocation{},
735                              SourceLocation{}, SourceLocation{}) {
736     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
737     setClauseList(getTrailingObjects(NumClauses));
738   }
739 
OpenACCUpdateConstruct(SourceLocation Start,SourceLocation DirectiveLoc,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses)740   OpenACCUpdateConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
741                          SourceLocation End,
742                          ArrayRef<const OpenACCClause *> Clauses)
743       : OpenACCConstructStmt(OpenACCUpdateConstructClass,
744                              OpenACCDirectiveKind::Update, Start, DirectiveLoc,
745                              End) {
746     llvm::uninitialized_copy(Clauses, getTrailingObjects());
747     setClauseList(getTrailingObjects(Clauses.size()));
748   }
749 
750 public:
classof(const Stmt * T)751   static bool classof(const Stmt *T) {
752     return T->getStmtClass() == OpenACCUpdateConstructClass;
753   }
754   static OpenACCUpdateConstruct *CreateEmpty(const ASTContext &C,
755                                              unsigned NumClauses);
756   static OpenACCUpdateConstruct *
757   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
758          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
759 };
760 
761 // This class represents the 'atomic' construct, which has an associated
762 // statement, but no clauses.
763 class OpenACCAtomicConstruct final
764     : public OpenACCAssociatedStmtConstruct,
765       private llvm::TrailingObjects<OpenACCAtomicConstruct,
766                                     const OpenACCClause *> {
767 
768   friend class ASTStmtReader;
769   friend TrailingObjects;
770   OpenACCAtomicKind AtomicKind = OpenACCAtomicKind::None;
771 
OpenACCAtomicConstruct(unsigned NumClauses)772   OpenACCAtomicConstruct(unsigned NumClauses)
773       : OpenACCAssociatedStmtConstruct(
774             OpenACCAtomicConstructClass, OpenACCDirectiveKind::Atomic,
775             SourceLocation{}, SourceLocation{}, SourceLocation{},
776             /*AssociatedStmt=*/nullptr) {
777     std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses);
778     setClauseList(getTrailingObjects(NumClauses));
779   }
780 
OpenACCAtomicConstruct(SourceLocation Start,SourceLocation DirectiveLoc,OpenACCAtomicKind AtKind,SourceLocation End,ArrayRef<const OpenACCClause * > Clauses,Stmt * AssociatedStmt)781   OpenACCAtomicConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
782                          OpenACCAtomicKind AtKind, SourceLocation End,
783                          ArrayRef<const OpenACCClause *> Clauses,
784                          Stmt *AssociatedStmt)
785       : OpenACCAssociatedStmtConstruct(OpenACCAtomicConstructClass,
786                                        OpenACCDirectiveKind::Atomic, Start,
787                                        DirectiveLoc, End, AssociatedStmt),
788         AtomicKind(AtKind) {
789     // Initialize the trailing storage.
790     llvm::uninitialized_copy(Clauses, getTrailingObjects());
791 
792     setClauseList(getTrailingObjects(Clauses.size()));
793   }
794 
setAssociatedStmt(Stmt * S)795   void setAssociatedStmt(Stmt *S) {
796     OpenACCAssociatedStmtConstruct::setAssociatedStmt(S);
797   }
798 
799 public:
classof(const Stmt * T)800   static bool classof(const Stmt *T) {
801     return T->getStmtClass() == OpenACCAtomicConstructClass;
802   }
803 
804   static OpenACCAtomicConstruct *CreateEmpty(const ASTContext &C,
805                                              unsigned NumClauses);
806   static OpenACCAtomicConstruct *
807   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
808          OpenACCAtomicKind AtKind, SourceLocation End,
809          ArrayRef<const OpenACCClause *> Clauses, Stmt *AssociatedStmt);
810 
getAtomicKind()811   OpenACCAtomicKind getAtomicKind() const { return AtomicKind; }
getAssociatedStmt()812   const Stmt *getAssociatedStmt() const {
813     return OpenACCAssociatedStmtConstruct::getAssociatedStmt();
814   }
getAssociatedStmt()815   Stmt *getAssociatedStmt() {
816     return OpenACCAssociatedStmtConstruct::getAssociatedStmt();
817   }
818 };
819 
820 } // namespace clang
821 #endif // LLVM_CLANG_AST_STMTOPENACC_H
822