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