xref: /freebsd/contrib/llvm-project/clang/include/clang/AST/StmtOpenMP.h (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1 //===- StmtOpenMP.h - Classes for OpenMP 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 OpenMP AST classes for executable directives and
10 /// clauses.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_AST_STMTOPENMP_H
15 #define LLVM_CLANG_AST_STMTOPENMP_H
16 
17 #include "clang/AST/ASTContext.h"
18 #include "clang/AST/Expr.h"
19 #include "clang/AST/OpenMPClause.h"
20 #include "clang/AST/Stmt.h"
21 #include "clang/AST/StmtCXX.h"
22 #include "clang/Basic/OpenMPKinds.h"
23 #include "clang/Basic/SourceLocation.h"
24 
25 namespace clang {
26 
27 //===----------------------------------------------------------------------===//
28 // AST classes for directives.
29 //===----------------------------------------------------------------------===//
30 
31 /// Representation of an OpenMP canonical loop.
32 ///
33 /// OpenMP 1.0 C/C++, section 2.4.1 for Construct; canonical-shape
34 /// OpenMP 2.0 C/C++, section 2.4.1 for Construct; canonical-shape
35 /// OpenMP 2.5, section 2.5.1 Loop Construct; canonical form
36 /// OpenMP 3.1, section 2.5.1 Loop Construct; canonical form
37 /// OpenMP 4.0, section 2.6 Canonical Loop Form
38 /// OpenMP 4.5, section 2.6 Canonical Loop Form
39 /// OpenMP 5.0, section 2.9.1 Canonical Loop Form
40 /// OpenMP 5.1, section 2.11.1 Canonical Loop Nest Form
41 ///
42 /// An OpenMP canonical loop is a for-statement or range-based for-statement
43 /// with additional requirements that ensure that the number of iterations is
44 /// known before entering the loop and allow skipping to an arbitrary iteration.
45 /// The OMPCanonicalLoop AST node wraps a ForStmt or CXXForRangeStmt that is
46 /// known to fulfill OpenMP's canonical loop requirements because of being
47 /// associated to an OMPLoopBasedDirective. That is, the general structure is:
48 ///
49 ///  OMPLoopBasedDirective
50 /// [`- CapturedStmt   ]
51 /// [   `- CapturedDecl]
52 ///        ` OMPCanonicalLoop
53 ///          `- ForStmt/CXXForRangeStmt
54 ///             `- Stmt
55 ///
56 /// One or multiple CapturedStmt/CapturedDecl pairs may be inserted by some
57 /// directives such as OMPParallelForDirective, but others do not need them
58 /// (such as OMPTileDirective). In  The OMPCanonicalLoop and
59 /// ForStmt/CXXForRangeStmt pair is repeated for loop associated with the
60 /// directive. A OMPCanonicalLoop must not appear in the AST unless associated
61 /// with a OMPLoopBasedDirective. In an imperfectly nested loop nest, the
62 /// OMPCanonicalLoop may also be wrapped in a CompoundStmt:
63 ///
64 /// [...]
65 ///  ` OMPCanonicalLoop
66 ///    `- ForStmt/CXXForRangeStmt
67 ///       `- CompoundStmt
68 ///          |- Leading in-between code (if any)
69 ///          |- OMPCanonicalLoop
70 ///          |  `- ForStmt/CXXForRangeStmt
71 ///          |     `- ...
72 ///          `- Trailing in-between code (if any)
73 ///
74 /// The leading/trailing in-between code must not itself be a OMPCanonicalLoop
75 /// to avoid confusion which loop belongs to the nesting.
76 ///
77 /// There are three different kinds of iteration variables for different
78 /// purposes:
79 /// * Loop user variable: The user-accessible variable with different value for
80 ///   each iteration.
81 /// * Loop iteration variable: The variable used to identify a loop iteration;
82 ///   for range-based for-statement, this is the hidden iterator '__begin'. For
83 ///   other loops, it is identical to the loop user variable. Must be a
84 ///   random-access iterator, pointer or integer type.
85 /// * Logical iteration counter: Normalized loop counter starting at 0 and
86 ///   incrementing by one at each iteration. Allows abstracting over the type
87 ///   of the loop iteration variable and is always an unsigned integer type
88 ///   appropriate to represent the range of the loop iteration variable. Its
89 ///   value corresponds to the logical iteration number in the OpenMP
90 ///   specification.
91 ///
92 /// This AST node provides two captured statements:
93 /// * The distance function which computes the number of iterations.
94 /// * The loop user variable function that computes the loop user variable when
95 ///   given a logical iteration number.
96 ///
97 /// These captured statements provide the link between C/C++ semantics and the
98 /// logical iteration counters used by the OpenMPIRBuilder which is
99 /// language-agnostic and therefore does not know e.g. how to advance a
100 /// random-access iterator. The OpenMPIRBuilder will use this information to
101 /// apply simd, workshare-loop, distribute, taskloop and loop directives to the
102 /// loop. For compatibility with the non-OpenMPIRBuilder codegen path, an
103 /// OMPCanonicalLoop can itself also be wrapped into the CapturedStmts of an
104 /// OMPLoopDirective and skipped when searching for the associated syntactical
105 /// loop.
106 ///
107 /// Example:
108 /// <code>
109 ///   std::vector<std::string> Container{1,2,3};
110 ///   for (std::string Str : Container)
111 ///      Body(Str);
112 /// </code>
113 /// which is syntactic sugar for approximately:
114 /// <code>
115 ///   auto &&__range = Container;
116 ///   auto __begin = std::begin(__range);
117 ///   auto __end = std::end(__range);
118 ///   for (; __begin != __end; ++__begin) {
119 ///     std::String Str = *__begin;
120 ///     Body(Str);
121 ///   }
122 /// </code>
123 /// In this example, the loop user variable is `Str`, the loop iteration
124 /// variable is `__begin` of type `std::vector<std::string>::iterator` and the
125 /// logical iteration number type is `size_t` (unsigned version of
126 /// `std::vector<std::string>::iterator::difference_type` aka `ptrdiff_t`).
127 /// Therefore, the distance function will be
128 /// <code>
129 ///   [&](size_t &Result) { Result = __end - __begin; }
130 /// </code>
131 /// and the loop variable function is
132 /// <code>
133 ///   [&,__begin](std::vector<std::string>::iterator &Result, size_t Logical) {
134 ///     Result = __begin + Logical;
135 ///   }
136 /// </code>
137 /// The variable `__begin`, aka the loop iteration variable, is captured by
138 /// value because it is modified in the loop body, but both functions require
139 /// the initial value. The OpenMP specification explicitly leaves unspecified
140 /// when the loop expressions are evaluated such that a capture by reference is
141 /// sufficient.
142 class OMPCanonicalLoop : public Stmt {
143   friend class ASTStmtReader;
144   friend class ASTStmtWriter;
145 
146   /// Children of this AST node.
147   enum {
148     LOOP_STMT,
149     DISTANCE_FUNC,
150     LOOPVAR_FUNC,
151     LOOPVAR_REF,
152     LastSubStmt = LOOPVAR_REF
153   };
154 
155 private:
156   /// This AST node's children.
157   Stmt *SubStmts[LastSubStmt + 1] = {};
158 
OMPCanonicalLoop()159   OMPCanonicalLoop() : Stmt(StmtClass::OMPCanonicalLoopClass) {}
160 
161 public:
162   /// Create a new OMPCanonicalLoop.
create(const ASTContext & Ctx,Stmt * LoopStmt,CapturedStmt * DistanceFunc,CapturedStmt * LoopVarFunc,DeclRefExpr * LoopVarRef)163   static OMPCanonicalLoop *create(const ASTContext &Ctx, Stmt *LoopStmt,
164                                   CapturedStmt *DistanceFunc,
165                                   CapturedStmt *LoopVarFunc,
166                                   DeclRefExpr *LoopVarRef) {
167     OMPCanonicalLoop *S = new (Ctx) OMPCanonicalLoop();
168     S->setLoopStmt(LoopStmt);
169     S->setDistanceFunc(DistanceFunc);
170     S->setLoopVarFunc(LoopVarFunc);
171     S->setLoopVarRef(LoopVarRef);
172     return S;
173   }
174 
175   /// Create an empty OMPCanonicalLoop for deserialization.
createEmpty(const ASTContext & Ctx)176   static OMPCanonicalLoop *createEmpty(const ASTContext &Ctx) {
177     return new (Ctx) OMPCanonicalLoop();
178   }
179 
classof(const Stmt * S)180   static bool classof(const Stmt *S) {
181     return S->getStmtClass() == StmtClass::OMPCanonicalLoopClass;
182   }
183 
getBeginLoc()184   SourceLocation getBeginLoc() const { return getLoopStmt()->getBeginLoc(); }
getEndLoc()185   SourceLocation getEndLoc() const { return getLoopStmt()->getEndLoc(); }
186 
187   /// Return this AST node's children.
188   /// @{
children()189   child_range children() {
190     return child_range(&SubStmts[0], &SubStmts[0] + LastSubStmt + 1);
191   }
children()192   const_child_range children() const {
193     return const_child_range(&SubStmts[0], &SubStmts[0] + LastSubStmt + 1);
194   }
195   /// @}
196 
197   /// The wrapped syntactic loop statement (ForStmt or CXXForRangeStmt).
198   /// @{
getLoopStmt()199   Stmt *getLoopStmt() { return SubStmts[LOOP_STMT]; }
getLoopStmt()200   const Stmt *getLoopStmt() const { return SubStmts[LOOP_STMT]; }
setLoopStmt(Stmt * S)201   void setLoopStmt(Stmt *S) {
202     assert((isa<ForStmt>(S) || isa<CXXForRangeStmt>(S)) &&
203            "Canonical loop must be a for loop (range-based or otherwise)");
204     SubStmts[LOOP_STMT] = S;
205   }
206   /// @}
207 
208   /// The function that computes the number of loop iterations. Can be evaluated
209   /// before entering the loop but after the syntactical loop's init
210   /// statement(s).
211   ///
212   /// Function signature: void(LogicalTy &Result)
213   /// Any values necessary to compute the distance are captures of the closure.
214   /// @{
getDistanceFunc()215   CapturedStmt *getDistanceFunc() {
216     return cast<CapturedStmt>(SubStmts[DISTANCE_FUNC]);
217   }
getDistanceFunc()218   const CapturedStmt *getDistanceFunc() const {
219     return cast<CapturedStmt>(SubStmts[DISTANCE_FUNC]);
220   }
setDistanceFunc(CapturedStmt * S)221   void setDistanceFunc(CapturedStmt *S) {
222     assert(S && "Expected non-null captured statement");
223     SubStmts[DISTANCE_FUNC] = S;
224   }
225   /// @}
226 
227   /// The function that computes the loop user variable from a logical iteration
228   /// counter. Can be evaluated as first statement in the loop.
229   ///
230   /// Function signature: void(LoopVarTy &Result, LogicalTy Number)
231   /// Any other values required to compute the loop user variable (such as start
232   /// value, step size) are captured by the closure. In particular, the initial
233   /// value of loop iteration variable is captured by value to be unaffected by
234   /// previous iterations.
235   /// @{
getLoopVarFunc()236   CapturedStmt *getLoopVarFunc() {
237     return cast<CapturedStmt>(SubStmts[LOOPVAR_FUNC]);
238   }
getLoopVarFunc()239   const CapturedStmt *getLoopVarFunc() const {
240     return cast<CapturedStmt>(SubStmts[LOOPVAR_FUNC]);
241   }
setLoopVarFunc(CapturedStmt * S)242   void setLoopVarFunc(CapturedStmt *S) {
243     assert(S && "Expected non-null captured statement");
244     SubStmts[LOOPVAR_FUNC] = S;
245   }
246   /// @}
247 
248   /// Reference to the loop user variable as accessed in the loop body.
249   /// @{
getLoopVarRef()250   DeclRefExpr *getLoopVarRef() {
251     return cast<DeclRefExpr>(SubStmts[LOOPVAR_REF]);
252   }
getLoopVarRef()253   const DeclRefExpr *getLoopVarRef() const {
254     return cast<DeclRefExpr>(SubStmts[LOOPVAR_REF]);
255   }
setLoopVarRef(DeclRefExpr * E)256   void setLoopVarRef(DeclRefExpr *E) {
257     assert(E && "Expected non-null loop variable");
258     SubStmts[LOOPVAR_REF] = E;
259   }
260   /// @}
261 };
262 
263 /// This is a basic class for representing single OpenMP executable
264 /// directive.
265 ///
266 class OMPExecutableDirective : public Stmt {
267   friend class ASTStmtReader;
268   friend class ASTStmtWriter;
269 
270   /// Kind of the directive.
271   OpenMPDirectiveKind Kind = llvm::omp::OMPD_unknown;
272   /// Starting location of the directive (directive keyword).
273   SourceLocation StartLoc;
274   /// Ending location of the directive.
275   SourceLocation EndLoc;
276 
277   /// Get the clauses storage.
getClauses()278   MutableArrayRef<OMPClause *> getClauses() {
279     if (!Data)
280       return std::nullopt;
281     return Data->getClauses();
282   }
283 
284   /// Was this directive mapped from an another directive?
285   /// e.g. 1) omp loop bind(parallel) is mapped to OMPD_for
286   ///      2) omp loop bind(teams) is mapped to OMPD_distribute
287   ///      3) omp loop bind(thread) is mapped to OMPD_simd
288   /// It was necessary to note it down in the Directive because of
289   /// clang::TreeTransform::TransformOMPExecutableDirective() pass in
290   /// the frontend.
291   OpenMPDirectiveKind PrevMappedDirective = llvm::omp::OMPD_unknown;
292 
293 protected:
294   /// Data, associated with the directive.
295   OMPChildren *Data = nullptr;
296 
297   /// Build instance of directive of class \a K.
298   ///
299   /// \param SC Statement class.
300   /// \param K Kind of OpenMP directive.
301   /// \param StartLoc Starting location of the directive (directive keyword).
302   /// \param EndLoc Ending location of the directive.
303   ///
OMPExecutableDirective(StmtClass SC,OpenMPDirectiveKind K,SourceLocation StartLoc,SourceLocation EndLoc)304   OMPExecutableDirective(StmtClass SC, OpenMPDirectiveKind K,
305                          SourceLocation StartLoc, SourceLocation EndLoc)
306       : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)),
307         EndLoc(std::move(EndLoc)) {}
308 
309   template <typename T, typename... Params>
createDirective(const ASTContext & C,ArrayRef<OMPClause * > Clauses,Stmt * AssociatedStmt,unsigned NumChildren,Params &&...P)310   static T *createDirective(const ASTContext &C, ArrayRef<OMPClause *> Clauses,
311                             Stmt *AssociatedStmt, unsigned NumChildren,
312                             Params &&... P) {
313     void *Mem =
314         C.Allocate(sizeof(T) + OMPChildren::size(Clauses.size(), AssociatedStmt,
315                                                  NumChildren),
316                    alignof(T));
317 
318     auto *Data = OMPChildren::Create(reinterpret_cast<T *>(Mem) + 1, Clauses,
319                                      AssociatedStmt, NumChildren);
320     auto *Inst = new (Mem) T(std::forward<Params>(P)...);
321     Inst->Data = Data;
322     return Inst;
323   }
324 
325   template <typename T, typename... Params>
createEmptyDirective(const ASTContext & C,unsigned NumClauses,bool HasAssociatedStmt,unsigned NumChildren,Params &&...P)326   static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
327                                  bool HasAssociatedStmt, unsigned NumChildren,
328                                  Params &&... P) {
329     void *Mem =
330         C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
331                                                  NumChildren),
332                    alignof(T));
333     auto *Data =
334         OMPChildren::CreateEmpty(reinterpret_cast<T *>(Mem) + 1, NumClauses,
335                                  HasAssociatedStmt, NumChildren);
336     auto *Inst = new (Mem) T(std::forward<Params>(P)...);
337     Inst->Data = Data;
338     return Inst;
339   }
340 
341   template <typename T>
342   static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
343                                  bool HasAssociatedStmt = false,
344                                  unsigned NumChildren = 0) {
345     void *Mem =
346         C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
347                                                  NumChildren),
348                    alignof(T));
349     auto *Data =
350         OMPChildren::CreateEmpty(reinterpret_cast<T *>(Mem) + 1, NumClauses,
351                                  HasAssociatedStmt, NumChildren);
352     auto *Inst = new (Mem) T;
353     Inst->Data = Data;
354     return Inst;
355   }
356 
setMappedDirective(OpenMPDirectiveKind MappedDirective)357   void setMappedDirective(OpenMPDirectiveKind MappedDirective) {
358     PrevMappedDirective = MappedDirective;
359   }
360 
361 public:
362   /// Iterates over expressions/statements used in the construct.
363   class used_clauses_child_iterator
364       : public llvm::iterator_adaptor_base<
365             used_clauses_child_iterator, ArrayRef<OMPClause *>::iterator,
366             std::forward_iterator_tag, Stmt *, ptrdiff_t, Stmt *, Stmt *> {
367     ArrayRef<OMPClause *>::iterator End;
368     OMPClause::child_iterator ChildI, ChildEnd;
369 
MoveToNext()370     void MoveToNext() {
371       if (ChildI != ChildEnd)
372         return;
373       while (this->I != End) {
374         ++this->I;
375         if (this->I != End) {
376           ChildI = (*this->I)->used_children().begin();
377           ChildEnd = (*this->I)->used_children().end();
378           if (ChildI != ChildEnd)
379             return;
380         }
381       }
382     }
383 
384   public:
used_clauses_child_iterator(ArrayRef<OMPClause * > Clauses)385     explicit used_clauses_child_iterator(ArrayRef<OMPClause *> Clauses)
386         : used_clauses_child_iterator::iterator_adaptor_base(Clauses.begin()),
387           End(Clauses.end()) {
388       if (this->I != End) {
389         ChildI = (*this->I)->used_children().begin();
390         ChildEnd = (*this->I)->used_children().end();
391         MoveToNext();
392       }
393     }
394     Stmt *operator*() const { return *ChildI; }
395     Stmt *operator->() const { return **this; }
396 
397     used_clauses_child_iterator &operator++() {
398       ++ChildI;
399       if (ChildI != ChildEnd)
400         return *this;
401       if (this->I != End) {
402         ++this->I;
403         if (this->I != End) {
404           ChildI = (*this->I)->used_children().begin();
405           ChildEnd = (*this->I)->used_children().end();
406         }
407       }
408       MoveToNext();
409       return *this;
410     }
411   };
412 
413   static llvm::iterator_range<used_clauses_child_iterator>
used_clauses_children(ArrayRef<OMPClause * > Clauses)414   used_clauses_children(ArrayRef<OMPClause *> Clauses) {
415     return {
416         used_clauses_child_iterator(Clauses),
417         used_clauses_child_iterator(llvm::ArrayRef(Clauses.end(), (size_t)0))};
418   }
419 
420   /// Iterates over a filtered subrange of clauses applied to a
421   /// directive.
422   ///
423   /// This iterator visits only clauses of type SpecificClause.
424   template <typename SpecificClause>
425   class specific_clause_iterator
426       : public llvm::iterator_adaptor_base<
427             specific_clause_iterator<SpecificClause>,
428             ArrayRef<OMPClause *>::const_iterator, std::forward_iterator_tag,
429             const SpecificClause *, ptrdiff_t, const SpecificClause *,
430             const SpecificClause *> {
431     ArrayRef<OMPClause *>::const_iterator End;
432 
SkipToNextClause()433     void SkipToNextClause() {
434       while (this->I != End && !isa<SpecificClause>(*this->I))
435         ++this->I;
436     }
437 
438   public:
specific_clause_iterator(ArrayRef<OMPClause * > Clauses)439     explicit specific_clause_iterator(ArrayRef<OMPClause *> Clauses)
440         : specific_clause_iterator::iterator_adaptor_base(Clauses.begin()),
441           End(Clauses.end()) {
442       SkipToNextClause();
443     }
444 
445     const SpecificClause *operator*() const {
446       return cast<SpecificClause>(*this->I);
447     }
448     const SpecificClause *operator->() const { return **this; }
449 
450     specific_clause_iterator &operator++() {
451       ++this->I;
452       SkipToNextClause();
453       return *this;
454     }
455   };
456 
457   template <typename SpecificClause>
458   static llvm::iterator_range<specific_clause_iterator<SpecificClause>>
getClausesOfKind(ArrayRef<OMPClause * > Clauses)459   getClausesOfKind(ArrayRef<OMPClause *> Clauses) {
460     return {specific_clause_iterator<SpecificClause>(Clauses),
461             specific_clause_iterator<SpecificClause>(
462                 llvm::ArrayRef(Clauses.end(), (size_t)0))};
463   }
464 
465   template <typename SpecificClause>
466   llvm::iterator_range<specific_clause_iterator<SpecificClause>>
getClausesOfKind()467   getClausesOfKind() const {
468     return getClausesOfKind<SpecificClause>(clauses());
469   }
470 
471   /// Gets a single clause of the specified kind associated with the
472   /// current directive iff there is only one clause of this kind (and assertion
473   /// is fired if there is more than one clause is associated with the
474   /// directive). Returns nullptr if no clause of this kind is associated with
475   /// the directive.
476   template <typename SpecificClause>
getSingleClause(ArrayRef<OMPClause * > Clauses)477   static const SpecificClause *getSingleClause(ArrayRef<OMPClause *> Clauses) {
478     auto ClausesOfKind = getClausesOfKind<SpecificClause>(Clauses);
479 
480     if (ClausesOfKind.begin() != ClausesOfKind.end()) {
481       assert(std::next(ClausesOfKind.begin()) == ClausesOfKind.end() &&
482              "There are at least 2 clauses of the specified kind");
483       return *ClausesOfKind.begin();
484     }
485     return nullptr;
486   }
487 
488   template <typename SpecificClause>
getSingleClause()489   const SpecificClause *getSingleClause() const {
490     return getSingleClause<SpecificClause>(clauses());
491   }
492 
493   /// Returns true if the current directive has one or more clauses of a
494   /// specific kind.
495   template <typename SpecificClause>
hasClausesOfKind()496   bool hasClausesOfKind() const {
497     auto Clauses = getClausesOfKind<SpecificClause>();
498     return Clauses.begin() != Clauses.end();
499   }
500 
501   /// Returns starting location of directive kind.
getBeginLoc()502   SourceLocation getBeginLoc() const { return StartLoc; }
503   /// Returns ending location of directive.
getEndLoc()504   SourceLocation getEndLoc() const { return EndLoc; }
505 
506   /// Set starting location of directive kind.
507   ///
508   /// \param Loc New starting location of directive.
509   ///
setLocStart(SourceLocation Loc)510   void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
511   /// Set ending location of directive.
512   ///
513   /// \param Loc New ending location of directive.
514   ///
setLocEnd(SourceLocation Loc)515   void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
516 
517   /// Get number of clauses.
getNumClauses()518   unsigned getNumClauses() const {
519     if (!Data)
520       return 0;
521     return Data->getNumClauses();
522   }
523 
524   /// Returns specified clause.
525   ///
526   /// \param I Number of clause.
527   ///
getClause(unsigned I)528   OMPClause *getClause(unsigned I) const { return clauses()[I]; }
529 
530   /// Returns true if directive has associated statement.
hasAssociatedStmt()531   bool hasAssociatedStmt() const { return Data && Data->hasAssociatedStmt(); }
532 
533   /// Returns statement associated with the directive.
getAssociatedStmt()534   const Stmt *getAssociatedStmt() const {
535     return const_cast<OMPExecutableDirective *>(this)->getAssociatedStmt();
536   }
getAssociatedStmt()537   Stmt *getAssociatedStmt() {
538     assert(hasAssociatedStmt() &&
539            "Expected directive with the associated statement.");
540     return Data->getAssociatedStmt();
541   }
542 
543   /// Returns the captured statement associated with the
544   /// component region within the (combined) directive.
545   ///
546   /// \param RegionKind Component region kind.
getCapturedStmt(OpenMPDirectiveKind RegionKind)547   const CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
548     assert(hasAssociatedStmt() &&
549            "Expected directive with the associated statement.");
550     SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
551     getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
552     return Data->getCapturedStmt(RegionKind, CaptureRegions);
553   }
554 
555   /// Get innermost captured statement for the construct.
getInnermostCapturedStmt()556   CapturedStmt *getInnermostCapturedStmt() {
557     assert(hasAssociatedStmt() &&
558            "Expected directive with the associated statement.");
559     SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
560     getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
561     return Data->getInnermostCapturedStmt(CaptureRegions);
562   }
563 
getInnermostCapturedStmt()564   const CapturedStmt *getInnermostCapturedStmt() const {
565     return const_cast<OMPExecutableDirective *>(this)
566         ->getInnermostCapturedStmt();
567   }
568 
getDirectiveKind()569   OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
570 
classof(const Stmt * S)571   static bool classof(const Stmt *S) {
572     return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
573            S->getStmtClass() <= lastOMPExecutableDirectiveConstant;
574   }
575 
children()576   child_range children() {
577     if (!Data)
578       return child_range(child_iterator(), child_iterator());
579     return Data->getAssociatedStmtAsRange();
580   }
581 
children()582   const_child_range children() const {
583     return const_cast<OMPExecutableDirective *>(this)->children();
584   }
585 
clauses()586   ArrayRef<OMPClause *> clauses() const {
587     if (!Data)
588       return std::nullopt;
589     return Data->getClauses();
590   }
591 
592   /// Returns whether or not this is a Standalone directive.
593   ///
594   /// Stand-alone directives are executable directives
595   /// that have no associated user code.
596   bool isStandaloneDirective() const;
597 
598   /// Returns the AST node representing OpenMP structured-block of this
599   /// OpenMP executable directive,
600   /// Prerequisite: Executable Directive must not be Standalone directive.
getStructuredBlock()601   const Stmt *getStructuredBlock() const {
602     return const_cast<OMPExecutableDirective *>(this)->getStructuredBlock();
603   }
604   Stmt *getStructuredBlock();
605 
getRawStmt()606   const Stmt *getRawStmt() const {
607     return const_cast<OMPExecutableDirective *>(this)->getRawStmt();
608   }
getRawStmt()609   Stmt *getRawStmt() {
610     assert(hasAssociatedStmt() &&
611            "Expected directive with the associated statement.");
612     return Data->getRawStmt();
613   }
614 
getMappedDirective()615   OpenMPDirectiveKind getMappedDirective() const { return PrevMappedDirective; }
616 };
617 
618 /// This represents '#pragma omp parallel' directive.
619 ///
620 /// \code
621 /// #pragma omp parallel private(a,b) reduction(+: c,d)
622 /// \endcode
623 /// In this example directive '#pragma omp parallel' has clauses 'private'
624 /// with the variables 'a' and 'b' and 'reduction' with operator '+' and
625 /// variables 'c' and 'd'.
626 ///
627 class OMPParallelDirective : public OMPExecutableDirective {
628   friend class ASTStmtReader;
629   friend class OMPExecutableDirective;
630   /// true if the construct has inner cancel directive.
631   bool HasCancel = false;
632 
633   /// Build directive with the given start and end location.
634   ///
635   /// \param StartLoc Starting location of the directive (directive keyword).
636   /// \param EndLoc Ending Location of the directive.
637   ///
OMPParallelDirective(SourceLocation StartLoc,SourceLocation EndLoc)638   OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
639       : OMPExecutableDirective(OMPParallelDirectiveClass,
640                                llvm::omp::OMPD_parallel, StartLoc, EndLoc) {}
641 
642   /// Build an empty directive.
643   ///
OMPParallelDirective()644   explicit OMPParallelDirective()
645       : OMPExecutableDirective(OMPParallelDirectiveClass,
646                                llvm::omp::OMPD_parallel, SourceLocation(),
647                                SourceLocation()) {}
648 
649   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)650   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
651 
652   /// Set cancel state.
setHasCancel(bool Has)653   void setHasCancel(bool Has) { HasCancel = Has; }
654 
655 public:
656   /// Creates directive with a list of \a Clauses.
657   ///
658   /// \param C AST context.
659   /// \param StartLoc Starting location of the directive kind.
660   /// \param EndLoc Ending Location of the directive.
661   /// \param Clauses List of clauses.
662   /// \param AssociatedStmt Statement associated with the directive.
663   /// \param TaskRedRef Task reduction special reference expression to handle
664   /// taskgroup descriptor.
665   /// \param HasCancel true if this directive has inner cancel directive.
666   ///
667   static OMPParallelDirective *
668   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
669          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
670          bool HasCancel);
671 
672   /// Creates an empty directive with the place for \a N clauses.
673   ///
674   /// \param C AST context.
675   /// \param NumClauses Number of clauses.
676   ///
677   static OMPParallelDirective *CreateEmpty(const ASTContext &C,
678                                            unsigned NumClauses, EmptyShell);
679 
680   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()681   Expr *getTaskReductionRefExpr() {
682     return cast_or_null<Expr>(Data->getChildren()[0]);
683   }
getTaskReductionRefExpr()684   const Expr *getTaskReductionRefExpr() const {
685     return const_cast<OMPParallelDirective *>(this)->getTaskReductionRefExpr();
686   }
687 
688   /// Return true if current directive has inner cancel directive.
hasCancel()689   bool hasCancel() const { return HasCancel; }
690 
classof(const Stmt * T)691   static bool classof(const Stmt *T) {
692     return T->getStmtClass() == OMPParallelDirectiveClass;
693   }
694 };
695 
696 /// The base class for all loop-based directives, including loop transformation
697 /// directives.
698 class OMPLoopBasedDirective : public OMPExecutableDirective {
699   friend class ASTStmtReader;
700 
701 protected:
702   /// Number of collapsed loops as specified by 'collapse' clause.
703   unsigned NumAssociatedLoops = 0;
704 
705   /// Build instance of loop directive of class \a Kind.
706   ///
707   /// \param SC Statement class.
708   /// \param Kind Kind of OpenMP directive.
709   /// \param StartLoc Starting location of the directive (directive keyword).
710   /// \param EndLoc Ending location of the directive.
711   /// \param NumAssociatedLoops Number of loops associated with the construct.
712   ///
OMPLoopBasedDirective(StmtClass SC,OpenMPDirectiveKind Kind,SourceLocation StartLoc,SourceLocation EndLoc,unsigned NumAssociatedLoops)713   OMPLoopBasedDirective(StmtClass SC, OpenMPDirectiveKind Kind,
714                         SourceLocation StartLoc, SourceLocation EndLoc,
715                         unsigned NumAssociatedLoops)
716       : OMPExecutableDirective(SC, Kind, StartLoc, EndLoc),
717         NumAssociatedLoops(NumAssociatedLoops) {}
718 
719 public:
720   /// The expressions built to support OpenMP loops in combined/composite
721   /// pragmas (e.g. pragma omp distribute parallel for)
722   struct DistCombinedHelperExprs {
723     /// DistributeLowerBound - used when composing 'omp distribute' with
724     /// 'omp for' in a same construct.
725     Expr *LB;
726     /// DistributeUpperBound - used when composing 'omp distribute' with
727     /// 'omp for' in a same construct.
728     Expr *UB;
729     /// DistributeEnsureUpperBound - used when composing 'omp distribute'
730     ///  with 'omp for' in a same construct, EUB depends on DistUB
731     Expr *EUB;
732     /// Distribute loop iteration variable init used when composing 'omp
733     /// distribute'
734     ///  with 'omp for' in a same construct
735     Expr *Init;
736     /// Distribute Loop condition used when composing 'omp distribute'
737     ///  with 'omp for' in a same construct
738     Expr *Cond;
739     /// Update of LowerBound for statically scheduled omp loops for
740     /// outer loop in combined constructs (e.g. 'distribute parallel for')
741     Expr *NLB;
742     /// Update of UpperBound for statically scheduled omp loops for
743     /// outer loop in combined constructs (e.g. 'distribute parallel for')
744     Expr *NUB;
745     /// Distribute Loop condition used when composing 'omp distribute'
746     ///  with 'omp for' in a same construct when schedule is chunked.
747     Expr *DistCond;
748     /// 'omp parallel for' loop condition used when composed with
749     /// 'omp distribute' in the same construct and when schedule is
750     /// chunked and the chunk size is 1.
751     Expr *ParForInDistCond;
752   };
753 
754   /// The expressions built for the OpenMP loop CodeGen for the
755   /// whole collapsed loop nest.
756   struct HelperExprs {
757     /// Loop iteration variable.
758     Expr *IterationVarRef;
759     /// Loop last iteration number.
760     Expr *LastIteration;
761     /// Loop number of iterations.
762     Expr *NumIterations;
763     /// Calculation of last iteration.
764     Expr *CalcLastIteration;
765     /// Loop pre-condition.
766     Expr *PreCond;
767     /// Loop condition.
768     Expr *Cond;
769     /// Loop iteration variable init.
770     Expr *Init;
771     /// Loop increment.
772     Expr *Inc;
773     /// IsLastIteration - local flag variable passed to runtime.
774     Expr *IL;
775     /// LowerBound - local variable passed to runtime.
776     Expr *LB;
777     /// UpperBound - local variable passed to runtime.
778     Expr *UB;
779     /// Stride - local variable passed to runtime.
780     Expr *ST;
781     /// EnsureUpperBound -- expression UB = min(UB, NumIterations).
782     Expr *EUB;
783     /// Update of LowerBound for statically scheduled 'omp for' loops.
784     Expr *NLB;
785     /// Update of UpperBound for statically scheduled 'omp for' loops.
786     Expr *NUB;
787     /// PreviousLowerBound - local variable passed to runtime in the
788     /// enclosing schedule or null if that does not apply.
789     Expr *PrevLB;
790     /// PreviousUpperBound - local variable passed to runtime in the
791     /// enclosing schedule or null if that does not apply.
792     Expr *PrevUB;
793     /// DistInc - increment expression for distribute loop when found
794     /// combined with a further loop level (e.g. in 'distribute parallel for')
795     /// expression IV = IV + ST
796     Expr *DistInc;
797     /// PrevEUB - expression similar to EUB but to be used when loop
798     /// scheduling uses PrevLB and PrevUB (e.g.  in 'distribute parallel for'
799     /// when ensuring that the UB is either the calculated UB by the runtime or
800     /// the end of the assigned distribute chunk)
801     /// expression UB = min (UB, PrevUB)
802     Expr *PrevEUB;
803     /// Counters Loop counters.
804     SmallVector<Expr *, 4> Counters;
805     /// PrivateCounters Loop counters.
806     SmallVector<Expr *, 4> PrivateCounters;
807     /// Expressions for loop counters inits for CodeGen.
808     SmallVector<Expr *, 4> Inits;
809     /// Expressions for loop counters update for CodeGen.
810     SmallVector<Expr *, 4> Updates;
811     /// Final loop counter values for GodeGen.
812     SmallVector<Expr *, 4> Finals;
813     /// List of counters required for the generation of the non-rectangular
814     /// loops.
815     SmallVector<Expr *, 4> DependentCounters;
816     /// List of initializers required for the generation of the non-rectangular
817     /// loops.
818     SmallVector<Expr *, 4> DependentInits;
819     /// List of final conditions required for the generation of the
820     /// non-rectangular loops.
821     SmallVector<Expr *, 4> FinalsConditions;
822     /// Init statement for all captured expressions.
823     Stmt *PreInits;
824 
825     /// Expressions used when combining OpenMP loop pragmas
826     DistCombinedHelperExprs DistCombinedFields;
827 
828     /// Check if all the expressions are built (does not check the
829     /// worksharing ones).
builtAllHelperExprs830     bool builtAll() {
831       return IterationVarRef != nullptr && LastIteration != nullptr &&
832              NumIterations != nullptr && PreCond != nullptr &&
833              Cond != nullptr && Init != nullptr && Inc != nullptr;
834     }
835 
836     /// Initialize all the fields to null.
837     /// \param Size Number of elements in the
838     /// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions
839     /// arrays.
clearHelperExprs840     void clear(unsigned Size) {
841       IterationVarRef = nullptr;
842       LastIteration = nullptr;
843       CalcLastIteration = nullptr;
844       PreCond = nullptr;
845       Cond = nullptr;
846       Init = nullptr;
847       Inc = nullptr;
848       IL = nullptr;
849       LB = nullptr;
850       UB = nullptr;
851       ST = nullptr;
852       EUB = nullptr;
853       NLB = nullptr;
854       NUB = nullptr;
855       NumIterations = nullptr;
856       PrevLB = nullptr;
857       PrevUB = nullptr;
858       DistInc = nullptr;
859       PrevEUB = nullptr;
860       Counters.resize(Size);
861       PrivateCounters.resize(Size);
862       Inits.resize(Size);
863       Updates.resize(Size);
864       Finals.resize(Size);
865       DependentCounters.resize(Size);
866       DependentInits.resize(Size);
867       FinalsConditions.resize(Size);
868       for (unsigned I = 0; I < Size; ++I) {
869         Counters[I] = nullptr;
870         PrivateCounters[I] = nullptr;
871         Inits[I] = nullptr;
872         Updates[I] = nullptr;
873         Finals[I] = nullptr;
874         DependentCounters[I] = nullptr;
875         DependentInits[I] = nullptr;
876         FinalsConditions[I] = nullptr;
877       }
878       PreInits = nullptr;
879       DistCombinedFields.LB = nullptr;
880       DistCombinedFields.UB = nullptr;
881       DistCombinedFields.EUB = nullptr;
882       DistCombinedFields.Init = nullptr;
883       DistCombinedFields.Cond = nullptr;
884       DistCombinedFields.NLB = nullptr;
885       DistCombinedFields.NUB = nullptr;
886       DistCombinedFields.DistCond = nullptr;
887       DistCombinedFields.ParForInDistCond = nullptr;
888     }
889   };
890 
891   /// Get number of collapsed loops.
getLoopsNumber()892   unsigned getLoopsNumber() const { return NumAssociatedLoops; }
893 
894   /// Try to find the next loop sub-statement in the specified statement \p
895   /// CurStmt.
896   /// \param TryImperfectlyNestedLoops true, if we need to try to look for the
897   /// imperfectly nested loop.
898   static Stmt *tryToFindNextInnerLoop(Stmt *CurStmt,
899                                       bool TryImperfectlyNestedLoops);
tryToFindNextInnerLoop(const Stmt * CurStmt,bool TryImperfectlyNestedLoops)900   static const Stmt *tryToFindNextInnerLoop(const Stmt *CurStmt,
901                                             bool TryImperfectlyNestedLoops) {
902     return tryToFindNextInnerLoop(const_cast<Stmt *>(CurStmt),
903                                   TryImperfectlyNestedLoops);
904   }
905 
906   /// Calls the specified callback function for all the loops in \p CurStmt,
907   /// from the outermost to the innermost.
908   static bool
909   doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops,
910                 unsigned NumLoops,
911                 llvm::function_ref<bool(unsigned, Stmt *)> Callback,
912                 llvm::function_ref<void(OMPLoopTransformationDirective *)>
913                     OnTransformationCallback);
914   static bool
doForAllLoops(const Stmt * CurStmt,bool TryImperfectlyNestedLoops,unsigned NumLoops,llvm::function_ref<bool (unsigned,const Stmt *)> Callback,llvm::function_ref<void (const OMPLoopTransformationDirective *)> OnTransformationCallback)915   doForAllLoops(const Stmt *CurStmt, bool TryImperfectlyNestedLoops,
916                 unsigned NumLoops,
917                 llvm::function_ref<bool(unsigned, const Stmt *)> Callback,
918                 llvm::function_ref<void(const OMPLoopTransformationDirective *)>
919                     OnTransformationCallback) {
920     auto &&NewCallback = [Callback](unsigned Cnt, Stmt *CurStmt) {
921       return Callback(Cnt, CurStmt);
922     };
923     auto &&NewTransformCb =
924         [OnTransformationCallback](OMPLoopTransformationDirective *A) {
925           OnTransformationCallback(A);
926         };
927     return doForAllLoops(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
928                          NumLoops, NewCallback, NewTransformCb);
929   }
930 
931   /// Calls the specified callback function for all the loops in \p CurStmt,
932   /// from the outermost to the innermost.
933   static bool
doForAllLoops(Stmt * CurStmt,bool TryImperfectlyNestedLoops,unsigned NumLoops,llvm::function_ref<bool (unsigned,Stmt *)> Callback)934   doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops,
935                 unsigned NumLoops,
936                 llvm::function_ref<bool(unsigned, Stmt *)> Callback) {
937     auto &&TransformCb = [](OMPLoopTransformationDirective *) {};
938     return doForAllLoops(CurStmt, TryImperfectlyNestedLoops, NumLoops, Callback,
939                          TransformCb);
940   }
941   static bool
doForAllLoops(const Stmt * CurStmt,bool TryImperfectlyNestedLoops,unsigned NumLoops,llvm::function_ref<bool (unsigned,const Stmt *)> Callback)942   doForAllLoops(const Stmt *CurStmt, bool TryImperfectlyNestedLoops,
943                 unsigned NumLoops,
944                 llvm::function_ref<bool(unsigned, const Stmt *)> Callback) {
945     auto &&NewCallback = [Callback](unsigned Cnt, const Stmt *CurStmt) {
946       return Callback(Cnt, CurStmt);
947     };
948     return doForAllLoops(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
949                          NumLoops, NewCallback);
950   }
951 
952   /// Calls the specified callback function for all the loop bodies in \p
953   /// CurStmt, from the outermost loop to the innermost.
954   static void doForAllLoopsBodies(
955       Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
956       llvm::function_ref<void(unsigned, Stmt *, Stmt *)> Callback);
doForAllLoopsBodies(const Stmt * CurStmt,bool TryImperfectlyNestedLoops,unsigned NumLoops,llvm::function_ref<void (unsigned,const Stmt *,const Stmt *)> Callback)957   static void doForAllLoopsBodies(
958       const Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
959       llvm::function_ref<void(unsigned, const Stmt *, const Stmt *)> Callback) {
960     auto &&NewCallback = [Callback](unsigned Cnt, Stmt *Loop, Stmt *Body) {
961       Callback(Cnt, Loop, Body);
962     };
963     doForAllLoopsBodies(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
964                         NumLoops, NewCallback);
965   }
966 
classof(const Stmt * T)967   static bool classof(const Stmt *T) {
968     if (auto *D = dyn_cast<OMPExecutableDirective>(T))
969       return isOpenMPLoopDirective(D->getDirectiveKind());
970     return false;
971   }
972 };
973 
974 /// The base class for all loop transformation directives.
975 class OMPLoopTransformationDirective : public OMPLoopBasedDirective {
976   friend class ASTStmtReader;
977 
978   /// Number of loops generated by this loop transformation.
979   unsigned NumGeneratedLoops = 0;
980 
981 protected:
OMPLoopTransformationDirective(StmtClass SC,OpenMPDirectiveKind Kind,SourceLocation StartLoc,SourceLocation EndLoc,unsigned NumAssociatedLoops)982   explicit OMPLoopTransformationDirective(StmtClass SC,
983                                           OpenMPDirectiveKind Kind,
984                                           SourceLocation StartLoc,
985                                           SourceLocation EndLoc,
986                                           unsigned NumAssociatedLoops)
987       : OMPLoopBasedDirective(SC, Kind, StartLoc, EndLoc, NumAssociatedLoops) {}
988 
989   /// Set the number of loops generated by this loop transformation.
setNumGeneratedLoops(unsigned Num)990   void setNumGeneratedLoops(unsigned Num) { NumGeneratedLoops = Num; }
991 
992 public:
993   /// Return the number of associated (consumed) loops.
getNumAssociatedLoops()994   unsigned getNumAssociatedLoops() const { return getLoopsNumber(); }
995 
996   /// Return the number of loops generated by this loop transformation.
getNumGeneratedLoops()997   unsigned getNumGeneratedLoops() const { return NumGeneratedLoops; }
998 
999   /// Get the de-sugared statements after the loop transformation.
1000   ///
1001   /// Might be nullptr if either the directive generates no loops and is handled
1002   /// directly in CodeGen, or resolving a template-dependence context is
1003   /// required.
1004   Stmt *getTransformedStmt() const;
1005 
1006   /// Return preinits statement.
1007   Stmt *getPreInits() const;
1008 
classof(const Stmt * T)1009   static bool classof(const Stmt *T) {
1010     Stmt::StmtClass C = T->getStmtClass();
1011     return C == OMPTileDirectiveClass || C == OMPUnrollDirectiveClass ||
1012            C == OMPReverseDirectiveClass || C == OMPInterchangeDirectiveClass;
1013   }
1014 };
1015 
1016 /// This is a common base class for loop directives ('omp simd', 'omp
1017 /// for', 'omp for simd' etc.). It is responsible for the loop code generation.
1018 ///
1019 class OMPLoopDirective : public OMPLoopBasedDirective {
1020   friend class ASTStmtReader;
1021 
1022   /// Offsets to the stored exprs.
1023   /// This enumeration contains offsets to all the pointers to children
1024   /// expressions stored in OMPLoopDirective.
1025   /// The first 9 children are necessary for all the loop directives,
1026   /// the next 8 are specific to the worksharing ones, and the next 11 are
1027   /// used for combined constructs containing two pragmas associated to loops.
1028   /// After the fixed children, three arrays of length NumAssociatedLoops are
1029   /// allocated: loop counters, their updates and final values.
1030   /// PrevLowerBound and PrevUpperBound are used to communicate blocking
1031   /// information in composite constructs which require loop blocking
1032   /// DistInc is used to generate the increment expression for the distribute
1033   /// loop when combined with a further nested loop
1034   /// PrevEnsureUpperBound is used as the EnsureUpperBound expression for the
1035   /// for loop when combined with a previous distribute loop in the same pragma
1036   /// (e.g. 'distribute parallel for')
1037   ///
1038   enum {
1039     IterationVariableOffset = 0,
1040     LastIterationOffset = 1,
1041     CalcLastIterationOffset = 2,
1042     PreConditionOffset = 3,
1043     CondOffset = 4,
1044     InitOffset = 5,
1045     IncOffset = 6,
1046     PreInitsOffset = 7,
1047     // The '...End' enumerators do not correspond to child expressions - they
1048     // specify the offset to the end (and start of the following counters/
1049     // updates/finals/dependent_counters/dependent_inits/finals_conditions
1050     // arrays).
1051     DefaultEnd = 8,
1052     // The following 8 exprs are used by worksharing and distribute loops only.
1053     IsLastIterVariableOffset = 8,
1054     LowerBoundVariableOffset = 9,
1055     UpperBoundVariableOffset = 10,
1056     StrideVariableOffset = 11,
1057     EnsureUpperBoundOffset = 12,
1058     NextLowerBoundOffset = 13,
1059     NextUpperBoundOffset = 14,
1060     NumIterationsOffset = 15,
1061     // Offset to the end for worksharing loop directives.
1062     WorksharingEnd = 16,
1063     PrevLowerBoundVariableOffset = 16,
1064     PrevUpperBoundVariableOffset = 17,
1065     DistIncOffset = 18,
1066     PrevEnsureUpperBoundOffset = 19,
1067     CombinedLowerBoundVariableOffset = 20,
1068     CombinedUpperBoundVariableOffset = 21,
1069     CombinedEnsureUpperBoundOffset = 22,
1070     CombinedInitOffset = 23,
1071     CombinedConditionOffset = 24,
1072     CombinedNextLowerBoundOffset = 25,
1073     CombinedNextUpperBoundOffset = 26,
1074     CombinedDistConditionOffset = 27,
1075     CombinedParForInDistConditionOffset = 28,
1076     // Offset to the end (and start of the following
1077     // counters/updates/finals/dependent_counters/dependent_inits/finals_conditions
1078     // arrays) for combined distribute loop directives.
1079     CombinedDistributeEnd = 29,
1080   };
1081 
1082   /// Get the counters storage.
getCounters()1083   MutableArrayRef<Expr *> getCounters() {
1084     auto **Storage = reinterpret_cast<Expr **>(
1085         &Data->getChildren()[getArraysOffset(getDirectiveKind())]);
1086     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1087   }
1088 
1089   /// Get the private counters storage.
getPrivateCounters()1090   MutableArrayRef<Expr *> getPrivateCounters() {
1091     auto **Storage = reinterpret_cast<Expr **>(
1092         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1093                              getLoopsNumber()]);
1094     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1095   }
1096 
1097   /// Get the updates storage.
getInits()1098   MutableArrayRef<Expr *> getInits() {
1099     auto **Storage = reinterpret_cast<Expr **>(
1100         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1101                              2 * getLoopsNumber()]);
1102     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1103   }
1104 
1105   /// Get the updates storage.
getUpdates()1106   MutableArrayRef<Expr *> getUpdates() {
1107     auto **Storage = reinterpret_cast<Expr **>(
1108         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1109                              3 * getLoopsNumber()]);
1110     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1111   }
1112 
1113   /// Get the final counter updates storage.
getFinals()1114   MutableArrayRef<Expr *> getFinals() {
1115     auto **Storage = reinterpret_cast<Expr **>(
1116         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1117                              4 * getLoopsNumber()]);
1118     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1119   }
1120 
1121   /// Get the dependent counters storage.
getDependentCounters()1122   MutableArrayRef<Expr *> getDependentCounters() {
1123     auto **Storage = reinterpret_cast<Expr **>(
1124         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1125                              5 * getLoopsNumber()]);
1126     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1127   }
1128 
1129   /// Get the dependent inits storage.
getDependentInits()1130   MutableArrayRef<Expr *> getDependentInits() {
1131     auto **Storage = reinterpret_cast<Expr **>(
1132         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1133                              6 * getLoopsNumber()]);
1134     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1135   }
1136 
1137   /// Get the finals conditions storage.
getFinalsConditions()1138   MutableArrayRef<Expr *> getFinalsConditions() {
1139     auto **Storage = reinterpret_cast<Expr **>(
1140         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1141                              7 * getLoopsNumber()]);
1142     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1143   }
1144 
1145 protected:
1146   /// Build instance of loop directive of class \a Kind.
1147   ///
1148   /// \param SC Statement class.
1149   /// \param Kind Kind of OpenMP directive.
1150   /// \param StartLoc Starting location of the directive (directive keyword).
1151   /// \param EndLoc Ending location of the directive.
1152   /// \param CollapsedNum Number of collapsed loops from 'collapse' clause.
1153   ///
OMPLoopDirective(StmtClass SC,OpenMPDirectiveKind Kind,SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)1154   OMPLoopDirective(StmtClass SC, OpenMPDirectiveKind Kind,
1155                    SourceLocation StartLoc, SourceLocation EndLoc,
1156                    unsigned CollapsedNum)
1157       : OMPLoopBasedDirective(SC, Kind, StartLoc, EndLoc, CollapsedNum) {}
1158 
1159   /// Offset to the start of children expression arrays.
getArraysOffset(OpenMPDirectiveKind Kind)1160   static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
1161     if (isOpenMPLoopBoundSharingDirective(Kind))
1162       return CombinedDistributeEnd;
1163     if (isOpenMPWorksharingDirective(Kind) || isOpenMPTaskLoopDirective(Kind) ||
1164         isOpenMPGenericLoopDirective(Kind) || isOpenMPDistributeDirective(Kind))
1165       return WorksharingEnd;
1166     return DefaultEnd;
1167   }
1168 
1169   /// Children number.
numLoopChildren(unsigned CollapsedNum,OpenMPDirectiveKind Kind)1170   static unsigned numLoopChildren(unsigned CollapsedNum,
1171                                   OpenMPDirectiveKind Kind) {
1172     return getArraysOffset(Kind) +
1173            8 * CollapsedNum; // Counters, PrivateCounters, Inits,
1174                              // Updates, Finals, DependentCounters,
1175                              // DependentInits, FinalsConditions.
1176   }
1177 
setIterationVariable(Expr * IV)1178   void setIterationVariable(Expr *IV) {
1179     Data->getChildren()[IterationVariableOffset] = IV;
1180   }
setLastIteration(Expr * LI)1181   void setLastIteration(Expr *LI) {
1182     Data->getChildren()[LastIterationOffset] = LI;
1183   }
setCalcLastIteration(Expr * CLI)1184   void setCalcLastIteration(Expr *CLI) {
1185     Data->getChildren()[CalcLastIterationOffset] = CLI;
1186   }
setPreCond(Expr * PC)1187   void setPreCond(Expr *PC) { Data->getChildren()[PreConditionOffset] = PC; }
setCond(Expr * Cond)1188   void setCond(Expr *Cond) { Data->getChildren()[CondOffset] = Cond; }
setInit(Expr * Init)1189   void setInit(Expr *Init) { Data->getChildren()[InitOffset] = Init; }
setInc(Expr * Inc)1190   void setInc(Expr *Inc) { Data->getChildren()[IncOffset] = Inc; }
setPreInits(Stmt * PreInits)1191   void setPreInits(Stmt *PreInits) {
1192     Data->getChildren()[PreInitsOffset] = PreInits;
1193   }
setIsLastIterVariable(Expr * IL)1194   void setIsLastIterVariable(Expr *IL) {
1195     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1196             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1197             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1198             isOpenMPDistributeDirective(getDirectiveKind())) &&
1199            "expected worksharing loop directive");
1200     Data->getChildren()[IsLastIterVariableOffset] = IL;
1201   }
setLowerBoundVariable(Expr * LB)1202   void setLowerBoundVariable(Expr *LB) {
1203     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1204             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1205             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1206             isOpenMPDistributeDirective(getDirectiveKind())) &&
1207            "expected worksharing loop directive");
1208     Data->getChildren()[LowerBoundVariableOffset] = LB;
1209   }
setUpperBoundVariable(Expr * UB)1210   void setUpperBoundVariable(Expr *UB) {
1211     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1212             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1213             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1214             isOpenMPDistributeDirective(getDirectiveKind())) &&
1215            "expected worksharing loop directive");
1216     Data->getChildren()[UpperBoundVariableOffset] = UB;
1217   }
setStrideVariable(Expr * ST)1218   void setStrideVariable(Expr *ST) {
1219     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1220             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1221             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1222             isOpenMPDistributeDirective(getDirectiveKind())) &&
1223            "expected worksharing loop directive");
1224     Data->getChildren()[StrideVariableOffset] = ST;
1225   }
setEnsureUpperBound(Expr * EUB)1226   void setEnsureUpperBound(Expr *EUB) {
1227     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1228             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1229             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1230             isOpenMPDistributeDirective(getDirectiveKind())) &&
1231            "expected worksharing loop directive");
1232     Data->getChildren()[EnsureUpperBoundOffset] = EUB;
1233   }
setNextLowerBound(Expr * NLB)1234   void setNextLowerBound(Expr *NLB) {
1235     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1236             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1237             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1238             isOpenMPDistributeDirective(getDirectiveKind())) &&
1239            "expected worksharing loop directive");
1240     Data->getChildren()[NextLowerBoundOffset] = NLB;
1241   }
setNextUpperBound(Expr * NUB)1242   void setNextUpperBound(Expr *NUB) {
1243     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1244             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1245             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1246             isOpenMPDistributeDirective(getDirectiveKind())) &&
1247            "expected worksharing loop directive");
1248     Data->getChildren()[NextUpperBoundOffset] = NUB;
1249   }
setNumIterations(Expr * NI)1250   void setNumIterations(Expr *NI) {
1251     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1252             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1253             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1254             isOpenMPDistributeDirective(getDirectiveKind())) &&
1255            "expected worksharing loop directive");
1256     Data->getChildren()[NumIterationsOffset] = NI;
1257   }
setPrevLowerBoundVariable(Expr * PrevLB)1258   void setPrevLowerBoundVariable(Expr *PrevLB) {
1259     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1260            "expected loop bound sharing directive");
1261     Data->getChildren()[PrevLowerBoundVariableOffset] = PrevLB;
1262   }
setPrevUpperBoundVariable(Expr * PrevUB)1263   void setPrevUpperBoundVariable(Expr *PrevUB) {
1264     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1265            "expected loop bound sharing directive");
1266     Data->getChildren()[PrevUpperBoundVariableOffset] = PrevUB;
1267   }
setDistInc(Expr * DistInc)1268   void setDistInc(Expr *DistInc) {
1269     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1270            "expected loop bound sharing directive");
1271     Data->getChildren()[DistIncOffset] = DistInc;
1272   }
setPrevEnsureUpperBound(Expr * PrevEUB)1273   void setPrevEnsureUpperBound(Expr *PrevEUB) {
1274     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1275            "expected loop bound sharing directive");
1276     Data->getChildren()[PrevEnsureUpperBoundOffset] = PrevEUB;
1277   }
setCombinedLowerBoundVariable(Expr * CombLB)1278   void setCombinedLowerBoundVariable(Expr *CombLB) {
1279     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1280            "expected loop bound sharing directive");
1281     Data->getChildren()[CombinedLowerBoundVariableOffset] = CombLB;
1282   }
setCombinedUpperBoundVariable(Expr * CombUB)1283   void setCombinedUpperBoundVariable(Expr *CombUB) {
1284     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1285            "expected loop bound sharing directive");
1286     Data->getChildren()[CombinedUpperBoundVariableOffset] = CombUB;
1287   }
setCombinedEnsureUpperBound(Expr * CombEUB)1288   void setCombinedEnsureUpperBound(Expr *CombEUB) {
1289     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1290            "expected loop bound sharing directive");
1291     Data->getChildren()[CombinedEnsureUpperBoundOffset] = CombEUB;
1292   }
setCombinedInit(Expr * CombInit)1293   void setCombinedInit(Expr *CombInit) {
1294     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1295            "expected loop bound sharing directive");
1296     Data->getChildren()[CombinedInitOffset] = CombInit;
1297   }
setCombinedCond(Expr * CombCond)1298   void setCombinedCond(Expr *CombCond) {
1299     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1300            "expected loop bound sharing directive");
1301     Data->getChildren()[CombinedConditionOffset] = CombCond;
1302   }
setCombinedNextLowerBound(Expr * CombNLB)1303   void setCombinedNextLowerBound(Expr *CombNLB) {
1304     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1305            "expected loop bound sharing directive");
1306     Data->getChildren()[CombinedNextLowerBoundOffset] = CombNLB;
1307   }
setCombinedNextUpperBound(Expr * CombNUB)1308   void setCombinedNextUpperBound(Expr *CombNUB) {
1309     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1310            "expected loop bound sharing directive");
1311     Data->getChildren()[CombinedNextUpperBoundOffset] = CombNUB;
1312   }
setCombinedDistCond(Expr * CombDistCond)1313   void setCombinedDistCond(Expr *CombDistCond) {
1314     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1315            "expected loop bound distribute sharing directive");
1316     Data->getChildren()[CombinedDistConditionOffset] = CombDistCond;
1317   }
setCombinedParForInDistCond(Expr * CombParForInDistCond)1318   void setCombinedParForInDistCond(Expr *CombParForInDistCond) {
1319     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1320            "expected loop bound distribute sharing directive");
1321     Data->getChildren()[CombinedParForInDistConditionOffset] =
1322         CombParForInDistCond;
1323   }
1324   void setCounters(ArrayRef<Expr *> A);
1325   void setPrivateCounters(ArrayRef<Expr *> A);
1326   void setInits(ArrayRef<Expr *> A);
1327   void setUpdates(ArrayRef<Expr *> A);
1328   void setFinals(ArrayRef<Expr *> A);
1329   void setDependentCounters(ArrayRef<Expr *> A);
1330   void setDependentInits(ArrayRef<Expr *> A);
1331   void setFinalsConditions(ArrayRef<Expr *> A);
1332 
1333 public:
getIterationVariable()1334   Expr *getIterationVariable() const {
1335     return cast<Expr>(Data->getChildren()[IterationVariableOffset]);
1336   }
getLastIteration()1337   Expr *getLastIteration() const {
1338     return cast<Expr>(Data->getChildren()[LastIterationOffset]);
1339   }
getCalcLastIteration()1340   Expr *getCalcLastIteration() const {
1341     return cast<Expr>(Data->getChildren()[CalcLastIterationOffset]);
1342   }
getPreCond()1343   Expr *getPreCond() const {
1344     return cast<Expr>(Data->getChildren()[PreConditionOffset]);
1345   }
getCond()1346   Expr *getCond() const { return cast<Expr>(Data->getChildren()[CondOffset]); }
getInit()1347   Expr *getInit() const { return cast<Expr>(Data->getChildren()[InitOffset]); }
getInc()1348   Expr *getInc() const { return cast<Expr>(Data->getChildren()[IncOffset]); }
getPreInits()1349   const Stmt *getPreInits() const {
1350     return Data->getChildren()[PreInitsOffset];
1351   }
getPreInits()1352   Stmt *getPreInits() { return Data->getChildren()[PreInitsOffset]; }
getIsLastIterVariable()1353   Expr *getIsLastIterVariable() const {
1354     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1355             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1356             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1357             isOpenMPDistributeDirective(getDirectiveKind())) &&
1358            "expected worksharing loop directive");
1359     return cast<Expr>(Data->getChildren()[IsLastIterVariableOffset]);
1360   }
getLowerBoundVariable()1361   Expr *getLowerBoundVariable() const {
1362     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1363             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1364             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1365             isOpenMPDistributeDirective(getDirectiveKind())) &&
1366            "expected worksharing loop directive");
1367     return cast<Expr>(Data->getChildren()[LowerBoundVariableOffset]);
1368   }
getUpperBoundVariable()1369   Expr *getUpperBoundVariable() const {
1370     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1371             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1372             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1373             isOpenMPDistributeDirective(getDirectiveKind())) &&
1374            "expected worksharing loop directive");
1375     return cast<Expr>(Data->getChildren()[UpperBoundVariableOffset]);
1376   }
getStrideVariable()1377   Expr *getStrideVariable() const {
1378     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1379             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1380             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1381             isOpenMPDistributeDirective(getDirectiveKind())) &&
1382            "expected worksharing loop directive");
1383     return cast<Expr>(Data->getChildren()[StrideVariableOffset]);
1384   }
getEnsureUpperBound()1385   Expr *getEnsureUpperBound() const {
1386     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1387             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1388             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1389             isOpenMPDistributeDirective(getDirectiveKind())) &&
1390            "expected worksharing loop directive");
1391     return cast<Expr>(Data->getChildren()[EnsureUpperBoundOffset]);
1392   }
getNextLowerBound()1393   Expr *getNextLowerBound() const {
1394     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1395             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1396             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1397             isOpenMPDistributeDirective(getDirectiveKind())) &&
1398            "expected worksharing loop directive");
1399     return cast<Expr>(Data->getChildren()[NextLowerBoundOffset]);
1400   }
getNextUpperBound()1401   Expr *getNextUpperBound() const {
1402     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1403             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1404             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1405             isOpenMPDistributeDirective(getDirectiveKind())) &&
1406            "expected worksharing loop directive");
1407     return cast<Expr>(Data->getChildren()[NextUpperBoundOffset]);
1408   }
getNumIterations()1409   Expr *getNumIterations() const {
1410     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1411             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1412             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1413             isOpenMPDistributeDirective(getDirectiveKind())) &&
1414            "expected worksharing loop directive");
1415     return cast<Expr>(Data->getChildren()[NumIterationsOffset]);
1416   }
getPrevLowerBoundVariable()1417   Expr *getPrevLowerBoundVariable() const {
1418     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1419            "expected loop bound sharing directive");
1420     return cast<Expr>(Data->getChildren()[PrevLowerBoundVariableOffset]);
1421   }
getPrevUpperBoundVariable()1422   Expr *getPrevUpperBoundVariable() const {
1423     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1424            "expected loop bound sharing directive");
1425     return cast<Expr>(Data->getChildren()[PrevUpperBoundVariableOffset]);
1426   }
getDistInc()1427   Expr *getDistInc() const {
1428     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1429            "expected loop bound sharing directive");
1430     return cast<Expr>(Data->getChildren()[DistIncOffset]);
1431   }
getPrevEnsureUpperBound()1432   Expr *getPrevEnsureUpperBound() const {
1433     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1434            "expected loop bound sharing directive");
1435     return cast<Expr>(Data->getChildren()[PrevEnsureUpperBoundOffset]);
1436   }
getCombinedLowerBoundVariable()1437   Expr *getCombinedLowerBoundVariable() const {
1438     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1439            "expected loop bound sharing directive");
1440     return cast<Expr>(Data->getChildren()[CombinedLowerBoundVariableOffset]);
1441   }
getCombinedUpperBoundVariable()1442   Expr *getCombinedUpperBoundVariable() const {
1443     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1444            "expected loop bound sharing directive");
1445     return cast<Expr>(Data->getChildren()[CombinedUpperBoundVariableOffset]);
1446   }
getCombinedEnsureUpperBound()1447   Expr *getCombinedEnsureUpperBound() const {
1448     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1449            "expected loop bound sharing directive");
1450     return cast<Expr>(Data->getChildren()[CombinedEnsureUpperBoundOffset]);
1451   }
getCombinedInit()1452   Expr *getCombinedInit() const {
1453     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1454            "expected loop bound sharing directive");
1455     return cast<Expr>(Data->getChildren()[CombinedInitOffset]);
1456   }
getCombinedCond()1457   Expr *getCombinedCond() const {
1458     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1459            "expected loop bound sharing directive");
1460     return cast<Expr>(Data->getChildren()[CombinedConditionOffset]);
1461   }
getCombinedNextLowerBound()1462   Expr *getCombinedNextLowerBound() const {
1463     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1464            "expected loop bound sharing directive");
1465     return cast<Expr>(Data->getChildren()[CombinedNextLowerBoundOffset]);
1466   }
getCombinedNextUpperBound()1467   Expr *getCombinedNextUpperBound() const {
1468     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1469            "expected loop bound sharing directive");
1470     return cast<Expr>(Data->getChildren()[CombinedNextUpperBoundOffset]);
1471   }
getCombinedDistCond()1472   Expr *getCombinedDistCond() const {
1473     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1474            "expected loop bound distribute sharing directive");
1475     return cast<Expr>(Data->getChildren()[CombinedDistConditionOffset]);
1476   }
getCombinedParForInDistCond()1477   Expr *getCombinedParForInDistCond() const {
1478     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1479            "expected loop bound distribute sharing directive");
1480     return cast<Expr>(Data->getChildren()[CombinedParForInDistConditionOffset]);
1481   }
1482   Stmt *getBody();
getBody()1483   const Stmt *getBody() const {
1484     return const_cast<OMPLoopDirective *>(this)->getBody();
1485   }
1486 
counters()1487   ArrayRef<Expr *> counters() { return getCounters(); }
1488 
counters()1489   ArrayRef<Expr *> counters() const {
1490     return const_cast<OMPLoopDirective *>(this)->getCounters();
1491   }
1492 
private_counters()1493   ArrayRef<Expr *> private_counters() { return getPrivateCounters(); }
1494 
private_counters()1495   ArrayRef<Expr *> private_counters() const {
1496     return const_cast<OMPLoopDirective *>(this)->getPrivateCounters();
1497   }
1498 
inits()1499   ArrayRef<Expr *> inits() { return getInits(); }
1500 
inits()1501   ArrayRef<Expr *> inits() const {
1502     return const_cast<OMPLoopDirective *>(this)->getInits();
1503   }
1504 
updates()1505   ArrayRef<Expr *> updates() { return getUpdates(); }
1506 
updates()1507   ArrayRef<Expr *> updates() const {
1508     return const_cast<OMPLoopDirective *>(this)->getUpdates();
1509   }
1510 
finals()1511   ArrayRef<Expr *> finals() { return getFinals(); }
1512 
finals()1513   ArrayRef<Expr *> finals() const {
1514     return const_cast<OMPLoopDirective *>(this)->getFinals();
1515   }
1516 
dependent_counters()1517   ArrayRef<Expr *> dependent_counters() { return getDependentCounters(); }
1518 
dependent_counters()1519   ArrayRef<Expr *> dependent_counters() const {
1520     return const_cast<OMPLoopDirective *>(this)->getDependentCounters();
1521   }
1522 
dependent_inits()1523   ArrayRef<Expr *> dependent_inits() { return getDependentInits(); }
1524 
dependent_inits()1525   ArrayRef<Expr *> dependent_inits() const {
1526     return const_cast<OMPLoopDirective *>(this)->getDependentInits();
1527   }
1528 
finals_conditions()1529   ArrayRef<Expr *> finals_conditions() { return getFinalsConditions(); }
1530 
finals_conditions()1531   ArrayRef<Expr *> finals_conditions() const {
1532     return const_cast<OMPLoopDirective *>(this)->getFinalsConditions();
1533   }
1534 
classof(const Stmt * T)1535   static bool classof(const Stmt *T) {
1536     return T->getStmtClass() == OMPSimdDirectiveClass ||
1537            T->getStmtClass() == OMPForDirectiveClass ||
1538            T->getStmtClass() == OMPForSimdDirectiveClass ||
1539            T->getStmtClass() == OMPParallelForDirectiveClass ||
1540            T->getStmtClass() == OMPParallelForSimdDirectiveClass ||
1541            T->getStmtClass() == OMPTaskLoopDirectiveClass ||
1542            T->getStmtClass() == OMPTaskLoopSimdDirectiveClass ||
1543            T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass ||
1544            T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass ||
1545            T->getStmtClass() == OMPMasterTaskLoopDirectiveClass ||
1546            T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass ||
1547            T->getStmtClass() == OMPGenericLoopDirectiveClass ||
1548            T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass ||
1549            T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass ||
1550            T->getStmtClass() == OMPParallelGenericLoopDirectiveClass ||
1551            T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass ||
1552            T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass ||
1553            T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass ||
1554            T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass ||
1555            T->getStmtClass() == OMPParallelMasterTaskLoopSimdDirectiveClass ||
1556            T->getStmtClass() == OMPDistributeDirectiveClass ||
1557            T->getStmtClass() == OMPTargetParallelForDirectiveClass ||
1558            T->getStmtClass() == OMPDistributeParallelForDirectiveClass ||
1559            T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass ||
1560            T->getStmtClass() == OMPDistributeSimdDirectiveClass ||
1561            T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass ||
1562            T->getStmtClass() == OMPTargetSimdDirectiveClass ||
1563            T->getStmtClass() == OMPTeamsDistributeDirectiveClass ||
1564            T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass ||
1565            T->getStmtClass() ==
1566                OMPTeamsDistributeParallelForSimdDirectiveClass ||
1567            T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass ||
1568            T->getStmtClass() ==
1569                OMPTargetTeamsDistributeParallelForDirectiveClass ||
1570            T->getStmtClass() ==
1571                OMPTargetTeamsDistributeParallelForSimdDirectiveClass ||
1572            T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass ||
1573            T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass;
1574   }
1575 };
1576 
1577 /// This represents '#pragma omp simd' directive.
1578 ///
1579 /// \code
1580 /// #pragma omp simd private(a,b) linear(i,j:s) reduction(+:c,d)
1581 /// \endcode
1582 /// In this example directive '#pragma omp simd' has clauses 'private'
1583 /// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
1584 /// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
1585 ///
1586 class OMPSimdDirective : public OMPLoopDirective {
1587   friend class ASTStmtReader;
1588   friend class OMPExecutableDirective;
1589   /// Build directive with the given start and end location.
1590   ///
1591   /// \param StartLoc Starting location of the directive kind.
1592   /// \param EndLoc Ending location of the directive.
1593   /// \param CollapsedNum Number of collapsed nested loops.
1594   ///
OMPSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)1595   OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
1596                    unsigned CollapsedNum)
1597       : OMPLoopDirective(OMPSimdDirectiveClass, llvm::omp::OMPD_simd, StartLoc,
1598                          EndLoc, CollapsedNum) {}
1599 
1600   /// Build an empty directive.
1601   ///
1602   /// \param CollapsedNum Number of collapsed nested loops.
1603   ///
OMPSimdDirective(unsigned CollapsedNum)1604   explicit OMPSimdDirective(unsigned CollapsedNum)
1605       : OMPLoopDirective(OMPSimdDirectiveClass, llvm::omp::OMPD_simd,
1606                          SourceLocation(), SourceLocation(), CollapsedNum) {}
1607 
1608 public:
1609   /// Creates directive with a list of \a Clauses.
1610   ///
1611   /// \param C AST context.
1612   /// \param StartLoc Starting location of the directive kind.
1613   /// \param EndLoc Ending Location of the directive.
1614   /// \param CollapsedNum Number of collapsed loops.
1615   /// \param Clauses List of clauses.
1616   /// \param AssociatedStmt Statement, associated with the directive.
1617   /// \param Exprs Helper expressions for CodeGen.
1618   ///
1619   static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc,
1620                                   SourceLocation EndLoc, unsigned CollapsedNum,
1621                                   ArrayRef<OMPClause *> Clauses,
1622                                   Stmt *AssociatedStmt,
1623                                   const HelperExprs &Exprs,
1624                                   OpenMPDirectiveKind ParamPrevMappedDirective);
1625 
1626   /// Creates an empty directive with the place
1627   /// for \a NumClauses clauses.
1628   ///
1629   /// \param C AST context.
1630   /// \param CollapsedNum Number of collapsed nested loops.
1631   /// \param NumClauses Number of clauses.
1632   ///
1633   static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
1634                                        unsigned CollapsedNum, EmptyShell);
1635 
classof(const Stmt * T)1636   static bool classof(const Stmt *T) {
1637     return T->getStmtClass() == OMPSimdDirectiveClass;
1638   }
1639 };
1640 
1641 /// This represents '#pragma omp for' directive.
1642 ///
1643 /// \code
1644 /// #pragma omp for private(a,b) reduction(+:c,d)
1645 /// \endcode
1646 /// In this example directive '#pragma omp for' has clauses 'private' with the
1647 /// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c'
1648 /// and 'd'.
1649 ///
1650 class OMPForDirective : public OMPLoopDirective {
1651   friend class ASTStmtReader;
1652   friend class OMPExecutableDirective;
1653   /// true if current directive has inner cancel directive.
1654   bool HasCancel = false;
1655 
1656   /// Build directive with the given start and end location.
1657   ///
1658   /// \param StartLoc Starting location of the directive kind.
1659   /// \param EndLoc Ending location of the directive.
1660   /// \param CollapsedNum Number of collapsed nested loops.
1661   ///
OMPForDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)1662   OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
1663                   unsigned CollapsedNum)
1664       : OMPLoopDirective(OMPForDirectiveClass, llvm::omp::OMPD_for, StartLoc,
1665                          EndLoc, CollapsedNum) {}
1666 
1667   /// Build an empty directive.
1668   ///
1669   /// \param CollapsedNum Number of collapsed nested loops.
1670   ///
OMPForDirective(unsigned CollapsedNum)1671   explicit OMPForDirective(unsigned CollapsedNum)
1672       : OMPLoopDirective(OMPForDirectiveClass, llvm::omp::OMPD_for,
1673                          SourceLocation(), SourceLocation(), CollapsedNum) {}
1674 
1675   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)1676   void setTaskReductionRefExpr(Expr *E) {
1677     Data->getChildren()[numLoopChildren(getLoopsNumber(),
1678                                         llvm::omp::OMPD_for)] = E;
1679   }
1680 
1681   /// Set cancel state.
setHasCancel(bool Has)1682   void setHasCancel(bool Has) { HasCancel = Has; }
1683 
1684 public:
1685   /// Creates directive with a list of \a Clauses.
1686   ///
1687   /// \param C AST context.
1688   /// \param StartLoc Starting location of the directive kind.
1689   /// \param EndLoc Ending Location of the directive.
1690   /// \param CollapsedNum Number of collapsed loops.
1691   /// \param Clauses List of clauses.
1692   /// \param AssociatedStmt Statement, associated with the directive.
1693   /// \param Exprs Helper expressions for CodeGen.
1694   /// \param TaskRedRef Task reduction special reference expression to handle
1695   /// taskgroup descriptor.
1696   /// \param HasCancel true if current directive has inner cancel directive.
1697   ///
1698   static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
1699                                  SourceLocation EndLoc, unsigned CollapsedNum,
1700                                  ArrayRef<OMPClause *> Clauses,
1701                                  Stmt *AssociatedStmt, const HelperExprs &Exprs,
1702                                  Expr *TaskRedRef, bool HasCancel,
1703                                  OpenMPDirectiveKind ParamPrevMappedDirective);
1704 
1705   /// Creates an empty directive with the place
1706   /// for \a NumClauses clauses.
1707   ///
1708   /// \param C AST context.
1709   /// \param CollapsedNum Number of collapsed nested loops.
1710   /// \param NumClauses Number of clauses.
1711   ///
1712   static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
1713                                       unsigned CollapsedNum, EmptyShell);
1714 
1715   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()1716   Expr *getTaskReductionRefExpr() {
1717     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
1718         getLoopsNumber(), llvm::omp::OMPD_for)]);
1719   }
getTaskReductionRefExpr()1720   const Expr *getTaskReductionRefExpr() const {
1721     return const_cast<OMPForDirective *>(this)->getTaskReductionRefExpr();
1722   }
1723 
1724   /// Return true if current directive has inner cancel directive.
hasCancel()1725   bool hasCancel() const { return HasCancel; }
1726 
classof(const Stmt * T)1727   static bool classof(const Stmt *T) {
1728     return T->getStmtClass() == OMPForDirectiveClass;
1729   }
1730 };
1731 
1732 /// This represents '#pragma omp for simd' directive.
1733 ///
1734 /// \code
1735 /// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d)
1736 /// \endcode
1737 /// In this example directive '#pragma omp for simd' has clauses 'private'
1738 /// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
1739 /// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
1740 ///
1741 class OMPForSimdDirective : public OMPLoopDirective {
1742   friend class ASTStmtReader;
1743   friend class OMPExecutableDirective;
1744   /// Build directive with the given start and end location.
1745   ///
1746   /// \param StartLoc Starting location of the directive kind.
1747   /// \param EndLoc Ending location of the directive.
1748   /// \param CollapsedNum Number of collapsed nested loops.
1749   ///
OMPForSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)1750   OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
1751                       unsigned CollapsedNum)
1752       : OMPLoopDirective(OMPForSimdDirectiveClass, llvm::omp::OMPD_for_simd,
1753                          StartLoc, EndLoc, CollapsedNum) {}
1754 
1755   /// Build an empty directive.
1756   ///
1757   /// \param CollapsedNum Number of collapsed nested loops.
1758   ///
OMPForSimdDirective(unsigned CollapsedNum)1759   explicit OMPForSimdDirective(unsigned CollapsedNum)
1760       : OMPLoopDirective(OMPForSimdDirectiveClass, llvm::omp::OMPD_for_simd,
1761                          SourceLocation(), SourceLocation(), CollapsedNum) {}
1762 
1763 public:
1764   /// Creates directive with a list of \a Clauses.
1765   ///
1766   /// \param C AST context.
1767   /// \param StartLoc Starting location of the directive kind.
1768   /// \param EndLoc Ending Location of the directive.
1769   /// \param CollapsedNum Number of collapsed loops.
1770   /// \param Clauses List of clauses.
1771   /// \param AssociatedStmt Statement, associated with the directive.
1772   /// \param Exprs Helper expressions for CodeGen.
1773   ///
1774   static OMPForSimdDirective *
1775   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
1776          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
1777          Stmt *AssociatedStmt, const HelperExprs &Exprs);
1778 
1779   /// Creates an empty directive with the place
1780   /// for \a NumClauses clauses.
1781   ///
1782   /// \param C AST context.
1783   /// \param CollapsedNum Number of collapsed nested loops.
1784   /// \param NumClauses Number of clauses.
1785   ///
1786   static OMPForSimdDirective *CreateEmpty(const ASTContext &C,
1787                                           unsigned NumClauses,
1788                                           unsigned CollapsedNum, EmptyShell);
1789 
classof(const Stmt * T)1790   static bool classof(const Stmt *T) {
1791     return T->getStmtClass() == OMPForSimdDirectiveClass;
1792   }
1793 };
1794 
1795 /// This represents '#pragma omp sections' directive.
1796 ///
1797 /// \code
1798 /// #pragma omp sections private(a,b) reduction(+:c,d)
1799 /// \endcode
1800 /// In this example directive '#pragma omp sections' has clauses 'private' with
1801 /// the variables 'a' and 'b' and 'reduction' with operator '+' and variables
1802 /// 'c' and 'd'.
1803 ///
1804 class OMPSectionsDirective : public OMPExecutableDirective {
1805   friend class ASTStmtReader;
1806   friend class OMPExecutableDirective;
1807 
1808   /// true if current directive has inner cancel directive.
1809   bool HasCancel = false;
1810 
1811   /// Build directive with the given start and end location.
1812   ///
1813   /// \param StartLoc Starting location of the directive kind.
1814   /// \param EndLoc Ending location of the directive.
1815   ///
OMPSectionsDirective(SourceLocation StartLoc,SourceLocation EndLoc)1816   OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1817       : OMPExecutableDirective(OMPSectionsDirectiveClass,
1818                                llvm::omp::OMPD_sections, StartLoc, EndLoc) {}
1819 
1820   /// Build an empty directive.
1821   ///
OMPSectionsDirective()1822   explicit OMPSectionsDirective()
1823       : OMPExecutableDirective(OMPSectionsDirectiveClass,
1824                                llvm::omp::OMPD_sections, SourceLocation(),
1825                                SourceLocation()) {}
1826 
1827   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)1828   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
1829 
1830   /// Set cancel state.
setHasCancel(bool Has)1831   void setHasCancel(bool Has) { HasCancel = Has; }
1832 
1833 public:
1834   /// Creates directive with a list of \a Clauses.
1835   ///
1836   /// \param C AST context.
1837   /// \param StartLoc Starting location of the directive kind.
1838   /// \param EndLoc Ending Location of the directive.
1839   /// \param Clauses List of clauses.
1840   /// \param AssociatedStmt Statement, associated with the directive.
1841   /// \param TaskRedRef Task reduction special reference expression to handle
1842   /// taskgroup descriptor.
1843   /// \param HasCancel true if current directive has inner directive.
1844   ///
1845   static OMPSectionsDirective *
1846   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
1847          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
1848          bool HasCancel);
1849 
1850   /// Creates an empty directive with the place for \a NumClauses
1851   /// clauses.
1852   ///
1853   /// \param C AST context.
1854   /// \param NumClauses Number of clauses.
1855   ///
1856   static OMPSectionsDirective *CreateEmpty(const ASTContext &C,
1857                                            unsigned NumClauses, EmptyShell);
1858 
1859   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()1860   Expr *getTaskReductionRefExpr() {
1861     return cast_or_null<Expr>(Data->getChildren()[0]);
1862   }
getTaskReductionRefExpr()1863   const Expr *getTaskReductionRefExpr() const {
1864     return const_cast<OMPSectionsDirective *>(this)->getTaskReductionRefExpr();
1865   }
1866 
1867   /// Return true if current directive has inner cancel directive.
hasCancel()1868   bool hasCancel() const { return HasCancel; }
1869 
classof(const Stmt * T)1870   static bool classof(const Stmt *T) {
1871     return T->getStmtClass() == OMPSectionsDirectiveClass;
1872   }
1873 };
1874 
1875 /// This represents '#pragma omp section' directive.
1876 ///
1877 /// \code
1878 /// #pragma omp section
1879 /// \endcode
1880 ///
1881 class OMPSectionDirective : public OMPExecutableDirective {
1882   friend class ASTStmtReader;
1883   friend class OMPExecutableDirective;
1884 
1885   /// true if current directive has inner cancel directive.
1886   bool HasCancel = false;
1887 
1888   /// Build directive with the given start and end location.
1889   ///
1890   /// \param StartLoc Starting location of the directive kind.
1891   /// \param EndLoc Ending location of the directive.
1892   ///
OMPSectionDirective(SourceLocation StartLoc,SourceLocation EndLoc)1893   OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1894       : OMPExecutableDirective(OMPSectionDirectiveClass,
1895                                llvm::omp::OMPD_section, StartLoc, EndLoc) {}
1896 
1897   /// Build an empty directive.
1898   ///
OMPSectionDirective()1899   explicit OMPSectionDirective()
1900       : OMPExecutableDirective(OMPSectionDirectiveClass,
1901                                llvm::omp::OMPD_section, SourceLocation(),
1902                                SourceLocation()) {}
1903 
1904 public:
1905   /// Creates directive.
1906   ///
1907   /// \param C AST context.
1908   /// \param StartLoc Starting location of the directive kind.
1909   /// \param EndLoc Ending Location of the directive.
1910   /// \param AssociatedStmt Statement, associated with the directive.
1911   /// \param HasCancel true if current directive has inner directive.
1912   ///
1913   static OMPSectionDirective *Create(const ASTContext &C,
1914                                      SourceLocation StartLoc,
1915                                      SourceLocation EndLoc,
1916                                      Stmt *AssociatedStmt, bool HasCancel);
1917 
1918   /// Creates an empty directive.
1919   ///
1920   /// \param C AST context.
1921   ///
1922   static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell);
1923 
1924   /// Set cancel state.
setHasCancel(bool Has)1925   void setHasCancel(bool Has) { HasCancel = Has; }
1926 
1927   /// Return true if current directive has inner cancel directive.
hasCancel()1928   bool hasCancel() const { return HasCancel; }
1929 
classof(const Stmt * T)1930   static bool classof(const Stmt *T) {
1931     return T->getStmtClass() == OMPSectionDirectiveClass;
1932   }
1933 };
1934 
1935 /// This represents '#pragma omp scope' directive.
1936 /// \code
1937 /// #pragma omp scope private(a,b) nowait
1938 /// \endcode
1939 /// In this example directive '#pragma omp scope' has clauses 'private' with
1940 /// the variables 'a' and 'b' and nowait.
1941 ///
1942 class OMPScopeDirective final : public OMPExecutableDirective {
1943   friend class ASTStmtReader;
1944   friend class OMPExecutableDirective;
1945 
1946   /// Build directive with the given start and end location.
1947   ///
1948   /// \param StartLoc Starting location of the directive kind.
1949   /// \param EndLoc Ending location of the directive.
1950   ///
OMPScopeDirective(SourceLocation StartLoc,SourceLocation EndLoc)1951   OMPScopeDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1952       : OMPExecutableDirective(OMPScopeDirectiveClass, llvm::omp::OMPD_scope,
1953                                StartLoc, EndLoc) {}
1954 
1955   /// Build an empty directive.
1956   ///
OMPScopeDirective()1957   explicit OMPScopeDirective()
1958       : OMPExecutableDirective(OMPScopeDirectiveClass, llvm::omp::OMPD_scope,
1959                                SourceLocation(), SourceLocation()) {}
1960 
1961 public:
1962   /// Creates directive.
1963   ///
1964   /// \param C AST context.
1965   /// \param StartLoc Starting location of the directive kind.
1966   /// \param EndLoc Ending Location of the directive.
1967   /// \param AssociatedStmt Statement, associated with the directive.
1968   ///
1969   static OMPScopeDirective *Create(const ASTContext &C, SourceLocation StartLoc,
1970                                    SourceLocation EndLoc,
1971                                    ArrayRef<OMPClause *> Clauses,
1972                                    Stmt *AssociatedStmt);
1973 
1974   /// Creates an empty directive.
1975   ///
1976   /// \param C AST context.
1977   ///
1978   static OMPScopeDirective *CreateEmpty(const ASTContext &C,
1979                                         unsigned NumClauses, EmptyShell);
1980 
classof(const Stmt * T)1981   static bool classof(const Stmt *T) {
1982     return T->getStmtClass() == OMPScopeDirectiveClass;
1983   }
1984 };
1985 
1986 /// This represents '#pragma omp single' directive.
1987 ///
1988 /// \code
1989 /// #pragma omp single private(a,b) copyprivate(c,d)
1990 /// \endcode
1991 /// In this example directive '#pragma omp single' has clauses 'private' with
1992 /// the variables 'a' and 'b' and 'copyprivate' with variables 'c' and 'd'.
1993 ///
1994 class OMPSingleDirective : public OMPExecutableDirective {
1995   friend class ASTStmtReader;
1996   friend class OMPExecutableDirective;
1997   /// Build directive with the given start and end location.
1998   ///
1999   /// \param StartLoc Starting location of the directive kind.
2000   /// \param EndLoc Ending location of the directive.
2001   ///
OMPSingleDirective(SourceLocation StartLoc,SourceLocation EndLoc)2002   OMPSingleDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2003       : OMPExecutableDirective(OMPSingleDirectiveClass, llvm::omp::OMPD_single,
2004                                StartLoc, EndLoc) {}
2005 
2006   /// Build an empty directive.
2007   ///
OMPSingleDirective()2008   explicit OMPSingleDirective()
2009       : OMPExecutableDirective(OMPSingleDirectiveClass, llvm::omp::OMPD_single,
2010                                SourceLocation(), SourceLocation()) {}
2011 
2012 public:
2013   /// Creates directive with a list of \a Clauses.
2014   ///
2015   /// \param C AST context.
2016   /// \param StartLoc Starting location of the directive kind.
2017   /// \param EndLoc Ending Location of the directive.
2018   /// \param Clauses List of clauses.
2019   /// \param AssociatedStmt Statement, associated with the directive.
2020   ///
2021   static OMPSingleDirective *
2022   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2023          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
2024 
2025   /// Creates an empty directive with the place for \a NumClauses
2026   /// clauses.
2027   ///
2028   /// \param C AST context.
2029   /// \param NumClauses Number of clauses.
2030   ///
2031   static OMPSingleDirective *CreateEmpty(const ASTContext &C,
2032                                          unsigned NumClauses, EmptyShell);
2033 
classof(const Stmt * T)2034   static bool classof(const Stmt *T) {
2035     return T->getStmtClass() == OMPSingleDirectiveClass;
2036   }
2037 };
2038 
2039 /// This represents '#pragma omp master' directive.
2040 ///
2041 /// \code
2042 /// #pragma omp master
2043 /// \endcode
2044 ///
2045 class OMPMasterDirective : public OMPExecutableDirective {
2046   friend class ASTStmtReader;
2047   friend class OMPExecutableDirective;
2048   /// Build directive with the given start and end location.
2049   ///
2050   /// \param StartLoc Starting location of the directive kind.
2051   /// \param EndLoc Ending location of the directive.
2052   ///
OMPMasterDirective(SourceLocation StartLoc,SourceLocation EndLoc)2053   OMPMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2054       : OMPExecutableDirective(OMPMasterDirectiveClass, llvm::omp::OMPD_master,
2055                                StartLoc, EndLoc) {}
2056 
2057   /// Build an empty directive.
2058   ///
OMPMasterDirective()2059   explicit OMPMasterDirective()
2060       : OMPExecutableDirective(OMPMasterDirectiveClass, llvm::omp::OMPD_master,
2061                                SourceLocation(), SourceLocation()) {}
2062 
2063 public:
2064   /// Creates directive.
2065   ///
2066   /// \param C AST context.
2067   /// \param StartLoc Starting location of the directive kind.
2068   /// \param EndLoc Ending Location of the directive.
2069   /// \param AssociatedStmt Statement, associated with the directive.
2070   ///
2071   static OMPMasterDirective *Create(const ASTContext &C,
2072                                     SourceLocation StartLoc,
2073                                     SourceLocation EndLoc,
2074                                     Stmt *AssociatedStmt);
2075 
2076   /// Creates an empty directive.
2077   ///
2078   /// \param C AST context.
2079   ///
2080   static OMPMasterDirective *CreateEmpty(const ASTContext &C, EmptyShell);
2081 
classof(const Stmt * T)2082   static bool classof(const Stmt *T) {
2083     return T->getStmtClass() == OMPMasterDirectiveClass;
2084   }
2085 };
2086 
2087 /// This represents '#pragma omp critical' directive.
2088 ///
2089 /// \code
2090 /// #pragma omp critical
2091 /// \endcode
2092 ///
2093 class OMPCriticalDirective : public OMPExecutableDirective {
2094   friend class ASTStmtReader;
2095   friend class OMPExecutableDirective;
2096   /// Name of the directive.
2097   DeclarationNameInfo DirName;
2098   /// Build directive with the given start and end location.
2099   ///
2100   /// \param Name Name of the directive.
2101   /// \param StartLoc Starting location of the directive kind.
2102   /// \param EndLoc Ending location of the directive.
2103   ///
OMPCriticalDirective(const DeclarationNameInfo & Name,SourceLocation StartLoc,SourceLocation EndLoc)2104   OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc,
2105                        SourceLocation EndLoc)
2106       : OMPExecutableDirective(OMPCriticalDirectiveClass,
2107                                llvm::omp::OMPD_critical, StartLoc, EndLoc),
2108         DirName(Name) {}
2109 
2110   /// Build an empty directive.
2111   ///
OMPCriticalDirective()2112   explicit OMPCriticalDirective()
2113       : OMPExecutableDirective(OMPCriticalDirectiveClass,
2114                                llvm::omp::OMPD_critical, SourceLocation(),
2115                                SourceLocation()) {}
2116 
2117   /// Set name of the directive.
2118   ///
2119   /// \param Name Name of the directive.
2120   ///
setDirectiveName(const DeclarationNameInfo & Name)2121   void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; }
2122 
2123 public:
2124   /// Creates directive.
2125   ///
2126   /// \param C AST context.
2127   /// \param Name Name of the directive.
2128   /// \param StartLoc Starting location of the directive kind.
2129   /// \param EndLoc Ending Location of the directive.
2130   /// \param Clauses List of clauses.
2131   /// \param AssociatedStmt Statement, associated with the directive.
2132   ///
2133   static OMPCriticalDirective *
2134   Create(const ASTContext &C, const DeclarationNameInfo &Name,
2135          SourceLocation StartLoc, SourceLocation EndLoc,
2136          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
2137 
2138   /// Creates an empty directive.
2139   ///
2140   /// \param C AST context.
2141   /// \param NumClauses Number of clauses.
2142   ///
2143   static OMPCriticalDirective *CreateEmpty(const ASTContext &C,
2144                                            unsigned NumClauses, EmptyShell);
2145 
2146   /// Return name of the directive.
2147   ///
getDirectiveName()2148   DeclarationNameInfo getDirectiveName() const { return DirName; }
2149 
classof(const Stmt * T)2150   static bool classof(const Stmt *T) {
2151     return T->getStmtClass() == OMPCriticalDirectiveClass;
2152   }
2153 };
2154 
2155 /// This represents '#pragma omp parallel for' directive.
2156 ///
2157 /// \code
2158 /// #pragma omp parallel for private(a,b) reduction(+:c,d)
2159 /// \endcode
2160 /// In this example directive '#pragma omp parallel for' has clauses 'private'
2161 /// with the variables 'a' and 'b' and 'reduction' with operator '+' and
2162 /// variables 'c' and 'd'.
2163 ///
2164 class OMPParallelForDirective : public OMPLoopDirective {
2165   friend class ASTStmtReader;
2166   friend class OMPExecutableDirective;
2167 
2168   /// true if current region has inner cancel directive.
2169   bool HasCancel = false;
2170 
2171   /// Build directive with the given start and end location.
2172   ///
2173   /// \param StartLoc Starting location of the directive kind.
2174   /// \param EndLoc Ending location of the directive.
2175   /// \param CollapsedNum Number of collapsed nested loops.
2176   ///
OMPParallelForDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)2177   OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
2178                           unsigned CollapsedNum)
2179       : OMPLoopDirective(OMPParallelForDirectiveClass,
2180                          llvm::omp::OMPD_parallel_for, StartLoc, EndLoc,
2181                          CollapsedNum) {}
2182 
2183   /// Build an empty directive.
2184   ///
2185   /// \param CollapsedNum Number of collapsed nested loops.
2186   ///
OMPParallelForDirective(unsigned CollapsedNum)2187   explicit OMPParallelForDirective(unsigned CollapsedNum)
2188       : OMPLoopDirective(OMPParallelForDirectiveClass,
2189                          llvm::omp::OMPD_parallel_for, SourceLocation(),
2190                          SourceLocation(), CollapsedNum) {}
2191 
2192   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)2193   void setTaskReductionRefExpr(Expr *E) {
2194     Data->getChildren()[numLoopChildren(getLoopsNumber(),
2195                                         llvm::omp::OMPD_parallel_for)] = E;
2196   }
2197 
2198   /// Set cancel state.
setHasCancel(bool Has)2199   void setHasCancel(bool Has) { HasCancel = Has; }
2200 
2201 public:
2202   /// Creates directive with a list of \a Clauses.
2203   ///
2204   /// \param C AST context.
2205   /// \param StartLoc Starting location of the directive kind.
2206   /// \param EndLoc Ending Location of the directive.
2207   /// \param CollapsedNum Number of collapsed loops.
2208   /// \param Clauses List of clauses.
2209   /// \param AssociatedStmt Statement, associated with the directive.
2210   /// \param Exprs Helper expressions for CodeGen.
2211   /// \param TaskRedRef Task reduction special reference expression to handle
2212   /// taskgroup descriptor.
2213   /// \param HasCancel true if current directive has inner cancel directive.
2214   ///
2215   static OMPParallelForDirective *
2216   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2217          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
2218          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
2219          bool HasCancel);
2220 
2221   /// Creates an empty directive with the place
2222   /// for \a NumClauses clauses.
2223   ///
2224   /// \param C AST context.
2225   /// \param CollapsedNum Number of collapsed nested loops.
2226   /// \param NumClauses Number of clauses.
2227   ///
2228   static OMPParallelForDirective *CreateEmpty(const ASTContext &C,
2229                                               unsigned NumClauses,
2230                                               unsigned CollapsedNum,
2231                                               EmptyShell);
2232 
2233   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()2234   Expr *getTaskReductionRefExpr() {
2235     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
2236         getLoopsNumber(), llvm::omp::OMPD_parallel_for)]);
2237   }
getTaskReductionRefExpr()2238   const Expr *getTaskReductionRefExpr() const {
2239     return const_cast<OMPParallelForDirective *>(this)
2240         ->getTaskReductionRefExpr();
2241   }
2242 
2243   /// Return true if current directive has inner cancel directive.
hasCancel()2244   bool hasCancel() const { return HasCancel; }
2245 
classof(const Stmt * T)2246   static bool classof(const Stmt *T) {
2247     return T->getStmtClass() == OMPParallelForDirectiveClass;
2248   }
2249 };
2250 
2251 /// This represents '#pragma omp parallel for simd' directive.
2252 ///
2253 /// \code
2254 /// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d)
2255 /// \endcode
2256 /// In this example directive '#pragma omp parallel for simd' has clauses
2257 /// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j'
2258 /// and linear step 's', 'reduction' with operator '+' and variables 'c' and
2259 /// 'd'.
2260 ///
2261 class OMPParallelForSimdDirective : public OMPLoopDirective {
2262   friend class ASTStmtReader;
2263   friend class OMPExecutableDirective;
2264   /// Build directive with the given start and end location.
2265   ///
2266   /// \param StartLoc Starting location of the directive kind.
2267   /// \param EndLoc Ending location of the directive.
2268   /// \param CollapsedNum Number of collapsed nested loops.
2269   ///
OMPParallelForSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)2270   OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
2271                               unsigned CollapsedNum)
2272       : OMPLoopDirective(OMPParallelForSimdDirectiveClass,
2273                          llvm::omp::OMPD_parallel_for_simd, StartLoc, EndLoc,
2274                          CollapsedNum) {}
2275 
2276   /// Build an empty directive.
2277   ///
2278   /// \param CollapsedNum Number of collapsed nested loops.
2279   ///
OMPParallelForSimdDirective(unsigned CollapsedNum)2280   explicit OMPParallelForSimdDirective(unsigned CollapsedNum)
2281       : OMPLoopDirective(OMPParallelForSimdDirectiveClass,
2282                          llvm::omp::OMPD_parallel_for_simd, SourceLocation(),
2283                          SourceLocation(), CollapsedNum) {}
2284 
2285 public:
2286   /// Creates directive with a list of \a Clauses.
2287   ///
2288   /// \param C AST context.
2289   /// \param StartLoc Starting location of the directive kind.
2290   /// \param EndLoc Ending Location of the directive.
2291   /// \param CollapsedNum Number of collapsed loops.
2292   /// \param Clauses List of clauses.
2293   /// \param AssociatedStmt Statement, associated with the directive.
2294   /// \param Exprs Helper expressions for CodeGen.
2295   ///
2296   static OMPParallelForSimdDirective *
2297   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2298          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
2299          Stmt *AssociatedStmt, const HelperExprs &Exprs);
2300 
2301   /// Creates an empty directive with the place
2302   /// for \a NumClauses clauses.
2303   ///
2304   /// \param C AST context.
2305   /// \param CollapsedNum Number of collapsed nested loops.
2306   /// \param NumClauses Number of clauses.
2307   ///
2308   static OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C,
2309                                                   unsigned NumClauses,
2310                                                   unsigned CollapsedNum,
2311                                                   EmptyShell);
2312 
classof(const Stmt * T)2313   static bool classof(const Stmt *T) {
2314     return T->getStmtClass() == OMPParallelForSimdDirectiveClass;
2315   }
2316 };
2317 
2318 /// This represents '#pragma omp parallel master' directive.
2319 ///
2320 /// \code
2321 /// #pragma omp parallel master private(a,b)
2322 /// \endcode
2323 /// In this example directive '#pragma omp parallel master' has clauses
2324 /// 'private' with the variables 'a' and 'b'
2325 ///
2326 class OMPParallelMasterDirective : public OMPExecutableDirective {
2327   friend class ASTStmtReader;
2328   friend class OMPExecutableDirective;
2329 
OMPParallelMasterDirective(SourceLocation StartLoc,SourceLocation EndLoc)2330   OMPParallelMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2331       : OMPExecutableDirective(OMPParallelMasterDirectiveClass,
2332                                llvm::omp::OMPD_parallel_master, StartLoc,
2333                                EndLoc) {}
2334 
OMPParallelMasterDirective()2335   explicit OMPParallelMasterDirective()
2336       : OMPExecutableDirective(OMPParallelMasterDirectiveClass,
2337                                llvm::omp::OMPD_parallel_master,
2338                                SourceLocation(), SourceLocation()) {}
2339 
2340   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)2341   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
2342 
2343 public:
2344   /// Creates directive with a list of \a Clauses.
2345   ///
2346   /// \param C AST context.
2347   /// \param StartLoc Starting location of the directive kind.
2348   /// \param EndLoc Ending Location of the directive.
2349   /// \param Clauses List of clauses.
2350   /// \param AssociatedStmt Statement, associated with the directive.
2351   /// \param TaskRedRef Task reduction special reference expression to handle
2352   /// taskgroup descriptor.
2353   ///
2354   static OMPParallelMasterDirective *
2355   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2356          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef);
2357 
2358   /// Creates an empty directive with the place for \a NumClauses
2359   /// clauses.
2360   ///
2361   /// \param C AST context.
2362   /// \param NumClauses Number of clauses.
2363   ///
2364   static OMPParallelMasterDirective *
2365   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
2366 
2367   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()2368   Expr *getTaskReductionRefExpr() {
2369     return cast_or_null<Expr>(Data->getChildren()[0]);
2370   }
getTaskReductionRefExpr()2371   const Expr *getTaskReductionRefExpr() const {
2372     return const_cast<OMPParallelMasterDirective *>(this)
2373         ->getTaskReductionRefExpr();
2374   }
2375 
classof(const Stmt * T)2376   static bool classof(const Stmt *T) {
2377     return T->getStmtClass() == OMPParallelMasterDirectiveClass;
2378   }
2379 };
2380 
2381 /// This represents '#pragma omp parallel masked' directive.
2382 ///
2383 /// \code
2384 /// #pragma omp parallel masked filter(tid)
2385 /// \endcode
2386 /// In this example directive '#pragma omp parallel masked' has a clause
2387 /// 'filter' with the variable tid
2388 ///
2389 class OMPParallelMaskedDirective final : public OMPExecutableDirective {
2390   friend class ASTStmtReader;
2391   friend class OMPExecutableDirective;
2392 
OMPParallelMaskedDirective(SourceLocation StartLoc,SourceLocation EndLoc)2393   OMPParallelMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2394       : OMPExecutableDirective(OMPParallelMaskedDirectiveClass,
2395                                llvm::omp::OMPD_parallel_masked, StartLoc,
2396                                EndLoc) {}
2397 
OMPParallelMaskedDirective()2398   explicit OMPParallelMaskedDirective()
2399       : OMPExecutableDirective(OMPParallelMaskedDirectiveClass,
2400                                llvm::omp::OMPD_parallel_masked,
2401                                SourceLocation(), SourceLocation()) {}
2402 
2403   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)2404   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
2405 
2406 public:
2407   /// Creates directive with a list of \a Clauses.
2408   ///
2409   /// \param C AST context.
2410   /// \param StartLoc Starting location of the directive kind.
2411   /// \param EndLoc Ending Location of the directive.
2412   /// \param Clauses List of clauses.
2413   /// \param AssociatedStmt Statement, associated with the directive.
2414   /// \param TaskRedRef Task reduction special reference expression to handle
2415   /// taskgroup descriptor.
2416   ///
2417   static OMPParallelMaskedDirective *
2418   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2419          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef);
2420 
2421   /// Creates an empty directive with the place for \a NumClauses
2422   /// clauses.
2423   ///
2424   /// \param C AST context.
2425   /// \param NumClauses Number of clauses.
2426   ///
2427   static OMPParallelMaskedDirective *
2428   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
2429 
2430   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()2431   Expr *getTaskReductionRefExpr() {
2432     return cast_or_null<Expr>(Data->getChildren()[0]);
2433   }
getTaskReductionRefExpr()2434   const Expr *getTaskReductionRefExpr() const {
2435     return const_cast<OMPParallelMaskedDirective *>(this)
2436         ->getTaskReductionRefExpr();
2437   }
2438 
classof(const Stmt * T)2439   static bool classof(const Stmt *T) {
2440     return T->getStmtClass() == OMPParallelMaskedDirectiveClass;
2441   }
2442 };
2443 
2444 /// This represents '#pragma omp parallel sections' directive.
2445 ///
2446 /// \code
2447 /// #pragma omp parallel sections private(a,b) reduction(+:c,d)
2448 /// \endcode
2449 /// In this example directive '#pragma omp parallel sections' has clauses
2450 /// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+'
2451 /// and variables 'c' and 'd'.
2452 ///
2453 class OMPParallelSectionsDirective : public OMPExecutableDirective {
2454   friend class ASTStmtReader;
2455   friend class OMPExecutableDirective;
2456 
2457   /// true if current directive has inner cancel directive.
2458   bool HasCancel = false;
2459 
2460   /// Build directive with the given start and end location.
2461   ///
2462   /// \param StartLoc Starting location of the directive kind.
2463   /// \param EndLoc Ending location of the directive.
2464   ///
OMPParallelSectionsDirective(SourceLocation StartLoc,SourceLocation EndLoc)2465   OMPParallelSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2466       : OMPExecutableDirective(OMPParallelSectionsDirectiveClass,
2467                                llvm::omp::OMPD_parallel_sections, StartLoc,
2468                                EndLoc) {}
2469 
2470   /// Build an empty directive.
2471   ///
OMPParallelSectionsDirective()2472   explicit OMPParallelSectionsDirective()
2473       : OMPExecutableDirective(OMPParallelSectionsDirectiveClass,
2474                                llvm::omp::OMPD_parallel_sections,
2475                                SourceLocation(), SourceLocation()) {}
2476 
2477   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)2478   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
2479 
2480   /// Set cancel state.
setHasCancel(bool Has)2481   void setHasCancel(bool Has) { HasCancel = Has; }
2482 
2483 public:
2484   /// Creates directive with a list of \a Clauses.
2485   ///
2486   /// \param C AST context.
2487   /// \param StartLoc Starting location of the directive kind.
2488   /// \param EndLoc Ending Location of the directive.
2489   /// \param Clauses List of clauses.
2490   /// \param AssociatedStmt Statement, associated with the directive.
2491   /// \param TaskRedRef Task reduction special reference expression to handle
2492   /// taskgroup descriptor.
2493   /// \param HasCancel true if current directive has inner cancel directive.
2494   ///
2495   static OMPParallelSectionsDirective *
2496   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2497          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
2498          bool HasCancel);
2499 
2500   /// Creates an empty directive with the place for \a NumClauses
2501   /// clauses.
2502   ///
2503   /// \param C AST context.
2504   /// \param NumClauses Number of clauses.
2505   ///
2506   static OMPParallelSectionsDirective *
2507   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
2508 
2509   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()2510   Expr *getTaskReductionRefExpr() {
2511     return cast_or_null<Expr>(Data->getChildren()[0]);
2512   }
getTaskReductionRefExpr()2513   const Expr *getTaskReductionRefExpr() const {
2514     return const_cast<OMPParallelSectionsDirective *>(this)
2515         ->getTaskReductionRefExpr();
2516   }
2517 
2518   /// Return true if current directive has inner cancel directive.
hasCancel()2519   bool hasCancel() const { return HasCancel; }
2520 
classof(const Stmt * T)2521   static bool classof(const Stmt *T) {
2522     return T->getStmtClass() == OMPParallelSectionsDirectiveClass;
2523   }
2524 };
2525 
2526 /// This represents '#pragma omp task' directive.
2527 ///
2528 /// \code
2529 /// #pragma omp task private(a,b) final(d)
2530 /// \endcode
2531 /// In this example directive '#pragma omp task' has clauses 'private' with the
2532 /// variables 'a' and 'b' and 'final' with condition 'd'.
2533 ///
2534 class OMPTaskDirective : public OMPExecutableDirective {
2535   friend class ASTStmtReader;
2536   friend class OMPExecutableDirective;
2537   /// true if this directive has inner cancel directive.
2538   bool HasCancel = false;
2539 
2540   /// Build directive with the given start and end location.
2541   ///
2542   /// \param StartLoc Starting location of the directive kind.
2543   /// \param EndLoc Ending location of the directive.
2544   ///
OMPTaskDirective(SourceLocation StartLoc,SourceLocation EndLoc)2545   OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2546       : OMPExecutableDirective(OMPTaskDirectiveClass, llvm::omp::OMPD_task,
2547                                StartLoc, EndLoc) {}
2548 
2549   /// Build an empty directive.
2550   ///
OMPTaskDirective()2551   explicit OMPTaskDirective()
2552       : OMPExecutableDirective(OMPTaskDirectiveClass, llvm::omp::OMPD_task,
2553                                SourceLocation(), SourceLocation()) {}
2554 
2555   /// Set cancel state.
setHasCancel(bool Has)2556   void setHasCancel(bool Has) { HasCancel = Has; }
2557 
2558 public:
2559   /// Creates directive with a list of \a Clauses.
2560   ///
2561   /// \param C AST context.
2562   /// \param StartLoc Starting location of the directive kind.
2563   /// \param EndLoc Ending Location of the directive.
2564   /// \param Clauses List of clauses.
2565   /// \param AssociatedStmt Statement, associated with the directive.
2566   /// \param HasCancel true, if current directive has inner cancel directive.
2567   ///
2568   static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc,
2569                                   SourceLocation EndLoc,
2570                                   ArrayRef<OMPClause *> Clauses,
2571                                   Stmt *AssociatedStmt, bool HasCancel);
2572 
2573   /// Creates an empty directive with the place for \a NumClauses
2574   /// clauses.
2575   ///
2576   /// \param C AST context.
2577   /// \param NumClauses Number of clauses.
2578   ///
2579   static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
2580                                        EmptyShell);
2581 
2582   /// Return true if current directive has inner cancel directive.
hasCancel()2583   bool hasCancel() const { return HasCancel; }
2584 
classof(const Stmt * T)2585   static bool classof(const Stmt *T) {
2586     return T->getStmtClass() == OMPTaskDirectiveClass;
2587   }
2588 };
2589 
2590 /// This represents '#pragma omp taskyield' directive.
2591 ///
2592 /// \code
2593 /// #pragma omp taskyield
2594 /// \endcode
2595 ///
2596 class OMPTaskyieldDirective : public OMPExecutableDirective {
2597   friend class ASTStmtReader;
2598   friend class OMPExecutableDirective;
2599   /// Build directive with the given start and end location.
2600   ///
2601   /// \param StartLoc Starting location of the directive kind.
2602   /// \param EndLoc Ending location of the directive.
2603   ///
OMPTaskyieldDirective(SourceLocation StartLoc,SourceLocation EndLoc)2604   OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2605       : OMPExecutableDirective(OMPTaskyieldDirectiveClass,
2606                                llvm::omp::OMPD_taskyield, StartLoc, EndLoc) {}
2607 
2608   /// Build an empty directive.
2609   ///
OMPTaskyieldDirective()2610   explicit OMPTaskyieldDirective()
2611       : OMPExecutableDirective(OMPTaskyieldDirectiveClass,
2612                                llvm::omp::OMPD_taskyield, SourceLocation(),
2613                                SourceLocation()) {}
2614 
2615 public:
2616   /// Creates directive.
2617   ///
2618   /// \param C AST context.
2619   /// \param StartLoc Starting location of the directive kind.
2620   /// \param EndLoc Ending Location of the directive.
2621   ///
2622   static OMPTaskyieldDirective *
2623   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
2624 
2625   /// Creates an empty directive.
2626   ///
2627   /// \param C AST context.
2628   ///
2629   static OMPTaskyieldDirective *CreateEmpty(const ASTContext &C, EmptyShell);
2630 
classof(const Stmt * T)2631   static bool classof(const Stmt *T) {
2632     return T->getStmtClass() == OMPTaskyieldDirectiveClass;
2633   }
2634 };
2635 
2636 /// This represents '#pragma omp barrier' directive.
2637 ///
2638 /// \code
2639 /// #pragma omp barrier
2640 /// \endcode
2641 ///
2642 class OMPBarrierDirective : public OMPExecutableDirective {
2643   friend class ASTStmtReader;
2644   friend class OMPExecutableDirective;
2645   /// Build directive with the given start and end location.
2646   ///
2647   /// \param StartLoc Starting location of the directive kind.
2648   /// \param EndLoc Ending location of the directive.
2649   ///
OMPBarrierDirective(SourceLocation StartLoc,SourceLocation EndLoc)2650   OMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2651       : OMPExecutableDirective(OMPBarrierDirectiveClass,
2652                                llvm::omp::OMPD_barrier, StartLoc, EndLoc) {}
2653 
2654   /// Build an empty directive.
2655   ///
OMPBarrierDirective()2656   explicit OMPBarrierDirective()
2657       : OMPExecutableDirective(OMPBarrierDirectiveClass,
2658                                llvm::omp::OMPD_barrier, SourceLocation(),
2659                                SourceLocation()) {}
2660 
2661 public:
2662   /// Creates directive.
2663   ///
2664   /// \param C AST context.
2665   /// \param StartLoc Starting location of the directive kind.
2666   /// \param EndLoc Ending Location of the directive.
2667   ///
2668   static OMPBarrierDirective *
2669   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
2670 
2671   /// Creates an empty directive.
2672   ///
2673   /// \param C AST context.
2674   ///
2675   static OMPBarrierDirective *CreateEmpty(const ASTContext &C, EmptyShell);
2676 
classof(const Stmt * T)2677   static bool classof(const Stmt *T) {
2678     return T->getStmtClass() == OMPBarrierDirectiveClass;
2679   }
2680 };
2681 
2682 /// This represents '#pragma omp taskwait' directive.
2683 ///
2684 /// \code
2685 /// #pragma omp taskwait
2686 /// \endcode
2687 ///
2688 class OMPTaskwaitDirective : public OMPExecutableDirective {
2689   friend class ASTStmtReader;
2690   friend class OMPExecutableDirective;
2691   /// Build directive with the given start and end location.
2692   ///
2693   /// \param StartLoc Starting location of the directive kind.
2694   /// \param EndLoc Ending location of the directive.
2695   ///
OMPTaskwaitDirective(SourceLocation StartLoc,SourceLocation EndLoc)2696   OMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2697       : OMPExecutableDirective(OMPTaskwaitDirectiveClass,
2698                                llvm::omp::OMPD_taskwait, StartLoc, EndLoc) {}
2699 
2700   /// Build an empty directive.
2701   ///
OMPTaskwaitDirective()2702   explicit OMPTaskwaitDirective()
2703       : OMPExecutableDirective(OMPTaskwaitDirectiveClass,
2704                                llvm::omp::OMPD_taskwait, SourceLocation(),
2705                                SourceLocation()) {}
2706 
2707 public:
2708   /// Creates directive.
2709   ///
2710   /// \param C AST context.
2711   /// \param StartLoc Starting location of the directive kind.
2712   /// \param EndLoc Ending Location of the directive.
2713   /// \param Clauses List of clauses.
2714   ///
2715   static OMPTaskwaitDirective *Create(const ASTContext &C,
2716                                       SourceLocation StartLoc,
2717                                       SourceLocation EndLoc,
2718                                       ArrayRef<OMPClause *> Clauses);
2719 
2720   /// Creates an empty directive.
2721   ///
2722   /// \param C AST context.
2723   /// \param NumClauses Number of clauses.
2724   ///
2725   static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C,
2726                                            unsigned NumClauses, EmptyShell);
2727 
classof(const Stmt * T)2728   static bool classof(const Stmt *T) {
2729     return T->getStmtClass() == OMPTaskwaitDirectiveClass;
2730   }
2731 };
2732 
2733 /// This represents '#pragma omp taskgroup' directive.
2734 ///
2735 /// \code
2736 /// #pragma omp taskgroup
2737 /// \endcode
2738 ///
2739 class OMPTaskgroupDirective : public OMPExecutableDirective {
2740   friend class ASTStmtReader;
2741   friend class OMPExecutableDirective;
2742   /// Build directive with the given start and end location.
2743   ///
2744   /// \param StartLoc Starting location of the directive kind.
2745   /// \param EndLoc Ending location of the directive.
2746   ///
OMPTaskgroupDirective(SourceLocation StartLoc,SourceLocation EndLoc)2747   OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2748       : OMPExecutableDirective(OMPTaskgroupDirectiveClass,
2749                                llvm::omp::OMPD_taskgroup, StartLoc, EndLoc) {}
2750 
2751   /// Build an empty directive.
2752   ///
OMPTaskgroupDirective()2753   explicit OMPTaskgroupDirective()
2754       : OMPExecutableDirective(OMPTaskgroupDirectiveClass,
2755                                llvm::omp::OMPD_taskgroup, SourceLocation(),
2756                                SourceLocation()) {}
2757 
2758   /// Sets the task_reduction return variable.
setReductionRef(Expr * RR)2759   void setReductionRef(Expr *RR) { Data->getChildren()[0] = RR; }
2760 
2761 public:
2762   /// Creates directive.
2763   ///
2764   /// \param C AST context.
2765   /// \param StartLoc Starting location of the directive kind.
2766   /// \param EndLoc Ending Location of the directive.
2767   /// \param Clauses List of clauses.
2768   /// \param AssociatedStmt Statement, associated with the directive.
2769   /// \param ReductionRef Reference to the task_reduction return variable.
2770   ///
2771   static OMPTaskgroupDirective *
2772   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2773          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
2774          Expr *ReductionRef);
2775 
2776   /// Creates an empty directive.
2777   ///
2778   /// \param C AST context.
2779   /// \param NumClauses Number of clauses.
2780   ///
2781   static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C,
2782                                             unsigned NumClauses, EmptyShell);
2783 
2784 
2785   /// Returns reference to the task_reduction return variable.
getReductionRef()2786   const Expr *getReductionRef() const {
2787     return const_cast<OMPTaskgroupDirective *>(this)->getReductionRef();
2788   }
getReductionRef()2789   Expr *getReductionRef() { return cast_or_null<Expr>(Data->getChildren()[0]); }
2790 
classof(const Stmt * T)2791   static bool classof(const Stmt *T) {
2792     return T->getStmtClass() == OMPTaskgroupDirectiveClass;
2793   }
2794 };
2795 
2796 /// This represents '#pragma omp flush' directive.
2797 ///
2798 /// \code
2799 /// #pragma omp flush(a,b)
2800 /// \endcode
2801 /// In this example directive '#pragma omp flush' has 2 arguments- variables 'a'
2802 /// and 'b'.
2803 /// 'omp flush' directive does not have clauses but have an optional list of
2804 /// variables to flush. This list of variables is stored within some fake clause
2805 /// FlushClause.
2806 class OMPFlushDirective : public OMPExecutableDirective {
2807   friend class ASTStmtReader;
2808   friend class OMPExecutableDirective;
2809   /// Build directive with the given start and end location.
2810   ///
2811   /// \param StartLoc Starting location of the directive kind.
2812   /// \param EndLoc Ending location of the directive.
2813   ///
OMPFlushDirective(SourceLocation StartLoc,SourceLocation EndLoc)2814   OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2815       : OMPExecutableDirective(OMPFlushDirectiveClass, llvm::omp::OMPD_flush,
2816                                StartLoc, EndLoc) {}
2817 
2818   /// Build an empty directive.
2819   ///
OMPFlushDirective()2820   explicit OMPFlushDirective()
2821       : OMPExecutableDirective(OMPFlushDirectiveClass, llvm::omp::OMPD_flush,
2822                                SourceLocation(), SourceLocation()) {}
2823 
2824 public:
2825   /// Creates directive with a list of \a Clauses.
2826   ///
2827   /// \param C AST context.
2828   /// \param StartLoc Starting location of the directive kind.
2829   /// \param EndLoc Ending Location of the directive.
2830   /// \param Clauses List of clauses (only single OMPFlushClause clause is
2831   /// allowed).
2832   ///
2833   static OMPFlushDirective *Create(const ASTContext &C, SourceLocation StartLoc,
2834                                    SourceLocation EndLoc,
2835                                    ArrayRef<OMPClause *> Clauses);
2836 
2837   /// Creates an empty directive with the place for \a NumClauses
2838   /// clauses.
2839   ///
2840   /// \param C AST context.
2841   /// \param NumClauses Number of clauses.
2842   ///
2843   static OMPFlushDirective *CreateEmpty(const ASTContext &C,
2844                                         unsigned NumClauses, EmptyShell);
2845 
classof(const Stmt * T)2846   static bool classof(const Stmt *T) {
2847     return T->getStmtClass() == OMPFlushDirectiveClass;
2848   }
2849 };
2850 
2851 /// This represents '#pragma omp depobj' directive.
2852 ///
2853 /// \code
2854 /// #pragma omp depobj(a) depend(in:x,y)
2855 /// \endcode
2856 /// In this example directive '#pragma omp  depobj' initializes a depobj object
2857 /// 'a' with dependence type 'in' and a list with 'x' and 'y' locators.
2858 class OMPDepobjDirective final : public OMPExecutableDirective {
2859   friend class ASTStmtReader;
2860   friend class OMPExecutableDirective;
2861 
2862   /// Build directive with the given start and end location.
2863   ///
2864   /// \param StartLoc Starting location of the directive kind.
2865   /// \param EndLoc Ending location of the directive.
2866   ///
OMPDepobjDirective(SourceLocation StartLoc,SourceLocation EndLoc)2867   OMPDepobjDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2868       : OMPExecutableDirective(OMPDepobjDirectiveClass, llvm::omp::OMPD_depobj,
2869                                StartLoc, EndLoc) {}
2870 
2871   /// Build an empty directive.
2872   ///
OMPDepobjDirective()2873   explicit OMPDepobjDirective()
2874       : OMPExecutableDirective(OMPDepobjDirectiveClass, llvm::omp::OMPD_depobj,
2875                                SourceLocation(), SourceLocation()) {}
2876 
2877 public:
2878   /// Creates directive with a list of \a Clauses.
2879   ///
2880   /// \param C AST context.
2881   /// \param StartLoc Starting location of the directive kind.
2882   /// \param EndLoc Ending Location of the directive.
2883   /// \param Clauses List of clauses.
2884   ///
2885   static OMPDepobjDirective *Create(const ASTContext &C,
2886                                     SourceLocation StartLoc,
2887                                     SourceLocation EndLoc,
2888                                     ArrayRef<OMPClause *> Clauses);
2889 
2890   /// Creates an empty directive with the place for \a NumClauses
2891   /// clauses.
2892   ///
2893   /// \param C AST context.
2894   /// \param NumClauses Number of clauses.
2895   ///
2896   static OMPDepobjDirective *CreateEmpty(const ASTContext &C,
2897                                          unsigned NumClauses, EmptyShell);
2898 
classof(const Stmt * T)2899   static bool classof(const Stmt *T) {
2900     return T->getStmtClass() == OMPDepobjDirectiveClass;
2901   }
2902 };
2903 
2904 /// This represents '#pragma omp ordered' directive.
2905 ///
2906 /// \code
2907 /// #pragma omp ordered
2908 /// \endcode
2909 ///
2910 class OMPOrderedDirective : public OMPExecutableDirective {
2911   friend class ASTStmtReader;
2912   friend class OMPExecutableDirective;
2913   /// Build directive with the given start and end location.
2914   ///
2915   /// \param StartLoc Starting location of the directive kind.
2916   /// \param EndLoc Ending location of the directive.
2917   ///
OMPOrderedDirective(SourceLocation StartLoc,SourceLocation EndLoc)2918   OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2919       : OMPExecutableDirective(OMPOrderedDirectiveClass,
2920                                llvm::omp::OMPD_ordered, StartLoc, EndLoc) {}
2921 
2922   /// Build an empty directive.
2923   ///
OMPOrderedDirective()2924   explicit OMPOrderedDirective()
2925       : OMPExecutableDirective(OMPOrderedDirectiveClass,
2926                                llvm::omp::OMPD_ordered, SourceLocation(),
2927                                SourceLocation()) {}
2928 
2929 public:
2930   /// Creates directive.
2931   ///
2932   /// \param C AST context.
2933   /// \param StartLoc Starting location of the directive kind.
2934   /// \param EndLoc Ending Location of the directive.
2935   /// \param Clauses List of clauses.
2936   /// \param AssociatedStmt Statement, associated with the directive.
2937   ///
2938   static OMPOrderedDirective *
2939   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2940          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
2941 
2942   /// Creates an empty directive.
2943   ///
2944   /// \param C AST context.
2945   /// \param NumClauses Number of clauses.
2946   /// \param IsStandalone true, if the standalone directive is created.
2947   ///
2948   static OMPOrderedDirective *CreateEmpty(const ASTContext &C,
2949                                           unsigned NumClauses,
2950                                           bool IsStandalone, EmptyShell);
2951 
classof(const Stmt * T)2952   static bool classof(const Stmt *T) {
2953     return T->getStmtClass() == OMPOrderedDirectiveClass;
2954   }
2955 };
2956 
2957 /// This represents '#pragma omp atomic' directive.
2958 ///
2959 /// \code
2960 /// #pragma omp atomic capture
2961 /// \endcode
2962 /// In this example directive '#pragma omp atomic' has clause 'capture'.
2963 ///
2964 class OMPAtomicDirective : public OMPExecutableDirective {
2965   friend class ASTStmtReader;
2966   friend class OMPExecutableDirective;
2967 
2968   struct FlagTy {
2969     /// Used for 'atomic update' or 'atomic capture' constructs. They may
2970     /// have atomic expressions of forms:
2971     /// \code
2972     /// x = x binop expr;
2973     /// x = expr binop x;
2974     /// \endcode
2975     /// This field is 1 for the first form of the expression and 0 for the
2976     /// second. Required for correct codegen of non-associative operations (like
2977     /// << or >>).
2978     LLVM_PREFERRED_TYPE(bool)
2979     uint8_t IsXLHSInRHSPart : 1;
2980     /// Used for 'atomic update' or 'atomic capture' constructs. They may
2981     /// have atomic expressions of forms:
2982     /// \code
2983     /// v = x; <update x>;
2984     /// <update x>; v = x;
2985     /// \endcode
2986     /// This field is 1 for the first(postfix) form of the expression and 0
2987     /// otherwise.
2988     LLVM_PREFERRED_TYPE(bool)
2989     uint8_t IsPostfixUpdate : 1;
2990     /// 1 if 'v' is updated only when the condition is false (compare capture
2991     /// only).
2992     LLVM_PREFERRED_TYPE(bool)
2993     uint8_t IsFailOnly : 1;
2994   } Flags;
2995 
2996   /// Build directive with the given start and end location.
2997   ///
2998   /// \param StartLoc Starting location of the directive kind.
2999   /// \param EndLoc Ending location of the directive.
3000   ///
OMPAtomicDirective(SourceLocation StartLoc,SourceLocation EndLoc)3001   OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3002       : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
3003                                StartLoc, EndLoc) {}
3004 
3005   /// Build an empty directive.
3006   ///
OMPAtomicDirective()3007   explicit OMPAtomicDirective()
3008       : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
3009                                SourceLocation(), SourceLocation()) {}
3010 
3011   enum DataPositionTy : size_t {
3012     POS_X = 0,
3013     POS_V,
3014     POS_E,
3015     POS_UpdateExpr,
3016     POS_D,
3017     POS_Cond,
3018     POS_R,
3019   };
3020 
3021   /// Set 'x' part of the associated expression/statement.
setX(Expr * X)3022   void setX(Expr *X) { Data->getChildren()[DataPositionTy::POS_X] = X; }
3023   /// Set helper expression of the form
3024   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
3025   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
setUpdateExpr(Expr * UE)3026   void setUpdateExpr(Expr *UE) {
3027     Data->getChildren()[DataPositionTy::POS_UpdateExpr] = UE;
3028   }
3029   /// Set 'v' part of the associated expression/statement.
setV(Expr * V)3030   void setV(Expr *V) { Data->getChildren()[DataPositionTy::POS_V] = V; }
3031   /// Set 'r' part of the associated expression/statement.
setR(Expr * R)3032   void setR(Expr *R) { Data->getChildren()[DataPositionTy::POS_R] = R; }
3033   /// Set 'expr' part of the associated expression/statement.
setExpr(Expr * E)3034   void setExpr(Expr *E) { Data->getChildren()[DataPositionTy::POS_E] = E; }
3035   /// Set 'd' part of the associated expression/statement.
setD(Expr * D)3036   void setD(Expr *D) { Data->getChildren()[DataPositionTy::POS_D] = D; }
3037   /// Set conditional expression in `atomic compare`.
setCond(Expr * C)3038   void setCond(Expr *C) { Data->getChildren()[DataPositionTy::POS_Cond] = C; }
3039 
3040 public:
3041   struct Expressions {
3042     /// 'x' part of the associated expression/statement.
3043     Expr *X = nullptr;
3044     /// 'v' part of the associated expression/statement.
3045     Expr *V = nullptr;
3046     // 'r' part of the associated expression/statement.
3047     Expr *R = nullptr;
3048     /// 'expr' part of the associated expression/statement.
3049     Expr *E = nullptr;
3050     /// UE Helper expression of the form:
3051     /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
3052     /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
3053     Expr *UE = nullptr;
3054     /// 'd' part of the associated expression/statement.
3055     Expr *D = nullptr;
3056     /// Conditional expression in `atomic compare` construct.
3057     Expr *Cond = nullptr;
3058     /// True if UE has the first form and false if the second.
3059     bool IsXLHSInRHSPart;
3060     /// True if original value of 'x' must be stored in 'v', not an updated one.
3061     bool IsPostfixUpdate;
3062     /// True if 'v' is updated only when the condition is false (compare capture
3063     /// only).
3064     bool IsFailOnly;
3065   };
3066 
3067   /// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
3068   /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for
3069   /// detailed description of 'x', 'v' and 'expr').
3070   ///
3071   /// \param C AST context.
3072   /// \param StartLoc Starting location of the directive kind.
3073   /// \param EndLoc Ending Location of the directive.
3074   /// \param Clauses List of clauses.
3075   /// \param AssociatedStmt Statement, associated with the directive.
3076   /// \param Exprs Associated expressions or statements.
3077   static OMPAtomicDirective *Create(const ASTContext &C,
3078                                     SourceLocation StartLoc,
3079                                     SourceLocation EndLoc,
3080                                     ArrayRef<OMPClause *> Clauses,
3081                                     Stmt *AssociatedStmt, Expressions Exprs);
3082 
3083   /// Creates an empty directive with the place for \a NumClauses
3084   /// clauses.
3085   ///
3086   /// \param C AST context.
3087   /// \param NumClauses Number of clauses.
3088   ///
3089   static OMPAtomicDirective *CreateEmpty(const ASTContext &C,
3090                                          unsigned NumClauses, EmptyShell);
3091 
3092   /// Get 'x' part of the associated expression/statement.
getX()3093   Expr *getX() {
3094     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_X]);
3095   }
getX()3096   const Expr *getX() const {
3097     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_X]);
3098   }
3099   /// Get helper expression of the form
3100   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
3101   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
getUpdateExpr()3102   Expr *getUpdateExpr() {
3103     return cast_or_null<Expr>(
3104         Data->getChildren()[DataPositionTy::POS_UpdateExpr]);
3105   }
getUpdateExpr()3106   const Expr *getUpdateExpr() const {
3107     return cast_or_null<Expr>(
3108         Data->getChildren()[DataPositionTy::POS_UpdateExpr]);
3109   }
3110   /// Return true if helper update expression has form
3111   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form
3112   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
isXLHSInRHSPart()3113   bool isXLHSInRHSPart() const { return Flags.IsXLHSInRHSPart; }
3114   /// Return true if 'v' expression must be updated to original value of
3115   /// 'x', false if 'v' must be updated to the new value of 'x'.
isPostfixUpdate()3116   bool isPostfixUpdate() const { return Flags.IsPostfixUpdate; }
3117   /// Return true if 'v' is updated only when the condition is evaluated false
3118   /// (compare capture only).
isFailOnly()3119   bool isFailOnly() const { return Flags.IsFailOnly; }
3120   /// Get 'v' part of the associated expression/statement.
getV()3121   Expr *getV() {
3122     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]);
3123   }
getV()3124   const Expr *getV() const {
3125     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]);
3126   }
3127   /// Get 'r' part of the associated expression/statement.
getR()3128   Expr *getR() {
3129     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]);
3130   }
getR()3131   const Expr *getR() const {
3132     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]);
3133   }
3134   /// Get 'expr' part of the associated expression/statement.
getExpr()3135   Expr *getExpr() {
3136     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
3137   }
getExpr()3138   const Expr *getExpr() const {
3139     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
3140   }
3141   /// Get 'd' part of the associated expression/statement.
getD()3142   Expr *getD() {
3143     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
3144   }
getD()3145   Expr *getD() const {
3146     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
3147   }
3148   /// Get the 'cond' part of the source atomic expression.
getCondExpr()3149   Expr *getCondExpr() {
3150     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
3151   }
getCondExpr()3152   Expr *getCondExpr() const {
3153     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
3154   }
3155 
classof(const Stmt * T)3156   static bool classof(const Stmt *T) {
3157     return T->getStmtClass() == OMPAtomicDirectiveClass;
3158   }
3159 };
3160 
3161 /// This represents '#pragma omp target' directive.
3162 ///
3163 /// \code
3164 /// #pragma omp target if(a)
3165 /// \endcode
3166 /// In this example directive '#pragma omp target' has clause 'if' with
3167 /// condition 'a'.
3168 ///
3169 class OMPTargetDirective : public OMPExecutableDirective {
3170   friend class ASTStmtReader;
3171   friend class OMPExecutableDirective;
3172   /// Build directive with the given start and end location.
3173   ///
3174   /// \param StartLoc Starting location of the directive kind.
3175   /// \param EndLoc Ending location of the directive.
3176   ///
OMPTargetDirective(SourceLocation StartLoc,SourceLocation EndLoc)3177   OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3178       : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
3179                                StartLoc, EndLoc) {}
3180 
3181   /// Build an empty directive.
3182   ///
OMPTargetDirective()3183   explicit OMPTargetDirective()
3184       : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
3185                                SourceLocation(), SourceLocation()) {}
3186 
3187 public:
3188   /// Creates directive with a list of \a Clauses.
3189   ///
3190   /// \param C AST context.
3191   /// \param StartLoc Starting location of the directive kind.
3192   /// \param EndLoc Ending Location of the directive.
3193   /// \param Clauses List of clauses.
3194   /// \param AssociatedStmt Statement, associated with the directive.
3195   ///
3196   static OMPTargetDirective *
3197   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3198          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3199 
3200   /// Creates an empty directive with the place for \a NumClauses
3201   /// clauses.
3202   ///
3203   /// \param C AST context.
3204   /// \param NumClauses Number of clauses.
3205   ///
3206   static OMPTargetDirective *CreateEmpty(const ASTContext &C,
3207                                          unsigned NumClauses, EmptyShell);
3208 
classof(const Stmt * T)3209   static bool classof(const Stmt *T) {
3210     return T->getStmtClass() == OMPTargetDirectiveClass;
3211   }
3212 };
3213 
3214 /// This represents '#pragma omp target data' directive.
3215 ///
3216 /// \code
3217 /// #pragma omp target data device(0) if(a) map(b[:])
3218 /// \endcode
3219 /// In this example directive '#pragma omp target data' has clauses 'device'
3220 /// with the value '0', 'if' with condition 'a' and 'map' with array
3221 /// section 'b[:]'.
3222 ///
3223 class OMPTargetDataDirective : public OMPExecutableDirective {
3224   friend class ASTStmtReader;
3225   friend class OMPExecutableDirective;
3226   /// Build directive with the given start and end location.
3227   ///
3228   /// \param StartLoc Starting location of the directive kind.
3229   /// \param EndLoc Ending Location of the directive.
3230   ///
OMPTargetDataDirective(SourceLocation StartLoc,SourceLocation EndLoc)3231   OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3232       : OMPExecutableDirective(OMPTargetDataDirectiveClass,
3233                                llvm::omp::OMPD_target_data, StartLoc, EndLoc) {}
3234 
3235   /// Build an empty directive.
3236   ///
OMPTargetDataDirective()3237   explicit OMPTargetDataDirective()
3238       : OMPExecutableDirective(OMPTargetDataDirectiveClass,
3239                                llvm::omp::OMPD_target_data, SourceLocation(),
3240                                SourceLocation()) {}
3241 
3242 public:
3243   /// Creates directive with a list of \a Clauses.
3244   ///
3245   /// \param C AST context.
3246   /// \param StartLoc Starting location of the directive kind.
3247   /// \param EndLoc Ending Location of the directive.
3248   /// \param Clauses List of clauses.
3249   /// \param AssociatedStmt Statement, associated with the directive.
3250   ///
3251   static OMPTargetDataDirective *
3252   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3253          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3254 
3255   /// Creates an empty directive with the place for \a N clauses.
3256   ///
3257   /// \param C AST context.
3258   /// \param N The number of clauses.
3259   ///
3260   static OMPTargetDataDirective *CreateEmpty(const ASTContext &C, unsigned N,
3261                                              EmptyShell);
3262 
classof(const Stmt * T)3263   static bool classof(const Stmt *T) {
3264     return T->getStmtClass() == OMPTargetDataDirectiveClass;
3265   }
3266 };
3267 
3268 /// This represents '#pragma omp target enter data' directive.
3269 ///
3270 /// \code
3271 /// #pragma omp target enter data device(0) if(a) map(b[:])
3272 /// \endcode
3273 /// In this example directive '#pragma omp target enter data' has clauses
3274 /// 'device' with the value '0', 'if' with condition 'a' and 'map' with array
3275 /// section 'b[:]'.
3276 ///
3277 class OMPTargetEnterDataDirective : public OMPExecutableDirective {
3278   friend class ASTStmtReader;
3279   friend class OMPExecutableDirective;
3280   /// Build directive with the given start and end location.
3281   ///
3282   /// \param StartLoc Starting location of the directive kind.
3283   /// \param EndLoc Ending Location of the directive.
3284   ///
OMPTargetEnterDataDirective(SourceLocation StartLoc,SourceLocation EndLoc)3285   OMPTargetEnterDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3286       : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
3287                                llvm::omp::OMPD_target_enter_data, StartLoc,
3288                                EndLoc) {}
3289 
3290   /// Build an empty directive.
3291   ///
OMPTargetEnterDataDirective()3292   explicit OMPTargetEnterDataDirective()
3293       : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
3294                                llvm::omp::OMPD_target_enter_data,
3295                                SourceLocation(), SourceLocation()) {}
3296 
3297 public:
3298   /// Creates directive with a list of \a Clauses.
3299   ///
3300   /// \param C AST context.
3301   /// \param StartLoc Starting location of the directive kind.
3302   /// \param EndLoc Ending Location of the directive.
3303   /// \param Clauses List of clauses.
3304   /// \param AssociatedStmt Statement, associated with the directive.
3305   ///
3306   static OMPTargetEnterDataDirective *
3307   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3308          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3309 
3310   /// Creates an empty directive with the place for \a N clauses.
3311   ///
3312   /// \param C AST context.
3313   /// \param N The number of clauses.
3314   ///
3315   static OMPTargetEnterDataDirective *CreateEmpty(const ASTContext &C,
3316                                                   unsigned N, EmptyShell);
3317 
classof(const Stmt * T)3318   static bool classof(const Stmt *T) {
3319     return T->getStmtClass() == OMPTargetEnterDataDirectiveClass;
3320   }
3321 };
3322 
3323 /// This represents '#pragma omp target exit data' directive.
3324 ///
3325 /// \code
3326 /// #pragma omp target exit data device(0) if(a) map(b[:])
3327 /// \endcode
3328 /// In this example directive '#pragma omp target exit data' has clauses
3329 /// 'device' with the value '0', 'if' with condition 'a' and 'map' with array
3330 /// section 'b[:]'.
3331 ///
3332 class OMPTargetExitDataDirective : public OMPExecutableDirective {
3333   friend class ASTStmtReader;
3334   friend class OMPExecutableDirective;
3335   /// Build directive with the given start and end location.
3336   ///
3337   /// \param StartLoc Starting location of the directive kind.
3338   /// \param EndLoc Ending Location of the directive.
3339   ///
OMPTargetExitDataDirective(SourceLocation StartLoc,SourceLocation EndLoc)3340   OMPTargetExitDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3341       : OMPExecutableDirective(OMPTargetExitDataDirectiveClass,
3342                                llvm::omp::OMPD_target_exit_data, StartLoc,
3343                                EndLoc) {}
3344 
3345   /// Build an empty directive.
3346   ///
OMPTargetExitDataDirective()3347   explicit OMPTargetExitDataDirective()
3348       : OMPExecutableDirective(OMPTargetExitDataDirectiveClass,
3349                                llvm::omp::OMPD_target_exit_data,
3350                                SourceLocation(), SourceLocation()) {}
3351 
3352 public:
3353   /// Creates directive with a list of \a Clauses.
3354   ///
3355   /// \param C AST context.
3356   /// \param StartLoc Starting location of the directive kind.
3357   /// \param EndLoc Ending Location of the directive.
3358   /// \param Clauses List of clauses.
3359   /// \param AssociatedStmt Statement, associated with the directive.
3360   ///
3361   static OMPTargetExitDataDirective *
3362   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3363          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3364 
3365   /// Creates an empty directive with the place for \a N clauses.
3366   ///
3367   /// \param C AST context.
3368   /// \param N The number of clauses.
3369   ///
3370   static OMPTargetExitDataDirective *CreateEmpty(const ASTContext &C,
3371                                                  unsigned N, EmptyShell);
3372 
classof(const Stmt * T)3373   static bool classof(const Stmt *T) {
3374     return T->getStmtClass() == OMPTargetExitDataDirectiveClass;
3375   }
3376 };
3377 
3378 /// This represents '#pragma omp target parallel' directive.
3379 ///
3380 /// \code
3381 /// #pragma omp target parallel if(a)
3382 /// \endcode
3383 /// In this example directive '#pragma omp target parallel' has clause 'if' with
3384 /// condition 'a'.
3385 ///
3386 class OMPTargetParallelDirective : public OMPExecutableDirective {
3387   friend class ASTStmtReader;
3388   friend class OMPExecutableDirective;
3389   /// true if the construct has inner cancel directive.
3390   bool HasCancel = false;
3391 
3392   /// Build directive with the given start and end location.
3393   ///
3394   /// \param StartLoc Starting location of the directive kind.
3395   /// \param EndLoc Ending location of the directive.
3396   ///
OMPTargetParallelDirective(SourceLocation StartLoc,SourceLocation EndLoc)3397   OMPTargetParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3398       : OMPExecutableDirective(OMPTargetParallelDirectiveClass,
3399                                llvm::omp::OMPD_target_parallel, StartLoc,
3400                                EndLoc) {}
3401 
3402   /// Build an empty directive.
3403   ///
OMPTargetParallelDirective()3404   explicit OMPTargetParallelDirective()
3405       : OMPExecutableDirective(OMPTargetParallelDirectiveClass,
3406                                llvm::omp::OMPD_target_parallel,
3407                                SourceLocation(), SourceLocation()) {}
3408 
3409   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)3410   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
3411   /// Set cancel state.
setHasCancel(bool Has)3412   void setHasCancel(bool Has) { HasCancel = Has; }
3413 
3414 public:
3415   /// Creates directive with a list of \a Clauses.
3416   ///
3417   /// \param C AST context.
3418   /// \param StartLoc Starting location of the directive kind.
3419   /// \param EndLoc Ending Location of the directive.
3420   /// \param Clauses List of clauses.
3421   /// \param AssociatedStmt Statement, associated with the directive.
3422   /// \param TaskRedRef Task reduction special reference expression to handle
3423   /// taskgroup descriptor.
3424   /// \param HasCancel true if this directive has inner cancel directive.
3425   ///
3426   static OMPTargetParallelDirective *
3427   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3428          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
3429          bool HasCancel);
3430 
3431   /// Creates an empty directive with the place for \a NumClauses
3432   /// clauses.
3433   ///
3434   /// \param C AST context.
3435   /// \param NumClauses Number of clauses.
3436   ///
3437   static OMPTargetParallelDirective *
3438   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
3439 
3440   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()3441   Expr *getTaskReductionRefExpr() {
3442     return cast_or_null<Expr>(Data->getChildren()[0]);
3443   }
getTaskReductionRefExpr()3444   const Expr *getTaskReductionRefExpr() const {
3445     return const_cast<OMPTargetParallelDirective *>(this)
3446         ->getTaskReductionRefExpr();
3447   }
3448 
3449   /// Return true if current directive has inner cancel directive.
hasCancel()3450   bool hasCancel() const { return HasCancel; }
3451 
classof(const Stmt * T)3452   static bool classof(const Stmt *T) {
3453     return T->getStmtClass() == OMPTargetParallelDirectiveClass;
3454   }
3455 };
3456 
3457 /// This represents '#pragma omp target parallel for' directive.
3458 ///
3459 /// \code
3460 /// #pragma omp target parallel for private(a,b) reduction(+:c,d)
3461 /// \endcode
3462 /// In this example directive '#pragma omp target parallel for' has clauses
3463 /// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+'
3464 /// and variables 'c' and 'd'.
3465 ///
3466 class OMPTargetParallelForDirective : public OMPLoopDirective {
3467   friend class ASTStmtReader;
3468   friend class OMPExecutableDirective;
3469 
3470   /// true if current region has inner cancel directive.
3471   bool HasCancel = false;
3472 
3473   /// Build directive with the given start and end location.
3474   ///
3475   /// \param StartLoc Starting location of the directive kind.
3476   /// \param EndLoc Ending location of the directive.
3477   /// \param CollapsedNum Number of collapsed nested loops.
3478   ///
OMPTargetParallelForDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)3479   OMPTargetParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3480                                 unsigned CollapsedNum)
3481       : OMPLoopDirective(OMPTargetParallelForDirectiveClass,
3482                          llvm::omp::OMPD_target_parallel_for, StartLoc, EndLoc,
3483                          CollapsedNum) {}
3484 
3485   /// Build an empty directive.
3486   ///
3487   /// \param CollapsedNum Number of collapsed nested loops.
3488   ///
OMPTargetParallelForDirective(unsigned CollapsedNum)3489   explicit OMPTargetParallelForDirective(unsigned CollapsedNum)
3490       : OMPLoopDirective(OMPTargetParallelForDirectiveClass,
3491                          llvm::omp::OMPD_target_parallel_for, SourceLocation(),
3492                          SourceLocation(), CollapsedNum) {}
3493 
3494   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)3495   void setTaskReductionRefExpr(Expr *E) {
3496     Data->getChildren()[numLoopChildren(
3497         getLoopsNumber(), llvm::omp::OMPD_target_parallel_for)] = E;
3498   }
3499 
3500   /// Set cancel state.
setHasCancel(bool Has)3501   void setHasCancel(bool Has) { HasCancel = Has; }
3502 
3503 public:
3504   /// Creates directive with a list of \a Clauses.
3505   ///
3506   /// \param C AST context.
3507   /// \param StartLoc Starting location of the directive kind.
3508   /// \param EndLoc Ending Location of the directive.
3509   /// \param CollapsedNum Number of collapsed loops.
3510   /// \param Clauses List of clauses.
3511   /// \param AssociatedStmt Statement, associated with the directive.
3512   /// \param Exprs Helper expressions for CodeGen.
3513   /// \param TaskRedRef Task reduction special reference expression to handle
3514   /// taskgroup descriptor.
3515   /// \param HasCancel true if current directive has inner cancel directive.
3516   ///
3517   static OMPTargetParallelForDirective *
3518   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3519          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3520          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
3521          bool HasCancel);
3522 
3523   /// Creates an empty directive with the place
3524   /// for \a NumClauses clauses.
3525   ///
3526   /// \param C AST context.
3527   /// \param CollapsedNum Number of collapsed nested loops.
3528   /// \param NumClauses Number of clauses.
3529   ///
3530   static OMPTargetParallelForDirective *CreateEmpty(const ASTContext &C,
3531                                                     unsigned NumClauses,
3532                                                     unsigned CollapsedNum,
3533                                                     EmptyShell);
3534 
3535   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()3536   Expr *getTaskReductionRefExpr() {
3537     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
3538         getLoopsNumber(), llvm::omp::OMPD_target_parallel_for)]);
3539   }
getTaskReductionRefExpr()3540   const Expr *getTaskReductionRefExpr() const {
3541     return const_cast<OMPTargetParallelForDirective *>(this)
3542         ->getTaskReductionRefExpr();
3543   }
3544 
3545   /// Return true if current directive has inner cancel directive.
hasCancel()3546   bool hasCancel() const { return HasCancel; }
3547 
classof(const Stmt * T)3548   static bool classof(const Stmt *T) {
3549     return T->getStmtClass() == OMPTargetParallelForDirectiveClass;
3550   }
3551 };
3552 
3553 /// This represents '#pragma omp teams' directive.
3554 ///
3555 /// \code
3556 /// #pragma omp teams if(a)
3557 /// \endcode
3558 /// In this example directive '#pragma omp teams' has clause 'if' with
3559 /// condition 'a'.
3560 ///
3561 class OMPTeamsDirective : public OMPExecutableDirective {
3562   friend class ASTStmtReader;
3563   friend class OMPExecutableDirective;
3564   /// Build directive with the given start and end location.
3565   ///
3566   /// \param StartLoc Starting location of the directive kind.
3567   /// \param EndLoc Ending location of the directive.
3568   ///
OMPTeamsDirective(SourceLocation StartLoc,SourceLocation EndLoc)3569   OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3570       : OMPExecutableDirective(OMPTeamsDirectiveClass, llvm::omp::OMPD_teams,
3571                                StartLoc, EndLoc) {}
3572 
3573   /// Build an empty directive.
3574   ///
OMPTeamsDirective()3575   explicit OMPTeamsDirective()
3576       : OMPExecutableDirective(OMPTeamsDirectiveClass, llvm::omp::OMPD_teams,
3577                                SourceLocation(), SourceLocation()) {}
3578 
3579 public:
3580   /// Creates directive with a list of \a Clauses.
3581   ///
3582   /// \param C AST context.
3583   /// \param StartLoc Starting location of the directive kind.
3584   /// \param EndLoc Ending Location of the directive.
3585   /// \param Clauses List of clauses.
3586   /// \param AssociatedStmt Statement, associated with the directive.
3587   ///
3588   static OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc,
3589                                    SourceLocation EndLoc,
3590                                    ArrayRef<OMPClause *> Clauses,
3591                                    Stmt *AssociatedStmt);
3592 
3593   /// Creates an empty directive with the place for \a NumClauses
3594   /// clauses.
3595   ///
3596   /// \param C AST context.
3597   /// \param NumClauses Number of clauses.
3598   ///
3599   static OMPTeamsDirective *CreateEmpty(const ASTContext &C,
3600                                         unsigned NumClauses, EmptyShell);
3601 
classof(const Stmt * T)3602   static bool classof(const Stmt *T) {
3603     return T->getStmtClass() == OMPTeamsDirectiveClass;
3604   }
3605 };
3606 
3607 /// This represents '#pragma omp cancellation point' directive.
3608 ///
3609 /// \code
3610 /// #pragma omp cancellation point for
3611 /// \endcode
3612 ///
3613 /// In this example a cancellation point is created for innermost 'for' region.
3614 class OMPCancellationPointDirective : public OMPExecutableDirective {
3615   friend class ASTStmtReader;
3616   friend class OMPExecutableDirective;
3617   OpenMPDirectiveKind CancelRegion = llvm::omp::OMPD_unknown;
3618   /// Build directive with the given start and end location.
3619   ///
3620   /// \param StartLoc Starting location of the directive kind.
3621   /// \param EndLoc Ending location of the directive.
3622   /// statements and child expressions.
3623   ///
OMPCancellationPointDirective(SourceLocation StartLoc,SourceLocation EndLoc)3624   OMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3625       : OMPExecutableDirective(OMPCancellationPointDirectiveClass,
3626                                llvm::omp::OMPD_cancellation_point, StartLoc,
3627                                EndLoc) {}
3628 
3629   /// Build an empty directive.
OMPCancellationPointDirective()3630   explicit OMPCancellationPointDirective()
3631       : OMPExecutableDirective(OMPCancellationPointDirectiveClass,
3632                                llvm::omp::OMPD_cancellation_point,
3633                                SourceLocation(), SourceLocation()) {}
3634 
3635   /// Set cancel region for current cancellation point.
3636   /// \param CR Cancellation region.
setCancelRegion(OpenMPDirectiveKind CR)3637   void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
3638 
3639 public:
3640   /// Creates directive.
3641   ///
3642   /// \param C AST context.
3643   /// \param StartLoc Starting location of the directive kind.
3644   /// \param EndLoc Ending Location of the directive.
3645   ///
3646   static OMPCancellationPointDirective *
3647   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3648          OpenMPDirectiveKind CancelRegion);
3649 
3650   /// Creates an empty directive.
3651   ///
3652   /// \param C AST context.
3653   ///
3654   static OMPCancellationPointDirective *CreateEmpty(const ASTContext &C,
3655                                                     EmptyShell);
3656 
3657   /// Get cancellation region for the current cancellation point.
getCancelRegion()3658   OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
3659 
classof(const Stmt * T)3660   static bool classof(const Stmt *T) {
3661     return T->getStmtClass() == OMPCancellationPointDirectiveClass;
3662   }
3663 };
3664 
3665 /// This represents '#pragma omp cancel' directive.
3666 ///
3667 /// \code
3668 /// #pragma omp cancel for
3669 /// \endcode
3670 ///
3671 /// In this example a cancel is created for innermost 'for' region.
3672 class OMPCancelDirective : public OMPExecutableDirective {
3673   friend class ASTStmtReader;
3674   friend class OMPExecutableDirective;
3675   OpenMPDirectiveKind CancelRegion = llvm::omp::OMPD_unknown;
3676   /// Build directive with the given start and end location.
3677   ///
3678   /// \param StartLoc Starting location of the directive kind.
3679   /// \param EndLoc Ending location of the directive.
3680   ///
OMPCancelDirective(SourceLocation StartLoc,SourceLocation EndLoc)3681   OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3682       : OMPExecutableDirective(OMPCancelDirectiveClass, llvm::omp::OMPD_cancel,
3683                                StartLoc, EndLoc) {}
3684 
3685   /// Build an empty directive.
3686   ///
OMPCancelDirective()3687   explicit OMPCancelDirective()
3688       : OMPExecutableDirective(OMPCancelDirectiveClass, llvm::omp::OMPD_cancel,
3689                                SourceLocation(), SourceLocation()) {}
3690 
3691   /// Set cancel region for current cancellation point.
3692   /// \param CR Cancellation region.
setCancelRegion(OpenMPDirectiveKind CR)3693   void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
3694 
3695 public:
3696   /// Creates directive.
3697   ///
3698   /// \param C AST context.
3699   /// \param StartLoc Starting location of the directive kind.
3700   /// \param EndLoc Ending Location of the directive.
3701   /// \param Clauses List of clauses.
3702   ///
3703   static OMPCancelDirective *
3704   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3705          ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion);
3706 
3707   /// Creates an empty directive.
3708   ///
3709   /// \param C AST context.
3710   /// \param NumClauses Number of clauses.
3711   ///
3712   static OMPCancelDirective *CreateEmpty(const ASTContext &C,
3713                                          unsigned NumClauses, EmptyShell);
3714 
3715   /// Get cancellation region for the current cancellation point.
getCancelRegion()3716   OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
3717 
classof(const Stmt * T)3718   static bool classof(const Stmt *T) {
3719     return T->getStmtClass() == OMPCancelDirectiveClass;
3720   }
3721 };
3722 
3723 /// This represents '#pragma omp taskloop' directive.
3724 ///
3725 /// \code
3726 /// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num)
3727 /// \endcode
3728 /// In this example directive '#pragma omp taskloop' has clauses 'private'
3729 /// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
3730 /// 'num_tasks' with expression 'num'.
3731 ///
3732 class OMPTaskLoopDirective : public OMPLoopDirective {
3733   friend class ASTStmtReader;
3734   friend class OMPExecutableDirective;
3735   /// true if the construct has inner cancel directive.
3736   bool HasCancel = false;
3737 
3738   /// Build directive with the given start and end location.
3739   ///
3740   /// \param StartLoc Starting location of the directive kind.
3741   /// \param EndLoc Ending location of the directive.
3742   /// \param CollapsedNum Number of collapsed nested loops.
3743   ///
OMPTaskLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)3744   OMPTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3745                        unsigned CollapsedNum)
3746       : OMPLoopDirective(OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop,
3747                          StartLoc, EndLoc, CollapsedNum) {}
3748 
3749   /// Build an empty directive.
3750   ///
3751   /// \param CollapsedNum Number of collapsed nested loops.
3752   ///
OMPTaskLoopDirective(unsigned CollapsedNum)3753   explicit OMPTaskLoopDirective(unsigned CollapsedNum)
3754       : OMPLoopDirective(OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop,
3755                          SourceLocation(), SourceLocation(), CollapsedNum) {}
3756 
3757   /// Set cancel state.
setHasCancel(bool Has)3758   void setHasCancel(bool Has) { HasCancel = Has; }
3759 
3760 public:
3761   /// Creates directive with a list of \a Clauses.
3762   ///
3763   /// \param C AST context.
3764   /// \param StartLoc Starting location of the directive kind.
3765   /// \param EndLoc Ending Location of the directive.
3766   /// \param CollapsedNum Number of collapsed loops.
3767   /// \param Clauses List of clauses.
3768   /// \param AssociatedStmt Statement, associated with the directive.
3769   /// \param Exprs Helper expressions for CodeGen.
3770   /// \param HasCancel true if this directive has inner cancel directive.
3771   ///
3772   static OMPTaskLoopDirective *
3773   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3774          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3775          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
3776 
3777   /// Creates an empty directive with the place
3778   /// for \a NumClauses clauses.
3779   ///
3780   /// \param C AST context.
3781   /// \param CollapsedNum Number of collapsed nested loops.
3782   /// \param NumClauses Number of clauses.
3783   ///
3784   static OMPTaskLoopDirective *CreateEmpty(const ASTContext &C,
3785                                            unsigned NumClauses,
3786                                            unsigned CollapsedNum, EmptyShell);
3787 
3788   /// Return true if current directive has inner cancel directive.
hasCancel()3789   bool hasCancel() const { return HasCancel; }
3790 
classof(const Stmt * T)3791   static bool classof(const Stmt *T) {
3792     return T->getStmtClass() == OMPTaskLoopDirectiveClass;
3793   }
3794 };
3795 
3796 /// This represents '#pragma omp taskloop simd' directive.
3797 ///
3798 /// \code
3799 /// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num)
3800 /// \endcode
3801 /// In this example directive '#pragma omp taskloop simd' has clauses 'private'
3802 /// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
3803 /// 'num_tasks' with expression 'num'.
3804 ///
3805 class OMPTaskLoopSimdDirective : public OMPLoopDirective {
3806   friend class ASTStmtReader;
3807   friend class OMPExecutableDirective;
3808   /// Build directive with the given start and end location.
3809   ///
3810   /// \param StartLoc Starting location of the directive kind.
3811   /// \param EndLoc Ending location of the directive.
3812   /// \param CollapsedNum Number of collapsed nested loops.
3813   ///
OMPTaskLoopSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)3814   OMPTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3815                            unsigned CollapsedNum)
3816       : OMPLoopDirective(OMPTaskLoopSimdDirectiveClass,
3817                          llvm::omp::OMPD_taskloop_simd, StartLoc, EndLoc,
3818                          CollapsedNum) {}
3819 
3820   /// Build an empty directive.
3821   ///
3822   /// \param CollapsedNum Number of collapsed nested loops.
3823   ///
OMPTaskLoopSimdDirective(unsigned CollapsedNum)3824   explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum)
3825       : OMPLoopDirective(OMPTaskLoopSimdDirectiveClass,
3826                          llvm::omp::OMPD_taskloop_simd, SourceLocation(),
3827                          SourceLocation(), CollapsedNum) {}
3828 
3829 public:
3830   /// Creates directive with a list of \a Clauses.
3831   ///
3832   /// \param C AST context.
3833   /// \param StartLoc Starting location of the directive kind.
3834   /// \param EndLoc Ending Location of the directive.
3835   /// \param CollapsedNum Number of collapsed loops.
3836   /// \param Clauses List of clauses.
3837   /// \param AssociatedStmt Statement, associated with the directive.
3838   /// \param Exprs Helper expressions for CodeGen.
3839   ///
3840   static OMPTaskLoopSimdDirective *
3841   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3842          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3843          Stmt *AssociatedStmt, const HelperExprs &Exprs);
3844 
3845   /// Creates an empty directive with the place
3846   /// for \a NumClauses clauses.
3847   ///
3848   /// \param C AST context.
3849   /// \param CollapsedNum Number of collapsed nested loops.
3850   /// \param NumClauses Number of clauses.
3851   ///
3852   static OMPTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
3853                                                unsigned NumClauses,
3854                                                unsigned CollapsedNum,
3855                                                EmptyShell);
3856 
classof(const Stmt * T)3857   static bool classof(const Stmt *T) {
3858     return T->getStmtClass() == OMPTaskLoopSimdDirectiveClass;
3859   }
3860 };
3861 
3862 /// This represents '#pragma omp master taskloop' directive.
3863 ///
3864 /// \code
3865 /// #pragma omp master taskloop private(a,b) grainsize(val) num_tasks(num)
3866 /// \endcode
3867 /// In this example directive '#pragma omp master taskloop' has clauses
3868 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
3869 /// and 'num_tasks' with expression 'num'.
3870 ///
3871 class OMPMasterTaskLoopDirective : public OMPLoopDirective {
3872   friend class ASTStmtReader;
3873   friend class OMPExecutableDirective;
3874   /// true if the construct has inner cancel directive.
3875   bool HasCancel = false;
3876 
3877   /// Build directive with the given start and end location.
3878   ///
3879   /// \param StartLoc Starting location of the directive kind.
3880   /// \param EndLoc Ending location of the directive.
3881   /// \param CollapsedNum Number of collapsed nested loops.
3882   ///
OMPMasterTaskLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)3883   OMPMasterTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3884                              unsigned CollapsedNum)
3885       : OMPLoopDirective(OMPMasterTaskLoopDirectiveClass,
3886                          llvm::omp::OMPD_master_taskloop, StartLoc, EndLoc,
3887                          CollapsedNum) {}
3888 
3889   /// Build an empty directive.
3890   ///
3891   /// \param CollapsedNum Number of collapsed nested loops.
3892   ///
OMPMasterTaskLoopDirective(unsigned CollapsedNum)3893   explicit OMPMasterTaskLoopDirective(unsigned CollapsedNum)
3894       : OMPLoopDirective(OMPMasterTaskLoopDirectiveClass,
3895                          llvm::omp::OMPD_master_taskloop, SourceLocation(),
3896                          SourceLocation(), CollapsedNum) {}
3897 
3898   /// Set cancel state.
setHasCancel(bool Has)3899   void setHasCancel(bool Has) { HasCancel = Has; }
3900 
3901 public:
3902   /// Creates directive with a list of \a Clauses.
3903   ///
3904   /// \param C AST context.
3905   /// \param StartLoc Starting location of the directive kind.
3906   /// \param EndLoc Ending Location of the directive.
3907   /// \param CollapsedNum Number of collapsed loops.
3908   /// \param Clauses List of clauses.
3909   /// \param AssociatedStmt Statement, associated with the directive.
3910   /// \param Exprs Helper expressions for CodeGen.
3911   /// \param HasCancel true if this directive has inner cancel directive.
3912   ///
3913   static OMPMasterTaskLoopDirective *
3914   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3915          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3916          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
3917 
3918   /// Creates an empty directive with the place
3919   /// for \a NumClauses clauses.
3920   ///
3921   /// \param C AST context.
3922   /// \param CollapsedNum Number of collapsed nested loops.
3923   /// \param NumClauses Number of clauses.
3924   ///
3925   static OMPMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
3926                                                  unsigned NumClauses,
3927                                                  unsigned CollapsedNum,
3928                                                  EmptyShell);
3929 
3930   /// Return true if current directive has inner cancel directive.
hasCancel()3931   bool hasCancel() const { return HasCancel; }
3932 
classof(const Stmt * T)3933   static bool classof(const Stmt *T) {
3934     return T->getStmtClass() == OMPMasterTaskLoopDirectiveClass;
3935   }
3936 };
3937 
3938 /// This represents '#pragma omp masked taskloop' directive.
3939 ///
3940 /// \code
3941 /// #pragma omp masked taskloop private(a,b) grainsize(val) num_tasks(num)
3942 /// \endcode
3943 /// In this example directive '#pragma omp masked taskloop' has clauses
3944 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
3945 /// and 'num_tasks' with expression 'num'.
3946 ///
3947 class OMPMaskedTaskLoopDirective final : public OMPLoopDirective {
3948   friend class ASTStmtReader;
3949   friend class OMPExecutableDirective;
3950   /// true if the construct has inner cancel directive.
3951   bool HasCancel = false;
3952 
3953   /// Build directive with the given start and end location.
3954   ///
3955   /// \param StartLoc Starting location of the directive kind.
3956   /// \param EndLoc Ending location of the directive.
3957   /// \param CollapsedNum Number of collapsed nested loops.
3958   ///
OMPMaskedTaskLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)3959   OMPMaskedTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3960                              unsigned CollapsedNum)
3961       : OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass,
3962                          llvm::omp::OMPD_masked_taskloop, StartLoc, EndLoc,
3963                          CollapsedNum) {}
3964 
3965   /// Build an empty directive.
3966   ///
3967   /// \param CollapsedNum Number of collapsed nested loops.
3968   ///
OMPMaskedTaskLoopDirective(unsigned CollapsedNum)3969   explicit OMPMaskedTaskLoopDirective(unsigned CollapsedNum)
3970       : OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass,
3971                          llvm::omp::OMPD_masked_taskloop, SourceLocation(),
3972                          SourceLocation(), CollapsedNum) {}
3973 
3974   /// Set cancel state.
setHasCancel(bool Has)3975   void setHasCancel(bool Has) { HasCancel = Has; }
3976 
3977 public:
3978   /// Creates directive with a list of \a Clauses.
3979   ///
3980   /// \param C AST context.
3981   /// \param StartLoc Starting location of the directive kind.
3982   /// \param EndLoc Ending Location of the directive.
3983   /// \param CollapsedNum Number of collapsed loops.
3984   /// \param Clauses List of clauses.
3985   /// \param AssociatedStmt Statement, associated with the directive.
3986   /// \param Exprs Helper expressions for CodeGen.
3987   /// \param HasCancel true if this directive has inner cancel directive.
3988   ///
3989   static OMPMaskedTaskLoopDirective *
3990   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3991          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3992          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
3993 
3994   /// Creates an empty directive with the place
3995   /// for \a NumClauses clauses.
3996   ///
3997   /// \param C AST context.
3998   /// \param CollapsedNum Number of collapsed nested loops.
3999   /// \param NumClauses Number of clauses.
4000   ///
4001   static OMPMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C,
4002                                                  unsigned NumClauses,
4003                                                  unsigned CollapsedNum,
4004                                                  EmptyShell);
4005 
4006   /// Return true if current directive has inner cancel directive.
hasCancel()4007   bool hasCancel() const { return HasCancel; }
4008 
classof(const Stmt * T)4009   static bool classof(const Stmt *T) {
4010     return T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass;
4011   }
4012 };
4013 
4014 /// This represents '#pragma omp master taskloop simd' directive.
4015 ///
4016 /// \code
4017 /// #pragma omp master taskloop simd private(a,b) grainsize(val) num_tasks(num)
4018 /// \endcode
4019 /// In this example directive '#pragma omp master taskloop simd' has clauses
4020 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4021 /// and 'num_tasks' with expression 'num'.
4022 ///
4023 class OMPMasterTaskLoopSimdDirective : public OMPLoopDirective {
4024   friend class ASTStmtReader;
4025   friend class OMPExecutableDirective;
4026   /// Build directive with the given start and end location.
4027   ///
4028   /// \param StartLoc Starting location of the directive kind.
4029   /// \param EndLoc Ending location of the directive.
4030   /// \param CollapsedNum Number of collapsed nested loops.
4031   ///
OMPMasterTaskLoopSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4032   OMPMasterTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4033                                  unsigned CollapsedNum)
4034       : OMPLoopDirective(OMPMasterTaskLoopSimdDirectiveClass,
4035                          llvm::omp::OMPD_master_taskloop_simd, StartLoc, EndLoc,
4036                          CollapsedNum) {}
4037 
4038   /// Build an empty directive.
4039   ///
4040   /// \param CollapsedNum Number of collapsed nested loops.
4041   ///
OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum)4042   explicit OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum)
4043       : OMPLoopDirective(OMPMasterTaskLoopSimdDirectiveClass,
4044                          llvm::omp::OMPD_master_taskloop_simd, SourceLocation(),
4045                          SourceLocation(), CollapsedNum) {}
4046 
4047 public:
4048   /// Creates directive with a list of \p Clauses.
4049   ///
4050   /// \param C AST context.
4051   /// \param StartLoc Starting location of the directive kind.
4052   /// \param EndLoc Ending Location of the directive.
4053   /// \param CollapsedNum Number of collapsed loops.
4054   /// \param Clauses List of clauses.
4055   /// \param AssociatedStmt Statement, associated with the directive.
4056   /// \param Exprs Helper expressions for CodeGen.
4057   ///
4058   static OMPMasterTaskLoopSimdDirective *
4059   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4060          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4061          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4062 
4063   /// Creates an empty directive with the place for \p NumClauses clauses.
4064   ///
4065   /// \param C AST context.
4066   /// \param CollapsedNum Number of collapsed nested loops.
4067   /// \param NumClauses Number of clauses.
4068   ///
4069   static OMPMasterTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
4070                                                      unsigned NumClauses,
4071                                                      unsigned CollapsedNum,
4072                                                      EmptyShell);
4073 
classof(const Stmt * T)4074   static bool classof(const Stmt *T) {
4075     return T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass;
4076   }
4077 };
4078 
4079 /// This represents '#pragma omp masked taskloop simd' directive.
4080 ///
4081 /// \code
4082 /// #pragma omp masked taskloop simd private(a,b) grainsize(val) num_tasks(num)
4083 /// \endcode
4084 /// In this example directive '#pragma omp masked taskloop simd' has clauses
4085 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4086 /// and 'num_tasks' with expression 'num'.
4087 ///
4088 class OMPMaskedTaskLoopSimdDirective final : public OMPLoopDirective {
4089   friend class ASTStmtReader;
4090   friend class OMPExecutableDirective;
4091   /// Build directive with the given start and end location.
4092   ///
4093   /// \param StartLoc Starting location of the directive kind.
4094   /// \param EndLoc Ending location of the directive.
4095   /// \param CollapsedNum Number of collapsed nested loops.
4096   ///
OMPMaskedTaskLoopSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4097   OMPMaskedTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4098                                  unsigned CollapsedNum)
4099       : OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass,
4100                          llvm::omp::OMPD_masked_taskloop_simd, StartLoc, EndLoc,
4101                          CollapsedNum) {}
4102 
4103   /// Build an empty directive.
4104   ///
4105   /// \param CollapsedNum Number of collapsed nested loops.
4106   ///
OMPMaskedTaskLoopSimdDirective(unsigned CollapsedNum)4107   explicit OMPMaskedTaskLoopSimdDirective(unsigned CollapsedNum)
4108       : OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass,
4109                          llvm::omp::OMPD_masked_taskloop_simd, SourceLocation(),
4110                          SourceLocation(), CollapsedNum) {}
4111 
4112 public:
4113   /// Creates directive with a list of \p Clauses.
4114   ///
4115   /// \param C AST context.
4116   /// \param StartLoc Starting location of the directive kind.
4117   /// \param EndLoc Ending Location of the directive.
4118   /// \param CollapsedNum Number of collapsed loops.
4119   /// \param Clauses List of clauses.
4120   /// \param AssociatedStmt Statement, associated with the directive.
4121   /// \param Exprs Helper expressions for CodeGen.
4122   ///
4123   static OMPMaskedTaskLoopSimdDirective *
4124   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4125          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4126          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4127 
4128   /// Creates an empty directive with the place for \p NumClauses clauses.
4129   ///
4130   /// \param C AST context.
4131   /// \param CollapsedNum Number of collapsed nested loops.
4132   /// \param NumClauses Number of clauses.
4133   ///
4134   static OMPMaskedTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
4135                                                      unsigned NumClauses,
4136                                                      unsigned CollapsedNum,
4137                                                      EmptyShell);
4138 
classof(const Stmt * T)4139   static bool classof(const Stmt *T) {
4140     return T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass;
4141   }
4142 };
4143 
4144 /// This represents '#pragma omp parallel master taskloop' directive.
4145 ///
4146 /// \code
4147 /// #pragma omp parallel master taskloop private(a,b) grainsize(val)
4148 /// num_tasks(num)
4149 /// \endcode
4150 /// In this example directive '#pragma omp parallel master taskloop' has clauses
4151 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4152 /// and 'num_tasks' with expression 'num'.
4153 ///
4154 class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
4155   friend class ASTStmtReader;
4156   friend class OMPExecutableDirective;
4157   /// true if the construct has inner cancel directive.
4158   bool HasCancel = false;
4159 
4160   /// Build directive with the given start and end location.
4161   ///
4162   /// \param StartLoc Starting location of the directive kind.
4163   /// \param EndLoc Ending location of the directive.
4164   /// \param CollapsedNum Number of collapsed nested loops.
4165   ///
OMPParallelMasterTaskLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4166   OMPParallelMasterTaskLoopDirective(SourceLocation StartLoc,
4167                                      SourceLocation EndLoc,
4168                                      unsigned CollapsedNum)
4169       : OMPLoopDirective(OMPParallelMasterTaskLoopDirectiveClass,
4170                          llvm::omp::OMPD_parallel_master_taskloop, StartLoc,
4171                          EndLoc, CollapsedNum) {}
4172 
4173   /// Build an empty directive.
4174   ///
4175   /// \param CollapsedNum Number of collapsed nested loops.
4176   ///
OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum)4177   explicit OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum)
4178       : OMPLoopDirective(OMPParallelMasterTaskLoopDirectiveClass,
4179                          llvm::omp::OMPD_parallel_master_taskloop,
4180                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4181 
4182   /// Set cancel state.
setHasCancel(bool Has)4183   void setHasCancel(bool Has) { HasCancel = Has; }
4184 
4185 public:
4186   /// Creates directive with a list of \a Clauses.
4187   ///
4188   /// \param C AST context.
4189   /// \param StartLoc Starting location of the directive kind.
4190   /// \param EndLoc Ending Location of the directive.
4191   /// \param CollapsedNum Number of collapsed loops.
4192   /// \param Clauses List of clauses.
4193   /// \param AssociatedStmt Statement, associated with the directive.
4194   /// \param Exprs Helper expressions for CodeGen.
4195   /// \param HasCancel true if this directive has inner cancel directive.
4196   ///
4197   static OMPParallelMasterTaskLoopDirective *
4198   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4199          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4200          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
4201 
4202   /// Creates an empty directive with the place
4203   /// for \a NumClauses clauses.
4204   ///
4205   /// \param C AST context.
4206   /// \param CollapsedNum Number of collapsed nested loops.
4207   /// \param NumClauses Number of clauses.
4208   ///
4209   static OMPParallelMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
4210                                                          unsigned NumClauses,
4211                                                          unsigned CollapsedNum,
4212                                                          EmptyShell);
4213 
4214   /// Return true if current directive has inner cancel directive.
hasCancel()4215   bool hasCancel() const { return HasCancel; }
4216 
classof(const Stmt * T)4217   static bool classof(const Stmt *T) {
4218     return T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass;
4219   }
4220 };
4221 
4222 /// This represents '#pragma omp parallel masked taskloop' directive.
4223 ///
4224 /// \code
4225 /// #pragma omp parallel masked taskloop private(a,b) grainsize(val)
4226 /// num_tasks(num)
4227 /// \endcode
4228 /// In this example directive '#pragma omp parallel masked taskloop' has clauses
4229 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4230 /// and 'num_tasks' with expression 'num'.
4231 ///
4232 class OMPParallelMaskedTaskLoopDirective final : public OMPLoopDirective {
4233   friend class ASTStmtReader;
4234   friend class OMPExecutableDirective;
4235   /// true if the construct has inner cancel directive.
4236   bool HasCancel = false;
4237 
4238   /// Build directive with the given start and end location.
4239   ///
4240   /// \param StartLoc Starting location of the directive kind.
4241   /// \param EndLoc Ending location of the directive.
4242   /// \param CollapsedNum Number of collapsed nested loops.
4243   ///
OMPParallelMaskedTaskLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4244   OMPParallelMaskedTaskLoopDirective(SourceLocation StartLoc,
4245                                      SourceLocation EndLoc,
4246                                      unsigned CollapsedNum)
4247       : OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass,
4248                          llvm::omp::OMPD_parallel_masked_taskloop, StartLoc,
4249                          EndLoc, CollapsedNum) {}
4250 
4251   /// Build an empty directive.
4252   ///
4253   /// \param CollapsedNum Number of collapsed nested loops.
4254   ///
OMPParallelMaskedTaskLoopDirective(unsigned CollapsedNum)4255   explicit OMPParallelMaskedTaskLoopDirective(unsigned CollapsedNum)
4256       : OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass,
4257                          llvm::omp::OMPD_parallel_masked_taskloop,
4258                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4259 
4260   /// Set cancel state.
setHasCancel(bool Has)4261   void setHasCancel(bool Has) { HasCancel = Has; }
4262 
4263 public:
4264   /// Creates directive with a list of \a Clauses.
4265   ///
4266   /// \param C AST context.
4267   /// \param StartLoc Starting location of the directive kind.
4268   /// \param EndLoc Ending Location of the directive.
4269   /// \param CollapsedNum Number of collapsed loops.
4270   /// \param Clauses List of clauses.
4271   /// \param AssociatedStmt Statement, associated with the directive.
4272   /// \param Exprs Helper expressions for CodeGen.
4273   /// \param HasCancel true if this directive has inner cancel directive.
4274   ///
4275   static OMPParallelMaskedTaskLoopDirective *
4276   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4277          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4278          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
4279 
4280   /// Creates an empty directive with the place
4281   /// for \a NumClauses clauses.
4282   ///
4283   /// \param C AST context.
4284   /// \param CollapsedNum Number of collapsed nested loops.
4285   /// \param NumClauses Number of clauses.
4286   ///
4287   static OMPParallelMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C,
4288                                                          unsigned NumClauses,
4289                                                          unsigned CollapsedNum,
4290                                                          EmptyShell);
4291 
4292   /// Return true if current directive has inner cancel directive.
hasCancel()4293   bool hasCancel() const { return HasCancel; }
4294 
classof(const Stmt * T)4295   static bool classof(const Stmt *T) {
4296     return T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass;
4297   }
4298 };
4299 
4300 /// This represents '#pragma omp parallel master taskloop simd' directive.
4301 ///
4302 /// \code
4303 /// #pragma omp parallel master taskloop simd private(a,b) grainsize(val)
4304 /// num_tasks(num)
4305 /// \endcode
4306 /// In this example directive '#pragma omp parallel master taskloop simd' has
4307 /// clauses 'private' with the variables 'a' and 'b', 'grainsize' with
4308 /// expression 'val' and 'num_tasks' with expression 'num'.
4309 ///
4310 class OMPParallelMasterTaskLoopSimdDirective : public OMPLoopDirective {
4311   friend class ASTStmtReader;
4312   friend class OMPExecutableDirective;
4313   /// Build directive with the given start and end location.
4314   ///
4315   /// \param StartLoc Starting location of the directive kind.
4316   /// \param EndLoc Ending location of the directive.
4317   /// \param CollapsedNum Number of collapsed nested loops.
4318   ///
OMPParallelMasterTaskLoopSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4319   OMPParallelMasterTaskLoopSimdDirective(SourceLocation StartLoc,
4320                                          SourceLocation EndLoc,
4321                                          unsigned CollapsedNum)
4322       : OMPLoopDirective(OMPParallelMasterTaskLoopSimdDirectiveClass,
4323                          llvm::omp::OMPD_parallel_master_taskloop_simd,
4324                          StartLoc, EndLoc, CollapsedNum) {}
4325 
4326   /// Build an empty directive.
4327   ///
4328   /// \param CollapsedNum Number of collapsed nested loops.
4329   ///
OMPParallelMasterTaskLoopSimdDirective(unsigned CollapsedNum)4330   explicit OMPParallelMasterTaskLoopSimdDirective(unsigned CollapsedNum)
4331       : OMPLoopDirective(OMPParallelMasterTaskLoopSimdDirectiveClass,
4332                          llvm::omp::OMPD_parallel_master_taskloop_simd,
4333                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4334 
4335 public:
4336   /// Creates directive with a list of \p Clauses.
4337   ///
4338   /// \param C AST context.
4339   /// \param StartLoc Starting location of the directive kind.
4340   /// \param EndLoc Ending Location of the directive.
4341   /// \param CollapsedNum Number of collapsed loops.
4342   /// \param Clauses List of clauses.
4343   /// \param AssociatedStmt Statement, associated with the directive.
4344   /// \param Exprs Helper expressions for CodeGen.
4345   ///
4346   static OMPParallelMasterTaskLoopSimdDirective *
4347   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4348          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4349          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4350 
4351   /// Creates an empty directive with the place
4352   /// for \a NumClauses clauses.
4353   ///
4354   /// \param C AST context.
4355   /// \param CollapsedNum Number of collapsed nested loops.
4356   /// \param NumClauses Number of clauses.
4357   ///
4358   static OMPParallelMasterTaskLoopSimdDirective *
4359   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
4360               EmptyShell);
4361 
classof(const Stmt * T)4362   static bool classof(const Stmt *T) {
4363     return T->getStmtClass() == OMPParallelMasterTaskLoopSimdDirectiveClass;
4364   }
4365 };
4366 
4367 /// This represents '#pragma omp parallel masked taskloop simd' directive.
4368 ///
4369 /// \code
4370 /// #pragma omp parallel masked taskloop simd private(a,b) grainsize(val)
4371 /// num_tasks(num)
4372 /// \endcode
4373 /// In this example directive '#pragma omp parallel masked taskloop simd' has
4374 /// clauses 'private' with the variables 'a' and 'b', 'grainsize' with
4375 /// expression 'val' and 'num_tasks' with expression 'num'.
4376 ///
4377 class OMPParallelMaskedTaskLoopSimdDirective final : public OMPLoopDirective {
4378   friend class ASTStmtReader;
4379   friend class OMPExecutableDirective;
4380   /// Build directive with the given start and end location.
4381   ///
4382   /// \param StartLoc Starting location of the directive kind.
4383   /// \param EndLoc Ending location of the directive.
4384   /// \param CollapsedNum Number of collapsed nested loops.
4385   ///
OMPParallelMaskedTaskLoopSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4386   OMPParallelMaskedTaskLoopSimdDirective(SourceLocation StartLoc,
4387                                          SourceLocation EndLoc,
4388                                          unsigned CollapsedNum)
4389       : OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass,
4390                          llvm::omp::OMPD_parallel_masked_taskloop_simd,
4391                          StartLoc, EndLoc, CollapsedNum) {}
4392 
4393   /// Build an empty directive.
4394   ///
4395   /// \param CollapsedNum Number of collapsed nested loops.
4396   ///
OMPParallelMaskedTaskLoopSimdDirective(unsigned CollapsedNum)4397   explicit OMPParallelMaskedTaskLoopSimdDirective(unsigned CollapsedNum)
4398       : OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass,
4399                          llvm::omp::OMPD_parallel_masked_taskloop_simd,
4400                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4401 
4402 public:
4403   /// Creates directive with a list of \p Clauses.
4404   ///
4405   /// \param C AST context.
4406   /// \param StartLoc Starting location of the directive kind.
4407   /// \param EndLoc Ending Location of the directive.
4408   /// \param CollapsedNum Number of collapsed loops.
4409   /// \param Clauses List of clauses.
4410   /// \param AssociatedStmt Statement, associated with the directive.
4411   /// \param Exprs Helper expressions for CodeGen.
4412   ///
4413   static OMPParallelMaskedTaskLoopSimdDirective *
4414   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4415          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4416          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4417 
4418   /// Creates an empty directive with the place
4419   /// for \a NumClauses clauses.
4420   ///
4421   /// \param C AST context.
4422   /// \param CollapsedNum Number of collapsed nested loops.
4423   /// \param NumClauses Number of clauses.
4424   ///
4425   static OMPParallelMaskedTaskLoopSimdDirective *
4426   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
4427               EmptyShell);
4428 
classof(const Stmt * T)4429   static bool classof(const Stmt *T) {
4430     return T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass;
4431   }
4432 };
4433 
4434 /// This represents '#pragma omp distribute' directive.
4435 ///
4436 /// \code
4437 /// #pragma omp distribute private(a,b)
4438 /// \endcode
4439 /// In this example directive '#pragma omp distribute' has clauses 'private'
4440 /// with the variables 'a' and 'b'
4441 ///
4442 class OMPDistributeDirective : public OMPLoopDirective {
4443   friend class ASTStmtReader;
4444   friend class OMPExecutableDirective;
4445 
4446   /// Build directive with the given start and end location.
4447   ///
4448   /// \param StartLoc Starting location of the directive kind.
4449   /// \param EndLoc Ending location of the directive.
4450   /// \param CollapsedNum Number of collapsed nested loops.
4451   ///
OMPDistributeDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4452   OMPDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4453                          unsigned CollapsedNum)
4454       : OMPLoopDirective(OMPDistributeDirectiveClass,
4455                          llvm::omp::OMPD_distribute, StartLoc, EndLoc,
4456                          CollapsedNum) {}
4457 
4458   /// Build an empty directive.
4459   ///
4460   /// \param CollapsedNum Number of collapsed nested loops.
4461   ///
OMPDistributeDirective(unsigned CollapsedNum)4462   explicit OMPDistributeDirective(unsigned CollapsedNum)
4463       : OMPLoopDirective(OMPDistributeDirectiveClass,
4464                          llvm::omp::OMPD_distribute, SourceLocation(),
4465                          SourceLocation(), CollapsedNum) {}
4466 
4467 public:
4468   /// Creates directive with a list of \a Clauses.
4469   ///
4470   /// \param C AST context.
4471   /// \param StartLoc Starting location of the directive kind.
4472   /// \param EndLoc Ending Location of the directive.
4473   /// \param CollapsedNum Number of collapsed loops.
4474   /// \param Clauses List of clauses.
4475   /// \param AssociatedStmt Statement, associated with the directive.
4476   /// \param Exprs Helper expressions for CodeGen.
4477   ///
4478   static OMPDistributeDirective *
4479   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4480          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4481          Stmt *AssociatedStmt, const HelperExprs &Exprs,
4482          OpenMPDirectiveKind ParamPrevMappedDirective);
4483 
4484   /// Creates an empty directive with the place
4485   /// for \a NumClauses clauses.
4486   ///
4487   /// \param C AST context.
4488   /// \param CollapsedNum Number of collapsed nested loops.
4489   /// \param NumClauses Number of clauses.
4490   ///
4491   static OMPDistributeDirective *CreateEmpty(const ASTContext &C,
4492                                              unsigned NumClauses,
4493                                              unsigned CollapsedNum, EmptyShell);
4494 
classof(const Stmt * T)4495   static bool classof(const Stmt *T) {
4496     return T->getStmtClass() == OMPDistributeDirectiveClass;
4497   }
4498 };
4499 
4500 /// This represents '#pragma omp target update' directive.
4501 ///
4502 /// \code
4503 /// #pragma omp target update to(a) from(b) device(1)
4504 /// \endcode
4505 /// In this example directive '#pragma omp target update' has clause 'to' with
4506 /// argument 'a', clause 'from' with argument 'b' and clause 'device' with
4507 /// argument '1'.
4508 ///
4509 class OMPTargetUpdateDirective : public OMPExecutableDirective {
4510   friend class ASTStmtReader;
4511   friend class OMPExecutableDirective;
4512   /// Build directive with the given start and end location.
4513   ///
4514   /// \param StartLoc Starting location of the directive kind.
4515   /// \param EndLoc Ending Location of the directive.
4516   ///
OMPTargetUpdateDirective(SourceLocation StartLoc,SourceLocation EndLoc)4517   OMPTargetUpdateDirective(SourceLocation StartLoc, SourceLocation EndLoc)
4518       : OMPExecutableDirective(OMPTargetUpdateDirectiveClass,
4519                                llvm::omp::OMPD_target_update, StartLoc,
4520                                EndLoc) {}
4521 
4522   /// Build an empty directive.
4523   ///
OMPTargetUpdateDirective()4524   explicit OMPTargetUpdateDirective()
4525       : OMPExecutableDirective(OMPTargetUpdateDirectiveClass,
4526                                llvm::omp::OMPD_target_update, SourceLocation(),
4527                                SourceLocation()) {}
4528 
4529 public:
4530   /// Creates directive with a list of \a Clauses.
4531   ///
4532   /// \param C AST context.
4533   /// \param StartLoc Starting location of the directive kind.
4534   /// \param EndLoc Ending Location of the directive.
4535   /// \param Clauses List of clauses.
4536   /// \param AssociatedStmt Statement, associated with the directive.
4537   ///
4538   static OMPTargetUpdateDirective *
4539   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4540          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
4541 
4542   /// Creates an empty directive with the place for \a NumClauses
4543   /// clauses.
4544   ///
4545   /// \param C AST context.
4546   /// \param NumClauses The number of clauses.
4547   ///
4548   static OMPTargetUpdateDirective *CreateEmpty(const ASTContext &C,
4549                                                unsigned NumClauses, EmptyShell);
4550 
classof(const Stmt * T)4551   static bool classof(const Stmt *T) {
4552     return T->getStmtClass() == OMPTargetUpdateDirectiveClass;
4553   }
4554 };
4555 
4556 /// This represents '#pragma omp distribute parallel for' composite
4557 ///  directive.
4558 ///
4559 /// \code
4560 /// #pragma omp distribute parallel for private(a,b)
4561 /// \endcode
4562 /// In this example directive '#pragma omp distribute parallel for' has clause
4563 /// 'private' with the variables 'a' and 'b'
4564 ///
4565 class OMPDistributeParallelForDirective : public OMPLoopDirective {
4566   friend class ASTStmtReader;
4567   friend class OMPExecutableDirective;
4568   /// true if the construct has inner cancel directive.
4569   bool HasCancel = false;
4570 
4571   /// Build directive with the given start and end location.
4572   ///
4573   /// \param StartLoc Starting location of the directive kind.
4574   /// \param EndLoc Ending location of the directive.
4575   /// \param CollapsedNum Number of collapsed nested loops.
4576   ///
OMPDistributeParallelForDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4577   OMPDistributeParallelForDirective(SourceLocation StartLoc,
4578                                     SourceLocation EndLoc,
4579                                     unsigned CollapsedNum)
4580       : OMPLoopDirective(OMPDistributeParallelForDirectiveClass,
4581                          llvm::omp::OMPD_distribute_parallel_for, StartLoc,
4582                          EndLoc, CollapsedNum) {}
4583 
4584   /// Build an empty directive.
4585   ///
4586   /// \param CollapsedNum Number of collapsed nested loops.
4587   ///
OMPDistributeParallelForDirective(unsigned CollapsedNum)4588   explicit OMPDistributeParallelForDirective(unsigned CollapsedNum)
4589       : OMPLoopDirective(OMPDistributeParallelForDirectiveClass,
4590                          llvm::omp::OMPD_distribute_parallel_for,
4591                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4592 
4593   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)4594   void setTaskReductionRefExpr(Expr *E) {
4595     Data->getChildren()[numLoopChildren(
4596         getLoopsNumber(), llvm::omp::OMPD_distribute_parallel_for)] = E;
4597   }
4598 
4599   /// Set cancel state.
setHasCancel(bool Has)4600   void setHasCancel(bool Has) { HasCancel = Has; }
4601 
4602 public:
4603   /// Creates directive with a list of \a Clauses.
4604   ///
4605   /// \param C AST context.
4606   /// \param StartLoc Starting location of the directive kind.
4607   /// \param EndLoc Ending Location of the directive.
4608   /// \param CollapsedNum Number of collapsed loops.
4609   /// \param Clauses List of clauses.
4610   /// \param AssociatedStmt Statement, associated with the directive.
4611   /// \param Exprs Helper expressions for CodeGen.
4612   /// \param TaskRedRef Task reduction special reference expression to handle
4613   /// taskgroup descriptor.
4614   /// \param HasCancel true if this directive has inner cancel directive.
4615   ///
4616   static OMPDistributeParallelForDirective *
4617   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4618          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4619          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
4620          bool HasCancel);
4621 
4622   /// Creates an empty directive with the place
4623   /// for \a NumClauses clauses.
4624   ///
4625   /// \param C AST context.
4626   /// \param CollapsedNum Number of collapsed nested loops.
4627   /// \param NumClauses Number of clauses.
4628   ///
4629   static OMPDistributeParallelForDirective *CreateEmpty(const ASTContext &C,
4630                                                         unsigned NumClauses,
4631                                                         unsigned CollapsedNum,
4632                                                         EmptyShell);
4633 
4634   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()4635   Expr *getTaskReductionRefExpr() {
4636     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
4637         getLoopsNumber(), llvm::omp::OMPD_distribute_parallel_for)]);
4638   }
getTaskReductionRefExpr()4639   const Expr *getTaskReductionRefExpr() const {
4640     return const_cast<OMPDistributeParallelForDirective *>(this)
4641         ->getTaskReductionRefExpr();
4642   }
4643 
4644   /// Return true if current directive has inner cancel directive.
hasCancel()4645   bool hasCancel() const { return HasCancel; }
4646 
classof(const Stmt * T)4647   static bool classof(const Stmt *T) {
4648     return T->getStmtClass() == OMPDistributeParallelForDirectiveClass;
4649   }
4650 };
4651 
4652 /// This represents '#pragma omp distribute parallel for simd' composite
4653 /// directive.
4654 ///
4655 /// \code
4656 /// #pragma omp distribute parallel for simd private(x)
4657 /// \endcode
4658 /// In this example directive '#pragma omp distribute parallel for simd' has
4659 /// clause 'private' with the variables 'x'
4660 ///
4661 class OMPDistributeParallelForSimdDirective final : public OMPLoopDirective {
4662   friend class ASTStmtReader;
4663   friend class OMPExecutableDirective;
4664 
4665   /// Build directive with the given start and end location.
4666   ///
4667   /// \param StartLoc Starting location of the directive kind.
4668   /// \param EndLoc Ending location of the directive.
4669   /// \param CollapsedNum Number of collapsed nested loops.
4670   ///
OMPDistributeParallelForSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4671   OMPDistributeParallelForSimdDirective(SourceLocation StartLoc,
4672                                         SourceLocation EndLoc,
4673                                         unsigned CollapsedNum)
4674       : OMPLoopDirective(OMPDistributeParallelForSimdDirectiveClass,
4675                          llvm::omp::OMPD_distribute_parallel_for_simd, StartLoc,
4676                          EndLoc, CollapsedNum) {}
4677 
4678   /// Build an empty directive.
4679   ///
4680   /// \param CollapsedNum Number of collapsed nested loops.
4681   ///
OMPDistributeParallelForSimdDirective(unsigned CollapsedNum)4682   explicit OMPDistributeParallelForSimdDirective(unsigned CollapsedNum)
4683       : OMPLoopDirective(OMPDistributeParallelForSimdDirectiveClass,
4684                          llvm::omp::OMPD_distribute_parallel_for_simd,
4685                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4686 
4687 public:
4688   /// Creates directive with a list of \a Clauses.
4689   ///
4690   /// \param C AST context.
4691   /// \param StartLoc Starting location of the directive kind.
4692   /// \param EndLoc Ending Location of the directive.
4693   /// \param CollapsedNum Number of collapsed loops.
4694   /// \param Clauses List of clauses.
4695   /// \param AssociatedStmt Statement, associated with the directive.
4696   /// \param Exprs Helper expressions for CodeGen.
4697   ///
4698   static OMPDistributeParallelForSimdDirective *Create(
4699       const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4700       unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4701       Stmt *AssociatedStmt, const HelperExprs &Exprs);
4702 
4703   /// Creates an empty directive with the place for \a NumClauses clauses.
4704   ///
4705   /// \param C AST context.
4706   /// \param CollapsedNum Number of collapsed nested loops.
4707   /// \param NumClauses Number of clauses.
4708   ///
4709   static OMPDistributeParallelForSimdDirective *CreateEmpty(
4710       const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
4711       EmptyShell);
4712 
classof(const Stmt * T)4713   static bool classof(const Stmt *T) {
4714     return T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass;
4715   }
4716 };
4717 
4718 /// This represents '#pragma omp distribute simd' composite directive.
4719 ///
4720 /// \code
4721 /// #pragma omp distribute simd private(x)
4722 /// \endcode
4723 /// In this example directive '#pragma omp distribute simd' has clause
4724 /// 'private' with the variables 'x'
4725 ///
4726 class OMPDistributeSimdDirective final : public OMPLoopDirective {
4727   friend class ASTStmtReader;
4728   friend class OMPExecutableDirective;
4729 
4730   /// Build directive with the given start and end location.
4731   ///
4732   /// \param StartLoc Starting location of the directive kind.
4733   /// \param EndLoc Ending location of the directive.
4734   /// \param CollapsedNum Number of collapsed nested loops.
4735   ///
OMPDistributeSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4736   OMPDistributeSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4737                              unsigned CollapsedNum)
4738       : OMPLoopDirective(OMPDistributeSimdDirectiveClass,
4739                          llvm::omp::OMPD_distribute_simd, StartLoc, EndLoc,
4740                          CollapsedNum) {}
4741 
4742   /// Build an empty directive.
4743   ///
4744   /// \param CollapsedNum Number of collapsed nested loops.
4745   ///
OMPDistributeSimdDirective(unsigned CollapsedNum)4746   explicit OMPDistributeSimdDirective(unsigned CollapsedNum)
4747       : OMPLoopDirective(OMPDistributeSimdDirectiveClass,
4748                          llvm::omp::OMPD_distribute_simd, SourceLocation(),
4749                          SourceLocation(), CollapsedNum) {}
4750 
4751 public:
4752   /// Creates directive with a list of \a Clauses.
4753   ///
4754   /// \param C AST context.
4755   /// \param StartLoc Starting location of the directive kind.
4756   /// \param EndLoc Ending Location of the directive.
4757   /// \param CollapsedNum Number of collapsed loops.
4758   /// \param Clauses List of clauses.
4759   /// \param AssociatedStmt Statement, associated with the directive.
4760   /// \param Exprs Helper expressions for CodeGen.
4761   ///
4762   static OMPDistributeSimdDirective *
4763   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4764          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4765          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4766 
4767   /// Creates an empty directive with the place for \a NumClauses clauses.
4768   ///
4769   /// \param C AST context.
4770   /// \param CollapsedNum Number of collapsed nested loops.
4771   /// \param NumClauses Number of clauses.
4772   ///
4773   static OMPDistributeSimdDirective *CreateEmpty(const ASTContext &C,
4774                                                  unsigned NumClauses,
4775                                                  unsigned CollapsedNum,
4776                                                  EmptyShell);
4777 
classof(const Stmt * T)4778   static bool classof(const Stmt *T) {
4779     return T->getStmtClass() == OMPDistributeSimdDirectiveClass;
4780   }
4781 };
4782 
4783 /// This represents '#pragma omp target parallel for simd' directive.
4784 ///
4785 /// \code
4786 /// #pragma omp target parallel for simd private(a) map(b) safelen(c)
4787 /// \endcode
4788 /// In this example directive '#pragma omp target parallel for simd' has clauses
4789 /// 'private' with the variable 'a', 'map' with the variable 'b' and 'safelen'
4790 /// with the variable 'c'.
4791 ///
4792 class OMPTargetParallelForSimdDirective final : public OMPLoopDirective {
4793   friend class ASTStmtReader;
4794   friend class OMPExecutableDirective;
4795 
4796   /// Build directive with the given start and end location.
4797   ///
4798   /// \param StartLoc Starting location of the directive kind.
4799   /// \param EndLoc Ending location of the directive.
4800   /// \param CollapsedNum Number of collapsed nested loops.
4801   ///
OMPTargetParallelForSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4802   OMPTargetParallelForSimdDirective(SourceLocation StartLoc,
4803                                     SourceLocation EndLoc,
4804                                     unsigned CollapsedNum)
4805       : OMPLoopDirective(OMPTargetParallelForSimdDirectiveClass,
4806                          llvm::omp::OMPD_target_parallel_for_simd, StartLoc,
4807                          EndLoc, CollapsedNum) {}
4808 
4809   /// Build an empty directive.
4810   ///
4811   /// \param CollapsedNum Number of collapsed nested loops.
4812   ///
OMPTargetParallelForSimdDirective(unsigned CollapsedNum)4813   explicit OMPTargetParallelForSimdDirective(unsigned CollapsedNum)
4814       : OMPLoopDirective(OMPTargetParallelForSimdDirectiveClass,
4815                          llvm::omp::OMPD_target_parallel_for_simd,
4816                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4817 
4818 public:
4819   /// Creates directive with a list of \a Clauses.
4820   ///
4821   /// \param C AST context.
4822   /// \param StartLoc Starting location of the directive kind.
4823   /// \param EndLoc Ending Location of the directive.
4824   /// \param CollapsedNum Number of collapsed loops.
4825   /// \param Clauses List of clauses.
4826   /// \param AssociatedStmt Statement, associated with the directive.
4827   /// \param Exprs Helper expressions for CodeGen.
4828   ///
4829   static OMPTargetParallelForSimdDirective *
4830   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4831          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4832          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4833 
4834   /// Creates an empty directive with the place for \a NumClauses clauses.
4835   ///
4836   /// \param C AST context.
4837   /// \param CollapsedNum Number of collapsed nested loops.
4838   /// \param NumClauses Number of clauses.
4839   ///
4840   static OMPTargetParallelForSimdDirective *CreateEmpty(const ASTContext &C,
4841                                                         unsigned NumClauses,
4842                                                         unsigned CollapsedNum,
4843                                                         EmptyShell);
4844 
classof(const Stmt * T)4845   static bool classof(const Stmt *T) {
4846     return T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass;
4847   }
4848 };
4849 
4850 /// This represents '#pragma omp target simd' directive.
4851 ///
4852 /// \code
4853 /// #pragma omp target simd private(a) map(b) safelen(c)
4854 /// \endcode
4855 /// In this example directive '#pragma omp target simd' has clauses 'private'
4856 /// with the variable 'a', 'map' with the variable 'b' and 'safelen' with
4857 /// the variable 'c'.
4858 ///
4859 class OMPTargetSimdDirective final : public OMPLoopDirective {
4860   friend class ASTStmtReader;
4861   friend class OMPExecutableDirective;
4862 
4863   /// Build directive with the given start and end location.
4864   ///
4865   /// \param StartLoc Starting location of the directive kind.
4866   /// \param EndLoc Ending location of the directive.
4867   /// \param CollapsedNum Number of collapsed nested loops.
4868   ///
OMPTargetSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4869   OMPTargetSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4870                          unsigned CollapsedNum)
4871       : OMPLoopDirective(OMPTargetSimdDirectiveClass,
4872                          llvm::omp::OMPD_target_simd, StartLoc, EndLoc,
4873                          CollapsedNum) {}
4874 
4875   /// Build an empty directive.
4876   ///
4877   /// \param CollapsedNum Number of collapsed nested loops.
4878   ///
OMPTargetSimdDirective(unsigned CollapsedNum)4879   explicit OMPTargetSimdDirective(unsigned CollapsedNum)
4880       : OMPLoopDirective(OMPTargetSimdDirectiveClass,
4881                          llvm::omp::OMPD_target_simd, SourceLocation(),
4882                          SourceLocation(), CollapsedNum) {}
4883 
4884 public:
4885   /// Creates directive with a list of \a Clauses.
4886   ///
4887   /// \param C AST context.
4888   /// \param StartLoc Starting location of the directive kind.
4889   /// \param EndLoc Ending Location of the directive.
4890   /// \param CollapsedNum Number of collapsed loops.
4891   /// \param Clauses List of clauses.
4892   /// \param AssociatedStmt Statement, associated with the directive.
4893   /// \param Exprs Helper expressions for CodeGen.
4894   ///
4895   static OMPTargetSimdDirective *
4896   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4897          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4898          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4899 
4900   /// Creates an empty directive with the place for \a NumClauses clauses.
4901   ///
4902   /// \param C AST context.
4903   /// \param CollapsedNum Number of collapsed nested loops.
4904   /// \param NumClauses Number of clauses.
4905   ///
4906   static OMPTargetSimdDirective *CreateEmpty(const ASTContext &C,
4907                                              unsigned NumClauses,
4908                                              unsigned CollapsedNum,
4909                                              EmptyShell);
4910 
classof(const Stmt * T)4911   static bool classof(const Stmt *T) {
4912     return T->getStmtClass() == OMPTargetSimdDirectiveClass;
4913   }
4914 };
4915 
4916 /// This represents '#pragma omp teams distribute' directive.
4917 ///
4918 /// \code
4919 /// #pragma omp teams distribute private(a,b)
4920 /// \endcode
4921 /// In this example directive '#pragma omp teams distribute' has clauses
4922 /// 'private' with the variables 'a' and 'b'
4923 ///
4924 class OMPTeamsDistributeDirective final : public OMPLoopDirective {
4925   friend class ASTStmtReader;
4926   friend class OMPExecutableDirective;
4927 
4928   /// Build directive with the given start and end location.
4929   ///
4930   /// \param StartLoc Starting location of the directive kind.
4931   /// \param EndLoc Ending location of the directive.
4932   /// \param CollapsedNum Number of collapsed nested loops.
4933   ///
OMPTeamsDistributeDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4934   OMPTeamsDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4935                               unsigned CollapsedNum)
4936       : OMPLoopDirective(OMPTeamsDistributeDirectiveClass,
4937                          llvm::omp::OMPD_teams_distribute, StartLoc, EndLoc,
4938                          CollapsedNum) {}
4939 
4940   /// Build an empty directive.
4941   ///
4942   /// \param CollapsedNum Number of collapsed nested loops.
4943   ///
OMPTeamsDistributeDirective(unsigned CollapsedNum)4944   explicit OMPTeamsDistributeDirective(unsigned CollapsedNum)
4945       : OMPLoopDirective(OMPTeamsDistributeDirectiveClass,
4946                          llvm::omp::OMPD_teams_distribute, SourceLocation(),
4947                          SourceLocation(), CollapsedNum) {}
4948 
4949 public:
4950   /// Creates directive with a list of \a Clauses.
4951   ///
4952   /// \param C AST context.
4953   /// \param StartLoc Starting location of the directive kind.
4954   /// \param EndLoc Ending Location of the directive.
4955   /// \param CollapsedNum Number of collapsed loops.
4956   /// \param Clauses List of clauses.
4957   /// \param AssociatedStmt Statement, associated with the directive.
4958   /// \param Exprs Helper expressions for CodeGen.
4959   ///
4960   static OMPTeamsDistributeDirective *
4961   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4962          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4963          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4964 
4965   /// Creates an empty directive with the place for \a NumClauses clauses.
4966   ///
4967   /// \param C AST context.
4968   /// \param CollapsedNum Number of collapsed nested loops.
4969   /// \param NumClauses Number of clauses.
4970   ///
4971   static OMPTeamsDistributeDirective *CreateEmpty(const ASTContext &C,
4972                                                   unsigned NumClauses,
4973                                                   unsigned CollapsedNum,
4974                                                   EmptyShell);
4975 
classof(const Stmt * T)4976   static bool classof(const Stmt *T) {
4977     return T->getStmtClass() == OMPTeamsDistributeDirectiveClass;
4978   }
4979 };
4980 
4981 /// This represents '#pragma omp teams distribute simd'
4982 /// combined directive.
4983 ///
4984 /// \code
4985 /// #pragma omp teams distribute simd private(a,b)
4986 /// \endcode
4987 /// In this example directive '#pragma omp teams distribute simd'
4988 /// has clause 'private' with the variables 'a' and 'b'
4989 ///
4990 class OMPTeamsDistributeSimdDirective final : public OMPLoopDirective {
4991   friend class ASTStmtReader;
4992   friend class OMPExecutableDirective;
4993 
4994   /// Build directive with the given start and end location.
4995   ///
4996   /// \param StartLoc Starting location of the directive kind.
4997   /// \param EndLoc Ending location of the directive.
4998   /// \param CollapsedNum Number of collapsed nested loops.
4999   ///
OMPTeamsDistributeSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5000   OMPTeamsDistributeSimdDirective(SourceLocation StartLoc,
5001                                   SourceLocation EndLoc, unsigned CollapsedNum)
5002       : OMPLoopDirective(OMPTeamsDistributeSimdDirectiveClass,
5003                          llvm::omp::OMPD_teams_distribute_simd, StartLoc,
5004                          EndLoc, CollapsedNum) {}
5005 
5006   /// Build an empty directive.
5007   ///
5008   /// \param CollapsedNum Number of collapsed nested loops.
5009   ///
OMPTeamsDistributeSimdDirective(unsigned CollapsedNum)5010   explicit OMPTeamsDistributeSimdDirective(unsigned CollapsedNum)
5011       : OMPLoopDirective(OMPTeamsDistributeSimdDirectiveClass,
5012                          llvm::omp::OMPD_teams_distribute_simd,
5013                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5014 
5015 public:
5016   /// Creates directive with a list of \a Clauses.
5017   ///
5018   /// \param C AST context.
5019   /// \param StartLoc Starting location of the directive kind.
5020   /// \param EndLoc Ending Location of the directive.
5021   /// \param CollapsedNum Number of collapsed loops.
5022   /// \param Clauses List of clauses.
5023   /// \param AssociatedStmt Statement, associated with the directive.
5024   /// \param Exprs Helper expressions for CodeGen.
5025   ///
5026   static OMPTeamsDistributeSimdDirective *
5027   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5028          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5029          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5030 
5031   /// Creates an empty directive with the place
5032   /// for \a NumClauses clauses.
5033   ///
5034   /// \param C AST context.
5035   /// \param CollapsedNum Number of collapsed nested loops.
5036   /// \param NumClauses Number of clauses.
5037   ///
5038   static OMPTeamsDistributeSimdDirective *CreateEmpty(const ASTContext &C,
5039                                                       unsigned NumClauses,
5040                                                       unsigned CollapsedNum,
5041                                                       EmptyShell);
5042 
classof(const Stmt * T)5043   static bool classof(const Stmt *T) {
5044     return T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass;
5045   }
5046 };
5047 
5048 /// This represents '#pragma omp teams distribute parallel for simd' composite
5049 /// directive.
5050 ///
5051 /// \code
5052 /// #pragma omp teams distribute parallel for simd private(x)
5053 /// \endcode
5054 /// In this example directive '#pragma omp teams distribute parallel for simd'
5055 /// has clause 'private' with the variables 'x'
5056 ///
5057 class OMPTeamsDistributeParallelForSimdDirective final
5058     : public OMPLoopDirective {
5059   friend class ASTStmtReader;
5060   friend class OMPExecutableDirective;
5061 
5062   /// Build directive with the given start and end location.
5063   ///
5064   /// \param StartLoc Starting location of the directive kind.
5065   /// \param EndLoc Ending location of the directive.
5066   /// \param CollapsedNum Number of collapsed nested loops.
5067   ///
OMPTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5068   OMPTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
5069                                              SourceLocation EndLoc,
5070                                              unsigned CollapsedNum)
5071       : OMPLoopDirective(OMPTeamsDistributeParallelForSimdDirectiveClass,
5072                          llvm::omp::OMPD_teams_distribute_parallel_for_simd,
5073                          StartLoc, EndLoc, CollapsedNum) {}
5074 
5075   /// Build an empty directive.
5076   ///
5077   /// \param CollapsedNum Number of collapsed nested loops.
5078   ///
OMPTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum)5079   explicit OMPTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum)
5080       : OMPLoopDirective(OMPTeamsDistributeParallelForSimdDirectiveClass,
5081                          llvm::omp::OMPD_teams_distribute_parallel_for_simd,
5082                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5083 
5084 public:
5085   /// Creates directive with a list of \a Clauses.
5086   ///
5087   /// \param C AST context.
5088   /// \param StartLoc Starting location of the directive kind.
5089   /// \param EndLoc Ending Location of the directive.
5090   /// \param CollapsedNum Number of collapsed loops.
5091   /// \param Clauses List of clauses.
5092   /// \param AssociatedStmt Statement, associated with the directive.
5093   /// \param Exprs Helper expressions for CodeGen.
5094   ///
5095   static OMPTeamsDistributeParallelForSimdDirective *
5096   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5097          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5098          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5099 
5100   /// Creates an empty directive with the place for \a NumClauses clauses.
5101   ///
5102   /// \param C AST context.
5103   /// \param CollapsedNum Number of collapsed nested loops.
5104   /// \param NumClauses Number of clauses.
5105   ///
5106   static OMPTeamsDistributeParallelForSimdDirective *
5107   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5108               EmptyShell);
5109 
classof(const Stmt * T)5110   static bool classof(const Stmt *T) {
5111     return T->getStmtClass() == OMPTeamsDistributeParallelForSimdDirectiveClass;
5112   }
5113 };
5114 
5115 /// This represents '#pragma omp teams distribute parallel for' composite
5116 /// directive.
5117 ///
5118 /// \code
5119 /// #pragma omp teams distribute parallel for private(x)
5120 /// \endcode
5121 /// In this example directive '#pragma omp teams distribute parallel for'
5122 /// has clause 'private' with the variables 'x'
5123 ///
5124 class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
5125   friend class ASTStmtReader;
5126   friend class OMPExecutableDirective;
5127   /// true if the construct has inner cancel directive.
5128   bool HasCancel = false;
5129 
5130   /// Build directive with the given start and end location.
5131   ///
5132   /// \param StartLoc Starting location of the directive kind.
5133   /// \param EndLoc Ending location of the directive.
5134   /// \param CollapsedNum Number of collapsed nested loops.
5135   ///
OMPTeamsDistributeParallelForDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5136   OMPTeamsDistributeParallelForDirective(SourceLocation StartLoc,
5137                                          SourceLocation EndLoc,
5138                                          unsigned CollapsedNum)
5139       : OMPLoopDirective(OMPTeamsDistributeParallelForDirectiveClass,
5140                          llvm::omp::OMPD_teams_distribute_parallel_for,
5141                          StartLoc, EndLoc, CollapsedNum) {}
5142 
5143   /// Build an empty directive.
5144   ///
5145   /// \param CollapsedNum Number of collapsed nested loops.
5146   ///
OMPTeamsDistributeParallelForDirective(unsigned CollapsedNum)5147   explicit OMPTeamsDistributeParallelForDirective(unsigned CollapsedNum)
5148       : OMPLoopDirective(OMPTeamsDistributeParallelForDirectiveClass,
5149                          llvm::omp::OMPD_teams_distribute_parallel_for,
5150                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5151 
5152   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)5153   void setTaskReductionRefExpr(Expr *E) {
5154     Data->getChildren()[numLoopChildren(
5155         getLoopsNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)] = E;
5156   }
5157 
5158   /// Set cancel state.
setHasCancel(bool Has)5159   void setHasCancel(bool Has) { HasCancel = Has; }
5160 
5161 public:
5162   /// Creates directive with a list of \a Clauses.
5163   ///
5164   /// \param C AST context.
5165   /// \param StartLoc Starting location of the directive kind.
5166   /// \param EndLoc Ending Location of the directive.
5167   /// \param CollapsedNum Number of collapsed loops.
5168   /// \param Clauses List of clauses.
5169   /// \param AssociatedStmt Statement, associated with the directive.
5170   /// \param Exprs Helper expressions for CodeGen.
5171   /// \param TaskRedRef Task reduction special reference expression to handle
5172   /// taskgroup descriptor.
5173   /// \param HasCancel true if this directive has inner cancel directive.
5174   ///
5175   static OMPTeamsDistributeParallelForDirective *
5176   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5177          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5178          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
5179          bool HasCancel);
5180 
5181   /// Creates an empty directive with the place for \a NumClauses clauses.
5182   ///
5183   /// \param C AST context.
5184   /// \param CollapsedNum Number of collapsed nested loops.
5185   /// \param NumClauses Number of clauses.
5186   ///
5187   static OMPTeamsDistributeParallelForDirective *
5188   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5189               EmptyShell);
5190 
5191   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()5192   Expr *getTaskReductionRefExpr() {
5193     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
5194         getLoopsNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)]);
5195   }
getTaskReductionRefExpr()5196   const Expr *getTaskReductionRefExpr() const {
5197     return const_cast<OMPTeamsDistributeParallelForDirective *>(this)
5198         ->getTaskReductionRefExpr();
5199   }
5200 
5201   /// Return true if current directive has inner cancel directive.
hasCancel()5202   bool hasCancel() const { return HasCancel; }
5203 
classof(const Stmt * T)5204   static bool classof(const Stmt *T) {
5205     return T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass;
5206   }
5207 };
5208 
5209 /// This represents '#pragma omp target teams' directive.
5210 ///
5211 /// \code
5212 /// #pragma omp target teams if(a>0)
5213 /// \endcode
5214 /// In this example directive '#pragma omp target teams' has clause 'if' with
5215 /// condition 'a>0'.
5216 ///
5217 class OMPTargetTeamsDirective final : public OMPExecutableDirective {
5218   friend class ASTStmtReader;
5219   friend class OMPExecutableDirective;
5220   /// Build directive with the given start and end location.
5221   ///
5222   /// \param StartLoc Starting location of the directive kind.
5223   /// \param EndLoc Ending location of the directive.
5224   ///
OMPTargetTeamsDirective(SourceLocation StartLoc,SourceLocation EndLoc)5225   OMPTargetTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5226       : OMPExecutableDirective(OMPTargetTeamsDirectiveClass,
5227                                llvm::omp::OMPD_target_teams, StartLoc, EndLoc) {
5228   }
5229 
5230   /// Build an empty directive.
5231   ///
OMPTargetTeamsDirective()5232   explicit OMPTargetTeamsDirective()
5233       : OMPExecutableDirective(OMPTargetTeamsDirectiveClass,
5234                                llvm::omp::OMPD_target_teams, SourceLocation(),
5235                                SourceLocation()) {}
5236 
5237 public:
5238   /// Creates directive with a list of \a Clauses.
5239   ///
5240   /// \param C AST context.
5241   /// \param StartLoc Starting location of the directive kind.
5242   /// \param EndLoc Ending Location of the directive.
5243   /// \param Clauses List of clauses.
5244   /// \param AssociatedStmt Statement, associated with the directive.
5245   ///
5246   static OMPTargetTeamsDirective *Create(const ASTContext &C,
5247                                          SourceLocation StartLoc,
5248                                          SourceLocation EndLoc,
5249                                          ArrayRef<OMPClause *> Clauses,
5250                                          Stmt *AssociatedStmt);
5251 
5252   /// Creates an empty directive with the place for \a NumClauses clauses.
5253   ///
5254   /// \param C AST context.
5255   /// \param NumClauses Number of clauses.
5256   ///
5257   static OMPTargetTeamsDirective *CreateEmpty(const ASTContext &C,
5258                                               unsigned NumClauses, EmptyShell);
5259 
classof(const Stmt * T)5260   static bool classof(const Stmt *T) {
5261     return T->getStmtClass() == OMPTargetTeamsDirectiveClass;
5262   }
5263 };
5264 
5265 /// This represents '#pragma omp target teams distribute' combined directive.
5266 ///
5267 /// \code
5268 /// #pragma omp target teams distribute private(x)
5269 /// \endcode
5270 /// In this example directive '#pragma omp target teams distribute' has clause
5271 /// 'private' with the variables 'x'
5272 ///
5273 class OMPTargetTeamsDistributeDirective final : public OMPLoopDirective {
5274   friend class ASTStmtReader;
5275   friend class OMPExecutableDirective;
5276 
5277   /// Build directive with the given start and end location.
5278   ///
5279   /// \param StartLoc Starting location of the directive kind.
5280   /// \param EndLoc Ending location of the directive.
5281   /// \param CollapsedNum Number of collapsed nested loops.
5282   ///
OMPTargetTeamsDistributeDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5283   OMPTargetTeamsDistributeDirective(SourceLocation StartLoc,
5284                                     SourceLocation EndLoc,
5285                                     unsigned CollapsedNum)
5286       : OMPLoopDirective(OMPTargetTeamsDistributeDirectiveClass,
5287                          llvm::omp::OMPD_target_teams_distribute, StartLoc,
5288                          EndLoc, CollapsedNum) {}
5289 
5290   /// Build an empty directive.
5291   ///
5292   /// \param CollapsedNum Number of collapsed nested loops.
5293   ///
OMPTargetTeamsDistributeDirective(unsigned CollapsedNum)5294   explicit OMPTargetTeamsDistributeDirective(unsigned CollapsedNum)
5295       : OMPLoopDirective(OMPTargetTeamsDistributeDirectiveClass,
5296                          llvm::omp::OMPD_target_teams_distribute,
5297                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5298 
5299 public:
5300   /// Creates directive with a list of \a Clauses.
5301   ///
5302   /// \param C AST context.
5303   /// \param StartLoc Starting location of the directive kind.
5304   /// \param EndLoc Ending Location of the directive.
5305   /// \param CollapsedNum Number of collapsed loops.
5306   /// \param Clauses List of clauses.
5307   /// \param AssociatedStmt Statement, associated with the directive.
5308   /// \param Exprs Helper expressions for CodeGen.
5309   ///
5310   static OMPTargetTeamsDistributeDirective *
5311   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5312          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5313          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5314 
5315   /// Creates an empty directive with the place for \a NumClauses clauses.
5316   ///
5317   /// \param C AST context.
5318   /// \param CollapsedNum Number of collapsed nested loops.
5319   /// \param NumClauses Number of clauses.
5320   ///
5321   static OMPTargetTeamsDistributeDirective *
5322   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5323               EmptyShell);
5324 
classof(const Stmt * T)5325   static bool classof(const Stmt *T) {
5326     return T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass;
5327   }
5328 };
5329 
5330 /// This represents '#pragma omp target teams distribute parallel for' combined
5331 /// directive.
5332 ///
5333 /// \code
5334 /// #pragma omp target teams distribute parallel for private(x)
5335 /// \endcode
5336 /// In this example directive '#pragma omp target teams distribute parallel
5337 /// for' has clause 'private' with the variables 'x'
5338 ///
5339 class OMPTargetTeamsDistributeParallelForDirective final
5340     : public OMPLoopDirective {
5341   friend class ASTStmtReader;
5342   friend class OMPExecutableDirective;
5343   /// true if the construct has inner cancel directive.
5344   bool HasCancel = false;
5345 
5346   /// Build directive with the given start and end location.
5347   ///
5348   /// \param StartLoc Starting location of the directive kind.
5349   /// \param EndLoc Ending location of the directive.
5350   /// \param CollapsedNum Number of collapsed nested loops.
5351   ///
OMPTargetTeamsDistributeParallelForDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5352   OMPTargetTeamsDistributeParallelForDirective(SourceLocation StartLoc,
5353                                                SourceLocation EndLoc,
5354                                                unsigned CollapsedNum)
5355       : OMPLoopDirective(OMPTargetTeamsDistributeParallelForDirectiveClass,
5356                          llvm::omp::OMPD_target_teams_distribute_parallel_for,
5357                          StartLoc, EndLoc, CollapsedNum) {}
5358 
5359   /// Build an empty directive.
5360   ///
5361   /// \param CollapsedNum Number of collapsed nested loops.
5362   ///
OMPTargetTeamsDistributeParallelForDirective(unsigned CollapsedNum)5363   explicit OMPTargetTeamsDistributeParallelForDirective(unsigned CollapsedNum)
5364       : OMPLoopDirective(OMPTargetTeamsDistributeParallelForDirectiveClass,
5365                          llvm::omp::OMPD_target_teams_distribute_parallel_for,
5366                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5367 
5368   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)5369   void setTaskReductionRefExpr(Expr *E) {
5370     Data->getChildren()[numLoopChildren(
5371         getLoopsNumber(),
5372         llvm::omp::OMPD_target_teams_distribute_parallel_for)] = E;
5373   }
5374 
5375   /// Set cancel state.
setHasCancel(bool Has)5376   void setHasCancel(bool Has) { HasCancel = Has; }
5377 
5378 public:
5379   /// Creates directive with a list of \a Clauses.
5380   ///
5381   /// \param C AST context.
5382   /// \param StartLoc Starting location of the directive kind.
5383   /// \param EndLoc Ending Location of the directive.
5384   /// \param CollapsedNum Number of collapsed loops.
5385   /// \param Clauses List of clauses.
5386   /// \param AssociatedStmt Statement, associated with the directive.
5387   /// \param Exprs Helper expressions for CodeGen.
5388   /// \param TaskRedRef Task reduction special reference expression to handle
5389   /// taskgroup descriptor.
5390   /// \param HasCancel true if this directive has inner cancel directive.
5391   ///
5392   static OMPTargetTeamsDistributeParallelForDirective *
5393   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5394          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5395          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
5396          bool HasCancel);
5397 
5398   /// Creates an empty directive with the place for \a NumClauses clauses.
5399   ///
5400   /// \param C AST context.
5401   /// \param CollapsedNum Number of collapsed nested loops.
5402   /// \param NumClauses Number of clauses.
5403   ///
5404   static OMPTargetTeamsDistributeParallelForDirective *
5405   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5406               EmptyShell);
5407 
5408   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()5409   Expr *getTaskReductionRefExpr() {
5410     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
5411         getLoopsNumber(),
5412         llvm::omp::OMPD_target_teams_distribute_parallel_for)]);
5413   }
getTaskReductionRefExpr()5414   const Expr *getTaskReductionRefExpr() const {
5415     return const_cast<OMPTargetTeamsDistributeParallelForDirective *>(this)
5416         ->getTaskReductionRefExpr();
5417   }
5418 
5419   /// Return true if current directive has inner cancel directive.
hasCancel()5420   bool hasCancel() const { return HasCancel; }
5421 
classof(const Stmt * T)5422   static bool classof(const Stmt *T) {
5423     return T->getStmtClass() ==
5424            OMPTargetTeamsDistributeParallelForDirectiveClass;
5425   }
5426 };
5427 
5428 /// This represents '#pragma omp target teams distribute parallel for simd'
5429 /// combined directive.
5430 ///
5431 /// \code
5432 /// #pragma omp target teams distribute parallel for simd private(x)
5433 /// \endcode
5434 /// In this example directive '#pragma omp target teams distribute parallel
5435 /// for simd' has clause 'private' with the variables 'x'
5436 ///
5437 class OMPTargetTeamsDistributeParallelForSimdDirective final
5438     : public OMPLoopDirective {
5439   friend class ASTStmtReader;
5440   friend class OMPExecutableDirective;
5441 
5442   /// Build directive with the given start and end location.
5443   ///
5444   /// \param StartLoc Starting location of the directive kind.
5445   /// \param EndLoc Ending location of the directive.
5446   /// \param CollapsedNum Number of collapsed nested loops.
5447   ///
OMPTargetTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5448   OMPTargetTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
5449                                                    SourceLocation EndLoc,
5450                                                    unsigned CollapsedNum)
5451       : OMPLoopDirective(
5452             OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
5453             llvm::omp::OMPD_target_teams_distribute_parallel_for_simd, StartLoc,
5454             EndLoc, CollapsedNum) {}
5455 
5456   /// Build an empty directive.
5457   ///
5458   /// \param CollapsedNum Number of collapsed nested loops.
5459   ///
OMPTargetTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum)5460   explicit OMPTargetTeamsDistributeParallelForSimdDirective(
5461       unsigned CollapsedNum)
5462       : OMPLoopDirective(
5463             OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
5464             llvm::omp::OMPD_target_teams_distribute_parallel_for_simd,
5465             SourceLocation(), SourceLocation(), CollapsedNum) {}
5466 
5467 public:
5468   /// Creates directive with a list of \a Clauses.
5469   ///
5470   /// \param C AST context.
5471   /// \param StartLoc Starting location of the directive kind.
5472   /// \param EndLoc Ending Location of the directive.
5473   /// \param CollapsedNum Number of collapsed loops.
5474   /// \param Clauses List of clauses.
5475   /// \param AssociatedStmt Statement, associated with the directive.
5476   /// \param Exprs Helper expressions for CodeGen.
5477   ///
5478   static OMPTargetTeamsDistributeParallelForSimdDirective *
5479   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5480          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5481          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5482 
5483   /// Creates an empty directive with the place for \a NumClauses clauses.
5484   ///
5485   /// \param C AST context.
5486   /// \param CollapsedNum Number of collapsed nested loops.
5487   /// \param NumClauses Number of clauses.
5488   ///
5489   static OMPTargetTeamsDistributeParallelForSimdDirective *
5490   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5491               EmptyShell);
5492 
classof(const Stmt * T)5493   static bool classof(const Stmt *T) {
5494     return T->getStmtClass() ==
5495            OMPTargetTeamsDistributeParallelForSimdDirectiveClass;
5496   }
5497 };
5498 
5499 /// This represents '#pragma omp target teams distribute simd' combined
5500 /// directive.
5501 ///
5502 /// \code
5503 /// #pragma omp target teams distribute simd private(x)
5504 /// \endcode
5505 /// In this example directive '#pragma omp target teams distribute simd'
5506 /// has clause 'private' with the variables 'x'
5507 ///
5508 class OMPTargetTeamsDistributeSimdDirective final : public OMPLoopDirective {
5509   friend class ASTStmtReader;
5510   friend class OMPExecutableDirective;
5511 
5512   /// Build directive with the given start and end location.
5513   ///
5514   /// \param StartLoc Starting location of the directive kind.
5515   /// \param EndLoc Ending location of the directive.
5516   /// \param CollapsedNum Number of collapsed nested loops.
5517   ///
OMPTargetTeamsDistributeSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5518   OMPTargetTeamsDistributeSimdDirective(SourceLocation StartLoc,
5519                                         SourceLocation EndLoc,
5520                                         unsigned CollapsedNum)
5521       : OMPLoopDirective(OMPTargetTeamsDistributeSimdDirectiveClass,
5522                          llvm::omp::OMPD_target_teams_distribute_simd, StartLoc,
5523                          EndLoc, CollapsedNum) {}
5524 
5525   /// Build an empty directive.
5526   ///
5527   /// \param CollapsedNum Number of collapsed nested loops.
5528   ///
OMPTargetTeamsDistributeSimdDirective(unsigned CollapsedNum)5529   explicit OMPTargetTeamsDistributeSimdDirective(unsigned CollapsedNum)
5530       : OMPLoopDirective(OMPTargetTeamsDistributeSimdDirectiveClass,
5531                          llvm::omp::OMPD_target_teams_distribute_simd,
5532                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5533 
5534 public:
5535   /// Creates directive with a list of \a Clauses.
5536   ///
5537   /// \param C AST context.
5538   /// \param StartLoc Starting location of the directive kind.
5539   /// \param EndLoc Ending Location of the directive.
5540   /// \param CollapsedNum Number of collapsed loops.
5541   /// \param Clauses List of clauses.
5542   /// \param AssociatedStmt Statement, associated with the directive.
5543   /// \param Exprs Helper expressions for CodeGen.
5544   ///
5545   static OMPTargetTeamsDistributeSimdDirective *
5546   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5547          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5548          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5549 
5550   /// Creates an empty directive with the place for \a NumClauses clauses.
5551   ///
5552   /// \param C AST context.
5553   /// \param CollapsedNum Number of collapsed nested loops.
5554   /// \param NumClauses Number of clauses.
5555   ///
5556   static OMPTargetTeamsDistributeSimdDirective *
5557   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5558               EmptyShell);
5559 
classof(const Stmt * T)5560   static bool classof(const Stmt *T) {
5561     return T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass;
5562   }
5563 };
5564 
5565 /// This represents the '#pragma omp tile' loop transformation directive.
5566 class OMPTileDirective final : public OMPLoopTransformationDirective {
5567   friend class ASTStmtReader;
5568   friend class OMPExecutableDirective;
5569 
5570   /// Default list of offsets.
5571   enum {
5572     PreInitsOffset = 0,
5573     TransformedStmtOffset,
5574   };
5575 
OMPTileDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned NumLoops)5576   explicit OMPTileDirective(SourceLocation StartLoc, SourceLocation EndLoc,
5577                             unsigned NumLoops)
5578       : OMPLoopTransformationDirective(OMPTileDirectiveClass,
5579                                        llvm::omp::OMPD_tile, StartLoc, EndLoc,
5580                                        NumLoops) {
5581     setNumGeneratedLoops(3 * NumLoops);
5582   }
5583 
setPreInits(Stmt * PreInits)5584   void setPreInits(Stmt *PreInits) {
5585     Data->getChildren()[PreInitsOffset] = PreInits;
5586   }
5587 
setTransformedStmt(Stmt * S)5588   void setTransformedStmt(Stmt *S) {
5589     Data->getChildren()[TransformedStmtOffset] = S;
5590   }
5591 
5592 public:
5593   /// Create a new AST node representation for '#pragma omp tile'.
5594   ///
5595   /// \param C         Context of the AST.
5596   /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
5597   /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
5598   /// \param Clauses   The directive's clauses.
5599   /// \param NumLoops  Number of associated loops (number of items in the
5600   ///                  'sizes' clause).
5601   /// \param AssociatedStmt The outermost associated loop.
5602   /// \param TransformedStmt The loop nest after tiling, or nullptr in
5603   ///                        dependent contexts.
5604   /// \param PreInits Helper preinits statements for the loop nest.
5605   static OMPTileDirective *Create(const ASTContext &C, SourceLocation StartLoc,
5606                                   SourceLocation EndLoc,
5607                                   ArrayRef<OMPClause *> Clauses,
5608                                   unsigned NumLoops, Stmt *AssociatedStmt,
5609                                   Stmt *TransformedStmt, Stmt *PreInits);
5610 
5611   /// Build an empty '#pragma omp tile' AST node for deserialization.
5612   ///
5613   /// \param C          Context of the AST.
5614   /// \param NumClauses Number of clauses to allocate.
5615   /// \param NumLoops   Number of associated loops to allocate.
5616   static OMPTileDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
5617                                        unsigned NumLoops);
5618 
5619   /// Gets/sets the associated loops after tiling.
5620   ///
5621   /// This is in de-sugared format stored as a CompoundStmt.
5622   ///
5623   /// \code
5624   ///   for (...)
5625   ///     ...
5626   /// \endcode
5627   ///
5628   /// Note that if the generated loops a become associated loops of another
5629   /// directive, they may need to be hoisted before them.
getTransformedStmt()5630   Stmt *getTransformedStmt() const {
5631     return Data->getChildren()[TransformedStmtOffset];
5632   }
5633 
5634   /// Return preinits statement.
getPreInits()5635   Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
5636 
classof(const Stmt * T)5637   static bool classof(const Stmt *T) {
5638     return T->getStmtClass() == OMPTileDirectiveClass;
5639   }
5640 };
5641 
5642 /// This represents the '#pragma omp unroll' loop transformation directive.
5643 ///
5644 /// \code
5645 /// #pragma omp unroll
5646 /// for (int i = 0; i < 64; ++i)
5647 /// \endcode
5648 class OMPUnrollDirective final : public OMPLoopTransformationDirective {
5649   friend class ASTStmtReader;
5650   friend class OMPExecutableDirective;
5651 
5652   /// Default list of offsets.
5653   enum {
5654     PreInitsOffset = 0,
5655     TransformedStmtOffset,
5656   };
5657 
OMPUnrollDirective(SourceLocation StartLoc,SourceLocation EndLoc)5658   explicit OMPUnrollDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5659       : OMPLoopTransformationDirective(OMPUnrollDirectiveClass,
5660                                        llvm::omp::OMPD_unroll, StartLoc, EndLoc,
5661                                        1) {}
5662 
5663   /// Set the pre-init statements.
setPreInits(Stmt * PreInits)5664   void setPreInits(Stmt *PreInits) {
5665     Data->getChildren()[PreInitsOffset] = PreInits;
5666   }
5667 
5668   /// Set the de-sugared statement.
setTransformedStmt(Stmt * S)5669   void setTransformedStmt(Stmt *S) {
5670     Data->getChildren()[TransformedStmtOffset] = S;
5671   }
5672 
5673 public:
5674   /// Create a new AST node representation for '#pragma omp unroll'.
5675   ///
5676   /// \param C         Context of the AST.
5677   /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
5678   /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
5679   /// \param Clauses   The directive's clauses.
5680   /// \param AssociatedStmt The outermost associated loop.
5681   /// \param TransformedStmt The loop nest after tiling, or nullptr in
5682   ///                        dependent contexts.
5683   /// \param PreInits   Helper preinits statements for the loop nest.
5684   static OMPUnrollDirective *
5685   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5686          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
5687          unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits);
5688 
5689   /// Build an empty '#pragma omp unroll' AST node for deserialization.
5690   ///
5691   /// \param C          Context of the AST.
5692   /// \param NumClauses Number of clauses to allocate.
5693   static OMPUnrollDirective *CreateEmpty(const ASTContext &C,
5694                                          unsigned NumClauses);
5695 
5696   /// Get the de-sugared associated loops after unrolling.
5697   ///
5698   /// This is only used if the unrolled loop becomes an associated loop of
5699   /// another directive, otherwise the loop is emitted directly using loop
5700   /// transformation metadata. When the unrolled loop cannot be used by another
5701   /// directive (e.g. because of the full clause), the transformed stmt can also
5702   /// be nullptr.
getTransformedStmt()5703   Stmt *getTransformedStmt() const {
5704     return Data->getChildren()[TransformedStmtOffset];
5705   }
5706 
5707   /// Return the pre-init statements.
getPreInits()5708   Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
5709 
classof(const Stmt * T)5710   static bool classof(const Stmt *T) {
5711     return T->getStmtClass() == OMPUnrollDirectiveClass;
5712   }
5713 };
5714 
5715 /// Represents the '#pragma omp reverse' loop transformation directive.
5716 ///
5717 /// \code
5718 /// #pragma omp reverse
5719 /// for (int i = 0; i < n; ++i)
5720 ///   ...
5721 /// \endcode
5722 class OMPReverseDirective final : public OMPLoopTransformationDirective {
5723   friend class ASTStmtReader;
5724   friend class OMPExecutableDirective;
5725 
5726   /// Offsets of child members.
5727   enum {
5728     PreInitsOffset = 0,
5729     TransformedStmtOffset,
5730   };
5731 
OMPReverseDirective(SourceLocation StartLoc,SourceLocation EndLoc)5732   explicit OMPReverseDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5733       : OMPLoopTransformationDirective(OMPReverseDirectiveClass,
5734                                        llvm::omp::OMPD_reverse, StartLoc,
5735                                        EndLoc, 1) {}
5736 
setPreInits(Stmt * PreInits)5737   void setPreInits(Stmt *PreInits) {
5738     Data->getChildren()[PreInitsOffset] = PreInits;
5739   }
5740 
setTransformedStmt(Stmt * S)5741   void setTransformedStmt(Stmt *S) {
5742     Data->getChildren()[TransformedStmtOffset] = S;
5743   }
5744 
5745 public:
5746   /// Create a new AST node representation for '#pragma omp reverse'.
5747   ///
5748   /// \param C         Context of the AST.
5749   /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
5750   /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
5751   /// \param AssociatedStmt  The outermost associated loop.
5752   /// \param TransformedStmt The loop nest after tiling, or nullptr in
5753   ///                        dependent contexts.
5754   /// \param PreInits   Helper preinits statements for the loop nest.
5755   static OMPReverseDirective *
5756   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5757          Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits);
5758 
5759   /// Build an empty '#pragma omp reverse' AST node for deserialization.
5760   ///
5761   /// \param C          Context of the AST.
5762   /// \param NumClauses Number of clauses to allocate.
5763   static OMPReverseDirective *CreateEmpty(const ASTContext &C);
5764 
5765   /// Gets/sets the associated loops after the transformation, i.e. after
5766   /// de-sugaring.
getTransformedStmt()5767   Stmt *getTransformedStmt() const {
5768     return Data->getChildren()[TransformedStmtOffset];
5769   }
5770 
5771   /// Return preinits statement.
getPreInits()5772   Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
5773 
classof(const Stmt * T)5774   static bool classof(const Stmt *T) {
5775     return T->getStmtClass() == OMPReverseDirectiveClass;
5776   }
5777 };
5778 
5779 /// Represents the '#pragma omp interchange' loop transformation directive.
5780 ///
5781 /// \code{c}
5782 ///   #pragma omp interchange
5783 ///   for (int i = 0; i < m; ++i)
5784 ///     for (int j = 0; j < n; ++j)
5785 ///       ..
5786 /// \endcode
5787 class OMPInterchangeDirective final : public OMPLoopTransformationDirective {
5788   friend class ASTStmtReader;
5789   friend class OMPExecutableDirective;
5790 
5791   /// Offsets of child members.
5792   enum {
5793     PreInitsOffset = 0,
5794     TransformedStmtOffset,
5795   };
5796 
OMPInterchangeDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned NumLoops)5797   explicit OMPInterchangeDirective(SourceLocation StartLoc,
5798                                    SourceLocation EndLoc, unsigned NumLoops)
5799       : OMPLoopTransformationDirective(OMPInterchangeDirectiveClass,
5800                                        llvm::omp::OMPD_interchange, StartLoc,
5801                                        EndLoc, NumLoops) {
5802     setNumGeneratedLoops(3 * NumLoops);
5803   }
5804 
setPreInits(Stmt * PreInits)5805   void setPreInits(Stmt *PreInits) {
5806     Data->getChildren()[PreInitsOffset] = PreInits;
5807   }
5808 
setTransformedStmt(Stmt * S)5809   void setTransformedStmt(Stmt *S) {
5810     Data->getChildren()[TransformedStmtOffset] = S;
5811   }
5812 
5813 public:
5814   /// Create a new AST node representation for '#pragma omp interchange'.
5815   ///
5816   /// \param C         Context of the AST.
5817   /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
5818   /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
5819   /// \param Clauses   The directive's clauses.
5820   /// \param NumLoops  Number of affected loops
5821   ///                  (number of items in the 'permutation' clause if present).
5822   /// \param AssociatedStmt  The outermost associated loop.
5823   /// \param TransformedStmt The loop nest after tiling, or nullptr in
5824   ///                        dependent contexts.
5825   /// \param PreInits  Helper preinits statements for the loop nest.
5826   static OMPInterchangeDirective *
5827   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5828          ArrayRef<OMPClause *> Clauses, unsigned NumLoops, Stmt *AssociatedStmt,
5829          Stmt *TransformedStmt, Stmt *PreInits);
5830 
5831   /// Build an empty '#pragma omp interchange' AST node for deserialization.
5832   ///
5833   /// \param C          Context of the AST.
5834   /// \param NumClauses Number of clauses to allocate.
5835   /// \param NumLoops   Number of associated loops to allocate.
5836   static OMPInterchangeDirective *
5837   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned NumLoops);
5838 
5839   /// Gets the associated loops after the transformation. This is the de-sugared
5840   /// replacement or nullptr in dependent contexts.
getTransformedStmt()5841   Stmt *getTransformedStmt() const {
5842     return Data->getChildren()[TransformedStmtOffset];
5843   }
5844 
5845   /// Return preinits statement.
getPreInits()5846   Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
5847 
classof(const Stmt * T)5848   static bool classof(const Stmt *T) {
5849     return T->getStmtClass() == OMPInterchangeDirectiveClass;
5850   }
5851 };
5852 
5853 /// This represents '#pragma omp scan' directive.
5854 ///
5855 /// \code
5856 /// #pragma omp scan inclusive(a)
5857 /// \endcode
5858 /// In this example directive '#pragma omp scan' has clause 'inclusive' with
5859 /// list item 'a'.
5860 class OMPScanDirective final : public OMPExecutableDirective {
5861   friend class ASTStmtReader;
5862   friend class OMPExecutableDirective;
5863   /// Build directive with the given start and end location.
5864   ///
5865   /// \param StartLoc Starting location of the directive kind.
5866   /// \param EndLoc Ending location of the directive.
5867   ///
OMPScanDirective(SourceLocation StartLoc,SourceLocation EndLoc)5868   OMPScanDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5869       : OMPExecutableDirective(OMPScanDirectiveClass, llvm::omp::OMPD_scan,
5870                                StartLoc, EndLoc) {}
5871 
5872   /// Build an empty directive.
5873   ///
OMPScanDirective()5874   explicit OMPScanDirective()
5875       : OMPExecutableDirective(OMPScanDirectiveClass, llvm::omp::OMPD_scan,
5876                                SourceLocation(), SourceLocation()) {}
5877 
5878 public:
5879   /// Creates directive with a list of \a Clauses.
5880   ///
5881   /// \param C AST context.
5882   /// \param StartLoc Starting location of the directive kind.
5883   /// \param EndLoc Ending Location of the directive.
5884   /// \param Clauses List of clauses (only single OMPFlushClause clause is
5885   /// allowed).
5886   ///
5887   static OMPScanDirective *Create(const ASTContext &C, SourceLocation StartLoc,
5888                                   SourceLocation EndLoc,
5889                                   ArrayRef<OMPClause *> Clauses);
5890 
5891   /// Creates an empty directive with the place for \a NumClauses
5892   /// clauses.
5893   ///
5894   /// \param C AST context.
5895   /// \param NumClauses Number of clauses.
5896   ///
5897   static OMPScanDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
5898                                        EmptyShell);
5899 
classof(const Stmt * T)5900   static bool classof(const Stmt *T) {
5901     return T->getStmtClass() == OMPScanDirectiveClass;
5902   }
5903 };
5904 
5905 /// This represents '#pragma omp interop' directive.
5906 ///
5907 /// \code
5908 /// #pragma omp interop init(target:obj) device(x) depend(inout:y) nowait
5909 /// \endcode
5910 /// In this example directive '#pragma omp interop' has
5911 /// clauses 'init', 'device', 'depend' and 'nowait'.
5912 ///
5913 class OMPInteropDirective final : public OMPExecutableDirective {
5914   friend class ASTStmtReader;
5915   friend class OMPExecutableDirective;
5916 
5917   /// Build directive with the given start and end location.
5918   ///
5919   /// \param StartLoc Starting location of the directive.
5920   /// \param EndLoc Ending location of the directive.
5921   ///
OMPInteropDirective(SourceLocation StartLoc,SourceLocation EndLoc)5922   OMPInteropDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5923       : OMPExecutableDirective(OMPInteropDirectiveClass,
5924                                llvm::omp::OMPD_interop, StartLoc, EndLoc) {}
5925 
5926   /// Build an empty directive.
5927   ///
OMPInteropDirective()5928   explicit OMPInteropDirective()
5929       : OMPExecutableDirective(OMPInteropDirectiveClass,
5930                                llvm::omp::OMPD_interop, SourceLocation(),
5931                                SourceLocation()) {}
5932 
5933 public:
5934   /// Creates directive.
5935   ///
5936   /// \param C AST context.
5937   /// \param StartLoc Starting location of the directive.
5938   /// \param EndLoc Ending Location of the directive.
5939   /// \param Clauses The directive's clauses.
5940   ///
5941   static OMPInteropDirective *Create(const ASTContext &C,
5942                                      SourceLocation StartLoc,
5943                                      SourceLocation EndLoc,
5944                                      ArrayRef<OMPClause *> Clauses);
5945 
5946   /// Creates an empty directive.
5947   ///
5948   /// \param C AST context.
5949   ///
5950   static OMPInteropDirective *CreateEmpty(const ASTContext &C,
5951                                           unsigned NumClauses, EmptyShell);
5952 
classof(const Stmt * T)5953   static bool classof(const Stmt *T) {
5954     return T->getStmtClass() == OMPInteropDirectiveClass;
5955   }
5956 };
5957 
5958 /// This represents '#pragma omp dispatch' directive.
5959 ///
5960 /// \code
5961 /// #pragma omp dispatch device(dnum)
5962 /// \endcode
5963 /// This example shows a directive '#pragma omp dispatch' with a
5964 /// device clause with variable 'dnum'.
5965 ///
5966 class OMPDispatchDirective final : public OMPExecutableDirective {
5967   friend class ASTStmtReader;
5968   friend class OMPExecutableDirective;
5969 
5970   /// The location of the target-call.
5971   SourceLocation TargetCallLoc;
5972 
5973   /// Set the location of the target-call.
setTargetCallLoc(SourceLocation Loc)5974   void setTargetCallLoc(SourceLocation Loc) { TargetCallLoc = Loc; }
5975 
5976   /// Build directive with the given start and end location.
5977   ///
5978   /// \param StartLoc Starting location of the directive kind.
5979   /// \param EndLoc Ending location of the directive.
5980   ///
OMPDispatchDirective(SourceLocation StartLoc,SourceLocation EndLoc)5981   OMPDispatchDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5982       : OMPExecutableDirective(OMPDispatchDirectiveClass,
5983                                llvm::omp::OMPD_dispatch, StartLoc, EndLoc) {}
5984 
5985   /// Build an empty directive.
5986   ///
OMPDispatchDirective()5987   explicit OMPDispatchDirective()
5988       : OMPExecutableDirective(OMPDispatchDirectiveClass,
5989                                llvm::omp::OMPD_dispatch, SourceLocation(),
5990                                SourceLocation()) {}
5991 
5992 public:
5993   /// Creates directive with a list of \a Clauses.
5994   ///
5995   /// \param C AST context.
5996   /// \param StartLoc Starting location of the directive kind.
5997   /// \param EndLoc Ending Location of the directive.
5998   /// \param Clauses List of clauses.
5999   /// \param AssociatedStmt Statement, associated with the directive.
6000   /// \param TargetCallLoc Location of the target-call.
6001   ///
6002   static OMPDispatchDirective *
6003   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6004          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
6005          SourceLocation TargetCallLoc);
6006 
6007   /// Creates an empty directive with the place for \a NumClauses
6008   /// clauses.
6009   ///
6010   /// \param C AST context.
6011   /// \param NumClauses Number of clauses.
6012   ///
6013   static OMPDispatchDirective *CreateEmpty(const ASTContext &C,
6014                                            unsigned NumClauses, EmptyShell);
6015 
6016   /// Return location of target-call.
getTargetCallLoc()6017   SourceLocation getTargetCallLoc() const { return TargetCallLoc; }
6018 
classof(const Stmt * T)6019   static bool classof(const Stmt *T) {
6020     return T->getStmtClass() == OMPDispatchDirectiveClass;
6021   }
6022 };
6023 
6024 /// This represents '#pragma omp masked' directive.
6025 /// \code
6026 /// #pragma omp masked filter(tid)
6027 /// \endcode
6028 /// This example shows a directive '#pragma omp masked' with a filter clause
6029 /// with variable 'tid'.
6030 ///
6031 class OMPMaskedDirective final : public OMPExecutableDirective {
6032   friend class ASTStmtReader;
6033   friend class OMPExecutableDirective;
6034 
6035   /// Build directive with the given start and end location.
6036   ///
6037   /// \param StartLoc Starting location of the directive kind.
6038   /// \param EndLoc Ending location of the directive.
6039   ///
OMPMaskedDirective(SourceLocation StartLoc,SourceLocation EndLoc)6040   OMPMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
6041       : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
6042                                StartLoc, EndLoc) {}
6043 
6044   /// Build an empty directive.
6045   ///
OMPMaskedDirective()6046   explicit OMPMaskedDirective()
6047       : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
6048                                SourceLocation(), SourceLocation()) {}
6049 
6050 public:
6051   /// Creates directive.
6052   ///
6053   /// \param C AST context.
6054   /// \param StartLoc Starting location of the directive kind.
6055   /// \param EndLoc Ending Location of the directive.
6056   /// \param AssociatedStmt Statement, associated with the directive.
6057   ///
6058   static OMPMaskedDirective *
6059   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6060          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
6061 
6062   /// Creates an empty directive.
6063   ///
6064   /// \param C AST context.
6065   ///
6066   static OMPMaskedDirective *CreateEmpty(const ASTContext &C,
6067                                          unsigned NumClauses, EmptyShell);
6068 
classof(const Stmt * T)6069   static bool classof(const Stmt *T) {
6070     return T->getStmtClass() == OMPMaskedDirectiveClass;
6071   }
6072 };
6073 
6074 /// This represents '#pragma omp metadirective' directive.
6075 ///
6076 /// \code
6077 /// #pragma omp metadirective when(user={condition(N>10)}: parallel for)
6078 /// \endcode
6079 /// In this example directive '#pragma omp metadirective' has clauses 'when'
6080 /// with a dynamic user condition to check if a variable 'N > 10'
6081 ///
6082 class OMPMetaDirective final : public OMPExecutableDirective {
6083   friend class ASTStmtReader;
6084   friend class OMPExecutableDirective;
6085   Stmt *IfStmt;
6086 
OMPMetaDirective(SourceLocation StartLoc,SourceLocation EndLoc)6087   OMPMetaDirective(SourceLocation StartLoc, SourceLocation EndLoc)
6088       : OMPExecutableDirective(OMPMetaDirectiveClass,
6089                                llvm::omp::OMPD_metadirective, StartLoc,
6090                                EndLoc) {}
OMPMetaDirective()6091   explicit OMPMetaDirective()
6092       : OMPExecutableDirective(OMPMetaDirectiveClass,
6093                                llvm::omp::OMPD_metadirective, SourceLocation(),
6094                                SourceLocation()) {}
6095 
setIfStmt(Stmt * S)6096   void setIfStmt(Stmt *S) { IfStmt = S; }
6097 
6098 public:
6099   static OMPMetaDirective *Create(const ASTContext &C, SourceLocation StartLoc,
6100                                   SourceLocation EndLoc,
6101                                   ArrayRef<OMPClause *> Clauses,
6102                                   Stmt *AssociatedStmt, Stmt *IfStmt);
6103   static OMPMetaDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
6104                                        EmptyShell);
getIfStmt()6105   Stmt *getIfStmt() const { return IfStmt; }
6106 
classof(const Stmt * T)6107   static bool classof(const Stmt *T) {
6108     return T->getStmtClass() == OMPMetaDirectiveClass;
6109   }
6110 };
6111 
6112 /// This represents '#pragma omp loop' directive.
6113 ///
6114 /// \code
6115 /// #pragma omp loop private(a,b) binding(parallel) order(concurrent)
6116 /// \endcode
6117 /// In this example directive '#pragma omp loop' has
6118 /// clauses 'private' with the variables 'a' and 'b', 'binding' with
6119 /// modifier 'parallel' and 'order(concurrent).
6120 ///
6121 class OMPGenericLoopDirective final : public OMPLoopDirective {
6122   friend class ASTStmtReader;
6123   friend class OMPExecutableDirective;
6124   /// Build directive with the given start and end location.
6125   ///
6126   /// \param StartLoc Starting location of the directive kind.
6127   /// \param EndLoc Ending location of the directive.
6128   /// \param CollapsedNum Number of collapsed nested loops.
6129   ///
OMPGenericLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)6130   OMPGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
6131                           unsigned CollapsedNum)
6132       : OMPLoopDirective(OMPGenericLoopDirectiveClass, llvm::omp::OMPD_loop,
6133                          StartLoc, EndLoc, CollapsedNum) {}
6134 
6135   /// Build an empty directive.
6136   ///
6137   /// \param CollapsedNum Number of collapsed nested loops.
6138   ///
OMPGenericLoopDirective(unsigned CollapsedNum)6139   explicit OMPGenericLoopDirective(unsigned CollapsedNum)
6140       : OMPLoopDirective(OMPGenericLoopDirectiveClass, llvm::omp::OMPD_loop,
6141                          SourceLocation(), SourceLocation(), CollapsedNum) {}
6142 
6143 public:
6144   /// Creates directive with a list of \p Clauses.
6145   ///
6146   /// \param C AST context.
6147   /// \param StartLoc Starting location of the directive kind.
6148   /// \param EndLoc Ending Location of the directive.
6149   /// \param CollapsedNum Number of collapsed loops.
6150   /// \param Clauses List of clauses.
6151   /// \param AssociatedStmt Statement, associated with the directive.
6152   /// \param Exprs Helper expressions for CodeGen.
6153   ///
6154   static OMPGenericLoopDirective *
6155   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6156          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6157          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6158 
6159   /// Creates an empty directive with a place for \a NumClauses clauses.
6160   ///
6161   /// \param C AST context.
6162   /// \param NumClauses Number of clauses.
6163   /// \param CollapsedNum Number of collapsed nested loops.
6164   ///
6165   static OMPGenericLoopDirective *CreateEmpty(const ASTContext &C,
6166                                               unsigned NumClauses,
6167                                               unsigned CollapsedNum,
6168                                               EmptyShell);
6169 
classof(const Stmt * T)6170   static bool classof(const Stmt *T) {
6171     return T->getStmtClass() == OMPGenericLoopDirectiveClass;
6172   }
6173 };
6174 
6175 /// This represents '#pragma omp teams loop' directive.
6176 ///
6177 /// \code
6178 /// #pragma omp teams loop private(a,b) order(concurrent)
6179 /// \endcode
6180 /// In this example directive '#pragma omp teams loop' has
6181 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6182 ///
6183 class OMPTeamsGenericLoopDirective final : public OMPLoopDirective {
6184   friend class ASTStmtReader;
6185   friend class OMPExecutableDirective;
6186   /// Build directive with the given start and end location.
6187   ///
6188   /// \param StartLoc Starting location of the directive kind.
6189   /// \param EndLoc Ending location of the directive.
6190   /// \param CollapsedNum Number of collapsed nested loops.
6191   ///
OMPTeamsGenericLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)6192   OMPTeamsGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
6193                                unsigned CollapsedNum)
6194       : OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass,
6195                          llvm::omp::OMPD_teams_loop, StartLoc, EndLoc,
6196                          CollapsedNum) {}
6197 
6198   /// Build an empty directive.
6199   ///
6200   /// \param CollapsedNum Number of collapsed nested loops.
6201   ///
OMPTeamsGenericLoopDirective(unsigned CollapsedNum)6202   explicit OMPTeamsGenericLoopDirective(unsigned CollapsedNum)
6203       : OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass,
6204                          llvm::omp::OMPD_teams_loop, SourceLocation(),
6205                          SourceLocation(), CollapsedNum) {}
6206 
6207 public:
6208   /// Creates directive with a list of \p Clauses.
6209   ///
6210   /// \param C AST context.
6211   /// \param StartLoc Starting location of the directive kind.
6212   /// \param EndLoc Ending Location of the directive.
6213   /// \param CollapsedNum Number of collapsed loops.
6214   /// \param Clauses List of clauses.
6215   /// \param AssociatedStmt Statement, associated with the directive.
6216   /// \param Exprs Helper expressions for CodeGen.
6217   ///
6218   static OMPTeamsGenericLoopDirective *
6219   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6220          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6221          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6222 
6223   /// Creates an empty directive with the place
6224   /// for \a NumClauses clauses.
6225   ///
6226   /// \param C AST context.
6227   /// \param CollapsedNum Number of collapsed nested loops.
6228   /// \param NumClauses Number of clauses.
6229   ///
6230   static OMPTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C,
6231                                                    unsigned NumClauses,
6232                                                    unsigned CollapsedNum,
6233                                                    EmptyShell);
6234 
classof(const Stmt * T)6235   static bool classof(const Stmt *T) {
6236     return T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass;
6237   }
6238 };
6239 
6240 /// This represents '#pragma omp target teams loop' directive.
6241 ///
6242 /// \code
6243 /// #pragma omp target teams loop private(a,b) order(concurrent)
6244 /// \endcode
6245 /// In this example directive '#pragma omp target teams loop' has
6246 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6247 ///
6248 class OMPTargetTeamsGenericLoopDirective final : public OMPLoopDirective {
6249   friend class ASTStmtReader;
6250   friend class OMPExecutableDirective;
6251   /// true if loop directive's associated loop can be a parallel for.
6252   bool CanBeParallelFor = false;
6253   /// Build directive with the given start and end location.
6254   ///
6255   /// \param StartLoc Starting location of the directive kind.
6256   /// \param EndLoc Ending location of the directive.
6257   /// \param CollapsedNum Number of collapsed nested loops.
6258   ///
OMPTargetTeamsGenericLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)6259   OMPTargetTeamsGenericLoopDirective(SourceLocation StartLoc,
6260                                      SourceLocation EndLoc,
6261                                      unsigned CollapsedNum)
6262       : OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass,
6263                          llvm::omp::OMPD_target_teams_loop, StartLoc, EndLoc,
6264                          CollapsedNum) {}
6265 
6266   /// Build an empty directive.
6267   ///
6268   /// \param CollapsedNum Number of collapsed nested loops.
6269   ///
OMPTargetTeamsGenericLoopDirective(unsigned CollapsedNum)6270   explicit OMPTargetTeamsGenericLoopDirective(unsigned CollapsedNum)
6271       : OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass,
6272                          llvm::omp::OMPD_target_teams_loop, SourceLocation(),
6273                          SourceLocation(), CollapsedNum) {}
6274 
6275   /// Set whether associated loop can be a parallel for.
setCanBeParallelFor(bool ParFor)6276   void setCanBeParallelFor(bool ParFor) { CanBeParallelFor = ParFor; }
6277 
6278 public:
6279   /// Creates directive with a list of \p Clauses.
6280   ///
6281   /// \param C AST context.
6282   /// \param StartLoc Starting location of the directive kind.
6283   /// \param EndLoc Ending Location of the directive.
6284   /// \param CollapsedNum Number of collapsed loops.
6285   /// \param Clauses List of clauses.
6286   /// \param AssociatedStmt Statement, associated with the directive.
6287   /// \param Exprs Helper expressions for CodeGen.
6288   ///
6289   static OMPTargetTeamsGenericLoopDirective *
6290   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6291          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6292          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor);
6293 
6294   /// Creates an empty directive with the place
6295   /// for \a NumClauses clauses.
6296   ///
6297   /// \param C AST context.
6298   /// \param CollapsedNum Number of collapsed nested loops.
6299   /// \param NumClauses Number of clauses.
6300   ///
6301   static OMPTargetTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C,
6302                                                          unsigned NumClauses,
6303                                                          unsigned CollapsedNum,
6304                                                          EmptyShell);
6305 
6306   /// Return true if current loop directive's associated loop can be a
6307   /// parallel for.
canBeParallelFor()6308   bool canBeParallelFor() const { return CanBeParallelFor; }
6309 
classof(const Stmt * T)6310   static bool classof(const Stmt *T) {
6311     return T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass;
6312   }
6313 };
6314 
6315 /// This represents '#pragma omp parallel loop' directive.
6316 ///
6317 /// \code
6318 /// #pragma omp parallel loop private(a,b) order(concurrent)
6319 /// \endcode
6320 /// In this example directive '#pragma omp parallel loop' has
6321 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6322 ///
6323 class OMPParallelGenericLoopDirective final : public OMPLoopDirective {
6324   friend class ASTStmtReader;
6325   friend class OMPExecutableDirective;
6326   /// Build directive with the given start and end location.
6327   ///
6328   /// \param StartLoc Starting location of the directive kind.
6329   /// \param EndLoc Ending location of the directive.
6330   /// \param CollapsedNum Number of collapsed nested loops.
6331   ///
OMPParallelGenericLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)6332   OMPParallelGenericLoopDirective(SourceLocation StartLoc,
6333                                   SourceLocation EndLoc, unsigned CollapsedNum)
6334       : OMPLoopDirective(OMPParallelGenericLoopDirectiveClass,
6335                          llvm::omp::OMPD_parallel_loop, StartLoc, EndLoc,
6336                          CollapsedNum) {}
6337 
6338   /// Build an empty directive.
6339   ///
6340   /// \param CollapsedNum Number of collapsed nested loops.
6341   ///
OMPParallelGenericLoopDirective(unsigned CollapsedNum)6342   explicit OMPParallelGenericLoopDirective(unsigned CollapsedNum)
6343       : OMPLoopDirective(OMPParallelGenericLoopDirectiveClass,
6344                          llvm::omp::OMPD_parallel_loop, SourceLocation(),
6345                          SourceLocation(), CollapsedNum) {}
6346 
6347 public:
6348   /// Creates directive with a list of \p Clauses.
6349   ///
6350   /// \param C AST context.
6351   /// \param StartLoc Starting location of the directive kind.
6352   /// \param EndLoc Ending Location of the directive.
6353   /// \param CollapsedNum Number of collapsed loops.
6354   /// \param Clauses List of clauses.
6355   /// \param AssociatedStmt Statement, associated with the directive.
6356   /// \param Exprs Helper expressions for CodeGen.
6357   ///
6358   static OMPParallelGenericLoopDirective *
6359   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6360          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6361          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6362 
6363   /// Creates an empty directive with the place
6364   /// for \a NumClauses clauses.
6365   ///
6366   /// \param C AST context.
6367   /// \param CollapsedNum Number of collapsed nested loops.
6368   /// \param NumClauses Number of clauses.
6369   ///
6370   static OMPParallelGenericLoopDirective *CreateEmpty(const ASTContext &C,
6371                                                       unsigned NumClauses,
6372                                                       unsigned CollapsedNum,
6373                                                       EmptyShell);
6374 
classof(const Stmt * T)6375   static bool classof(const Stmt *T) {
6376     return T->getStmtClass() == OMPParallelGenericLoopDirectiveClass;
6377   }
6378 };
6379 
6380 /// This represents '#pragma omp target parallel loop' directive.
6381 ///
6382 /// \code
6383 /// #pragma omp target parallel loop private(a,b) order(concurrent)
6384 /// \endcode
6385 /// In this example directive '#pragma omp target parallel loop' has
6386 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6387 ///
6388 class OMPTargetParallelGenericLoopDirective final : public OMPLoopDirective {
6389   friend class ASTStmtReader;
6390   friend class OMPExecutableDirective;
6391   /// Build directive with the given start and end location.
6392   ///
6393   /// \param StartLoc Starting location of the directive kind.
6394   /// \param EndLoc Ending location of the directive.
6395   /// \param CollapsedNum Number of collapsed nested loops.
6396   ///
OMPTargetParallelGenericLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)6397   OMPTargetParallelGenericLoopDirective(SourceLocation StartLoc,
6398                                         SourceLocation EndLoc,
6399                                         unsigned CollapsedNum)
6400       : OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass,
6401                          llvm::omp::OMPD_target_parallel_loop, StartLoc, EndLoc,
6402                          CollapsedNum) {}
6403 
6404   /// Build an empty directive.
6405   ///
6406   /// \param CollapsedNum Number of collapsed nested loops.
6407   ///
OMPTargetParallelGenericLoopDirective(unsigned CollapsedNum)6408   explicit OMPTargetParallelGenericLoopDirective(unsigned CollapsedNum)
6409       : OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass,
6410                          llvm::omp::OMPD_target_parallel_loop, SourceLocation(),
6411                          SourceLocation(), CollapsedNum) {}
6412 
6413 public:
6414   /// Creates directive with a list of \p Clauses.
6415   ///
6416   /// \param C AST context.
6417   /// \param StartLoc Starting location of the directive kind.
6418   /// \param EndLoc Ending Location of the directive.
6419   /// \param CollapsedNum Number of collapsed loops.
6420   /// \param Clauses List of clauses.
6421   /// \param AssociatedStmt Statement, associated with the directive.
6422   /// \param Exprs Helper expressions for CodeGen.
6423   ///
6424   static OMPTargetParallelGenericLoopDirective *
6425   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6426          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6427          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6428 
6429   /// Creates an empty directive with the place
6430   /// for \a NumClauses clauses.
6431   ///
6432   /// \param C AST context.
6433   /// \param CollapsedNum Number of collapsed nested loops.
6434   /// \param NumClauses Number of clauses.
6435   ///
6436   static OMPTargetParallelGenericLoopDirective *
6437   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
6438               EmptyShell);
6439 
classof(const Stmt * T)6440   static bool classof(const Stmt *T) {
6441     return T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass;
6442   }
6443 };
6444 
6445 /// This represents '#pragma omp error' directive.
6446 ///
6447 /// \code
6448 /// #pragma omp error
6449 /// \endcode
6450 class OMPErrorDirective final : public OMPExecutableDirective {
6451   friend class ASTStmtReader;
6452   friend class OMPExecutableDirective;
6453   /// Build directive with the given start and end location.
6454   ///
6455   /// \param StartLoc Starting location of the directive kind.
6456   /// \param EndLoc Ending location of the directive.
6457   ///
OMPErrorDirective(SourceLocation StartLoc,SourceLocation EndLoc)6458   OMPErrorDirective(SourceLocation StartLoc, SourceLocation EndLoc)
6459       : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error,
6460                                StartLoc, EndLoc) {}
6461   /// Build an empty directive.
6462   ///
OMPErrorDirective()6463   explicit OMPErrorDirective()
6464       : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error,
6465                                SourceLocation(), SourceLocation()) {}
6466 
6467 public:
6468   ///
6469   /// \param C AST context.
6470   /// \param StartLoc Starting location of the directive kind.
6471   /// \param EndLoc Ending Location of the directive.
6472   /// \param Clauses List of clauses.
6473   ///
6474   static OMPErrorDirective *Create(const ASTContext &C, SourceLocation StartLoc,
6475                                    SourceLocation EndLoc,
6476                                    ArrayRef<OMPClause *> Clauses);
6477 
6478   /// Creates an empty directive.
6479   ///
6480   /// \param C AST context.
6481   ///
6482   static OMPErrorDirective *CreateEmpty(const ASTContext &C,
6483                                         unsigned NumClauses, EmptyShell);
6484 
classof(const Stmt * T)6485   static bool classof(const Stmt *T) {
6486     return T->getStmtClass() == OMPErrorDirectiveClass;
6487   }
6488 };
6489 } // end namespace clang
6490 
6491 #endif
6492