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