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     uint8_t IsXLHSInRHSPart : 1;
2978     /// Used for 'atomic update' or 'atomic capture' constructs. They may
2979     /// have atomic expressions of forms:
2980     /// \code
2981     /// v = x; <update x>;
2982     /// <update x>; v = x;
2983     /// \endcode
2984     /// This field is 1 for the first(postfix) form of the expression and 0
2985     /// otherwise.
2986     uint8_t IsPostfixUpdate : 1;
2987     /// 1 if 'v' is updated only when the condition is false (compare capture
2988     /// only).
2989     uint8_t IsFailOnly : 1;
2990   } Flags;
2991 
2992   /// Build directive with the given start and end location.
2993   ///
2994   /// \param StartLoc Starting location of the directive kind.
2995   /// \param EndLoc Ending location of the directive.
2996   ///
OMPAtomicDirective(SourceLocation StartLoc,SourceLocation EndLoc)2997   OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2998       : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
2999                                StartLoc, EndLoc) {}
3000 
3001   /// Build an empty directive.
3002   ///
OMPAtomicDirective()3003   explicit OMPAtomicDirective()
3004       : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
3005                                SourceLocation(), SourceLocation()) {}
3006 
3007   enum DataPositionTy : size_t {
3008     POS_X = 0,
3009     POS_V,
3010     POS_E,
3011     POS_UpdateExpr,
3012     POS_D,
3013     POS_Cond,
3014     POS_R,
3015   };
3016 
3017   /// Set 'x' part of the associated expression/statement.
setX(Expr * X)3018   void setX(Expr *X) { Data->getChildren()[DataPositionTy::POS_X] = X; }
3019   /// Set helper expression of the form
3020   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
3021   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
setUpdateExpr(Expr * UE)3022   void setUpdateExpr(Expr *UE) {
3023     Data->getChildren()[DataPositionTy::POS_UpdateExpr] = UE;
3024   }
3025   /// Set 'v' part of the associated expression/statement.
setV(Expr * V)3026   void setV(Expr *V) { Data->getChildren()[DataPositionTy::POS_V] = V; }
3027   /// Set 'r' part of the associated expression/statement.
setR(Expr * R)3028   void setR(Expr *R) { Data->getChildren()[DataPositionTy::POS_R] = R; }
3029   /// Set 'expr' part of the associated expression/statement.
setExpr(Expr * E)3030   void setExpr(Expr *E) { Data->getChildren()[DataPositionTy::POS_E] = E; }
3031   /// Set 'd' part of the associated expression/statement.
setD(Expr * D)3032   void setD(Expr *D) { Data->getChildren()[DataPositionTy::POS_D] = D; }
3033   /// Set conditional expression in `atomic compare`.
setCond(Expr * C)3034   void setCond(Expr *C) { Data->getChildren()[DataPositionTy::POS_Cond] = C; }
3035 
3036 public:
3037   struct Expressions {
3038     /// 'x' part of the associated expression/statement.
3039     Expr *X = nullptr;
3040     /// 'v' part of the associated expression/statement.
3041     Expr *V = nullptr;
3042     // 'r' part of the associated expression/statement.
3043     Expr *R = nullptr;
3044     /// 'expr' part of the associated expression/statement.
3045     Expr *E = nullptr;
3046     /// UE Helper expression of the form:
3047     /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
3048     /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
3049     Expr *UE = nullptr;
3050     /// 'd' part of the associated expression/statement.
3051     Expr *D = nullptr;
3052     /// Conditional expression in `atomic compare` construct.
3053     Expr *Cond = nullptr;
3054     /// True if UE has the first form and false if the second.
3055     bool IsXLHSInRHSPart;
3056     /// True if original value of 'x' must be stored in 'v', not an updated one.
3057     bool IsPostfixUpdate;
3058     /// True if 'v' is updated only when the condition is false (compare capture
3059     /// only).
3060     bool IsFailOnly;
3061   };
3062 
3063   /// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
3064   /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for
3065   /// detailed description of 'x', 'v' and 'expr').
3066   ///
3067   /// \param C AST context.
3068   /// \param StartLoc Starting location of the directive kind.
3069   /// \param EndLoc Ending Location of the directive.
3070   /// \param Clauses List of clauses.
3071   /// \param AssociatedStmt Statement, associated with the directive.
3072   /// \param Exprs Associated expressions or statements.
3073   static OMPAtomicDirective *Create(const ASTContext &C,
3074                                     SourceLocation StartLoc,
3075                                     SourceLocation EndLoc,
3076                                     ArrayRef<OMPClause *> Clauses,
3077                                     Stmt *AssociatedStmt, Expressions Exprs);
3078 
3079   /// Creates an empty directive with the place for \a NumClauses
3080   /// clauses.
3081   ///
3082   /// \param C AST context.
3083   /// \param NumClauses Number of clauses.
3084   ///
3085   static OMPAtomicDirective *CreateEmpty(const ASTContext &C,
3086                                          unsigned NumClauses, EmptyShell);
3087 
3088   /// Get 'x' part of the associated expression/statement.
getX()3089   Expr *getX() {
3090     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_X]);
3091   }
getX()3092   const Expr *getX() const {
3093     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_X]);
3094   }
3095   /// Get helper expression of the form
3096   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
3097   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
getUpdateExpr()3098   Expr *getUpdateExpr() {
3099     return cast_or_null<Expr>(
3100         Data->getChildren()[DataPositionTy::POS_UpdateExpr]);
3101   }
getUpdateExpr()3102   const Expr *getUpdateExpr() const {
3103     return cast_or_null<Expr>(
3104         Data->getChildren()[DataPositionTy::POS_UpdateExpr]);
3105   }
3106   /// Return true if helper update expression has form
3107   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form
3108   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
isXLHSInRHSPart()3109   bool isXLHSInRHSPart() const { return Flags.IsXLHSInRHSPart; }
3110   /// Return true if 'v' expression must be updated to original value of
3111   /// 'x', false if 'v' must be updated to the new value of 'x'.
isPostfixUpdate()3112   bool isPostfixUpdate() const { return Flags.IsPostfixUpdate; }
3113   /// Return true if 'v' is updated only when the condition is evaluated false
3114   /// (compare capture only).
isFailOnly()3115   bool isFailOnly() const { return Flags.IsFailOnly; }
3116   /// Get 'v' part of the associated expression/statement.
getV()3117   Expr *getV() {
3118     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]);
3119   }
getV()3120   const Expr *getV() const {
3121     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]);
3122   }
3123   /// Get 'r' part of the associated expression/statement.
getR()3124   Expr *getR() {
3125     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]);
3126   }
getR()3127   const Expr *getR() const {
3128     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]);
3129   }
3130   /// Get 'expr' part of the associated expression/statement.
getExpr()3131   Expr *getExpr() {
3132     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
3133   }
getExpr()3134   const Expr *getExpr() const {
3135     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
3136   }
3137   /// Get 'd' part of the associated expression/statement.
getD()3138   Expr *getD() {
3139     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
3140   }
getD()3141   Expr *getD() const {
3142     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
3143   }
3144   /// Get the 'cond' part of the source atomic expression.
getCondExpr()3145   Expr *getCondExpr() {
3146     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
3147   }
getCondExpr()3148   Expr *getCondExpr() const {
3149     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
3150   }
3151 
classof(const Stmt * T)3152   static bool classof(const Stmt *T) {
3153     return T->getStmtClass() == OMPAtomicDirectiveClass;
3154   }
3155 };
3156 
3157 /// This represents '#pragma omp target' directive.
3158 ///
3159 /// \code
3160 /// #pragma omp target if(a)
3161 /// \endcode
3162 /// In this example directive '#pragma omp target' has clause 'if' with
3163 /// condition 'a'.
3164 ///
3165 class OMPTargetDirective : public OMPExecutableDirective {
3166   friend class ASTStmtReader;
3167   friend class OMPExecutableDirective;
3168   /// Build directive with the given start and end location.
3169   ///
3170   /// \param StartLoc Starting location of the directive kind.
3171   /// \param EndLoc Ending location of the directive.
3172   ///
OMPTargetDirective(SourceLocation StartLoc,SourceLocation EndLoc)3173   OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3174       : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
3175                                StartLoc, EndLoc) {}
3176 
3177   /// Build an empty directive.
3178   ///
OMPTargetDirective()3179   explicit OMPTargetDirective()
3180       : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
3181                                SourceLocation(), SourceLocation()) {}
3182 
3183 public:
3184   /// Creates directive with a list of \a Clauses.
3185   ///
3186   /// \param C AST context.
3187   /// \param StartLoc Starting location of the directive kind.
3188   /// \param EndLoc Ending Location of the directive.
3189   /// \param Clauses List of clauses.
3190   /// \param AssociatedStmt Statement, associated with the directive.
3191   ///
3192   static OMPTargetDirective *
3193   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3194          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3195 
3196   /// Creates an empty directive with the place for \a NumClauses
3197   /// clauses.
3198   ///
3199   /// \param C AST context.
3200   /// \param NumClauses Number of clauses.
3201   ///
3202   static OMPTargetDirective *CreateEmpty(const ASTContext &C,
3203                                          unsigned NumClauses, EmptyShell);
3204 
classof(const Stmt * T)3205   static bool classof(const Stmt *T) {
3206     return T->getStmtClass() == OMPTargetDirectiveClass;
3207   }
3208 };
3209 
3210 /// This represents '#pragma omp target data' directive.
3211 ///
3212 /// \code
3213 /// #pragma omp target data device(0) if(a) map(b[:])
3214 /// \endcode
3215 /// In this example directive '#pragma omp target data' has clauses 'device'
3216 /// with the value '0', 'if' with condition 'a' and 'map' with array
3217 /// section 'b[:]'.
3218 ///
3219 class OMPTargetDataDirective : public OMPExecutableDirective {
3220   friend class ASTStmtReader;
3221   friend class OMPExecutableDirective;
3222   /// Build directive with the given start and end location.
3223   ///
3224   /// \param StartLoc Starting location of the directive kind.
3225   /// \param EndLoc Ending Location of the directive.
3226   ///
OMPTargetDataDirective(SourceLocation StartLoc,SourceLocation EndLoc)3227   OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3228       : OMPExecutableDirective(OMPTargetDataDirectiveClass,
3229                                llvm::omp::OMPD_target_data, StartLoc, EndLoc) {}
3230 
3231   /// Build an empty directive.
3232   ///
OMPTargetDataDirective()3233   explicit OMPTargetDataDirective()
3234       : OMPExecutableDirective(OMPTargetDataDirectiveClass,
3235                                llvm::omp::OMPD_target_data, SourceLocation(),
3236                                SourceLocation()) {}
3237 
3238 public:
3239   /// Creates directive with a list of \a Clauses.
3240   ///
3241   /// \param C AST context.
3242   /// \param StartLoc Starting location of the directive kind.
3243   /// \param EndLoc Ending Location of the directive.
3244   /// \param Clauses List of clauses.
3245   /// \param AssociatedStmt Statement, associated with the directive.
3246   ///
3247   static OMPTargetDataDirective *
3248   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3249          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3250 
3251   /// Creates an empty directive with the place for \a N clauses.
3252   ///
3253   /// \param C AST context.
3254   /// \param N The number of clauses.
3255   ///
3256   static OMPTargetDataDirective *CreateEmpty(const ASTContext &C, unsigned N,
3257                                              EmptyShell);
3258 
classof(const Stmt * T)3259   static bool classof(const Stmt *T) {
3260     return T->getStmtClass() == OMPTargetDataDirectiveClass;
3261   }
3262 };
3263 
3264 /// This represents '#pragma omp target enter data' directive.
3265 ///
3266 /// \code
3267 /// #pragma omp target enter data device(0) if(a) map(b[:])
3268 /// \endcode
3269 /// In this example directive '#pragma omp target enter data' has clauses
3270 /// 'device' with the value '0', 'if' with condition 'a' and 'map' with array
3271 /// section 'b[:]'.
3272 ///
3273 class OMPTargetEnterDataDirective : public OMPExecutableDirective {
3274   friend class ASTStmtReader;
3275   friend class OMPExecutableDirective;
3276   /// Build directive with the given start and end location.
3277   ///
3278   /// \param StartLoc Starting location of the directive kind.
3279   /// \param EndLoc Ending Location of the directive.
3280   ///
OMPTargetEnterDataDirective(SourceLocation StartLoc,SourceLocation EndLoc)3281   OMPTargetEnterDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3282       : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
3283                                llvm::omp::OMPD_target_enter_data, StartLoc,
3284                                EndLoc) {}
3285 
3286   /// Build an empty directive.
3287   ///
OMPTargetEnterDataDirective()3288   explicit OMPTargetEnterDataDirective()
3289       : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
3290                                llvm::omp::OMPD_target_enter_data,
3291                                SourceLocation(), SourceLocation()) {}
3292 
3293 public:
3294   /// Creates directive with a list of \a Clauses.
3295   ///
3296   /// \param C AST context.
3297   /// \param StartLoc Starting location of the directive kind.
3298   /// \param EndLoc Ending Location of the directive.
3299   /// \param Clauses List of clauses.
3300   /// \param AssociatedStmt Statement, associated with the directive.
3301   ///
3302   static OMPTargetEnterDataDirective *
3303   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3304          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3305 
3306   /// Creates an empty directive with the place for \a N clauses.
3307   ///
3308   /// \param C AST context.
3309   /// \param N The number of clauses.
3310   ///
3311   static OMPTargetEnterDataDirective *CreateEmpty(const ASTContext &C,
3312                                                   unsigned N, EmptyShell);
3313 
classof(const Stmt * T)3314   static bool classof(const Stmt *T) {
3315     return T->getStmtClass() == OMPTargetEnterDataDirectiveClass;
3316   }
3317 };
3318 
3319 /// This represents '#pragma omp target exit data' directive.
3320 ///
3321 /// \code
3322 /// #pragma omp target exit data device(0) if(a) map(b[:])
3323 /// \endcode
3324 /// In this example directive '#pragma omp target exit data' has clauses
3325 /// 'device' with the value '0', 'if' with condition 'a' and 'map' with array
3326 /// section 'b[:]'.
3327 ///
3328 class OMPTargetExitDataDirective : public OMPExecutableDirective {
3329   friend class ASTStmtReader;
3330   friend class OMPExecutableDirective;
3331   /// Build directive with the given start and end location.
3332   ///
3333   /// \param StartLoc Starting location of the directive kind.
3334   /// \param EndLoc Ending Location of the directive.
3335   ///
OMPTargetExitDataDirective(SourceLocation StartLoc,SourceLocation EndLoc)3336   OMPTargetExitDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3337       : OMPExecutableDirective(OMPTargetExitDataDirectiveClass,
3338                                llvm::omp::OMPD_target_exit_data, StartLoc,
3339                                EndLoc) {}
3340 
3341   /// Build an empty directive.
3342   ///
OMPTargetExitDataDirective()3343   explicit OMPTargetExitDataDirective()
3344       : OMPExecutableDirective(OMPTargetExitDataDirectiveClass,
3345                                llvm::omp::OMPD_target_exit_data,
3346                                SourceLocation(), SourceLocation()) {}
3347 
3348 public:
3349   /// Creates directive with a list of \a Clauses.
3350   ///
3351   /// \param C AST context.
3352   /// \param StartLoc Starting location of the directive kind.
3353   /// \param EndLoc Ending Location of the directive.
3354   /// \param Clauses List of clauses.
3355   /// \param AssociatedStmt Statement, associated with the directive.
3356   ///
3357   static OMPTargetExitDataDirective *
3358   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3359          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3360 
3361   /// Creates an empty directive with the place for \a N clauses.
3362   ///
3363   /// \param C AST context.
3364   /// \param N The number of clauses.
3365   ///
3366   static OMPTargetExitDataDirective *CreateEmpty(const ASTContext &C,
3367                                                  unsigned N, EmptyShell);
3368 
classof(const Stmt * T)3369   static bool classof(const Stmt *T) {
3370     return T->getStmtClass() == OMPTargetExitDataDirectiveClass;
3371   }
3372 };
3373 
3374 /// This represents '#pragma omp target parallel' directive.
3375 ///
3376 /// \code
3377 /// #pragma omp target parallel if(a)
3378 /// \endcode
3379 /// In this example directive '#pragma omp target parallel' has clause 'if' with
3380 /// condition 'a'.
3381 ///
3382 class OMPTargetParallelDirective : public OMPExecutableDirective {
3383   friend class ASTStmtReader;
3384   friend class OMPExecutableDirective;
3385   /// true if the construct has inner cancel directive.
3386   bool HasCancel = false;
3387 
3388   /// Build directive with the given start and end location.
3389   ///
3390   /// \param StartLoc Starting location of the directive kind.
3391   /// \param EndLoc Ending location of the directive.
3392   ///
OMPTargetParallelDirective(SourceLocation StartLoc,SourceLocation EndLoc)3393   OMPTargetParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3394       : OMPExecutableDirective(OMPTargetParallelDirectiveClass,
3395                                llvm::omp::OMPD_target_parallel, StartLoc,
3396                                EndLoc) {}
3397 
3398   /// Build an empty directive.
3399   ///
OMPTargetParallelDirective()3400   explicit OMPTargetParallelDirective()
3401       : OMPExecutableDirective(OMPTargetParallelDirectiveClass,
3402                                llvm::omp::OMPD_target_parallel,
3403                                SourceLocation(), SourceLocation()) {}
3404 
3405   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)3406   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
3407   /// Set cancel state.
setHasCancel(bool Has)3408   void setHasCancel(bool Has) { HasCancel = Has; }
3409 
3410 public:
3411   /// Creates directive with a list of \a Clauses.
3412   ///
3413   /// \param C AST context.
3414   /// \param StartLoc Starting location of the directive kind.
3415   /// \param EndLoc Ending Location of the directive.
3416   /// \param Clauses List of clauses.
3417   /// \param AssociatedStmt Statement, associated with the directive.
3418   /// \param TaskRedRef Task reduction special reference expression to handle
3419   /// taskgroup descriptor.
3420   /// \param HasCancel true if this directive has inner cancel directive.
3421   ///
3422   static OMPTargetParallelDirective *
3423   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3424          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
3425          bool HasCancel);
3426 
3427   /// Creates an empty directive with the place for \a NumClauses
3428   /// clauses.
3429   ///
3430   /// \param C AST context.
3431   /// \param NumClauses Number of clauses.
3432   ///
3433   static OMPTargetParallelDirective *
3434   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
3435 
3436   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()3437   Expr *getTaskReductionRefExpr() {
3438     return cast_or_null<Expr>(Data->getChildren()[0]);
3439   }
getTaskReductionRefExpr()3440   const Expr *getTaskReductionRefExpr() const {
3441     return const_cast<OMPTargetParallelDirective *>(this)
3442         ->getTaskReductionRefExpr();
3443   }
3444 
3445   /// Return true if current directive has inner cancel directive.
hasCancel()3446   bool hasCancel() const { return HasCancel; }
3447 
classof(const Stmt * T)3448   static bool classof(const Stmt *T) {
3449     return T->getStmtClass() == OMPTargetParallelDirectiveClass;
3450   }
3451 };
3452 
3453 /// This represents '#pragma omp target parallel for' directive.
3454 ///
3455 /// \code
3456 /// #pragma omp target parallel for private(a,b) reduction(+:c,d)
3457 /// \endcode
3458 /// In this example directive '#pragma omp target parallel for' has clauses
3459 /// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+'
3460 /// and variables 'c' and 'd'.
3461 ///
3462 class OMPTargetParallelForDirective : public OMPLoopDirective {
3463   friend class ASTStmtReader;
3464   friend class OMPExecutableDirective;
3465 
3466   /// true if current region has inner cancel directive.
3467   bool HasCancel = false;
3468 
3469   /// Build directive with the given start and end location.
3470   ///
3471   /// \param StartLoc Starting location of the directive kind.
3472   /// \param EndLoc Ending location of the directive.
3473   /// \param CollapsedNum Number of collapsed nested loops.
3474   ///
OMPTargetParallelForDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)3475   OMPTargetParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3476                                 unsigned CollapsedNum)
3477       : OMPLoopDirective(OMPTargetParallelForDirectiveClass,
3478                          llvm::omp::OMPD_target_parallel_for, StartLoc, EndLoc,
3479                          CollapsedNum) {}
3480 
3481   /// Build an empty directive.
3482   ///
3483   /// \param CollapsedNum Number of collapsed nested loops.
3484   ///
OMPTargetParallelForDirective(unsigned CollapsedNum)3485   explicit OMPTargetParallelForDirective(unsigned CollapsedNum)
3486       : OMPLoopDirective(OMPTargetParallelForDirectiveClass,
3487                          llvm::omp::OMPD_target_parallel_for, SourceLocation(),
3488                          SourceLocation(), CollapsedNum) {}
3489 
3490   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)3491   void setTaskReductionRefExpr(Expr *E) {
3492     Data->getChildren()[numLoopChildren(
3493         getLoopsNumber(), llvm::omp::OMPD_target_parallel_for)] = E;
3494   }
3495 
3496   /// Set cancel state.
setHasCancel(bool Has)3497   void setHasCancel(bool Has) { HasCancel = Has; }
3498 
3499 public:
3500   /// Creates directive with a list of \a Clauses.
3501   ///
3502   /// \param C AST context.
3503   /// \param StartLoc Starting location of the directive kind.
3504   /// \param EndLoc Ending Location of the directive.
3505   /// \param CollapsedNum Number of collapsed loops.
3506   /// \param Clauses List of clauses.
3507   /// \param AssociatedStmt Statement, associated with the directive.
3508   /// \param Exprs Helper expressions for CodeGen.
3509   /// \param TaskRedRef Task reduction special reference expression to handle
3510   /// taskgroup descriptor.
3511   /// \param HasCancel true if current directive has inner cancel directive.
3512   ///
3513   static OMPTargetParallelForDirective *
3514   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3515          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3516          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
3517          bool HasCancel);
3518 
3519   /// Creates an empty directive with the place
3520   /// for \a NumClauses clauses.
3521   ///
3522   /// \param C AST context.
3523   /// \param CollapsedNum Number of collapsed nested loops.
3524   /// \param NumClauses Number of clauses.
3525   ///
3526   static OMPTargetParallelForDirective *CreateEmpty(const ASTContext &C,
3527                                                     unsigned NumClauses,
3528                                                     unsigned CollapsedNum,
3529                                                     EmptyShell);
3530 
3531   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()3532   Expr *getTaskReductionRefExpr() {
3533     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
3534         getLoopsNumber(), llvm::omp::OMPD_target_parallel_for)]);
3535   }
getTaskReductionRefExpr()3536   const Expr *getTaskReductionRefExpr() const {
3537     return const_cast<OMPTargetParallelForDirective *>(this)
3538         ->getTaskReductionRefExpr();
3539   }
3540 
3541   /// Return true if current directive has inner cancel directive.
hasCancel()3542   bool hasCancel() const { return HasCancel; }
3543 
classof(const Stmt * T)3544   static bool classof(const Stmt *T) {
3545     return T->getStmtClass() == OMPTargetParallelForDirectiveClass;
3546   }
3547 };
3548 
3549 /// This represents '#pragma omp teams' directive.
3550 ///
3551 /// \code
3552 /// #pragma omp teams if(a)
3553 /// \endcode
3554 /// In this example directive '#pragma omp teams' has clause 'if' with
3555 /// condition 'a'.
3556 ///
3557 class OMPTeamsDirective : public OMPExecutableDirective {
3558   friend class ASTStmtReader;
3559   friend class OMPExecutableDirective;
3560   /// Build directive with the given start and end location.
3561   ///
3562   /// \param StartLoc Starting location of the directive kind.
3563   /// \param EndLoc Ending location of the directive.
3564   ///
OMPTeamsDirective(SourceLocation StartLoc,SourceLocation EndLoc)3565   OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3566       : OMPExecutableDirective(OMPTeamsDirectiveClass, llvm::omp::OMPD_teams,
3567                                StartLoc, EndLoc) {}
3568 
3569   /// Build an empty directive.
3570   ///
OMPTeamsDirective()3571   explicit OMPTeamsDirective()
3572       : OMPExecutableDirective(OMPTeamsDirectiveClass, llvm::omp::OMPD_teams,
3573                                SourceLocation(), SourceLocation()) {}
3574 
3575 public:
3576   /// Creates directive with a list of \a Clauses.
3577   ///
3578   /// \param C AST context.
3579   /// \param StartLoc Starting location of the directive kind.
3580   /// \param EndLoc Ending Location of the directive.
3581   /// \param Clauses List of clauses.
3582   /// \param AssociatedStmt Statement, associated with the directive.
3583   ///
3584   static OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc,
3585                                    SourceLocation EndLoc,
3586                                    ArrayRef<OMPClause *> Clauses,
3587                                    Stmt *AssociatedStmt);
3588 
3589   /// Creates an empty directive with the place for \a NumClauses
3590   /// clauses.
3591   ///
3592   /// \param C AST context.
3593   /// \param NumClauses Number of clauses.
3594   ///
3595   static OMPTeamsDirective *CreateEmpty(const ASTContext &C,
3596                                         unsigned NumClauses, EmptyShell);
3597 
classof(const Stmt * T)3598   static bool classof(const Stmt *T) {
3599     return T->getStmtClass() == OMPTeamsDirectiveClass;
3600   }
3601 };
3602 
3603 /// This represents '#pragma omp cancellation point' directive.
3604 ///
3605 /// \code
3606 /// #pragma omp cancellation point for
3607 /// \endcode
3608 ///
3609 /// In this example a cancellation point is created for innermost 'for' region.
3610 class OMPCancellationPointDirective : public OMPExecutableDirective {
3611   friend class ASTStmtReader;
3612   friend class OMPExecutableDirective;
3613   OpenMPDirectiveKind CancelRegion = llvm::omp::OMPD_unknown;
3614   /// Build directive with the given start and end location.
3615   ///
3616   /// \param StartLoc Starting location of the directive kind.
3617   /// \param EndLoc Ending location of the directive.
3618   /// statements and child expressions.
3619   ///
OMPCancellationPointDirective(SourceLocation StartLoc,SourceLocation EndLoc)3620   OMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3621       : OMPExecutableDirective(OMPCancellationPointDirectiveClass,
3622                                llvm::omp::OMPD_cancellation_point, StartLoc,
3623                                EndLoc) {}
3624 
3625   /// Build an empty directive.
OMPCancellationPointDirective()3626   explicit OMPCancellationPointDirective()
3627       : OMPExecutableDirective(OMPCancellationPointDirectiveClass,
3628                                llvm::omp::OMPD_cancellation_point,
3629                                SourceLocation(), SourceLocation()) {}
3630 
3631   /// Set cancel region for current cancellation point.
3632   /// \param CR Cancellation region.
setCancelRegion(OpenMPDirectiveKind CR)3633   void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
3634 
3635 public:
3636   /// Creates directive.
3637   ///
3638   /// \param C AST context.
3639   /// \param StartLoc Starting location of the directive kind.
3640   /// \param EndLoc Ending Location of the directive.
3641   ///
3642   static OMPCancellationPointDirective *
3643   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3644          OpenMPDirectiveKind CancelRegion);
3645 
3646   /// Creates an empty directive.
3647   ///
3648   /// \param C AST context.
3649   ///
3650   static OMPCancellationPointDirective *CreateEmpty(const ASTContext &C,
3651                                                     EmptyShell);
3652 
3653   /// Get cancellation region for the current cancellation point.
getCancelRegion()3654   OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
3655 
classof(const Stmt * T)3656   static bool classof(const Stmt *T) {
3657     return T->getStmtClass() == OMPCancellationPointDirectiveClass;
3658   }
3659 };
3660 
3661 /// This represents '#pragma omp cancel' directive.
3662 ///
3663 /// \code
3664 /// #pragma omp cancel for
3665 /// \endcode
3666 ///
3667 /// In this example a cancel is created for innermost 'for' region.
3668 class OMPCancelDirective : public OMPExecutableDirective {
3669   friend class ASTStmtReader;
3670   friend class OMPExecutableDirective;
3671   OpenMPDirectiveKind CancelRegion = llvm::omp::OMPD_unknown;
3672   /// Build directive with the given start and end location.
3673   ///
3674   /// \param StartLoc Starting location of the directive kind.
3675   /// \param EndLoc Ending location of the directive.
3676   ///
OMPCancelDirective(SourceLocation StartLoc,SourceLocation EndLoc)3677   OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3678       : OMPExecutableDirective(OMPCancelDirectiveClass, llvm::omp::OMPD_cancel,
3679                                StartLoc, EndLoc) {}
3680 
3681   /// Build an empty directive.
3682   ///
OMPCancelDirective()3683   explicit OMPCancelDirective()
3684       : OMPExecutableDirective(OMPCancelDirectiveClass, llvm::omp::OMPD_cancel,
3685                                SourceLocation(), SourceLocation()) {}
3686 
3687   /// Set cancel region for current cancellation point.
3688   /// \param CR Cancellation region.
setCancelRegion(OpenMPDirectiveKind CR)3689   void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
3690 
3691 public:
3692   /// Creates directive.
3693   ///
3694   /// \param C AST context.
3695   /// \param StartLoc Starting location of the directive kind.
3696   /// \param EndLoc Ending Location of the directive.
3697   /// \param Clauses List of clauses.
3698   ///
3699   static OMPCancelDirective *
3700   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3701          ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion);
3702 
3703   /// Creates an empty directive.
3704   ///
3705   /// \param C AST context.
3706   /// \param NumClauses Number of clauses.
3707   ///
3708   static OMPCancelDirective *CreateEmpty(const ASTContext &C,
3709                                          unsigned NumClauses, EmptyShell);
3710 
3711   /// Get cancellation region for the current cancellation point.
getCancelRegion()3712   OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
3713 
classof(const Stmt * T)3714   static bool classof(const Stmt *T) {
3715     return T->getStmtClass() == OMPCancelDirectiveClass;
3716   }
3717 };
3718 
3719 /// This represents '#pragma omp taskloop' directive.
3720 ///
3721 /// \code
3722 /// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num)
3723 /// \endcode
3724 /// In this example directive '#pragma omp taskloop' has clauses 'private'
3725 /// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
3726 /// 'num_tasks' with expression 'num'.
3727 ///
3728 class OMPTaskLoopDirective : public OMPLoopDirective {
3729   friend class ASTStmtReader;
3730   friend class OMPExecutableDirective;
3731   /// true if the construct has inner cancel directive.
3732   bool HasCancel = false;
3733 
3734   /// Build directive with the given start and end location.
3735   ///
3736   /// \param StartLoc Starting location of the directive kind.
3737   /// \param EndLoc Ending location of the directive.
3738   /// \param CollapsedNum Number of collapsed nested loops.
3739   ///
OMPTaskLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)3740   OMPTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3741                        unsigned CollapsedNum)
3742       : OMPLoopDirective(OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop,
3743                          StartLoc, EndLoc, CollapsedNum) {}
3744 
3745   /// Build an empty directive.
3746   ///
3747   /// \param CollapsedNum Number of collapsed nested loops.
3748   ///
OMPTaskLoopDirective(unsigned CollapsedNum)3749   explicit OMPTaskLoopDirective(unsigned CollapsedNum)
3750       : OMPLoopDirective(OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop,
3751                          SourceLocation(), SourceLocation(), CollapsedNum) {}
3752 
3753   /// Set cancel state.
setHasCancel(bool Has)3754   void setHasCancel(bool Has) { HasCancel = Has; }
3755 
3756 public:
3757   /// Creates directive with a list of \a Clauses.
3758   ///
3759   /// \param C AST context.
3760   /// \param StartLoc Starting location of the directive kind.
3761   /// \param EndLoc Ending Location of the directive.
3762   /// \param CollapsedNum Number of collapsed loops.
3763   /// \param Clauses List of clauses.
3764   /// \param AssociatedStmt Statement, associated with the directive.
3765   /// \param Exprs Helper expressions for CodeGen.
3766   /// \param HasCancel true if this directive has inner cancel directive.
3767   ///
3768   static OMPTaskLoopDirective *
3769   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3770          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3771          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
3772 
3773   /// Creates an empty directive with the place
3774   /// for \a NumClauses clauses.
3775   ///
3776   /// \param C AST context.
3777   /// \param CollapsedNum Number of collapsed nested loops.
3778   /// \param NumClauses Number of clauses.
3779   ///
3780   static OMPTaskLoopDirective *CreateEmpty(const ASTContext &C,
3781                                            unsigned NumClauses,
3782                                            unsigned CollapsedNum, EmptyShell);
3783 
3784   /// Return true if current directive has inner cancel directive.
hasCancel()3785   bool hasCancel() const { return HasCancel; }
3786 
classof(const Stmt * T)3787   static bool classof(const Stmt *T) {
3788     return T->getStmtClass() == OMPTaskLoopDirectiveClass;
3789   }
3790 };
3791 
3792 /// This represents '#pragma omp taskloop simd' directive.
3793 ///
3794 /// \code
3795 /// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num)
3796 /// \endcode
3797 /// In this example directive '#pragma omp taskloop simd' has clauses 'private'
3798 /// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
3799 /// 'num_tasks' with expression 'num'.
3800 ///
3801 class OMPTaskLoopSimdDirective : public OMPLoopDirective {
3802   friend class ASTStmtReader;
3803   friend class OMPExecutableDirective;
3804   /// Build directive with the given start and end location.
3805   ///
3806   /// \param StartLoc Starting location of the directive kind.
3807   /// \param EndLoc Ending location of the directive.
3808   /// \param CollapsedNum Number of collapsed nested loops.
3809   ///
OMPTaskLoopSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)3810   OMPTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3811                            unsigned CollapsedNum)
3812       : OMPLoopDirective(OMPTaskLoopSimdDirectiveClass,
3813                          llvm::omp::OMPD_taskloop_simd, StartLoc, EndLoc,
3814                          CollapsedNum) {}
3815 
3816   /// Build an empty directive.
3817   ///
3818   /// \param CollapsedNum Number of collapsed nested loops.
3819   ///
OMPTaskLoopSimdDirective(unsigned CollapsedNum)3820   explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum)
3821       : OMPLoopDirective(OMPTaskLoopSimdDirectiveClass,
3822                          llvm::omp::OMPD_taskloop_simd, SourceLocation(),
3823                          SourceLocation(), CollapsedNum) {}
3824 
3825 public:
3826   /// Creates directive with a list of \a Clauses.
3827   ///
3828   /// \param C AST context.
3829   /// \param StartLoc Starting location of the directive kind.
3830   /// \param EndLoc Ending Location of the directive.
3831   /// \param CollapsedNum Number of collapsed loops.
3832   /// \param Clauses List of clauses.
3833   /// \param AssociatedStmt Statement, associated with the directive.
3834   /// \param Exprs Helper expressions for CodeGen.
3835   ///
3836   static OMPTaskLoopSimdDirective *
3837   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3838          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3839          Stmt *AssociatedStmt, const HelperExprs &Exprs);
3840 
3841   /// Creates an empty directive with the place
3842   /// for \a NumClauses clauses.
3843   ///
3844   /// \param C AST context.
3845   /// \param CollapsedNum Number of collapsed nested loops.
3846   /// \param NumClauses Number of clauses.
3847   ///
3848   static OMPTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
3849                                                unsigned NumClauses,
3850                                                unsigned CollapsedNum,
3851                                                EmptyShell);
3852 
classof(const Stmt * T)3853   static bool classof(const Stmt *T) {
3854     return T->getStmtClass() == OMPTaskLoopSimdDirectiveClass;
3855   }
3856 };
3857 
3858 /// This represents '#pragma omp master taskloop' directive.
3859 ///
3860 /// \code
3861 /// #pragma omp master taskloop private(a,b) grainsize(val) num_tasks(num)
3862 /// \endcode
3863 /// In this example directive '#pragma omp master taskloop' has clauses
3864 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
3865 /// and 'num_tasks' with expression 'num'.
3866 ///
3867 class OMPMasterTaskLoopDirective : public OMPLoopDirective {
3868   friend class ASTStmtReader;
3869   friend class OMPExecutableDirective;
3870   /// true if the construct has inner cancel directive.
3871   bool HasCancel = false;
3872 
3873   /// Build directive with the given start and end location.
3874   ///
3875   /// \param StartLoc Starting location of the directive kind.
3876   /// \param EndLoc Ending location of the directive.
3877   /// \param CollapsedNum Number of collapsed nested loops.
3878   ///
OMPMasterTaskLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)3879   OMPMasterTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3880                              unsigned CollapsedNum)
3881       : OMPLoopDirective(OMPMasterTaskLoopDirectiveClass,
3882                          llvm::omp::OMPD_master_taskloop, StartLoc, EndLoc,
3883                          CollapsedNum) {}
3884 
3885   /// Build an empty directive.
3886   ///
3887   /// \param CollapsedNum Number of collapsed nested loops.
3888   ///
OMPMasterTaskLoopDirective(unsigned CollapsedNum)3889   explicit OMPMasterTaskLoopDirective(unsigned CollapsedNum)
3890       : OMPLoopDirective(OMPMasterTaskLoopDirectiveClass,
3891                          llvm::omp::OMPD_master_taskloop, SourceLocation(),
3892                          SourceLocation(), CollapsedNum) {}
3893 
3894   /// Set cancel state.
setHasCancel(bool Has)3895   void setHasCancel(bool Has) { HasCancel = Has; }
3896 
3897 public:
3898   /// Creates directive with a list of \a Clauses.
3899   ///
3900   /// \param C AST context.
3901   /// \param StartLoc Starting location of the directive kind.
3902   /// \param EndLoc Ending Location of the directive.
3903   /// \param CollapsedNum Number of collapsed loops.
3904   /// \param Clauses List of clauses.
3905   /// \param AssociatedStmt Statement, associated with the directive.
3906   /// \param Exprs Helper expressions for CodeGen.
3907   /// \param HasCancel true if this directive has inner cancel directive.
3908   ///
3909   static OMPMasterTaskLoopDirective *
3910   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3911          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3912          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
3913 
3914   /// Creates an empty directive with the place
3915   /// for \a NumClauses clauses.
3916   ///
3917   /// \param C AST context.
3918   /// \param CollapsedNum Number of collapsed nested loops.
3919   /// \param NumClauses Number of clauses.
3920   ///
3921   static OMPMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
3922                                                  unsigned NumClauses,
3923                                                  unsigned CollapsedNum,
3924                                                  EmptyShell);
3925 
3926   /// Return true if current directive has inner cancel directive.
hasCancel()3927   bool hasCancel() const { return HasCancel; }
3928 
classof(const Stmt * T)3929   static bool classof(const Stmt *T) {
3930     return T->getStmtClass() == OMPMasterTaskLoopDirectiveClass;
3931   }
3932 };
3933 
3934 /// This represents '#pragma omp masked taskloop' directive.
3935 ///
3936 /// \code
3937 /// #pragma omp masked taskloop private(a,b) grainsize(val) num_tasks(num)
3938 /// \endcode
3939 /// In this example directive '#pragma omp masked taskloop' has clauses
3940 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
3941 /// and 'num_tasks' with expression 'num'.
3942 ///
3943 class OMPMaskedTaskLoopDirective final : public OMPLoopDirective {
3944   friend class ASTStmtReader;
3945   friend class OMPExecutableDirective;
3946   /// true if the construct has inner cancel directive.
3947   bool HasCancel = false;
3948 
3949   /// Build directive with the given start and end location.
3950   ///
3951   /// \param StartLoc Starting location of the directive kind.
3952   /// \param EndLoc Ending location of the directive.
3953   /// \param CollapsedNum Number of collapsed nested loops.
3954   ///
OMPMaskedTaskLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)3955   OMPMaskedTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3956                              unsigned CollapsedNum)
3957       : OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass,
3958                          llvm::omp::OMPD_masked_taskloop, StartLoc, EndLoc,
3959                          CollapsedNum) {}
3960 
3961   /// Build an empty directive.
3962   ///
3963   /// \param CollapsedNum Number of collapsed nested loops.
3964   ///
OMPMaskedTaskLoopDirective(unsigned CollapsedNum)3965   explicit OMPMaskedTaskLoopDirective(unsigned CollapsedNum)
3966       : OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass,
3967                          llvm::omp::OMPD_masked_taskloop, SourceLocation(),
3968                          SourceLocation(), CollapsedNum) {}
3969 
3970   /// Set cancel state.
setHasCancel(bool Has)3971   void setHasCancel(bool Has) { HasCancel = Has; }
3972 
3973 public:
3974   /// Creates directive with a list of \a Clauses.
3975   ///
3976   /// \param C AST context.
3977   /// \param StartLoc Starting location of the directive kind.
3978   /// \param EndLoc Ending Location of the directive.
3979   /// \param CollapsedNum Number of collapsed loops.
3980   /// \param Clauses List of clauses.
3981   /// \param AssociatedStmt Statement, associated with the directive.
3982   /// \param Exprs Helper expressions for CodeGen.
3983   /// \param HasCancel true if this directive has inner cancel directive.
3984   ///
3985   static OMPMaskedTaskLoopDirective *
3986   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3987          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3988          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
3989 
3990   /// Creates an empty directive with the place
3991   /// for \a NumClauses clauses.
3992   ///
3993   /// \param C AST context.
3994   /// \param CollapsedNum Number of collapsed nested loops.
3995   /// \param NumClauses Number of clauses.
3996   ///
3997   static OMPMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C,
3998                                                  unsigned NumClauses,
3999                                                  unsigned CollapsedNum,
4000                                                  EmptyShell);
4001 
4002   /// Return true if current directive has inner cancel directive.
hasCancel()4003   bool hasCancel() const { return HasCancel; }
4004 
classof(const Stmt * T)4005   static bool classof(const Stmt *T) {
4006     return T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass;
4007   }
4008 };
4009 
4010 /// This represents '#pragma omp master taskloop simd' directive.
4011 ///
4012 /// \code
4013 /// #pragma omp master taskloop simd private(a,b) grainsize(val) num_tasks(num)
4014 /// \endcode
4015 /// In this example directive '#pragma omp master taskloop simd' has clauses
4016 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4017 /// and 'num_tasks' with expression 'num'.
4018 ///
4019 class OMPMasterTaskLoopSimdDirective : public OMPLoopDirective {
4020   friend class ASTStmtReader;
4021   friend class OMPExecutableDirective;
4022   /// Build directive with the given start and end location.
4023   ///
4024   /// \param StartLoc Starting location of the directive kind.
4025   /// \param EndLoc Ending location of the directive.
4026   /// \param CollapsedNum Number of collapsed nested loops.
4027   ///
OMPMasterTaskLoopSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4028   OMPMasterTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4029                                  unsigned CollapsedNum)
4030       : OMPLoopDirective(OMPMasterTaskLoopSimdDirectiveClass,
4031                          llvm::omp::OMPD_master_taskloop_simd, StartLoc, EndLoc,
4032                          CollapsedNum) {}
4033 
4034   /// Build an empty directive.
4035   ///
4036   /// \param CollapsedNum Number of collapsed nested loops.
4037   ///
OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum)4038   explicit OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum)
4039       : OMPLoopDirective(OMPMasterTaskLoopSimdDirectiveClass,
4040                          llvm::omp::OMPD_master_taskloop_simd, SourceLocation(),
4041                          SourceLocation(), CollapsedNum) {}
4042 
4043 public:
4044   /// Creates directive with a list of \p Clauses.
4045   ///
4046   /// \param C AST context.
4047   /// \param StartLoc Starting location of the directive kind.
4048   /// \param EndLoc Ending Location of the directive.
4049   /// \param CollapsedNum Number of collapsed loops.
4050   /// \param Clauses List of clauses.
4051   /// \param AssociatedStmt Statement, associated with the directive.
4052   /// \param Exprs Helper expressions for CodeGen.
4053   ///
4054   static OMPMasterTaskLoopSimdDirective *
4055   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4056          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4057          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4058 
4059   /// Creates an empty directive with the place for \p NumClauses clauses.
4060   ///
4061   /// \param C AST context.
4062   /// \param CollapsedNum Number of collapsed nested loops.
4063   /// \param NumClauses Number of clauses.
4064   ///
4065   static OMPMasterTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
4066                                                      unsigned NumClauses,
4067                                                      unsigned CollapsedNum,
4068                                                      EmptyShell);
4069 
classof(const Stmt * T)4070   static bool classof(const Stmt *T) {
4071     return T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass;
4072   }
4073 };
4074 
4075 /// This represents '#pragma omp masked taskloop simd' directive.
4076 ///
4077 /// \code
4078 /// #pragma omp masked taskloop simd private(a,b) grainsize(val) num_tasks(num)
4079 /// \endcode
4080 /// In this example directive '#pragma omp masked taskloop simd' has clauses
4081 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4082 /// and 'num_tasks' with expression 'num'.
4083 ///
4084 class OMPMaskedTaskLoopSimdDirective final : public OMPLoopDirective {
4085   friend class ASTStmtReader;
4086   friend class OMPExecutableDirective;
4087   /// Build directive with the given start and end location.
4088   ///
4089   /// \param StartLoc Starting location of the directive kind.
4090   /// \param EndLoc Ending location of the directive.
4091   /// \param CollapsedNum Number of collapsed nested loops.
4092   ///
OMPMaskedTaskLoopSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4093   OMPMaskedTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4094                                  unsigned CollapsedNum)
4095       : OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass,
4096                          llvm::omp::OMPD_masked_taskloop_simd, StartLoc, EndLoc,
4097                          CollapsedNum) {}
4098 
4099   /// Build an empty directive.
4100   ///
4101   /// \param CollapsedNum Number of collapsed nested loops.
4102   ///
OMPMaskedTaskLoopSimdDirective(unsigned CollapsedNum)4103   explicit OMPMaskedTaskLoopSimdDirective(unsigned CollapsedNum)
4104       : OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass,
4105                          llvm::omp::OMPD_masked_taskloop_simd, SourceLocation(),
4106                          SourceLocation(), CollapsedNum) {}
4107 
4108 public:
4109   /// Creates directive with a list of \p Clauses.
4110   ///
4111   /// \param C AST context.
4112   /// \param StartLoc Starting location of the directive kind.
4113   /// \param EndLoc Ending Location of the directive.
4114   /// \param CollapsedNum Number of collapsed loops.
4115   /// \param Clauses List of clauses.
4116   /// \param AssociatedStmt Statement, associated with the directive.
4117   /// \param Exprs Helper expressions for CodeGen.
4118   ///
4119   static OMPMaskedTaskLoopSimdDirective *
4120   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4121          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4122          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4123 
4124   /// Creates an empty directive with the place for \p NumClauses clauses.
4125   ///
4126   /// \param C AST context.
4127   /// \param CollapsedNum Number of collapsed nested loops.
4128   /// \param NumClauses Number of clauses.
4129   ///
4130   static OMPMaskedTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
4131                                                      unsigned NumClauses,
4132                                                      unsigned CollapsedNum,
4133                                                      EmptyShell);
4134 
classof(const Stmt * T)4135   static bool classof(const Stmt *T) {
4136     return T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass;
4137   }
4138 };
4139 
4140 /// This represents '#pragma omp parallel master taskloop' directive.
4141 ///
4142 /// \code
4143 /// #pragma omp parallel master taskloop private(a,b) grainsize(val)
4144 /// num_tasks(num)
4145 /// \endcode
4146 /// In this example directive '#pragma omp parallel master taskloop' has clauses
4147 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4148 /// and 'num_tasks' with expression 'num'.
4149 ///
4150 class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
4151   friend class ASTStmtReader;
4152   friend class OMPExecutableDirective;
4153   /// true if the construct has inner cancel directive.
4154   bool HasCancel = false;
4155 
4156   /// Build directive with the given start and end location.
4157   ///
4158   /// \param StartLoc Starting location of the directive kind.
4159   /// \param EndLoc Ending location of the directive.
4160   /// \param CollapsedNum Number of collapsed nested loops.
4161   ///
OMPParallelMasterTaskLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4162   OMPParallelMasterTaskLoopDirective(SourceLocation StartLoc,
4163                                      SourceLocation EndLoc,
4164                                      unsigned CollapsedNum)
4165       : OMPLoopDirective(OMPParallelMasterTaskLoopDirectiveClass,
4166                          llvm::omp::OMPD_parallel_master_taskloop, StartLoc,
4167                          EndLoc, CollapsedNum) {}
4168 
4169   /// Build an empty directive.
4170   ///
4171   /// \param CollapsedNum Number of collapsed nested loops.
4172   ///
OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum)4173   explicit OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum)
4174       : OMPLoopDirective(OMPParallelMasterTaskLoopDirectiveClass,
4175                          llvm::omp::OMPD_parallel_master_taskloop,
4176                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4177 
4178   /// Set cancel state.
setHasCancel(bool Has)4179   void setHasCancel(bool Has) { HasCancel = Has; }
4180 
4181 public:
4182   /// Creates directive with a list of \a Clauses.
4183   ///
4184   /// \param C AST context.
4185   /// \param StartLoc Starting location of the directive kind.
4186   /// \param EndLoc Ending Location of the directive.
4187   /// \param CollapsedNum Number of collapsed loops.
4188   /// \param Clauses List of clauses.
4189   /// \param AssociatedStmt Statement, associated with the directive.
4190   /// \param Exprs Helper expressions for CodeGen.
4191   /// \param HasCancel true if this directive has inner cancel directive.
4192   ///
4193   static OMPParallelMasterTaskLoopDirective *
4194   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4195          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4196          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
4197 
4198   /// Creates an empty directive with the place
4199   /// for \a NumClauses clauses.
4200   ///
4201   /// \param C AST context.
4202   /// \param CollapsedNum Number of collapsed nested loops.
4203   /// \param NumClauses Number of clauses.
4204   ///
4205   static OMPParallelMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
4206                                                          unsigned NumClauses,
4207                                                          unsigned CollapsedNum,
4208                                                          EmptyShell);
4209 
4210   /// Return true if current directive has inner cancel directive.
hasCancel()4211   bool hasCancel() const { return HasCancel; }
4212 
classof(const Stmt * T)4213   static bool classof(const Stmt *T) {
4214     return T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass;
4215   }
4216 };
4217 
4218 /// This represents '#pragma omp parallel masked taskloop' directive.
4219 ///
4220 /// \code
4221 /// #pragma omp parallel masked taskloop private(a,b) grainsize(val)
4222 /// num_tasks(num)
4223 /// \endcode
4224 /// In this example directive '#pragma omp parallel masked taskloop' has clauses
4225 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4226 /// and 'num_tasks' with expression 'num'.
4227 ///
4228 class OMPParallelMaskedTaskLoopDirective final : public OMPLoopDirective {
4229   friend class ASTStmtReader;
4230   friend class OMPExecutableDirective;
4231   /// true if the construct has inner cancel directive.
4232   bool HasCancel = false;
4233 
4234   /// Build directive with the given start and end location.
4235   ///
4236   /// \param StartLoc Starting location of the directive kind.
4237   /// \param EndLoc Ending location of the directive.
4238   /// \param CollapsedNum Number of collapsed nested loops.
4239   ///
OMPParallelMaskedTaskLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4240   OMPParallelMaskedTaskLoopDirective(SourceLocation StartLoc,
4241                                      SourceLocation EndLoc,
4242                                      unsigned CollapsedNum)
4243       : OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass,
4244                          llvm::omp::OMPD_parallel_masked_taskloop, StartLoc,
4245                          EndLoc, CollapsedNum) {}
4246 
4247   /// Build an empty directive.
4248   ///
4249   /// \param CollapsedNum Number of collapsed nested loops.
4250   ///
OMPParallelMaskedTaskLoopDirective(unsigned CollapsedNum)4251   explicit OMPParallelMaskedTaskLoopDirective(unsigned CollapsedNum)
4252       : OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass,
4253                          llvm::omp::OMPD_parallel_masked_taskloop,
4254                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4255 
4256   /// Set cancel state.
setHasCancel(bool Has)4257   void setHasCancel(bool Has) { HasCancel = Has; }
4258 
4259 public:
4260   /// Creates directive with a list of \a Clauses.
4261   ///
4262   /// \param C AST context.
4263   /// \param StartLoc Starting location of the directive kind.
4264   /// \param EndLoc Ending Location of the directive.
4265   /// \param CollapsedNum Number of collapsed loops.
4266   /// \param Clauses List of clauses.
4267   /// \param AssociatedStmt Statement, associated with the directive.
4268   /// \param Exprs Helper expressions for CodeGen.
4269   /// \param HasCancel true if this directive has inner cancel directive.
4270   ///
4271   static OMPParallelMaskedTaskLoopDirective *
4272   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4273          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4274          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
4275 
4276   /// Creates an empty directive with the place
4277   /// for \a NumClauses clauses.
4278   ///
4279   /// \param C AST context.
4280   /// \param CollapsedNum Number of collapsed nested loops.
4281   /// \param NumClauses Number of clauses.
4282   ///
4283   static OMPParallelMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C,
4284                                                          unsigned NumClauses,
4285                                                          unsigned CollapsedNum,
4286                                                          EmptyShell);
4287 
4288   /// Return true if current directive has inner cancel directive.
hasCancel()4289   bool hasCancel() const { return HasCancel; }
4290 
classof(const Stmt * T)4291   static bool classof(const Stmt *T) {
4292     return T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass;
4293   }
4294 };
4295 
4296 /// This represents '#pragma omp parallel master taskloop simd' directive.
4297 ///
4298 /// \code
4299 /// #pragma omp parallel master taskloop simd private(a,b) grainsize(val)
4300 /// num_tasks(num)
4301 /// \endcode
4302 /// In this example directive '#pragma omp parallel master taskloop simd' has
4303 /// clauses 'private' with the variables 'a' and 'b', 'grainsize' with
4304 /// expression 'val' and 'num_tasks' with expression 'num'.
4305 ///
4306 class OMPParallelMasterTaskLoopSimdDirective : public OMPLoopDirective {
4307   friend class ASTStmtReader;
4308   friend class OMPExecutableDirective;
4309   /// Build directive with the given start and end location.
4310   ///
4311   /// \param StartLoc Starting location of the directive kind.
4312   /// \param EndLoc Ending location of the directive.
4313   /// \param CollapsedNum Number of collapsed nested loops.
4314   ///
OMPParallelMasterTaskLoopSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4315   OMPParallelMasterTaskLoopSimdDirective(SourceLocation StartLoc,
4316                                          SourceLocation EndLoc,
4317                                          unsigned CollapsedNum)
4318       : OMPLoopDirective(OMPParallelMasterTaskLoopSimdDirectiveClass,
4319                          llvm::omp::OMPD_parallel_master_taskloop_simd,
4320                          StartLoc, EndLoc, CollapsedNum) {}
4321 
4322   /// Build an empty directive.
4323   ///
4324   /// \param CollapsedNum Number of collapsed nested loops.
4325   ///
OMPParallelMasterTaskLoopSimdDirective(unsigned CollapsedNum)4326   explicit OMPParallelMasterTaskLoopSimdDirective(unsigned CollapsedNum)
4327       : OMPLoopDirective(OMPParallelMasterTaskLoopSimdDirectiveClass,
4328                          llvm::omp::OMPD_parallel_master_taskloop_simd,
4329                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4330 
4331 public:
4332   /// Creates directive with a list of \p Clauses.
4333   ///
4334   /// \param C AST context.
4335   /// \param StartLoc Starting location of the directive kind.
4336   /// \param EndLoc Ending Location of the directive.
4337   /// \param CollapsedNum Number of collapsed loops.
4338   /// \param Clauses List of clauses.
4339   /// \param AssociatedStmt Statement, associated with the directive.
4340   /// \param Exprs Helper expressions for CodeGen.
4341   ///
4342   static OMPParallelMasterTaskLoopSimdDirective *
4343   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4344          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4345          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4346 
4347   /// Creates an empty directive with the place
4348   /// for \a NumClauses clauses.
4349   ///
4350   /// \param C AST context.
4351   /// \param CollapsedNum Number of collapsed nested loops.
4352   /// \param NumClauses Number of clauses.
4353   ///
4354   static OMPParallelMasterTaskLoopSimdDirective *
4355   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
4356               EmptyShell);
4357 
classof(const Stmt * T)4358   static bool classof(const Stmt *T) {
4359     return T->getStmtClass() == OMPParallelMasterTaskLoopSimdDirectiveClass;
4360   }
4361 };
4362 
4363 /// This represents '#pragma omp parallel masked taskloop simd' directive.
4364 ///
4365 /// \code
4366 /// #pragma omp parallel masked taskloop simd private(a,b) grainsize(val)
4367 /// num_tasks(num)
4368 /// \endcode
4369 /// In this example directive '#pragma omp parallel masked taskloop simd' has
4370 /// clauses 'private' with the variables 'a' and 'b', 'grainsize' with
4371 /// expression 'val' and 'num_tasks' with expression 'num'.
4372 ///
4373 class OMPParallelMaskedTaskLoopSimdDirective final : public OMPLoopDirective {
4374   friend class ASTStmtReader;
4375   friend class OMPExecutableDirective;
4376   /// Build directive with the given start and end location.
4377   ///
4378   /// \param StartLoc Starting location of the directive kind.
4379   /// \param EndLoc Ending location of the directive.
4380   /// \param CollapsedNum Number of collapsed nested loops.
4381   ///
OMPParallelMaskedTaskLoopSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4382   OMPParallelMaskedTaskLoopSimdDirective(SourceLocation StartLoc,
4383                                          SourceLocation EndLoc,
4384                                          unsigned CollapsedNum)
4385       : OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass,
4386                          llvm::omp::OMPD_parallel_masked_taskloop_simd,
4387                          StartLoc, EndLoc, CollapsedNum) {}
4388 
4389   /// Build an empty directive.
4390   ///
4391   /// \param CollapsedNum Number of collapsed nested loops.
4392   ///
OMPParallelMaskedTaskLoopSimdDirective(unsigned CollapsedNum)4393   explicit OMPParallelMaskedTaskLoopSimdDirective(unsigned CollapsedNum)
4394       : OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass,
4395                          llvm::omp::OMPD_parallel_masked_taskloop_simd,
4396                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4397 
4398 public:
4399   /// Creates directive with a list of \p Clauses.
4400   ///
4401   /// \param C AST context.
4402   /// \param StartLoc Starting location of the directive kind.
4403   /// \param EndLoc Ending Location of the directive.
4404   /// \param CollapsedNum Number of collapsed loops.
4405   /// \param Clauses List of clauses.
4406   /// \param AssociatedStmt Statement, associated with the directive.
4407   /// \param Exprs Helper expressions for CodeGen.
4408   ///
4409   static OMPParallelMaskedTaskLoopSimdDirective *
4410   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4411          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4412          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4413 
4414   /// Creates an empty directive with the place
4415   /// for \a NumClauses clauses.
4416   ///
4417   /// \param C AST context.
4418   /// \param CollapsedNum Number of collapsed nested loops.
4419   /// \param NumClauses Number of clauses.
4420   ///
4421   static OMPParallelMaskedTaskLoopSimdDirective *
4422   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
4423               EmptyShell);
4424 
classof(const Stmt * T)4425   static bool classof(const Stmt *T) {
4426     return T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass;
4427   }
4428 };
4429 
4430 /// This represents '#pragma omp distribute' directive.
4431 ///
4432 /// \code
4433 /// #pragma omp distribute private(a,b)
4434 /// \endcode
4435 /// In this example directive '#pragma omp distribute' has clauses 'private'
4436 /// with the variables 'a' and 'b'
4437 ///
4438 class OMPDistributeDirective : public OMPLoopDirective {
4439   friend class ASTStmtReader;
4440   friend class OMPExecutableDirective;
4441 
4442   /// Build directive with the given start and end location.
4443   ///
4444   /// \param StartLoc Starting location of the directive kind.
4445   /// \param EndLoc Ending location of the directive.
4446   /// \param CollapsedNum Number of collapsed nested loops.
4447   ///
OMPDistributeDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4448   OMPDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4449                          unsigned CollapsedNum)
4450       : OMPLoopDirective(OMPDistributeDirectiveClass,
4451                          llvm::omp::OMPD_distribute, StartLoc, EndLoc,
4452                          CollapsedNum) {}
4453 
4454   /// Build an empty directive.
4455   ///
4456   /// \param CollapsedNum Number of collapsed nested loops.
4457   ///
OMPDistributeDirective(unsigned CollapsedNum)4458   explicit OMPDistributeDirective(unsigned CollapsedNum)
4459       : OMPLoopDirective(OMPDistributeDirectiveClass,
4460                          llvm::omp::OMPD_distribute, SourceLocation(),
4461                          SourceLocation(), CollapsedNum) {}
4462 
4463 public:
4464   /// Creates directive with a list of \a Clauses.
4465   ///
4466   /// \param C AST context.
4467   /// \param StartLoc Starting location of the directive kind.
4468   /// \param EndLoc Ending Location of the directive.
4469   /// \param CollapsedNum Number of collapsed loops.
4470   /// \param Clauses List of clauses.
4471   /// \param AssociatedStmt Statement, associated with the directive.
4472   /// \param Exprs Helper expressions for CodeGen.
4473   ///
4474   static OMPDistributeDirective *
4475   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4476          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4477          Stmt *AssociatedStmt, const HelperExprs &Exprs,
4478          OpenMPDirectiveKind ParamPrevMappedDirective);
4479 
4480   /// Creates an empty directive with the place
4481   /// for \a NumClauses clauses.
4482   ///
4483   /// \param C AST context.
4484   /// \param CollapsedNum Number of collapsed nested loops.
4485   /// \param NumClauses Number of clauses.
4486   ///
4487   static OMPDistributeDirective *CreateEmpty(const ASTContext &C,
4488                                              unsigned NumClauses,
4489                                              unsigned CollapsedNum, EmptyShell);
4490 
classof(const Stmt * T)4491   static bool classof(const Stmt *T) {
4492     return T->getStmtClass() == OMPDistributeDirectiveClass;
4493   }
4494 };
4495 
4496 /// This represents '#pragma omp target update' directive.
4497 ///
4498 /// \code
4499 /// #pragma omp target update to(a) from(b) device(1)
4500 /// \endcode
4501 /// In this example directive '#pragma omp target update' has clause 'to' with
4502 /// argument 'a', clause 'from' with argument 'b' and clause 'device' with
4503 /// argument '1'.
4504 ///
4505 class OMPTargetUpdateDirective : public OMPExecutableDirective {
4506   friend class ASTStmtReader;
4507   friend class OMPExecutableDirective;
4508   /// Build directive with the given start and end location.
4509   ///
4510   /// \param StartLoc Starting location of the directive kind.
4511   /// \param EndLoc Ending Location of the directive.
4512   ///
OMPTargetUpdateDirective(SourceLocation StartLoc,SourceLocation EndLoc)4513   OMPTargetUpdateDirective(SourceLocation StartLoc, SourceLocation EndLoc)
4514       : OMPExecutableDirective(OMPTargetUpdateDirectiveClass,
4515                                llvm::omp::OMPD_target_update, StartLoc,
4516                                EndLoc) {}
4517 
4518   /// Build an empty directive.
4519   ///
OMPTargetUpdateDirective()4520   explicit OMPTargetUpdateDirective()
4521       : OMPExecutableDirective(OMPTargetUpdateDirectiveClass,
4522                                llvm::omp::OMPD_target_update, SourceLocation(),
4523                                SourceLocation()) {}
4524 
4525 public:
4526   /// Creates directive with a list of \a Clauses.
4527   ///
4528   /// \param C AST context.
4529   /// \param StartLoc Starting location of the directive kind.
4530   /// \param EndLoc Ending Location of the directive.
4531   /// \param Clauses List of clauses.
4532   /// \param AssociatedStmt Statement, associated with the directive.
4533   ///
4534   static OMPTargetUpdateDirective *
4535   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4536          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
4537 
4538   /// Creates an empty directive with the place for \a NumClauses
4539   /// clauses.
4540   ///
4541   /// \param C AST context.
4542   /// \param NumClauses The number of clauses.
4543   ///
4544   static OMPTargetUpdateDirective *CreateEmpty(const ASTContext &C,
4545                                                unsigned NumClauses, EmptyShell);
4546 
classof(const Stmt * T)4547   static bool classof(const Stmt *T) {
4548     return T->getStmtClass() == OMPTargetUpdateDirectiveClass;
4549   }
4550 };
4551 
4552 /// This represents '#pragma omp distribute parallel for' composite
4553 ///  directive.
4554 ///
4555 /// \code
4556 /// #pragma omp distribute parallel for private(a,b)
4557 /// \endcode
4558 /// In this example directive '#pragma omp distribute parallel for' has clause
4559 /// 'private' with the variables 'a' and 'b'
4560 ///
4561 class OMPDistributeParallelForDirective : public OMPLoopDirective {
4562   friend class ASTStmtReader;
4563   friend class OMPExecutableDirective;
4564   /// true if the construct has inner cancel directive.
4565   bool HasCancel = false;
4566 
4567   /// Build directive with the given start and end location.
4568   ///
4569   /// \param StartLoc Starting location of the directive kind.
4570   /// \param EndLoc Ending location of the directive.
4571   /// \param CollapsedNum Number of collapsed nested loops.
4572   ///
OMPDistributeParallelForDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4573   OMPDistributeParallelForDirective(SourceLocation StartLoc,
4574                                     SourceLocation EndLoc,
4575                                     unsigned CollapsedNum)
4576       : OMPLoopDirective(OMPDistributeParallelForDirectiveClass,
4577                          llvm::omp::OMPD_distribute_parallel_for, StartLoc,
4578                          EndLoc, CollapsedNum) {}
4579 
4580   /// Build an empty directive.
4581   ///
4582   /// \param CollapsedNum Number of collapsed nested loops.
4583   ///
OMPDistributeParallelForDirective(unsigned CollapsedNum)4584   explicit OMPDistributeParallelForDirective(unsigned CollapsedNum)
4585       : OMPLoopDirective(OMPDistributeParallelForDirectiveClass,
4586                          llvm::omp::OMPD_distribute_parallel_for,
4587                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4588 
4589   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)4590   void setTaskReductionRefExpr(Expr *E) {
4591     Data->getChildren()[numLoopChildren(
4592         getLoopsNumber(), llvm::omp::OMPD_distribute_parallel_for)] = E;
4593   }
4594 
4595   /// Set cancel state.
setHasCancel(bool Has)4596   void setHasCancel(bool Has) { HasCancel = Has; }
4597 
4598 public:
4599   /// Creates directive with a list of \a Clauses.
4600   ///
4601   /// \param C AST context.
4602   /// \param StartLoc Starting location of the directive kind.
4603   /// \param EndLoc Ending Location of the directive.
4604   /// \param CollapsedNum Number of collapsed loops.
4605   /// \param Clauses List of clauses.
4606   /// \param AssociatedStmt Statement, associated with the directive.
4607   /// \param Exprs Helper expressions for CodeGen.
4608   /// \param TaskRedRef Task reduction special reference expression to handle
4609   /// taskgroup descriptor.
4610   /// \param HasCancel true if this directive has inner cancel directive.
4611   ///
4612   static OMPDistributeParallelForDirective *
4613   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4614          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4615          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
4616          bool HasCancel);
4617 
4618   /// Creates an empty directive with the place
4619   /// for \a NumClauses clauses.
4620   ///
4621   /// \param C AST context.
4622   /// \param CollapsedNum Number of collapsed nested loops.
4623   /// \param NumClauses Number of clauses.
4624   ///
4625   static OMPDistributeParallelForDirective *CreateEmpty(const ASTContext &C,
4626                                                         unsigned NumClauses,
4627                                                         unsigned CollapsedNum,
4628                                                         EmptyShell);
4629 
4630   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()4631   Expr *getTaskReductionRefExpr() {
4632     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
4633         getLoopsNumber(), llvm::omp::OMPD_distribute_parallel_for)]);
4634   }
getTaskReductionRefExpr()4635   const Expr *getTaskReductionRefExpr() const {
4636     return const_cast<OMPDistributeParallelForDirective *>(this)
4637         ->getTaskReductionRefExpr();
4638   }
4639 
4640   /// Return true if current directive has inner cancel directive.
hasCancel()4641   bool hasCancel() const { return HasCancel; }
4642 
classof(const Stmt * T)4643   static bool classof(const Stmt *T) {
4644     return T->getStmtClass() == OMPDistributeParallelForDirectiveClass;
4645   }
4646 };
4647 
4648 /// This represents '#pragma omp distribute parallel for simd' composite
4649 /// directive.
4650 ///
4651 /// \code
4652 /// #pragma omp distribute parallel for simd private(x)
4653 /// \endcode
4654 /// In this example directive '#pragma omp distribute parallel for simd' has
4655 /// clause 'private' with the variables 'x'
4656 ///
4657 class OMPDistributeParallelForSimdDirective final : public OMPLoopDirective {
4658   friend class ASTStmtReader;
4659   friend class OMPExecutableDirective;
4660 
4661   /// Build directive with the given start and end location.
4662   ///
4663   /// \param StartLoc Starting location of the directive kind.
4664   /// \param EndLoc Ending location of the directive.
4665   /// \param CollapsedNum Number of collapsed nested loops.
4666   ///
OMPDistributeParallelForSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4667   OMPDistributeParallelForSimdDirective(SourceLocation StartLoc,
4668                                         SourceLocation EndLoc,
4669                                         unsigned CollapsedNum)
4670       : OMPLoopDirective(OMPDistributeParallelForSimdDirectiveClass,
4671                          llvm::omp::OMPD_distribute_parallel_for_simd, StartLoc,
4672                          EndLoc, CollapsedNum) {}
4673 
4674   /// Build an empty directive.
4675   ///
4676   /// \param CollapsedNum Number of collapsed nested loops.
4677   ///
OMPDistributeParallelForSimdDirective(unsigned CollapsedNum)4678   explicit OMPDistributeParallelForSimdDirective(unsigned CollapsedNum)
4679       : OMPLoopDirective(OMPDistributeParallelForSimdDirectiveClass,
4680                          llvm::omp::OMPD_distribute_parallel_for_simd,
4681                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4682 
4683 public:
4684   /// Creates directive with a list of \a Clauses.
4685   ///
4686   /// \param C AST context.
4687   /// \param StartLoc Starting location of the directive kind.
4688   /// \param EndLoc Ending Location of the directive.
4689   /// \param CollapsedNum Number of collapsed loops.
4690   /// \param Clauses List of clauses.
4691   /// \param AssociatedStmt Statement, associated with the directive.
4692   /// \param Exprs Helper expressions for CodeGen.
4693   ///
4694   static OMPDistributeParallelForSimdDirective *Create(
4695       const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4696       unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4697       Stmt *AssociatedStmt, const HelperExprs &Exprs);
4698 
4699   /// Creates an empty directive with the place for \a NumClauses clauses.
4700   ///
4701   /// \param C AST context.
4702   /// \param CollapsedNum Number of collapsed nested loops.
4703   /// \param NumClauses Number of clauses.
4704   ///
4705   static OMPDistributeParallelForSimdDirective *CreateEmpty(
4706       const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
4707       EmptyShell);
4708 
classof(const Stmt * T)4709   static bool classof(const Stmt *T) {
4710     return T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass;
4711   }
4712 };
4713 
4714 /// This represents '#pragma omp distribute simd' composite directive.
4715 ///
4716 /// \code
4717 /// #pragma omp distribute simd private(x)
4718 /// \endcode
4719 /// In this example directive '#pragma omp distribute simd' has clause
4720 /// 'private' with the variables 'x'
4721 ///
4722 class OMPDistributeSimdDirective final : public OMPLoopDirective {
4723   friend class ASTStmtReader;
4724   friend class OMPExecutableDirective;
4725 
4726   /// Build directive with the given start and end location.
4727   ///
4728   /// \param StartLoc Starting location of the directive kind.
4729   /// \param EndLoc Ending location of the directive.
4730   /// \param CollapsedNum Number of collapsed nested loops.
4731   ///
OMPDistributeSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4732   OMPDistributeSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4733                              unsigned CollapsedNum)
4734       : OMPLoopDirective(OMPDistributeSimdDirectiveClass,
4735                          llvm::omp::OMPD_distribute_simd, StartLoc, EndLoc,
4736                          CollapsedNum) {}
4737 
4738   /// Build an empty directive.
4739   ///
4740   /// \param CollapsedNum Number of collapsed nested loops.
4741   ///
OMPDistributeSimdDirective(unsigned CollapsedNum)4742   explicit OMPDistributeSimdDirective(unsigned CollapsedNum)
4743       : OMPLoopDirective(OMPDistributeSimdDirectiveClass,
4744                          llvm::omp::OMPD_distribute_simd, SourceLocation(),
4745                          SourceLocation(), CollapsedNum) {}
4746 
4747 public:
4748   /// Creates directive with a list of \a Clauses.
4749   ///
4750   /// \param C AST context.
4751   /// \param StartLoc Starting location of the directive kind.
4752   /// \param EndLoc Ending Location of the directive.
4753   /// \param CollapsedNum Number of collapsed loops.
4754   /// \param Clauses List of clauses.
4755   /// \param AssociatedStmt Statement, associated with the directive.
4756   /// \param Exprs Helper expressions for CodeGen.
4757   ///
4758   static OMPDistributeSimdDirective *
4759   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4760          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4761          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4762 
4763   /// Creates an empty directive with the place for \a NumClauses clauses.
4764   ///
4765   /// \param C AST context.
4766   /// \param CollapsedNum Number of collapsed nested loops.
4767   /// \param NumClauses Number of clauses.
4768   ///
4769   static OMPDistributeSimdDirective *CreateEmpty(const ASTContext &C,
4770                                                  unsigned NumClauses,
4771                                                  unsigned CollapsedNum,
4772                                                  EmptyShell);
4773 
classof(const Stmt * T)4774   static bool classof(const Stmt *T) {
4775     return T->getStmtClass() == OMPDistributeSimdDirectiveClass;
4776   }
4777 };
4778 
4779 /// This represents '#pragma omp target parallel for simd' directive.
4780 ///
4781 /// \code
4782 /// #pragma omp target parallel for simd private(a) map(b) safelen(c)
4783 /// \endcode
4784 /// In this example directive '#pragma omp target parallel for simd' has clauses
4785 /// 'private' with the variable 'a', 'map' with the variable 'b' and 'safelen'
4786 /// with the variable 'c'.
4787 ///
4788 class OMPTargetParallelForSimdDirective final : public OMPLoopDirective {
4789   friend class ASTStmtReader;
4790   friend class OMPExecutableDirective;
4791 
4792   /// Build directive with the given start and end location.
4793   ///
4794   /// \param StartLoc Starting location of the directive kind.
4795   /// \param EndLoc Ending location of the directive.
4796   /// \param CollapsedNum Number of collapsed nested loops.
4797   ///
OMPTargetParallelForSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4798   OMPTargetParallelForSimdDirective(SourceLocation StartLoc,
4799                                     SourceLocation EndLoc,
4800                                     unsigned CollapsedNum)
4801       : OMPLoopDirective(OMPTargetParallelForSimdDirectiveClass,
4802                          llvm::omp::OMPD_target_parallel_for_simd, StartLoc,
4803                          EndLoc, CollapsedNum) {}
4804 
4805   /// Build an empty directive.
4806   ///
4807   /// \param CollapsedNum Number of collapsed nested loops.
4808   ///
OMPTargetParallelForSimdDirective(unsigned CollapsedNum)4809   explicit OMPTargetParallelForSimdDirective(unsigned CollapsedNum)
4810       : OMPLoopDirective(OMPTargetParallelForSimdDirectiveClass,
4811                          llvm::omp::OMPD_target_parallel_for_simd,
4812                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4813 
4814 public:
4815   /// Creates directive with a list of \a Clauses.
4816   ///
4817   /// \param C AST context.
4818   /// \param StartLoc Starting location of the directive kind.
4819   /// \param EndLoc Ending Location of the directive.
4820   /// \param CollapsedNum Number of collapsed loops.
4821   /// \param Clauses List of clauses.
4822   /// \param AssociatedStmt Statement, associated with the directive.
4823   /// \param Exprs Helper expressions for CodeGen.
4824   ///
4825   static OMPTargetParallelForSimdDirective *
4826   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4827          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4828          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4829 
4830   /// Creates an empty directive with the place for \a NumClauses clauses.
4831   ///
4832   /// \param C AST context.
4833   /// \param CollapsedNum Number of collapsed nested loops.
4834   /// \param NumClauses Number of clauses.
4835   ///
4836   static OMPTargetParallelForSimdDirective *CreateEmpty(const ASTContext &C,
4837                                                         unsigned NumClauses,
4838                                                         unsigned CollapsedNum,
4839                                                         EmptyShell);
4840 
classof(const Stmt * T)4841   static bool classof(const Stmt *T) {
4842     return T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass;
4843   }
4844 };
4845 
4846 /// This represents '#pragma omp target simd' directive.
4847 ///
4848 /// \code
4849 /// #pragma omp target simd private(a) map(b) safelen(c)
4850 /// \endcode
4851 /// In this example directive '#pragma omp target simd' has clauses 'private'
4852 /// with the variable 'a', 'map' with the variable 'b' and 'safelen' with
4853 /// the variable 'c'.
4854 ///
4855 class OMPTargetSimdDirective final : public OMPLoopDirective {
4856   friend class ASTStmtReader;
4857   friend class OMPExecutableDirective;
4858 
4859   /// Build directive with the given start and end location.
4860   ///
4861   /// \param StartLoc Starting location of the directive kind.
4862   /// \param EndLoc Ending location of the directive.
4863   /// \param CollapsedNum Number of collapsed nested loops.
4864   ///
OMPTargetSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4865   OMPTargetSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4866                          unsigned CollapsedNum)
4867       : OMPLoopDirective(OMPTargetSimdDirectiveClass,
4868                          llvm::omp::OMPD_target_simd, StartLoc, EndLoc,
4869                          CollapsedNum) {}
4870 
4871   /// Build an empty directive.
4872   ///
4873   /// \param CollapsedNum Number of collapsed nested loops.
4874   ///
OMPTargetSimdDirective(unsigned CollapsedNum)4875   explicit OMPTargetSimdDirective(unsigned CollapsedNum)
4876       : OMPLoopDirective(OMPTargetSimdDirectiveClass,
4877                          llvm::omp::OMPD_target_simd, SourceLocation(),
4878                          SourceLocation(), CollapsedNum) {}
4879 
4880 public:
4881   /// Creates directive with a list of \a Clauses.
4882   ///
4883   /// \param C AST context.
4884   /// \param StartLoc Starting location of the directive kind.
4885   /// \param EndLoc Ending Location of the directive.
4886   /// \param CollapsedNum Number of collapsed loops.
4887   /// \param Clauses List of clauses.
4888   /// \param AssociatedStmt Statement, associated with the directive.
4889   /// \param Exprs Helper expressions for CodeGen.
4890   ///
4891   static OMPTargetSimdDirective *
4892   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4893          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4894          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4895 
4896   /// Creates an empty directive with the place for \a NumClauses clauses.
4897   ///
4898   /// \param C AST context.
4899   /// \param CollapsedNum Number of collapsed nested loops.
4900   /// \param NumClauses Number of clauses.
4901   ///
4902   static OMPTargetSimdDirective *CreateEmpty(const ASTContext &C,
4903                                              unsigned NumClauses,
4904                                              unsigned CollapsedNum,
4905                                              EmptyShell);
4906 
classof(const Stmt * T)4907   static bool classof(const Stmt *T) {
4908     return T->getStmtClass() == OMPTargetSimdDirectiveClass;
4909   }
4910 };
4911 
4912 /// This represents '#pragma omp teams distribute' directive.
4913 ///
4914 /// \code
4915 /// #pragma omp teams distribute private(a,b)
4916 /// \endcode
4917 /// In this example directive '#pragma omp teams distribute' has clauses
4918 /// 'private' with the variables 'a' and 'b'
4919 ///
4920 class OMPTeamsDistributeDirective final : public OMPLoopDirective {
4921   friend class ASTStmtReader;
4922   friend class OMPExecutableDirective;
4923 
4924   /// Build directive with the given start and end location.
4925   ///
4926   /// \param StartLoc Starting location of the directive kind.
4927   /// \param EndLoc Ending location of the directive.
4928   /// \param CollapsedNum Number of collapsed nested loops.
4929   ///
OMPTeamsDistributeDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4930   OMPTeamsDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4931                               unsigned CollapsedNum)
4932       : OMPLoopDirective(OMPTeamsDistributeDirectiveClass,
4933                          llvm::omp::OMPD_teams_distribute, StartLoc, EndLoc,
4934                          CollapsedNum) {}
4935 
4936   /// Build an empty directive.
4937   ///
4938   /// \param CollapsedNum Number of collapsed nested loops.
4939   ///
OMPTeamsDistributeDirective(unsigned CollapsedNum)4940   explicit OMPTeamsDistributeDirective(unsigned CollapsedNum)
4941       : OMPLoopDirective(OMPTeamsDistributeDirectiveClass,
4942                          llvm::omp::OMPD_teams_distribute, SourceLocation(),
4943                          SourceLocation(), CollapsedNum) {}
4944 
4945 public:
4946   /// Creates directive with a list of \a Clauses.
4947   ///
4948   /// \param C AST context.
4949   /// \param StartLoc Starting location of the directive kind.
4950   /// \param EndLoc Ending Location of the directive.
4951   /// \param CollapsedNum Number of collapsed loops.
4952   /// \param Clauses List of clauses.
4953   /// \param AssociatedStmt Statement, associated with the directive.
4954   /// \param Exprs Helper expressions for CodeGen.
4955   ///
4956   static OMPTeamsDistributeDirective *
4957   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4958          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4959          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4960 
4961   /// Creates an empty directive with the place for \a NumClauses clauses.
4962   ///
4963   /// \param C AST context.
4964   /// \param CollapsedNum Number of collapsed nested loops.
4965   /// \param NumClauses Number of clauses.
4966   ///
4967   static OMPTeamsDistributeDirective *CreateEmpty(const ASTContext &C,
4968                                                   unsigned NumClauses,
4969                                                   unsigned CollapsedNum,
4970                                                   EmptyShell);
4971 
classof(const Stmt * T)4972   static bool classof(const Stmt *T) {
4973     return T->getStmtClass() == OMPTeamsDistributeDirectiveClass;
4974   }
4975 };
4976 
4977 /// This represents '#pragma omp teams distribute simd'
4978 /// combined directive.
4979 ///
4980 /// \code
4981 /// #pragma omp teams distribute simd private(a,b)
4982 /// \endcode
4983 /// In this example directive '#pragma omp teams distribute simd'
4984 /// has clause 'private' with the variables 'a' and 'b'
4985 ///
4986 class OMPTeamsDistributeSimdDirective final : public OMPLoopDirective {
4987   friend class ASTStmtReader;
4988   friend class OMPExecutableDirective;
4989 
4990   /// Build directive with the given start and end location.
4991   ///
4992   /// \param StartLoc Starting location of the directive kind.
4993   /// \param EndLoc Ending location of the directive.
4994   /// \param CollapsedNum Number of collapsed nested loops.
4995   ///
OMPTeamsDistributeSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)4996   OMPTeamsDistributeSimdDirective(SourceLocation StartLoc,
4997                                   SourceLocation EndLoc, unsigned CollapsedNum)
4998       : OMPLoopDirective(OMPTeamsDistributeSimdDirectiveClass,
4999                          llvm::omp::OMPD_teams_distribute_simd, StartLoc,
5000                          EndLoc, CollapsedNum) {}
5001 
5002   /// Build an empty directive.
5003   ///
5004   /// \param CollapsedNum Number of collapsed nested loops.
5005   ///
OMPTeamsDistributeSimdDirective(unsigned CollapsedNum)5006   explicit OMPTeamsDistributeSimdDirective(unsigned CollapsedNum)
5007       : OMPLoopDirective(OMPTeamsDistributeSimdDirectiveClass,
5008                          llvm::omp::OMPD_teams_distribute_simd,
5009                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5010 
5011 public:
5012   /// Creates directive with a list of \a Clauses.
5013   ///
5014   /// \param C AST context.
5015   /// \param StartLoc Starting location of the directive kind.
5016   /// \param EndLoc Ending Location of the directive.
5017   /// \param CollapsedNum Number of collapsed loops.
5018   /// \param Clauses List of clauses.
5019   /// \param AssociatedStmt Statement, associated with the directive.
5020   /// \param Exprs Helper expressions for CodeGen.
5021   ///
5022   static OMPTeamsDistributeSimdDirective *
5023   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5024          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5025          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5026 
5027   /// Creates an empty directive with the place
5028   /// for \a NumClauses clauses.
5029   ///
5030   /// \param C AST context.
5031   /// \param CollapsedNum Number of collapsed nested loops.
5032   /// \param NumClauses Number of clauses.
5033   ///
5034   static OMPTeamsDistributeSimdDirective *CreateEmpty(const ASTContext &C,
5035                                                       unsigned NumClauses,
5036                                                       unsigned CollapsedNum,
5037                                                       EmptyShell);
5038 
classof(const Stmt * T)5039   static bool classof(const Stmt *T) {
5040     return T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass;
5041   }
5042 };
5043 
5044 /// This represents '#pragma omp teams distribute parallel for simd' composite
5045 /// directive.
5046 ///
5047 /// \code
5048 /// #pragma omp teams distribute parallel for simd private(x)
5049 /// \endcode
5050 /// In this example directive '#pragma omp teams distribute parallel for simd'
5051 /// has clause 'private' with the variables 'x'
5052 ///
5053 class OMPTeamsDistributeParallelForSimdDirective final
5054     : public OMPLoopDirective {
5055   friend class ASTStmtReader;
5056   friend class OMPExecutableDirective;
5057 
5058   /// Build directive with the given start and end location.
5059   ///
5060   /// \param StartLoc Starting location of the directive kind.
5061   /// \param EndLoc Ending location of the directive.
5062   /// \param CollapsedNum Number of collapsed nested loops.
5063   ///
OMPTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5064   OMPTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
5065                                              SourceLocation EndLoc,
5066                                              unsigned CollapsedNum)
5067       : OMPLoopDirective(OMPTeamsDistributeParallelForSimdDirectiveClass,
5068                          llvm::omp::OMPD_teams_distribute_parallel_for_simd,
5069                          StartLoc, EndLoc, CollapsedNum) {}
5070 
5071   /// Build an empty directive.
5072   ///
5073   /// \param CollapsedNum Number of collapsed nested loops.
5074   ///
OMPTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum)5075   explicit OMPTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum)
5076       : OMPLoopDirective(OMPTeamsDistributeParallelForSimdDirectiveClass,
5077                          llvm::omp::OMPD_teams_distribute_parallel_for_simd,
5078                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5079 
5080 public:
5081   /// Creates directive with a list of \a Clauses.
5082   ///
5083   /// \param C AST context.
5084   /// \param StartLoc Starting location of the directive kind.
5085   /// \param EndLoc Ending Location of the directive.
5086   /// \param CollapsedNum Number of collapsed loops.
5087   /// \param Clauses List of clauses.
5088   /// \param AssociatedStmt Statement, associated with the directive.
5089   /// \param Exprs Helper expressions for CodeGen.
5090   ///
5091   static OMPTeamsDistributeParallelForSimdDirective *
5092   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5093          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5094          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5095 
5096   /// Creates an empty directive with the place for \a NumClauses clauses.
5097   ///
5098   /// \param C AST context.
5099   /// \param CollapsedNum Number of collapsed nested loops.
5100   /// \param NumClauses Number of clauses.
5101   ///
5102   static OMPTeamsDistributeParallelForSimdDirective *
5103   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5104               EmptyShell);
5105 
classof(const Stmt * T)5106   static bool classof(const Stmt *T) {
5107     return T->getStmtClass() == OMPTeamsDistributeParallelForSimdDirectiveClass;
5108   }
5109 };
5110 
5111 /// This represents '#pragma omp teams distribute parallel for' composite
5112 /// directive.
5113 ///
5114 /// \code
5115 /// #pragma omp teams distribute parallel for private(x)
5116 /// \endcode
5117 /// In this example directive '#pragma omp teams distribute parallel for'
5118 /// has clause 'private' with the variables 'x'
5119 ///
5120 class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
5121   friend class ASTStmtReader;
5122   friend class OMPExecutableDirective;
5123   /// true if the construct has inner cancel directive.
5124   bool HasCancel = false;
5125 
5126   /// Build directive with the given start and end location.
5127   ///
5128   /// \param StartLoc Starting location of the directive kind.
5129   /// \param EndLoc Ending location of the directive.
5130   /// \param CollapsedNum Number of collapsed nested loops.
5131   ///
OMPTeamsDistributeParallelForDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5132   OMPTeamsDistributeParallelForDirective(SourceLocation StartLoc,
5133                                          SourceLocation EndLoc,
5134                                          unsigned CollapsedNum)
5135       : OMPLoopDirective(OMPTeamsDistributeParallelForDirectiveClass,
5136                          llvm::omp::OMPD_teams_distribute_parallel_for,
5137                          StartLoc, EndLoc, CollapsedNum) {}
5138 
5139   /// Build an empty directive.
5140   ///
5141   /// \param CollapsedNum Number of collapsed nested loops.
5142   ///
OMPTeamsDistributeParallelForDirective(unsigned CollapsedNum)5143   explicit OMPTeamsDistributeParallelForDirective(unsigned CollapsedNum)
5144       : OMPLoopDirective(OMPTeamsDistributeParallelForDirectiveClass,
5145                          llvm::omp::OMPD_teams_distribute_parallel_for,
5146                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5147 
5148   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)5149   void setTaskReductionRefExpr(Expr *E) {
5150     Data->getChildren()[numLoopChildren(
5151         getLoopsNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)] = E;
5152   }
5153 
5154   /// Set cancel state.
setHasCancel(bool Has)5155   void setHasCancel(bool Has) { HasCancel = Has; }
5156 
5157 public:
5158   /// Creates directive with a list of \a Clauses.
5159   ///
5160   /// \param C AST context.
5161   /// \param StartLoc Starting location of the directive kind.
5162   /// \param EndLoc Ending Location of the directive.
5163   /// \param CollapsedNum Number of collapsed loops.
5164   /// \param Clauses List of clauses.
5165   /// \param AssociatedStmt Statement, associated with the directive.
5166   /// \param Exprs Helper expressions for CodeGen.
5167   /// \param TaskRedRef Task reduction special reference expression to handle
5168   /// taskgroup descriptor.
5169   /// \param HasCancel true if this directive has inner cancel directive.
5170   ///
5171   static OMPTeamsDistributeParallelForDirective *
5172   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5173          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5174          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
5175          bool HasCancel);
5176 
5177   /// Creates an empty directive with the place for \a NumClauses clauses.
5178   ///
5179   /// \param C AST context.
5180   /// \param CollapsedNum Number of collapsed nested loops.
5181   /// \param NumClauses Number of clauses.
5182   ///
5183   static OMPTeamsDistributeParallelForDirective *
5184   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5185               EmptyShell);
5186 
5187   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()5188   Expr *getTaskReductionRefExpr() {
5189     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
5190         getLoopsNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)]);
5191   }
getTaskReductionRefExpr()5192   const Expr *getTaskReductionRefExpr() const {
5193     return const_cast<OMPTeamsDistributeParallelForDirective *>(this)
5194         ->getTaskReductionRefExpr();
5195   }
5196 
5197   /// Return true if current directive has inner cancel directive.
hasCancel()5198   bool hasCancel() const { return HasCancel; }
5199 
classof(const Stmt * T)5200   static bool classof(const Stmt *T) {
5201     return T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass;
5202   }
5203 };
5204 
5205 /// This represents '#pragma omp target teams' directive.
5206 ///
5207 /// \code
5208 /// #pragma omp target teams if(a>0)
5209 /// \endcode
5210 /// In this example directive '#pragma omp target teams' has clause 'if' with
5211 /// condition 'a>0'.
5212 ///
5213 class OMPTargetTeamsDirective final : public OMPExecutableDirective {
5214   friend class ASTStmtReader;
5215   friend class OMPExecutableDirective;
5216   /// Build directive with the given start and end location.
5217   ///
5218   /// \param StartLoc Starting location of the directive kind.
5219   /// \param EndLoc Ending location of the directive.
5220   ///
OMPTargetTeamsDirective(SourceLocation StartLoc,SourceLocation EndLoc)5221   OMPTargetTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5222       : OMPExecutableDirective(OMPTargetTeamsDirectiveClass,
5223                                llvm::omp::OMPD_target_teams, StartLoc, EndLoc) {
5224   }
5225 
5226   /// Build an empty directive.
5227   ///
OMPTargetTeamsDirective()5228   explicit OMPTargetTeamsDirective()
5229       : OMPExecutableDirective(OMPTargetTeamsDirectiveClass,
5230                                llvm::omp::OMPD_target_teams, SourceLocation(),
5231                                SourceLocation()) {}
5232 
5233 public:
5234   /// Creates directive with a list of \a Clauses.
5235   ///
5236   /// \param C AST context.
5237   /// \param StartLoc Starting location of the directive kind.
5238   /// \param EndLoc Ending Location of the directive.
5239   /// \param Clauses List of clauses.
5240   /// \param AssociatedStmt Statement, associated with the directive.
5241   ///
5242   static OMPTargetTeamsDirective *Create(const ASTContext &C,
5243                                          SourceLocation StartLoc,
5244                                          SourceLocation EndLoc,
5245                                          ArrayRef<OMPClause *> Clauses,
5246                                          Stmt *AssociatedStmt);
5247 
5248   /// Creates an empty directive with the place for \a NumClauses clauses.
5249   ///
5250   /// \param C AST context.
5251   /// \param NumClauses Number of clauses.
5252   ///
5253   static OMPTargetTeamsDirective *CreateEmpty(const ASTContext &C,
5254                                               unsigned NumClauses, EmptyShell);
5255 
classof(const Stmt * T)5256   static bool classof(const Stmt *T) {
5257     return T->getStmtClass() == OMPTargetTeamsDirectiveClass;
5258   }
5259 };
5260 
5261 /// This represents '#pragma omp target teams distribute' combined directive.
5262 ///
5263 /// \code
5264 /// #pragma omp target teams distribute private(x)
5265 /// \endcode
5266 /// In this example directive '#pragma omp target teams distribute' has clause
5267 /// 'private' with the variables 'x'
5268 ///
5269 class OMPTargetTeamsDistributeDirective final : public OMPLoopDirective {
5270   friend class ASTStmtReader;
5271   friend class OMPExecutableDirective;
5272 
5273   /// Build directive with the given start and end location.
5274   ///
5275   /// \param StartLoc Starting location of the directive kind.
5276   /// \param EndLoc Ending location of the directive.
5277   /// \param CollapsedNum Number of collapsed nested loops.
5278   ///
OMPTargetTeamsDistributeDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5279   OMPTargetTeamsDistributeDirective(SourceLocation StartLoc,
5280                                     SourceLocation EndLoc,
5281                                     unsigned CollapsedNum)
5282       : OMPLoopDirective(OMPTargetTeamsDistributeDirectiveClass,
5283                          llvm::omp::OMPD_target_teams_distribute, StartLoc,
5284                          EndLoc, CollapsedNum) {}
5285 
5286   /// Build an empty directive.
5287   ///
5288   /// \param CollapsedNum Number of collapsed nested loops.
5289   ///
OMPTargetTeamsDistributeDirective(unsigned CollapsedNum)5290   explicit OMPTargetTeamsDistributeDirective(unsigned CollapsedNum)
5291       : OMPLoopDirective(OMPTargetTeamsDistributeDirectiveClass,
5292                          llvm::omp::OMPD_target_teams_distribute,
5293                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5294 
5295 public:
5296   /// Creates directive with a list of \a Clauses.
5297   ///
5298   /// \param C AST context.
5299   /// \param StartLoc Starting location of the directive kind.
5300   /// \param EndLoc Ending Location of the directive.
5301   /// \param CollapsedNum Number of collapsed loops.
5302   /// \param Clauses List of clauses.
5303   /// \param AssociatedStmt Statement, associated with the directive.
5304   /// \param Exprs Helper expressions for CodeGen.
5305   ///
5306   static OMPTargetTeamsDistributeDirective *
5307   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5308          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5309          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5310 
5311   /// Creates an empty directive with the place for \a NumClauses clauses.
5312   ///
5313   /// \param C AST context.
5314   /// \param CollapsedNum Number of collapsed nested loops.
5315   /// \param NumClauses Number of clauses.
5316   ///
5317   static OMPTargetTeamsDistributeDirective *
5318   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5319               EmptyShell);
5320 
classof(const Stmt * T)5321   static bool classof(const Stmt *T) {
5322     return T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass;
5323   }
5324 };
5325 
5326 /// This represents '#pragma omp target teams distribute parallel for' combined
5327 /// directive.
5328 ///
5329 /// \code
5330 /// #pragma omp target teams distribute parallel for private(x)
5331 /// \endcode
5332 /// In this example directive '#pragma omp target teams distribute parallel
5333 /// for' has clause 'private' with the variables 'x'
5334 ///
5335 class OMPTargetTeamsDistributeParallelForDirective final
5336     : public OMPLoopDirective {
5337   friend class ASTStmtReader;
5338   friend class OMPExecutableDirective;
5339   /// true if the construct has inner cancel directive.
5340   bool HasCancel = false;
5341 
5342   /// Build directive with the given start and end location.
5343   ///
5344   /// \param StartLoc Starting location of the directive kind.
5345   /// \param EndLoc Ending location of the directive.
5346   /// \param CollapsedNum Number of collapsed nested loops.
5347   ///
OMPTargetTeamsDistributeParallelForDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5348   OMPTargetTeamsDistributeParallelForDirective(SourceLocation StartLoc,
5349                                                SourceLocation EndLoc,
5350                                                unsigned CollapsedNum)
5351       : OMPLoopDirective(OMPTargetTeamsDistributeParallelForDirectiveClass,
5352                          llvm::omp::OMPD_target_teams_distribute_parallel_for,
5353                          StartLoc, EndLoc, CollapsedNum) {}
5354 
5355   /// Build an empty directive.
5356   ///
5357   /// \param CollapsedNum Number of collapsed nested loops.
5358   ///
OMPTargetTeamsDistributeParallelForDirective(unsigned CollapsedNum)5359   explicit OMPTargetTeamsDistributeParallelForDirective(unsigned CollapsedNum)
5360       : OMPLoopDirective(OMPTargetTeamsDistributeParallelForDirectiveClass,
5361                          llvm::omp::OMPD_target_teams_distribute_parallel_for,
5362                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5363 
5364   /// Sets special task reduction descriptor.
setTaskReductionRefExpr(Expr * E)5365   void setTaskReductionRefExpr(Expr *E) {
5366     Data->getChildren()[numLoopChildren(
5367         getLoopsNumber(),
5368         llvm::omp::OMPD_target_teams_distribute_parallel_for)] = E;
5369   }
5370 
5371   /// Set cancel state.
setHasCancel(bool Has)5372   void setHasCancel(bool Has) { HasCancel = Has; }
5373 
5374 public:
5375   /// Creates directive with a list of \a Clauses.
5376   ///
5377   /// \param C AST context.
5378   /// \param StartLoc Starting location of the directive kind.
5379   /// \param EndLoc Ending Location of the directive.
5380   /// \param CollapsedNum Number of collapsed loops.
5381   /// \param Clauses List of clauses.
5382   /// \param AssociatedStmt Statement, associated with the directive.
5383   /// \param Exprs Helper expressions for CodeGen.
5384   /// \param TaskRedRef Task reduction special reference expression to handle
5385   /// taskgroup descriptor.
5386   /// \param HasCancel true if this directive has inner cancel directive.
5387   ///
5388   static OMPTargetTeamsDistributeParallelForDirective *
5389   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5390          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5391          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
5392          bool HasCancel);
5393 
5394   /// Creates an empty directive with the place for \a NumClauses clauses.
5395   ///
5396   /// \param C AST context.
5397   /// \param CollapsedNum Number of collapsed nested loops.
5398   /// \param NumClauses Number of clauses.
5399   ///
5400   static OMPTargetTeamsDistributeParallelForDirective *
5401   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5402               EmptyShell);
5403 
5404   /// Returns special task reduction reference expression.
getTaskReductionRefExpr()5405   Expr *getTaskReductionRefExpr() {
5406     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
5407         getLoopsNumber(),
5408         llvm::omp::OMPD_target_teams_distribute_parallel_for)]);
5409   }
getTaskReductionRefExpr()5410   const Expr *getTaskReductionRefExpr() const {
5411     return const_cast<OMPTargetTeamsDistributeParallelForDirective *>(this)
5412         ->getTaskReductionRefExpr();
5413   }
5414 
5415   /// Return true if current directive has inner cancel directive.
hasCancel()5416   bool hasCancel() const { return HasCancel; }
5417 
classof(const Stmt * T)5418   static bool classof(const Stmt *T) {
5419     return T->getStmtClass() ==
5420            OMPTargetTeamsDistributeParallelForDirectiveClass;
5421   }
5422 };
5423 
5424 /// This represents '#pragma omp target teams distribute parallel for simd'
5425 /// combined directive.
5426 ///
5427 /// \code
5428 /// #pragma omp target teams distribute parallel for simd private(x)
5429 /// \endcode
5430 /// In this example directive '#pragma omp target teams distribute parallel
5431 /// for simd' has clause 'private' with the variables 'x'
5432 ///
5433 class OMPTargetTeamsDistributeParallelForSimdDirective final
5434     : public OMPLoopDirective {
5435   friend class ASTStmtReader;
5436   friend class OMPExecutableDirective;
5437 
5438   /// Build directive with the given start and end location.
5439   ///
5440   /// \param StartLoc Starting location of the directive kind.
5441   /// \param EndLoc Ending location of the directive.
5442   /// \param CollapsedNum Number of collapsed nested loops.
5443   ///
OMPTargetTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5444   OMPTargetTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
5445                                                    SourceLocation EndLoc,
5446                                                    unsigned CollapsedNum)
5447       : OMPLoopDirective(
5448             OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
5449             llvm::omp::OMPD_target_teams_distribute_parallel_for_simd, StartLoc,
5450             EndLoc, CollapsedNum) {}
5451 
5452   /// Build an empty directive.
5453   ///
5454   /// \param CollapsedNum Number of collapsed nested loops.
5455   ///
OMPTargetTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum)5456   explicit OMPTargetTeamsDistributeParallelForSimdDirective(
5457       unsigned CollapsedNum)
5458       : OMPLoopDirective(
5459             OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
5460             llvm::omp::OMPD_target_teams_distribute_parallel_for_simd,
5461             SourceLocation(), SourceLocation(), CollapsedNum) {}
5462 
5463 public:
5464   /// Creates directive with a list of \a Clauses.
5465   ///
5466   /// \param C AST context.
5467   /// \param StartLoc Starting location of the directive kind.
5468   /// \param EndLoc Ending Location of the directive.
5469   /// \param CollapsedNum Number of collapsed loops.
5470   /// \param Clauses List of clauses.
5471   /// \param AssociatedStmt Statement, associated with the directive.
5472   /// \param Exprs Helper expressions for CodeGen.
5473   ///
5474   static OMPTargetTeamsDistributeParallelForSimdDirective *
5475   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5476          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5477          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5478 
5479   /// Creates an empty directive with the place for \a NumClauses clauses.
5480   ///
5481   /// \param C AST context.
5482   /// \param CollapsedNum Number of collapsed nested loops.
5483   /// \param NumClauses Number of clauses.
5484   ///
5485   static OMPTargetTeamsDistributeParallelForSimdDirective *
5486   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5487               EmptyShell);
5488 
classof(const Stmt * T)5489   static bool classof(const Stmt *T) {
5490     return T->getStmtClass() ==
5491            OMPTargetTeamsDistributeParallelForSimdDirectiveClass;
5492   }
5493 };
5494 
5495 /// This represents '#pragma omp target teams distribute simd' combined
5496 /// directive.
5497 ///
5498 /// \code
5499 /// #pragma omp target teams distribute simd private(x)
5500 /// \endcode
5501 /// In this example directive '#pragma omp target teams distribute simd'
5502 /// has clause 'private' with the variables 'x'
5503 ///
5504 class OMPTargetTeamsDistributeSimdDirective final : public OMPLoopDirective {
5505   friend class ASTStmtReader;
5506   friend class OMPExecutableDirective;
5507 
5508   /// Build directive with the given start and end location.
5509   ///
5510   /// \param StartLoc Starting location of the directive kind.
5511   /// \param EndLoc Ending location of the directive.
5512   /// \param CollapsedNum Number of collapsed nested loops.
5513   ///
OMPTargetTeamsDistributeSimdDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5514   OMPTargetTeamsDistributeSimdDirective(SourceLocation StartLoc,
5515                                         SourceLocation EndLoc,
5516                                         unsigned CollapsedNum)
5517       : OMPLoopDirective(OMPTargetTeamsDistributeSimdDirectiveClass,
5518                          llvm::omp::OMPD_target_teams_distribute_simd, StartLoc,
5519                          EndLoc, CollapsedNum) {}
5520 
5521   /// Build an empty directive.
5522   ///
5523   /// \param CollapsedNum Number of collapsed nested loops.
5524   ///
OMPTargetTeamsDistributeSimdDirective(unsigned CollapsedNum)5525   explicit OMPTargetTeamsDistributeSimdDirective(unsigned CollapsedNum)
5526       : OMPLoopDirective(OMPTargetTeamsDistributeSimdDirectiveClass,
5527                          llvm::omp::OMPD_target_teams_distribute_simd,
5528                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5529 
5530 public:
5531   /// Creates directive with a list of \a Clauses.
5532   ///
5533   /// \param C AST context.
5534   /// \param StartLoc Starting location of the directive kind.
5535   /// \param EndLoc Ending Location of the directive.
5536   /// \param CollapsedNum Number of collapsed loops.
5537   /// \param Clauses List of clauses.
5538   /// \param AssociatedStmt Statement, associated with the directive.
5539   /// \param Exprs Helper expressions for CodeGen.
5540   ///
5541   static OMPTargetTeamsDistributeSimdDirective *
5542   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5543          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5544          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5545 
5546   /// Creates an empty directive with the place for \a NumClauses clauses.
5547   ///
5548   /// \param C AST context.
5549   /// \param CollapsedNum Number of collapsed nested loops.
5550   /// \param NumClauses Number of clauses.
5551   ///
5552   static OMPTargetTeamsDistributeSimdDirective *
5553   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5554               EmptyShell);
5555 
classof(const Stmt * T)5556   static bool classof(const Stmt *T) {
5557     return T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass;
5558   }
5559 };
5560 
5561 /// This represents the '#pragma omp tile' loop transformation directive.
5562 class OMPTileDirective final : public OMPLoopTransformationDirective {
5563   friend class ASTStmtReader;
5564   friend class OMPExecutableDirective;
5565 
5566   /// Default list of offsets.
5567   enum {
5568     PreInitsOffset = 0,
5569     TransformedStmtOffset,
5570   };
5571 
OMPTileDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned NumLoops)5572   explicit OMPTileDirective(SourceLocation StartLoc, SourceLocation EndLoc,
5573                             unsigned NumLoops)
5574       : OMPLoopTransformationDirective(OMPTileDirectiveClass,
5575                                        llvm::omp::OMPD_tile, StartLoc, EndLoc,
5576                                        NumLoops) {
5577     setNumGeneratedLoops(3 * NumLoops);
5578   }
5579 
setPreInits(Stmt * PreInits)5580   void setPreInits(Stmt *PreInits) {
5581     Data->getChildren()[PreInitsOffset] = PreInits;
5582   }
5583 
setTransformedStmt(Stmt * S)5584   void setTransformedStmt(Stmt *S) {
5585     Data->getChildren()[TransformedStmtOffset] = S;
5586   }
5587 
5588 public:
5589   /// Create a new AST node representation for '#pragma omp tile'.
5590   ///
5591   /// \param C         Context of the AST.
5592   /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
5593   /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
5594   /// \param Clauses   The directive's clauses.
5595   /// \param NumLoops  Number of associated loops (number of items in the
5596   ///                  'sizes' clause).
5597   /// \param AssociatedStmt The outermost associated loop.
5598   /// \param TransformedStmt The loop nest after tiling, or nullptr in
5599   ///                        dependent contexts.
5600   /// \param PreInits Helper preinits statements for the loop nest.
5601   static OMPTileDirective *Create(const ASTContext &C, SourceLocation StartLoc,
5602                                   SourceLocation EndLoc,
5603                                   ArrayRef<OMPClause *> Clauses,
5604                                   unsigned NumLoops, Stmt *AssociatedStmt,
5605                                   Stmt *TransformedStmt, Stmt *PreInits);
5606 
5607   /// Build an empty '#pragma omp tile' AST node for deserialization.
5608   ///
5609   /// \param C          Context of the AST.
5610   /// \param NumClauses Number of clauses to allocate.
5611   /// \param NumLoops   Number of associated loops to allocate.
5612   static OMPTileDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
5613                                        unsigned NumLoops);
5614 
5615   /// Gets/sets the associated loops after tiling.
5616   ///
5617   /// This is in de-sugared format stored as a CompoundStmt.
5618   ///
5619   /// \code
5620   ///   for (...)
5621   ///     ...
5622   /// \endcode
5623   ///
5624   /// Note that if the generated loops a become associated loops of another
5625   /// directive, they may need to be hoisted before them.
getTransformedStmt()5626   Stmt *getTransformedStmt() const {
5627     return Data->getChildren()[TransformedStmtOffset];
5628   }
5629 
5630   /// Return preinits statement.
getPreInits()5631   Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
5632 
classof(const Stmt * T)5633   static bool classof(const Stmt *T) {
5634     return T->getStmtClass() == OMPTileDirectiveClass;
5635   }
5636 };
5637 
5638 /// This represents the '#pragma omp unroll' loop transformation directive.
5639 ///
5640 /// \code
5641 /// #pragma omp unroll
5642 /// for (int i = 0; i < 64; ++i)
5643 /// \endcode
5644 class OMPUnrollDirective final : public OMPLoopTransformationDirective {
5645   friend class ASTStmtReader;
5646   friend class OMPExecutableDirective;
5647 
5648   /// Default list of offsets.
5649   enum {
5650     PreInitsOffset = 0,
5651     TransformedStmtOffset,
5652   };
5653 
OMPUnrollDirective(SourceLocation StartLoc,SourceLocation EndLoc)5654   explicit OMPUnrollDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5655       : OMPLoopTransformationDirective(OMPUnrollDirectiveClass,
5656                                        llvm::omp::OMPD_unroll, StartLoc, EndLoc,
5657                                        1) {}
5658 
5659   /// Set the pre-init statements.
setPreInits(Stmt * PreInits)5660   void setPreInits(Stmt *PreInits) {
5661     Data->getChildren()[PreInitsOffset] = PreInits;
5662   }
5663 
5664   /// Set the de-sugared statement.
setTransformedStmt(Stmt * S)5665   void setTransformedStmt(Stmt *S) {
5666     Data->getChildren()[TransformedStmtOffset] = S;
5667   }
5668 
5669 public:
5670   /// Create a new AST node representation for '#pragma omp unroll'.
5671   ///
5672   /// \param C         Context of the AST.
5673   /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
5674   /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
5675   /// \param Clauses   The directive's clauses.
5676   /// \param AssociatedStmt The outermost associated loop.
5677   /// \param TransformedStmt The loop nest after tiling, or nullptr in
5678   ///                        dependent contexts.
5679   /// \param PreInits   Helper preinits statements for the loop nest.
5680   static OMPUnrollDirective *
5681   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5682          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
5683          unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits);
5684 
5685   /// Build an empty '#pragma omp unroll' AST node for deserialization.
5686   ///
5687   /// \param C          Context of the AST.
5688   /// \param NumClauses Number of clauses to allocate.
5689   static OMPUnrollDirective *CreateEmpty(const ASTContext &C,
5690                                          unsigned NumClauses);
5691 
5692   /// Get the de-sugared associated loops after unrolling.
5693   ///
5694   /// This is only used if the unrolled loop becomes an associated loop of
5695   /// another directive, otherwise the loop is emitted directly using loop
5696   /// transformation metadata. When the unrolled loop cannot be used by another
5697   /// directive (e.g. because of the full clause), the transformed stmt can also
5698   /// be nullptr.
getTransformedStmt()5699   Stmt *getTransformedStmt() const {
5700     return Data->getChildren()[TransformedStmtOffset];
5701   }
5702 
5703   /// Return the pre-init statements.
getPreInits()5704   Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
5705 
classof(const Stmt * T)5706   static bool classof(const Stmt *T) {
5707     return T->getStmtClass() == OMPUnrollDirectiveClass;
5708   }
5709 };
5710 
5711 /// This represents '#pragma omp scan' directive.
5712 ///
5713 /// \code
5714 /// #pragma omp scan inclusive(a)
5715 /// \endcode
5716 /// In this example directive '#pragma omp scan' has clause 'inclusive' with
5717 /// list item 'a'.
5718 class OMPScanDirective final : public OMPExecutableDirective {
5719   friend class ASTStmtReader;
5720   friend class OMPExecutableDirective;
5721   /// Build directive with the given start and end location.
5722   ///
5723   /// \param StartLoc Starting location of the directive kind.
5724   /// \param EndLoc Ending location of the directive.
5725   ///
OMPScanDirective(SourceLocation StartLoc,SourceLocation EndLoc)5726   OMPScanDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5727       : OMPExecutableDirective(OMPScanDirectiveClass, llvm::omp::OMPD_scan,
5728                                StartLoc, EndLoc) {}
5729 
5730   /// Build an empty directive.
5731   ///
OMPScanDirective()5732   explicit OMPScanDirective()
5733       : OMPExecutableDirective(OMPScanDirectiveClass, llvm::omp::OMPD_scan,
5734                                SourceLocation(), SourceLocation()) {}
5735 
5736 public:
5737   /// Creates directive with a list of \a Clauses.
5738   ///
5739   /// \param C AST context.
5740   /// \param StartLoc Starting location of the directive kind.
5741   /// \param EndLoc Ending Location of the directive.
5742   /// \param Clauses List of clauses (only single OMPFlushClause clause is
5743   /// allowed).
5744   ///
5745   static OMPScanDirective *Create(const ASTContext &C, SourceLocation StartLoc,
5746                                   SourceLocation EndLoc,
5747                                   ArrayRef<OMPClause *> Clauses);
5748 
5749   /// Creates an empty directive with the place for \a NumClauses
5750   /// clauses.
5751   ///
5752   /// \param C AST context.
5753   /// \param NumClauses Number of clauses.
5754   ///
5755   static OMPScanDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
5756                                        EmptyShell);
5757 
classof(const Stmt * T)5758   static bool classof(const Stmt *T) {
5759     return T->getStmtClass() == OMPScanDirectiveClass;
5760   }
5761 };
5762 
5763 /// This represents '#pragma omp interop' directive.
5764 ///
5765 /// \code
5766 /// #pragma omp interop init(target:obj) device(x) depend(inout:y) nowait
5767 /// \endcode
5768 /// In this example directive '#pragma omp interop' has
5769 /// clauses 'init', 'device', 'depend' and 'nowait'.
5770 ///
5771 class OMPInteropDirective final : public OMPExecutableDirective {
5772   friend class ASTStmtReader;
5773   friend class OMPExecutableDirective;
5774 
5775   /// Build directive with the given start and end location.
5776   ///
5777   /// \param StartLoc Starting location of the directive.
5778   /// \param EndLoc Ending location of the directive.
5779   ///
OMPInteropDirective(SourceLocation StartLoc,SourceLocation EndLoc)5780   OMPInteropDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5781       : OMPExecutableDirective(OMPInteropDirectiveClass,
5782                                llvm::omp::OMPD_interop, StartLoc, EndLoc) {}
5783 
5784   /// Build an empty directive.
5785   ///
OMPInteropDirective()5786   explicit OMPInteropDirective()
5787       : OMPExecutableDirective(OMPInteropDirectiveClass,
5788                                llvm::omp::OMPD_interop, SourceLocation(),
5789                                SourceLocation()) {}
5790 
5791 public:
5792   /// Creates directive.
5793   ///
5794   /// \param C AST context.
5795   /// \param StartLoc Starting location of the directive.
5796   /// \param EndLoc Ending Location of the directive.
5797   /// \param Clauses The directive's clauses.
5798   ///
5799   static OMPInteropDirective *Create(const ASTContext &C,
5800                                      SourceLocation StartLoc,
5801                                      SourceLocation EndLoc,
5802                                      ArrayRef<OMPClause *> Clauses);
5803 
5804   /// Creates an empty directive.
5805   ///
5806   /// \param C AST context.
5807   ///
5808   static OMPInteropDirective *CreateEmpty(const ASTContext &C,
5809                                           unsigned NumClauses, EmptyShell);
5810 
classof(const Stmt * T)5811   static bool classof(const Stmt *T) {
5812     return T->getStmtClass() == OMPInteropDirectiveClass;
5813   }
5814 };
5815 
5816 /// This represents '#pragma omp dispatch' directive.
5817 ///
5818 /// \code
5819 /// #pragma omp dispatch device(dnum)
5820 /// \endcode
5821 /// This example shows a directive '#pragma omp dispatch' with a
5822 /// device clause with variable 'dnum'.
5823 ///
5824 class OMPDispatchDirective final : public OMPExecutableDirective {
5825   friend class ASTStmtReader;
5826   friend class OMPExecutableDirective;
5827 
5828   /// The location of the target-call.
5829   SourceLocation TargetCallLoc;
5830 
5831   /// Set the location of the target-call.
setTargetCallLoc(SourceLocation Loc)5832   void setTargetCallLoc(SourceLocation Loc) { TargetCallLoc = Loc; }
5833 
5834   /// Build directive with the given start and end location.
5835   ///
5836   /// \param StartLoc Starting location of the directive kind.
5837   /// \param EndLoc Ending location of the directive.
5838   ///
OMPDispatchDirective(SourceLocation StartLoc,SourceLocation EndLoc)5839   OMPDispatchDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5840       : OMPExecutableDirective(OMPDispatchDirectiveClass,
5841                                llvm::omp::OMPD_dispatch, StartLoc, EndLoc) {}
5842 
5843   /// Build an empty directive.
5844   ///
OMPDispatchDirective()5845   explicit OMPDispatchDirective()
5846       : OMPExecutableDirective(OMPDispatchDirectiveClass,
5847                                llvm::omp::OMPD_dispatch, SourceLocation(),
5848                                SourceLocation()) {}
5849 
5850 public:
5851   /// Creates directive with a list of \a Clauses.
5852   ///
5853   /// \param C AST context.
5854   /// \param StartLoc Starting location of the directive kind.
5855   /// \param EndLoc Ending Location of the directive.
5856   /// \param Clauses List of clauses.
5857   /// \param AssociatedStmt Statement, associated with the directive.
5858   /// \param TargetCallLoc Location of the target-call.
5859   ///
5860   static OMPDispatchDirective *
5861   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5862          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
5863          SourceLocation TargetCallLoc);
5864 
5865   /// Creates an empty directive with the place for \a NumClauses
5866   /// clauses.
5867   ///
5868   /// \param C AST context.
5869   /// \param NumClauses Number of clauses.
5870   ///
5871   static OMPDispatchDirective *CreateEmpty(const ASTContext &C,
5872                                            unsigned NumClauses, EmptyShell);
5873 
5874   /// Return location of target-call.
getTargetCallLoc()5875   SourceLocation getTargetCallLoc() const { return TargetCallLoc; }
5876 
classof(const Stmt * T)5877   static bool classof(const Stmt *T) {
5878     return T->getStmtClass() == OMPDispatchDirectiveClass;
5879   }
5880 };
5881 
5882 /// This represents '#pragma omp masked' directive.
5883 /// \code
5884 /// #pragma omp masked filter(tid)
5885 /// \endcode
5886 /// This example shows a directive '#pragma omp masked' with a filter clause
5887 /// with variable 'tid'.
5888 ///
5889 class OMPMaskedDirective final : public OMPExecutableDirective {
5890   friend class ASTStmtReader;
5891   friend class OMPExecutableDirective;
5892 
5893   /// Build directive with the given start and end location.
5894   ///
5895   /// \param StartLoc Starting location of the directive kind.
5896   /// \param EndLoc Ending location of the directive.
5897   ///
OMPMaskedDirective(SourceLocation StartLoc,SourceLocation EndLoc)5898   OMPMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5899       : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
5900                                StartLoc, EndLoc) {}
5901 
5902   /// Build an empty directive.
5903   ///
OMPMaskedDirective()5904   explicit OMPMaskedDirective()
5905       : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
5906                                SourceLocation(), SourceLocation()) {}
5907 
5908 public:
5909   /// Creates directive.
5910   ///
5911   /// \param C AST context.
5912   /// \param StartLoc Starting location of the directive kind.
5913   /// \param EndLoc Ending Location of the directive.
5914   /// \param AssociatedStmt Statement, associated with the directive.
5915   ///
5916   static OMPMaskedDirective *
5917   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5918          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
5919 
5920   /// Creates an empty directive.
5921   ///
5922   /// \param C AST context.
5923   ///
5924   static OMPMaskedDirective *CreateEmpty(const ASTContext &C,
5925                                          unsigned NumClauses, EmptyShell);
5926 
classof(const Stmt * T)5927   static bool classof(const Stmt *T) {
5928     return T->getStmtClass() == OMPMaskedDirectiveClass;
5929   }
5930 };
5931 
5932 /// This represents '#pragma omp metadirective' directive.
5933 ///
5934 /// \code
5935 /// #pragma omp metadirective when(user={condition(N>10)}: parallel for)
5936 /// \endcode
5937 /// In this example directive '#pragma omp metadirective' has clauses 'when'
5938 /// with a dynamic user condition to check if a variable 'N > 10'
5939 ///
5940 class OMPMetaDirective final : public OMPExecutableDirective {
5941   friend class ASTStmtReader;
5942   friend class OMPExecutableDirective;
5943   Stmt *IfStmt;
5944 
OMPMetaDirective(SourceLocation StartLoc,SourceLocation EndLoc)5945   OMPMetaDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5946       : OMPExecutableDirective(OMPMetaDirectiveClass,
5947                                llvm::omp::OMPD_metadirective, StartLoc,
5948                                EndLoc) {}
OMPMetaDirective()5949   explicit OMPMetaDirective()
5950       : OMPExecutableDirective(OMPMetaDirectiveClass,
5951                                llvm::omp::OMPD_metadirective, SourceLocation(),
5952                                SourceLocation()) {}
5953 
setIfStmt(Stmt * S)5954   void setIfStmt(Stmt *S) { IfStmt = S; }
5955 
5956 public:
5957   static OMPMetaDirective *Create(const ASTContext &C, SourceLocation StartLoc,
5958                                   SourceLocation EndLoc,
5959                                   ArrayRef<OMPClause *> Clauses,
5960                                   Stmt *AssociatedStmt, Stmt *IfStmt);
5961   static OMPMetaDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
5962                                        EmptyShell);
getIfStmt()5963   Stmt *getIfStmt() const { return IfStmt; }
5964 
classof(const Stmt * T)5965   static bool classof(const Stmt *T) {
5966     return T->getStmtClass() == OMPMetaDirectiveClass;
5967   }
5968 };
5969 
5970 /// This represents '#pragma omp loop' directive.
5971 ///
5972 /// \code
5973 /// #pragma omp loop private(a,b) binding(parallel) order(concurrent)
5974 /// \endcode
5975 /// In this example directive '#pragma omp loop' has
5976 /// clauses 'private' with the variables 'a' and 'b', 'binding' with
5977 /// modifier 'parallel' and 'order(concurrent).
5978 ///
5979 class OMPGenericLoopDirective final : public OMPLoopDirective {
5980   friend class ASTStmtReader;
5981   friend class OMPExecutableDirective;
5982   /// Build directive with the given start and end location.
5983   ///
5984   /// \param StartLoc Starting location of the directive kind.
5985   /// \param EndLoc Ending location of the directive.
5986   /// \param CollapsedNum Number of collapsed nested loops.
5987   ///
OMPGenericLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)5988   OMPGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
5989                           unsigned CollapsedNum)
5990       : OMPLoopDirective(OMPGenericLoopDirectiveClass, llvm::omp::OMPD_loop,
5991                          StartLoc, EndLoc, CollapsedNum) {}
5992 
5993   /// Build an empty directive.
5994   ///
5995   /// \param CollapsedNum Number of collapsed nested loops.
5996   ///
OMPGenericLoopDirective(unsigned CollapsedNum)5997   explicit OMPGenericLoopDirective(unsigned CollapsedNum)
5998       : OMPLoopDirective(OMPGenericLoopDirectiveClass, llvm::omp::OMPD_loop,
5999                          SourceLocation(), SourceLocation(), CollapsedNum) {}
6000 
6001 public:
6002   /// Creates directive with a list of \p Clauses.
6003   ///
6004   /// \param C AST context.
6005   /// \param StartLoc Starting location of the directive kind.
6006   /// \param EndLoc Ending Location of the directive.
6007   /// \param CollapsedNum Number of collapsed loops.
6008   /// \param Clauses List of clauses.
6009   /// \param AssociatedStmt Statement, associated with the directive.
6010   /// \param Exprs Helper expressions for CodeGen.
6011   ///
6012   static OMPGenericLoopDirective *
6013   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6014          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6015          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6016 
6017   /// Creates an empty directive with a place for \a NumClauses clauses.
6018   ///
6019   /// \param C AST context.
6020   /// \param NumClauses Number of clauses.
6021   /// \param CollapsedNum Number of collapsed nested loops.
6022   ///
6023   static OMPGenericLoopDirective *CreateEmpty(const ASTContext &C,
6024                                               unsigned NumClauses,
6025                                               unsigned CollapsedNum,
6026                                               EmptyShell);
6027 
classof(const Stmt * T)6028   static bool classof(const Stmt *T) {
6029     return T->getStmtClass() == OMPGenericLoopDirectiveClass;
6030   }
6031 };
6032 
6033 /// This represents '#pragma omp teams loop' directive.
6034 ///
6035 /// \code
6036 /// #pragma omp teams loop private(a,b) order(concurrent)
6037 /// \endcode
6038 /// In this example directive '#pragma omp teams loop' has
6039 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6040 ///
6041 class OMPTeamsGenericLoopDirective final : public OMPLoopDirective {
6042   friend class ASTStmtReader;
6043   friend class OMPExecutableDirective;
6044   /// Build directive with the given start and end location.
6045   ///
6046   /// \param StartLoc Starting location of the directive kind.
6047   /// \param EndLoc Ending location of the directive.
6048   /// \param CollapsedNum Number of collapsed nested loops.
6049   ///
OMPTeamsGenericLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)6050   OMPTeamsGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
6051                                unsigned CollapsedNum)
6052       : OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass,
6053                          llvm::omp::OMPD_teams_loop, StartLoc, EndLoc,
6054                          CollapsedNum) {}
6055 
6056   /// Build an empty directive.
6057   ///
6058   /// \param CollapsedNum Number of collapsed nested loops.
6059   ///
OMPTeamsGenericLoopDirective(unsigned CollapsedNum)6060   explicit OMPTeamsGenericLoopDirective(unsigned CollapsedNum)
6061       : OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass,
6062                          llvm::omp::OMPD_teams_loop, SourceLocation(),
6063                          SourceLocation(), CollapsedNum) {}
6064 
6065 public:
6066   /// Creates directive with a list of \p Clauses.
6067   ///
6068   /// \param C AST context.
6069   /// \param StartLoc Starting location of the directive kind.
6070   /// \param EndLoc Ending Location of the directive.
6071   /// \param CollapsedNum Number of collapsed loops.
6072   /// \param Clauses List of clauses.
6073   /// \param AssociatedStmt Statement, associated with the directive.
6074   /// \param Exprs Helper expressions for CodeGen.
6075   ///
6076   static OMPTeamsGenericLoopDirective *
6077   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6078          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6079          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6080 
6081   /// Creates an empty directive with the place
6082   /// for \a NumClauses clauses.
6083   ///
6084   /// \param C AST context.
6085   /// \param CollapsedNum Number of collapsed nested loops.
6086   /// \param NumClauses Number of clauses.
6087   ///
6088   static OMPTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C,
6089                                                    unsigned NumClauses,
6090                                                    unsigned CollapsedNum,
6091                                                    EmptyShell);
6092 
classof(const Stmt * T)6093   static bool classof(const Stmt *T) {
6094     return T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass;
6095   }
6096 };
6097 
6098 /// This represents '#pragma omp target teams loop' directive.
6099 ///
6100 /// \code
6101 /// #pragma omp target teams loop private(a,b) order(concurrent)
6102 /// \endcode
6103 /// In this example directive '#pragma omp target teams loop' has
6104 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6105 ///
6106 class OMPTargetTeamsGenericLoopDirective final : public OMPLoopDirective {
6107   friend class ASTStmtReader;
6108   friend class OMPExecutableDirective;
6109   /// Build directive with the given start and end location.
6110   ///
6111   /// \param StartLoc Starting location of the directive kind.
6112   /// \param EndLoc Ending location of the directive.
6113   /// \param CollapsedNum Number of collapsed nested loops.
6114   ///
OMPTargetTeamsGenericLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)6115   OMPTargetTeamsGenericLoopDirective(SourceLocation StartLoc,
6116                                      SourceLocation EndLoc,
6117                                      unsigned CollapsedNum)
6118       : OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass,
6119                          llvm::omp::OMPD_target_teams_loop, StartLoc, EndLoc,
6120                          CollapsedNum) {}
6121 
6122   /// Build an empty directive.
6123   ///
6124   /// \param CollapsedNum Number of collapsed nested loops.
6125   ///
OMPTargetTeamsGenericLoopDirective(unsigned CollapsedNum)6126   explicit OMPTargetTeamsGenericLoopDirective(unsigned CollapsedNum)
6127       : OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass,
6128                          llvm::omp::OMPD_target_teams_loop, SourceLocation(),
6129                          SourceLocation(), CollapsedNum) {}
6130 
6131 public:
6132   /// Creates directive with a list of \p Clauses.
6133   ///
6134   /// \param C AST context.
6135   /// \param StartLoc Starting location of the directive kind.
6136   /// \param EndLoc Ending Location of the directive.
6137   /// \param CollapsedNum Number of collapsed loops.
6138   /// \param Clauses List of clauses.
6139   /// \param AssociatedStmt Statement, associated with the directive.
6140   /// \param Exprs Helper expressions for CodeGen.
6141   ///
6142   static OMPTargetTeamsGenericLoopDirective *
6143   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6144          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6145          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6146 
6147   /// Creates an empty directive with the place
6148   /// for \a NumClauses clauses.
6149   ///
6150   /// \param C AST context.
6151   /// \param CollapsedNum Number of collapsed nested loops.
6152   /// \param NumClauses Number of clauses.
6153   ///
6154   static OMPTargetTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C,
6155                                                          unsigned NumClauses,
6156                                                          unsigned CollapsedNum,
6157                                                          EmptyShell);
6158 
classof(const Stmt * T)6159   static bool classof(const Stmt *T) {
6160     return T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass;
6161   }
6162 };
6163 
6164 /// This represents '#pragma omp parallel loop' directive.
6165 ///
6166 /// \code
6167 /// #pragma omp parallel loop private(a,b) order(concurrent)
6168 /// \endcode
6169 /// In this example directive '#pragma omp parallel loop' has
6170 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6171 ///
6172 class OMPParallelGenericLoopDirective final : public OMPLoopDirective {
6173   friend class ASTStmtReader;
6174   friend class OMPExecutableDirective;
6175   /// Build directive with the given start and end location.
6176   ///
6177   /// \param StartLoc Starting location of the directive kind.
6178   /// \param EndLoc Ending location of the directive.
6179   /// \param CollapsedNum Number of collapsed nested loops.
6180   ///
OMPParallelGenericLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)6181   OMPParallelGenericLoopDirective(SourceLocation StartLoc,
6182                                   SourceLocation EndLoc, unsigned CollapsedNum)
6183       : OMPLoopDirective(OMPParallelGenericLoopDirectiveClass,
6184                          llvm::omp::OMPD_parallel_loop, StartLoc, EndLoc,
6185                          CollapsedNum) {}
6186 
6187   /// Build an empty directive.
6188   ///
6189   /// \param CollapsedNum Number of collapsed nested loops.
6190   ///
OMPParallelGenericLoopDirective(unsigned CollapsedNum)6191   explicit OMPParallelGenericLoopDirective(unsigned CollapsedNum)
6192       : OMPLoopDirective(OMPParallelGenericLoopDirectiveClass,
6193                          llvm::omp::OMPD_parallel_loop, SourceLocation(),
6194                          SourceLocation(), CollapsedNum) {}
6195 
6196 public:
6197   /// Creates directive with a list of \p Clauses.
6198   ///
6199   /// \param C AST context.
6200   /// \param StartLoc Starting location of the directive kind.
6201   /// \param EndLoc Ending Location of the directive.
6202   /// \param CollapsedNum Number of collapsed loops.
6203   /// \param Clauses List of clauses.
6204   /// \param AssociatedStmt Statement, associated with the directive.
6205   /// \param Exprs Helper expressions for CodeGen.
6206   ///
6207   static OMPParallelGenericLoopDirective *
6208   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6209          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6210          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6211 
6212   /// Creates an empty directive with the place
6213   /// for \a NumClauses clauses.
6214   ///
6215   /// \param C AST context.
6216   /// \param CollapsedNum Number of collapsed nested loops.
6217   /// \param NumClauses Number of clauses.
6218   ///
6219   static OMPParallelGenericLoopDirective *CreateEmpty(const ASTContext &C,
6220                                                       unsigned NumClauses,
6221                                                       unsigned CollapsedNum,
6222                                                       EmptyShell);
6223 
classof(const Stmt * T)6224   static bool classof(const Stmt *T) {
6225     return T->getStmtClass() == OMPParallelGenericLoopDirectiveClass;
6226   }
6227 };
6228 
6229 /// This represents '#pragma omp target parallel loop' directive.
6230 ///
6231 /// \code
6232 /// #pragma omp target parallel loop private(a,b) order(concurrent)
6233 /// \endcode
6234 /// In this example directive '#pragma omp target parallel loop' has
6235 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6236 ///
6237 class OMPTargetParallelGenericLoopDirective final : public OMPLoopDirective {
6238   friend class ASTStmtReader;
6239   friend class OMPExecutableDirective;
6240   /// Build directive with the given start and end location.
6241   ///
6242   /// \param StartLoc Starting location of the directive kind.
6243   /// \param EndLoc Ending location of the directive.
6244   /// \param CollapsedNum Number of collapsed nested loops.
6245   ///
OMPTargetParallelGenericLoopDirective(SourceLocation StartLoc,SourceLocation EndLoc,unsigned CollapsedNum)6246   OMPTargetParallelGenericLoopDirective(SourceLocation StartLoc,
6247                                         SourceLocation EndLoc,
6248                                         unsigned CollapsedNum)
6249       : OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass,
6250                          llvm::omp::OMPD_target_parallel_loop, StartLoc, EndLoc,
6251                          CollapsedNum) {}
6252 
6253   /// Build an empty directive.
6254   ///
6255   /// \param CollapsedNum Number of collapsed nested loops.
6256   ///
OMPTargetParallelGenericLoopDirective(unsigned CollapsedNum)6257   explicit OMPTargetParallelGenericLoopDirective(unsigned CollapsedNum)
6258       : OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass,
6259                          llvm::omp::OMPD_target_parallel_loop, SourceLocation(),
6260                          SourceLocation(), CollapsedNum) {}
6261 
6262 public:
6263   /// Creates directive with a list of \p Clauses.
6264   ///
6265   /// \param C AST context.
6266   /// \param StartLoc Starting location of the directive kind.
6267   /// \param EndLoc Ending Location of the directive.
6268   /// \param CollapsedNum Number of collapsed loops.
6269   /// \param Clauses List of clauses.
6270   /// \param AssociatedStmt Statement, associated with the directive.
6271   /// \param Exprs Helper expressions for CodeGen.
6272   ///
6273   static OMPTargetParallelGenericLoopDirective *
6274   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6275          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6276          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6277 
6278   /// Creates an empty directive with the place
6279   /// for \a NumClauses clauses.
6280   ///
6281   /// \param C AST context.
6282   /// \param CollapsedNum Number of collapsed nested loops.
6283   /// \param NumClauses Number of clauses.
6284   ///
6285   static OMPTargetParallelGenericLoopDirective *
6286   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
6287               EmptyShell);
6288 
classof(const Stmt * T)6289   static bool classof(const Stmt *T) {
6290     return T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass;
6291   }
6292 };
6293 
6294 /// This represents '#pragma omp error' directive.
6295 ///
6296 /// \code
6297 /// #pragma omp error
6298 /// \endcode
6299 class OMPErrorDirective final : public OMPExecutableDirective {
6300   friend class ASTStmtReader;
6301   friend class OMPExecutableDirective;
6302   /// Build directive with the given start and end location.
6303   ///
6304   /// \param StartLoc Starting location of the directive kind.
6305   /// \param EndLoc Ending location of the directive.
6306   ///
OMPErrorDirective(SourceLocation StartLoc,SourceLocation EndLoc)6307   OMPErrorDirective(SourceLocation StartLoc, SourceLocation EndLoc)
6308       : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error,
6309                                StartLoc, EndLoc) {}
6310   /// Build an empty directive.
6311   ///
OMPErrorDirective()6312   explicit OMPErrorDirective()
6313       : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error,
6314                                SourceLocation(), SourceLocation()) {}
6315 
6316 public:
6317   ///
6318   /// \param C AST context.
6319   /// \param StartLoc Starting location of the directive kind.
6320   /// \param EndLoc Ending Location of the directive.
6321   /// \param Clauses List of clauses.
6322   ///
6323   static OMPErrorDirective *Create(const ASTContext &C, SourceLocation StartLoc,
6324                                    SourceLocation EndLoc,
6325                                    ArrayRef<OMPClause *> Clauses);
6326 
6327   /// Creates an empty directive.
6328   ///
6329   /// \param C AST context.
6330   ///
6331   static OMPErrorDirective *CreateEmpty(const ASTContext &C,
6332                                         unsigned NumClauses, EmptyShell);
6333 
classof(const Stmt * T)6334   static bool classof(const Stmt *T) {
6335     return T->getStmtClass() == OMPErrorDirectiveClass;
6336   }
6337 };
6338 } // end namespace clang
6339 
6340 #endif
6341