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