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