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