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