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