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