Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:43

0001 //===- StmtOpenMP.h - Classes for OpenMP directives  ------------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 /// \file
0009 /// This file defines OpenMP AST classes for executable directives and
0010 /// clauses.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_AST_STMTOPENMP_H
0015 #define LLVM_CLANG_AST_STMTOPENMP_H
0016 
0017 #include "clang/AST/ASTContext.h"
0018 #include "clang/AST/Expr.h"
0019 #include "clang/AST/OpenMPClause.h"
0020 #include "clang/AST/Stmt.h"
0021 #include "clang/AST/StmtCXX.h"
0022 #include "clang/Basic/OpenMPKinds.h"
0023 #include "clang/Basic/SourceLocation.h"
0024 
0025 namespace clang {
0026 
0027 //===----------------------------------------------------------------------===//
0028 // AST classes for directives.
0029 //===----------------------------------------------------------------------===//
0030 
0031 /// Representation of an OpenMP canonical loop.
0032 ///
0033 /// OpenMP 1.0 C/C++, section 2.4.1 for Construct; canonical-shape
0034 /// OpenMP 2.0 C/C++, section 2.4.1 for Construct; canonical-shape
0035 /// OpenMP 2.5, section 2.5.1 Loop Construct; canonical form
0036 /// OpenMP 3.1, section 2.5.1 Loop Construct; canonical form
0037 /// OpenMP 4.0, section 2.6 Canonical Loop Form
0038 /// OpenMP 4.5, section 2.6 Canonical Loop Form
0039 /// OpenMP 5.0, section 2.9.1 Canonical Loop Form
0040 /// OpenMP 5.1, section 2.11.1 Canonical Loop Nest Form
0041 ///
0042 /// An OpenMP canonical loop is a for-statement or range-based for-statement
0043 /// with additional requirements that ensure that the number of iterations is
0044 /// known before entering the loop and allow skipping to an arbitrary iteration.
0045 /// The OMPCanonicalLoop AST node wraps a ForStmt or CXXForRangeStmt that is
0046 /// known to fulfill OpenMP's canonical loop requirements because of being
0047 /// associated to an OMPLoopBasedDirective. That is, the general structure is:
0048 ///
0049 ///  OMPLoopBasedDirective
0050 /// [`- CapturedStmt   ]
0051 /// [   `- CapturedDecl]
0052 ///        ` OMPCanonicalLoop
0053 ///          `- ForStmt/CXXForRangeStmt
0054 ///             `- Stmt
0055 ///
0056 /// One or multiple CapturedStmt/CapturedDecl pairs may be inserted by some
0057 /// directives such as OMPParallelForDirective, but others do not need them
0058 /// (such as OMPTileDirective). In  The OMPCanonicalLoop and
0059 /// ForStmt/CXXForRangeStmt pair is repeated for loop associated with the
0060 /// directive. A OMPCanonicalLoop must not appear in the AST unless associated
0061 /// with a OMPLoopBasedDirective. In an imperfectly nested loop nest, the
0062 /// OMPCanonicalLoop may also be wrapped in a CompoundStmt:
0063 ///
0064 /// [...]
0065 ///  ` OMPCanonicalLoop
0066 ///    `- ForStmt/CXXForRangeStmt
0067 ///       `- CompoundStmt
0068 ///          |- Leading in-between code (if any)
0069 ///          |- OMPCanonicalLoop
0070 ///          |  `- ForStmt/CXXForRangeStmt
0071 ///          |     `- ...
0072 ///          `- Trailing in-between code (if any)
0073 ///
0074 /// The leading/trailing in-between code must not itself be a OMPCanonicalLoop
0075 /// to avoid confusion which loop belongs to the nesting.
0076 ///
0077 /// There are three different kinds of iteration variables for different
0078 /// purposes:
0079 /// * Loop user variable: The user-accessible variable with different value for
0080 ///   each iteration.
0081 /// * Loop iteration variable: The variable used to identify a loop iteration;
0082 ///   for range-based for-statement, this is the hidden iterator '__begin'. For
0083 ///   other loops, it is identical to the loop user variable. Must be a
0084 ///   random-access iterator, pointer or integer type.
0085 /// * Logical iteration counter: Normalized loop counter starting at 0 and
0086 ///   incrementing by one at each iteration. Allows abstracting over the type
0087 ///   of the loop iteration variable and is always an unsigned integer type
0088 ///   appropriate to represent the range of the loop iteration variable. Its
0089 ///   value corresponds to the logical iteration number in the OpenMP
0090 ///   specification.
0091 ///
0092 /// This AST node provides two captured statements:
0093 /// * The distance function which computes the number of iterations.
0094 /// * The loop user variable function that computes the loop user variable when
0095 ///   given a logical iteration number.
0096 ///
0097 /// These captured statements provide the link between C/C++ semantics and the
0098 /// logical iteration counters used by the OpenMPIRBuilder which is
0099 /// language-agnostic and therefore does not know e.g. how to advance a
0100 /// random-access iterator. The OpenMPIRBuilder will use this information to
0101 /// apply simd, workshare-loop, distribute, taskloop and loop directives to the
0102 /// loop. For compatibility with the non-OpenMPIRBuilder codegen path, an
0103 /// OMPCanonicalLoop can itself also be wrapped into the CapturedStmts of an
0104 /// OMPLoopDirective and skipped when searching for the associated syntactical
0105 /// loop.
0106 ///
0107 /// Example:
0108 /// <code>
0109 ///   std::vector<std::string> Container{1,2,3};
0110 ///   for (std::string Str : Container)
0111 ///      Body(Str);
0112 /// </code>
0113 /// which is syntactic sugar for approximately:
0114 /// <code>
0115 ///   auto &&__range = Container;
0116 ///   auto __begin = std::begin(__range);
0117 ///   auto __end = std::end(__range);
0118 ///   for (; __begin != __end; ++__begin) {
0119 ///     std::String Str = *__begin;
0120 ///     Body(Str);
0121 ///   }
0122 /// </code>
0123 /// In this example, the loop user variable is `Str`, the loop iteration
0124 /// variable is `__begin` of type `std::vector<std::string>::iterator` and the
0125 /// logical iteration number type is `size_t` (unsigned version of
0126 /// `std::vector<std::string>::iterator::difference_type` aka `ptrdiff_t`).
0127 /// Therefore, the distance function will be
0128 /// <code>
0129 ///   [&](size_t &Result) { Result = __end - __begin; }
0130 /// </code>
0131 /// and the loop variable function is
0132 /// <code>
0133 ///   [&,__begin](std::vector<std::string>::iterator &Result, size_t Logical) {
0134 ///     Result = __begin + Logical;
0135 ///   }
0136 /// </code>
0137 /// The variable `__begin`, aka the loop iteration variable, is captured by
0138 /// value because it is modified in the loop body, but both functions require
0139 /// the initial value. The OpenMP specification explicitly leaves unspecified
0140 /// when the loop expressions are evaluated such that a capture by reference is
0141 /// sufficient.
0142 class OMPCanonicalLoop : public Stmt {
0143   friend class ASTStmtReader;
0144   friend class ASTStmtWriter;
0145 
0146   /// Children of this AST node.
0147   enum {
0148     LOOP_STMT,
0149     DISTANCE_FUNC,
0150     LOOPVAR_FUNC,
0151     LOOPVAR_REF,
0152     LastSubStmt = LOOPVAR_REF
0153   };
0154 
0155 private:
0156   /// This AST node's children.
0157   Stmt *SubStmts[LastSubStmt + 1] = {};
0158 
0159   OMPCanonicalLoop() : Stmt(StmtClass::OMPCanonicalLoopClass) {}
0160 
0161 public:
0162   /// Create a new OMPCanonicalLoop.
0163   static OMPCanonicalLoop *create(const ASTContext &Ctx, Stmt *LoopStmt,
0164                                   CapturedStmt *DistanceFunc,
0165                                   CapturedStmt *LoopVarFunc,
0166                                   DeclRefExpr *LoopVarRef) {
0167     OMPCanonicalLoop *S = new (Ctx) OMPCanonicalLoop();
0168     S->setLoopStmt(LoopStmt);
0169     S->setDistanceFunc(DistanceFunc);
0170     S->setLoopVarFunc(LoopVarFunc);
0171     S->setLoopVarRef(LoopVarRef);
0172     return S;
0173   }
0174 
0175   /// Create an empty OMPCanonicalLoop for deserialization.
0176   static OMPCanonicalLoop *createEmpty(const ASTContext &Ctx) {
0177     return new (Ctx) OMPCanonicalLoop();
0178   }
0179 
0180   static bool classof(const Stmt *S) {
0181     return S->getStmtClass() == StmtClass::OMPCanonicalLoopClass;
0182   }
0183 
0184   SourceLocation getBeginLoc() const { return getLoopStmt()->getBeginLoc(); }
0185   SourceLocation getEndLoc() const { return getLoopStmt()->getEndLoc(); }
0186 
0187   /// Return this AST node's children.
0188   /// @{
0189   child_range children() {
0190     return child_range(&SubStmts[0], &SubStmts[0] + LastSubStmt + 1);
0191   }
0192   const_child_range children() const {
0193     return const_child_range(&SubStmts[0], &SubStmts[0] + LastSubStmt + 1);
0194   }
0195   /// @}
0196 
0197   /// The wrapped syntactic loop statement (ForStmt or CXXForRangeStmt).
0198   /// @{
0199   Stmt *getLoopStmt() { return SubStmts[LOOP_STMT]; }
0200   const Stmt *getLoopStmt() const { return SubStmts[LOOP_STMT]; }
0201   void setLoopStmt(Stmt *S) {
0202     assert((isa<ForStmt>(S) || isa<CXXForRangeStmt>(S)) &&
0203            "Canonical loop must be a for loop (range-based or otherwise)");
0204     SubStmts[LOOP_STMT] = S;
0205   }
0206   /// @}
0207 
0208   /// The function that computes the number of loop iterations. Can be evaluated
0209   /// before entering the loop but after the syntactical loop's init
0210   /// statement(s).
0211   ///
0212   /// Function signature: void(LogicalTy &Result)
0213   /// Any values necessary to compute the distance are captures of the closure.
0214   /// @{
0215   CapturedStmt *getDistanceFunc() {
0216     return cast<CapturedStmt>(SubStmts[DISTANCE_FUNC]);
0217   }
0218   const CapturedStmt *getDistanceFunc() const {
0219     return cast<CapturedStmt>(SubStmts[DISTANCE_FUNC]);
0220   }
0221   void setDistanceFunc(CapturedStmt *S) {
0222     assert(S && "Expected non-null captured statement");
0223     SubStmts[DISTANCE_FUNC] = S;
0224   }
0225   /// @}
0226 
0227   /// The function that computes the loop user variable from a logical iteration
0228   /// counter. Can be evaluated as first statement in the loop.
0229   ///
0230   /// Function signature: void(LoopVarTy &Result, LogicalTy Number)
0231   /// Any other values required to compute the loop user variable (such as start
0232   /// value, step size) are captured by the closure. In particular, the initial
0233   /// value of loop iteration variable is captured by value to be unaffected by
0234   /// previous iterations.
0235   /// @{
0236   CapturedStmt *getLoopVarFunc() {
0237     return cast<CapturedStmt>(SubStmts[LOOPVAR_FUNC]);
0238   }
0239   const CapturedStmt *getLoopVarFunc() const {
0240     return cast<CapturedStmt>(SubStmts[LOOPVAR_FUNC]);
0241   }
0242   void setLoopVarFunc(CapturedStmt *S) {
0243     assert(S && "Expected non-null captured statement");
0244     SubStmts[LOOPVAR_FUNC] = S;
0245   }
0246   /// @}
0247 
0248   /// Reference to the loop user variable as accessed in the loop body.
0249   /// @{
0250   DeclRefExpr *getLoopVarRef() {
0251     return cast<DeclRefExpr>(SubStmts[LOOPVAR_REF]);
0252   }
0253   const DeclRefExpr *getLoopVarRef() const {
0254     return cast<DeclRefExpr>(SubStmts[LOOPVAR_REF]);
0255   }
0256   void setLoopVarRef(DeclRefExpr *E) {
0257     assert(E && "Expected non-null loop variable");
0258     SubStmts[LOOPVAR_REF] = E;
0259   }
0260   /// @}
0261 };
0262 
0263 /// This is a basic class for representing single OpenMP executable
0264 /// directive.
0265 ///
0266 class OMPExecutableDirective : public Stmt {
0267   friend class ASTStmtReader;
0268   friend class ASTStmtWriter;
0269 
0270   /// Kind of the directive.
0271   OpenMPDirectiveKind Kind = llvm::omp::OMPD_unknown;
0272   /// Starting location of the directive (directive keyword).
0273   SourceLocation StartLoc;
0274   /// Ending location of the directive.
0275   SourceLocation EndLoc;
0276 
0277   /// Get the clauses storage.
0278   MutableArrayRef<OMPClause *> getClauses() {
0279     if (!Data)
0280       return {};
0281     return Data->getClauses();
0282   }
0283 
0284 protected:
0285   /// Data, associated with the directive.
0286   OMPChildren *Data = nullptr;
0287 
0288   /// Build instance of directive of class \a K.
0289   ///
0290   /// \param SC Statement class.
0291   /// \param K Kind of OpenMP directive.
0292   /// \param StartLoc Starting location of the directive (directive keyword).
0293   /// \param EndLoc Ending location of the directive.
0294   ///
0295   OMPExecutableDirective(StmtClass SC, OpenMPDirectiveKind K,
0296                          SourceLocation StartLoc, SourceLocation EndLoc)
0297       : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)),
0298         EndLoc(std::move(EndLoc)) {}
0299 
0300   template <typename T, typename... Params>
0301   static T *createDirective(const ASTContext &C, ArrayRef<OMPClause *> Clauses,
0302                             Stmt *AssociatedStmt, unsigned NumChildren,
0303                             Params &&... P) {
0304     void *Mem =
0305         C.Allocate(sizeof(T) + OMPChildren::size(Clauses.size(), AssociatedStmt,
0306                                                  NumChildren),
0307                    alignof(T));
0308 
0309     auto *Data = OMPChildren::Create(reinterpret_cast<T *>(Mem) + 1, Clauses,
0310                                      AssociatedStmt, NumChildren);
0311     auto *Inst = new (Mem) T(std::forward<Params>(P)...);
0312     Inst->Data = Data;
0313     return Inst;
0314   }
0315 
0316   template <typename T, typename... Params>
0317   static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
0318                                  bool HasAssociatedStmt, unsigned NumChildren,
0319                                  Params &&... P) {
0320     void *Mem =
0321         C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
0322                                                  NumChildren),
0323                    alignof(T));
0324     auto *Data =
0325         OMPChildren::CreateEmpty(reinterpret_cast<T *>(Mem) + 1, NumClauses,
0326                                  HasAssociatedStmt, NumChildren);
0327     auto *Inst = new (Mem) T(std::forward<Params>(P)...);
0328     Inst->Data = Data;
0329     return Inst;
0330   }
0331 
0332   template <typename T>
0333   static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
0334                                  bool HasAssociatedStmt = false,
0335                                  unsigned NumChildren = 0) {
0336     void *Mem =
0337         C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
0338                                                  NumChildren),
0339                    alignof(T));
0340     auto *Data =
0341         OMPChildren::CreateEmpty(reinterpret_cast<T *>(Mem) + 1, NumClauses,
0342                                  HasAssociatedStmt, NumChildren);
0343     auto *Inst = new (Mem) T;
0344     Inst->Data = Data;
0345     return Inst;
0346   }
0347 
0348 public:
0349   /// Iterates over expressions/statements used in the construct.
0350   class used_clauses_child_iterator
0351       : public llvm::iterator_adaptor_base<
0352             used_clauses_child_iterator, ArrayRef<OMPClause *>::iterator,
0353             std::forward_iterator_tag, Stmt *, ptrdiff_t, Stmt *, Stmt *> {
0354     ArrayRef<OMPClause *>::iterator End;
0355     OMPClause::child_iterator ChildI, ChildEnd;
0356 
0357     void MoveToNext() {
0358       if (ChildI != ChildEnd)
0359         return;
0360       while (this->I != End) {
0361         ++this->I;
0362         if (this->I != End) {
0363           ChildI = (*this->I)->used_children().begin();
0364           ChildEnd = (*this->I)->used_children().end();
0365           if (ChildI != ChildEnd)
0366             return;
0367         }
0368       }
0369     }
0370 
0371   public:
0372     explicit used_clauses_child_iterator(ArrayRef<OMPClause *> Clauses)
0373         : used_clauses_child_iterator::iterator_adaptor_base(Clauses.begin()),
0374           End(Clauses.end()) {
0375       if (this->I != End) {
0376         ChildI = (*this->I)->used_children().begin();
0377         ChildEnd = (*this->I)->used_children().end();
0378         MoveToNext();
0379       }
0380     }
0381     Stmt *operator*() const { return *ChildI; }
0382     Stmt *operator->() const { return **this; }
0383 
0384     used_clauses_child_iterator &operator++() {
0385       ++ChildI;
0386       if (ChildI != ChildEnd)
0387         return *this;
0388       if (this->I != End) {
0389         ++this->I;
0390         if (this->I != End) {
0391           ChildI = (*this->I)->used_children().begin();
0392           ChildEnd = (*this->I)->used_children().end();
0393         }
0394       }
0395       MoveToNext();
0396       return *this;
0397     }
0398   };
0399 
0400   static llvm::iterator_range<used_clauses_child_iterator>
0401   used_clauses_children(ArrayRef<OMPClause *> Clauses) {
0402     return {
0403         used_clauses_child_iterator(Clauses),
0404         used_clauses_child_iterator(llvm::ArrayRef(Clauses.end(), (size_t)0))};
0405   }
0406 
0407   /// Iterates over a filtered subrange of clauses applied to a
0408   /// directive.
0409   ///
0410   /// This iterator visits only clauses of type SpecificClause.
0411   template <typename SpecificClause>
0412   class specific_clause_iterator
0413       : public llvm::iterator_adaptor_base<
0414             specific_clause_iterator<SpecificClause>,
0415             ArrayRef<OMPClause *>::const_iterator, std::forward_iterator_tag,
0416             const SpecificClause *, ptrdiff_t, const SpecificClause *,
0417             const SpecificClause *> {
0418     ArrayRef<OMPClause *>::const_iterator End;
0419 
0420     void SkipToNextClause() {
0421       while (this->I != End && !isa<SpecificClause>(*this->I))
0422         ++this->I;
0423     }
0424 
0425   public:
0426     explicit specific_clause_iterator(ArrayRef<OMPClause *> Clauses)
0427         : specific_clause_iterator::iterator_adaptor_base(Clauses.begin()),
0428           End(Clauses.end()) {
0429       SkipToNextClause();
0430     }
0431 
0432     const SpecificClause *operator*() const {
0433       return cast<SpecificClause>(*this->I);
0434     }
0435     const SpecificClause *operator->() const { return **this; }
0436 
0437     specific_clause_iterator &operator++() {
0438       ++this->I;
0439       SkipToNextClause();
0440       return *this;
0441     }
0442   };
0443 
0444   template <typename SpecificClause>
0445   static llvm::iterator_range<specific_clause_iterator<SpecificClause>>
0446   getClausesOfKind(ArrayRef<OMPClause *> Clauses) {
0447     return {specific_clause_iterator<SpecificClause>(Clauses),
0448             specific_clause_iterator<SpecificClause>(
0449                 llvm::ArrayRef(Clauses.end(), (size_t)0))};
0450   }
0451 
0452   template <typename SpecificClause>
0453   llvm::iterator_range<specific_clause_iterator<SpecificClause>>
0454   getClausesOfKind() const {
0455     return getClausesOfKind<SpecificClause>(clauses());
0456   }
0457 
0458   /// Gets a single clause of the specified kind associated with the
0459   /// current directive iff there is only one clause of this kind (and assertion
0460   /// is fired if there is more than one clause is associated with the
0461   /// directive). Returns nullptr if no clause of this kind is associated with
0462   /// the directive.
0463   template <typename SpecificClause>
0464   static const SpecificClause *getSingleClause(ArrayRef<OMPClause *> Clauses) {
0465     auto ClausesOfKind = getClausesOfKind<SpecificClause>(Clauses);
0466 
0467     if (ClausesOfKind.begin() != ClausesOfKind.end()) {
0468       assert(std::next(ClausesOfKind.begin()) == ClausesOfKind.end() &&
0469              "There are at least 2 clauses of the specified kind");
0470       return *ClausesOfKind.begin();
0471     }
0472     return nullptr;
0473   }
0474 
0475   template <typename SpecificClause>
0476   const SpecificClause *getSingleClause() const {
0477     return getSingleClause<SpecificClause>(clauses());
0478   }
0479 
0480   /// Returns true if the current directive has one or more clauses of a
0481   /// specific kind.
0482   template <typename SpecificClause>
0483   bool hasClausesOfKind() const {
0484     auto Clauses = getClausesOfKind<SpecificClause>();
0485     return Clauses.begin() != Clauses.end();
0486   }
0487 
0488   /// Returns starting location of directive kind.
0489   SourceLocation getBeginLoc() const { return StartLoc; }
0490   /// Returns ending location of directive.
0491   SourceLocation getEndLoc() const { return EndLoc; }
0492 
0493   /// Set starting location of directive kind.
0494   ///
0495   /// \param Loc New starting location of directive.
0496   ///
0497   void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
0498   /// Set ending location of directive.
0499   ///
0500   /// \param Loc New ending location of directive.
0501   ///
0502   void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
0503 
0504   /// Get number of clauses.
0505   unsigned getNumClauses() const {
0506     if (!Data)
0507       return 0;
0508     return Data->getNumClauses();
0509   }
0510 
0511   /// Returns specified clause.
0512   ///
0513   /// \param I Number of clause.
0514   ///
0515   OMPClause *getClause(unsigned I) const { return clauses()[I]; }
0516 
0517   /// Returns true if directive has associated statement.
0518   bool hasAssociatedStmt() const { return Data && Data->hasAssociatedStmt(); }
0519 
0520   /// Returns statement associated with the directive.
0521   const Stmt *getAssociatedStmt() const {
0522     return const_cast<OMPExecutableDirective *>(this)->getAssociatedStmt();
0523   }
0524   Stmt *getAssociatedStmt() {
0525     assert(hasAssociatedStmt() &&
0526            "Expected directive with the associated statement.");
0527     return Data->getAssociatedStmt();
0528   }
0529 
0530   /// Returns the captured statement associated with the
0531   /// component region within the (combined) directive.
0532   ///
0533   /// \param RegionKind Component region kind.
0534   const CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
0535     assert(hasAssociatedStmt() &&
0536            "Expected directive with the associated statement.");
0537     SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
0538     getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
0539     return Data->getCapturedStmt(RegionKind, CaptureRegions);
0540   }
0541 
0542   /// Get innermost captured statement for the construct.
0543   CapturedStmt *getInnermostCapturedStmt() {
0544     assert(hasAssociatedStmt() &&
0545            "Expected directive with the associated statement.");
0546     SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
0547     getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
0548     return Data->getInnermostCapturedStmt(CaptureRegions);
0549   }
0550 
0551   const CapturedStmt *getInnermostCapturedStmt() const {
0552     return const_cast<OMPExecutableDirective *>(this)
0553         ->getInnermostCapturedStmt();
0554   }
0555 
0556   OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
0557 
0558   static bool classof(const Stmt *S) {
0559     return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
0560            S->getStmtClass() <= lastOMPExecutableDirectiveConstant;
0561   }
0562 
0563   child_range children() {
0564     if (!Data)
0565       return child_range(child_iterator(), child_iterator());
0566     return Data->getAssociatedStmtAsRange();
0567   }
0568 
0569   const_child_range children() const {
0570     return const_cast<OMPExecutableDirective *>(this)->children();
0571   }
0572 
0573   ArrayRef<OMPClause *> clauses() const {
0574     if (!Data)
0575       return {};
0576     return Data->getClauses();
0577   }
0578 
0579   /// Returns whether or not this is a Standalone directive.
0580   ///
0581   /// Stand-alone directives are executable directives
0582   /// that have no associated user code.
0583   bool isStandaloneDirective() const;
0584 
0585   /// Returns the AST node representing OpenMP structured-block of this
0586   /// OpenMP executable directive,
0587   /// Prerequisite: Executable Directive must not be Standalone directive.
0588   const Stmt *getStructuredBlock() const {
0589     return const_cast<OMPExecutableDirective *>(this)->getStructuredBlock();
0590   }
0591   Stmt *getStructuredBlock();
0592 
0593   const Stmt *getRawStmt() const {
0594     return const_cast<OMPExecutableDirective *>(this)->getRawStmt();
0595   }
0596   Stmt *getRawStmt() {
0597     assert(hasAssociatedStmt() &&
0598            "Expected directive with the associated statement.");
0599     return Data->getRawStmt();
0600   }
0601 };
0602 
0603 /// This represents '#pragma omp parallel' directive.
0604 ///
0605 /// \code
0606 /// #pragma omp parallel private(a,b) reduction(+: c,d)
0607 /// \endcode
0608 /// In this example directive '#pragma omp parallel' has clauses 'private'
0609 /// with the variables 'a' and 'b' and 'reduction' with operator '+' and
0610 /// variables 'c' and 'd'.
0611 ///
0612 class OMPParallelDirective : public OMPExecutableDirective {
0613   friend class ASTStmtReader;
0614   friend class OMPExecutableDirective;
0615   /// true if the construct has inner cancel directive.
0616   bool HasCancel = false;
0617 
0618   /// Build directive with the given start and end location.
0619   ///
0620   /// \param StartLoc Starting location of the directive (directive keyword).
0621   /// \param EndLoc Ending Location of the directive.
0622   ///
0623   OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
0624       : OMPExecutableDirective(OMPParallelDirectiveClass,
0625                                llvm::omp::OMPD_parallel, StartLoc, EndLoc) {}
0626 
0627   /// Build an empty directive.
0628   ///
0629   explicit OMPParallelDirective()
0630       : OMPExecutableDirective(OMPParallelDirectiveClass,
0631                                llvm::omp::OMPD_parallel, SourceLocation(),
0632                                SourceLocation()) {}
0633 
0634   /// Sets special task reduction descriptor.
0635   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
0636 
0637   /// Set cancel state.
0638   void setHasCancel(bool Has) { HasCancel = Has; }
0639 
0640 public:
0641   /// Creates directive with a list of \a Clauses.
0642   ///
0643   /// \param C AST context.
0644   /// \param StartLoc Starting location of the directive kind.
0645   /// \param EndLoc Ending Location of the directive.
0646   /// \param Clauses List of clauses.
0647   /// \param AssociatedStmt Statement associated with the directive.
0648   /// \param TaskRedRef Task reduction special reference expression to handle
0649   /// taskgroup descriptor.
0650   /// \param HasCancel true if this directive has inner cancel directive.
0651   ///
0652   static OMPParallelDirective *
0653   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
0654          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
0655          bool HasCancel);
0656 
0657   /// Creates an empty directive with the place for \a N clauses.
0658   ///
0659   /// \param C AST context.
0660   /// \param NumClauses Number of clauses.
0661   ///
0662   static OMPParallelDirective *CreateEmpty(const ASTContext &C,
0663                                            unsigned NumClauses, EmptyShell);
0664 
0665   /// Returns special task reduction reference expression.
0666   Expr *getTaskReductionRefExpr() {
0667     return cast_or_null<Expr>(Data->getChildren()[0]);
0668   }
0669   const Expr *getTaskReductionRefExpr() const {
0670     return const_cast<OMPParallelDirective *>(this)->getTaskReductionRefExpr();
0671   }
0672 
0673   /// Return true if current directive has inner cancel directive.
0674   bool hasCancel() const { return HasCancel; }
0675 
0676   static bool classof(const Stmt *T) {
0677     return T->getStmtClass() == OMPParallelDirectiveClass;
0678   }
0679 };
0680 
0681 /// The base class for all loop-based directives, including loop transformation
0682 /// directives.
0683 class OMPLoopBasedDirective : public OMPExecutableDirective {
0684   friend class ASTStmtReader;
0685 
0686 protected:
0687   /// Number of collapsed loops as specified by 'collapse' clause.
0688   unsigned NumAssociatedLoops = 0;
0689 
0690   /// Build instance of loop directive of class \a Kind.
0691   ///
0692   /// \param SC Statement class.
0693   /// \param Kind Kind of OpenMP directive.
0694   /// \param StartLoc Starting location of the directive (directive keyword).
0695   /// \param EndLoc Ending location of the directive.
0696   /// \param NumAssociatedLoops Number of loops associated with the construct.
0697   ///
0698   OMPLoopBasedDirective(StmtClass SC, OpenMPDirectiveKind Kind,
0699                         SourceLocation StartLoc, SourceLocation EndLoc,
0700                         unsigned NumAssociatedLoops)
0701       : OMPExecutableDirective(SC, Kind, StartLoc, EndLoc),
0702         NumAssociatedLoops(NumAssociatedLoops) {}
0703 
0704 public:
0705   /// The expressions built to support OpenMP loops in combined/composite
0706   /// pragmas (e.g. pragma omp distribute parallel for)
0707   struct DistCombinedHelperExprs {
0708     /// DistributeLowerBound - used when composing 'omp distribute' with
0709     /// 'omp for' in a same construct.
0710     Expr *LB;
0711     /// DistributeUpperBound - used when composing 'omp distribute' with
0712     /// 'omp for' in a same construct.
0713     Expr *UB;
0714     /// DistributeEnsureUpperBound - used when composing 'omp distribute'
0715     ///  with 'omp for' in a same construct, EUB depends on DistUB
0716     Expr *EUB;
0717     /// Distribute loop iteration variable init used when composing 'omp
0718     /// distribute'
0719     ///  with 'omp for' in a same construct
0720     Expr *Init;
0721     /// Distribute Loop condition used when composing 'omp distribute'
0722     ///  with 'omp for' in a same construct
0723     Expr *Cond;
0724     /// Update of LowerBound for statically scheduled omp loops for
0725     /// outer loop in combined constructs (e.g. 'distribute parallel for')
0726     Expr *NLB;
0727     /// Update of UpperBound for statically scheduled omp loops for
0728     /// outer loop in combined constructs (e.g. 'distribute parallel for')
0729     Expr *NUB;
0730     /// Distribute Loop condition used when composing 'omp distribute'
0731     ///  with 'omp for' in a same construct when schedule is chunked.
0732     Expr *DistCond;
0733     /// 'omp parallel for' loop condition used when composed with
0734     /// 'omp distribute' in the same construct and when schedule is
0735     /// chunked and the chunk size is 1.
0736     Expr *ParForInDistCond;
0737   };
0738 
0739   /// The expressions built for the OpenMP loop CodeGen for the
0740   /// whole collapsed loop nest.
0741   struct HelperExprs {
0742     /// Loop iteration variable.
0743     Expr *IterationVarRef;
0744     /// Loop last iteration number.
0745     Expr *LastIteration;
0746     /// Loop number of iterations.
0747     Expr *NumIterations;
0748     /// Calculation of last iteration.
0749     Expr *CalcLastIteration;
0750     /// Loop pre-condition.
0751     Expr *PreCond;
0752     /// Loop condition.
0753     Expr *Cond;
0754     /// Loop iteration variable init.
0755     Expr *Init;
0756     /// Loop increment.
0757     Expr *Inc;
0758     /// IsLastIteration - local flag variable passed to runtime.
0759     Expr *IL;
0760     /// LowerBound - local variable passed to runtime.
0761     Expr *LB;
0762     /// UpperBound - local variable passed to runtime.
0763     Expr *UB;
0764     /// Stride - local variable passed to runtime.
0765     Expr *ST;
0766     /// EnsureUpperBound -- expression UB = min(UB, NumIterations).
0767     Expr *EUB;
0768     /// Update of LowerBound for statically scheduled 'omp for' loops.
0769     Expr *NLB;
0770     /// Update of UpperBound for statically scheduled 'omp for' loops.
0771     Expr *NUB;
0772     /// PreviousLowerBound - local variable passed to runtime in the
0773     /// enclosing schedule or null if that does not apply.
0774     Expr *PrevLB;
0775     /// PreviousUpperBound - local variable passed to runtime in the
0776     /// enclosing schedule or null if that does not apply.
0777     Expr *PrevUB;
0778     /// DistInc - increment expression for distribute loop when found
0779     /// combined with a further loop level (e.g. in 'distribute parallel for')
0780     /// expression IV = IV + ST
0781     Expr *DistInc;
0782     /// PrevEUB - expression similar to EUB but to be used when loop
0783     /// scheduling uses PrevLB and PrevUB (e.g.  in 'distribute parallel for'
0784     /// when ensuring that the UB is either the calculated UB by the runtime or
0785     /// the end of the assigned distribute chunk)
0786     /// expression UB = min (UB, PrevUB)
0787     Expr *PrevEUB;
0788     /// Counters Loop counters.
0789     SmallVector<Expr *, 4> Counters;
0790     /// PrivateCounters Loop counters.
0791     SmallVector<Expr *, 4> PrivateCounters;
0792     /// Expressions for loop counters inits for CodeGen.
0793     SmallVector<Expr *, 4> Inits;
0794     /// Expressions for loop counters update for CodeGen.
0795     SmallVector<Expr *, 4> Updates;
0796     /// Final loop counter values for GodeGen.
0797     SmallVector<Expr *, 4> Finals;
0798     /// List of counters required for the generation of the non-rectangular
0799     /// loops.
0800     SmallVector<Expr *, 4> DependentCounters;
0801     /// List of initializers required for the generation of the non-rectangular
0802     /// loops.
0803     SmallVector<Expr *, 4> DependentInits;
0804     /// List of final conditions required for the generation of the
0805     /// non-rectangular loops.
0806     SmallVector<Expr *, 4> FinalsConditions;
0807     /// Init statement for all captured expressions.
0808     Stmt *PreInits;
0809 
0810     /// Expressions used when combining OpenMP loop pragmas
0811     DistCombinedHelperExprs DistCombinedFields;
0812 
0813     /// Check if all the expressions are built (does not check the
0814     /// worksharing ones).
0815     bool builtAll() {
0816       return IterationVarRef != nullptr && LastIteration != nullptr &&
0817              NumIterations != nullptr && PreCond != nullptr &&
0818              Cond != nullptr && Init != nullptr && Inc != nullptr;
0819     }
0820 
0821     /// Initialize all the fields to null.
0822     /// \param Size Number of elements in the
0823     /// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions
0824     /// arrays.
0825     void clear(unsigned Size) {
0826       IterationVarRef = nullptr;
0827       LastIteration = nullptr;
0828       CalcLastIteration = nullptr;
0829       PreCond = nullptr;
0830       Cond = nullptr;
0831       Init = nullptr;
0832       Inc = nullptr;
0833       IL = nullptr;
0834       LB = nullptr;
0835       UB = nullptr;
0836       ST = nullptr;
0837       EUB = nullptr;
0838       NLB = nullptr;
0839       NUB = nullptr;
0840       NumIterations = nullptr;
0841       PrevLB = nullptr;
0842       PrevUB = nullptr;
0843       DistInc = nullptr;
0844       PrevEUB = nullptr;
0845       Counters.resize(Size);
0846       PrivateCounters.resize(Size);
0847       Inits.resize(Size);
0848       Updates.resize(Size);
0849       Finals.resize(Size);
0850       DependentCounters.resize(Size);
0851       DependentInits.resize(Size);
0852       FinalsConditions.resize(Size);
0853       for (unsigned I = 0; I < Size; ++I) {
0854         Counters[I] = nullptr;
0855         PrivateCounters[I] = nullptr;
0856         Inits[I] = nullptr;
0857         Updates[I] = nullptr;
0858         Finals[I] = nullptr;
0859         DependentCounters[I] = nullptr;
0860         DependentInits[I] = nullptr;
0861         FinalsConditions[I] = nullptr;
0862       }
0863       PreInits = nullptr;
0864       DistCombinedFields.LB = nullptr;
0865       DistCombinedFields.UB = nullptr;
0866       DistCombinedFields.EUB = nullptr;
0867       DistCombinedFields.Init = nullptr;
0868       DistCombinedFields.Cond = nullptr;
0869       DistCombinedFields.NLB = nullptr;
0870       DistCombinedFields.NUB = nullptr;
0871       DistCombinedFields.DistCond = nullptr;
0872       DistCombinedFields.ParForInDistCond = nullptr;
0873     }
0874   };
0875 
0876   /// Get number of collapsed loops.
0877   unsigned getLoopsNumber() const { return NumAssociatedLoops; }
0878 
0879   /// Try to find the next loop sub-statement in the specified statement \p
0880   /// CurStmt.
0881   /// \param TryImperfectlyNestedLoops true, if we need to try to look for the
0882   /// imperfectly nested loop.
0883   static Stmt *tryToFindNextInnerLoop(Stmt *CurStmt,
0884                                       bool TryImperfectlyNestedLoops);
0885   static const Stmt *tryToFindNextInnerLoop(const Stmt *CurStmt,
0886                                             bool TryImperfectlyNestedLoops) {
0887     return tryToFindNextInnerLoop(const_cast<Stmt *>(CurStmt),
0888                                   TryImperfectlyNestedLoops);
0889   }
0890 
0891   /// Calls the specified callback function for all the loops in \p CurStmt,
0892   /// from the outermost to the innermost.
0893   static bool
0894   doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops,
0895                 unsigned NumLoops,
0896                 llvm::function_ref<bool(unsigned, Stmt *)> Callback,
0897                 llvm::function_ref<void(OMPLoopTransformationDirective *)>
0898                     OnTransformationCallback);
0899   static bool
0900   doForAllLoops(const Stmt *CurStmt, bool TryImperfectlyNestedLoops,
0901                 unsigned NumLoops,
0902                 llvm::function_ref<bool(unsigned, const Stmt *)> Callback,
0903                 llvm::function_ref<void(const OMPLoopTransformationDirective *)>
0904                     OnTransformationCallback) {
0905     auto &&NewCallback = [Callback](unsigned Cnt, Stmt *CurStmt) {
0906       return Callback(Cnt, CurStmt);
0907     };
0908     auto &&NewTransformCb =
0909         [OnTransformationCallback](OMPLoopTransformationDirective *A) {
0910           OnTransformationCallback(A);
0911         };
0912     return doForAllLoops(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
0913                          NumLoops, NewCallback, NewTransformCb);
0914   }
0915 
0916   /// Calls the specified callback function for all the loops in \p CurStmt,
0917   /// from the outermost to the innermost.
0918   static bool
0919   doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops,
0920                 unsigned NumLoops,
0921                 llvm::function_ref<bool(unsigned, Stmt *)> Callback) {
0922     auto &&TransformCb = [](OMPLoopTransformationDirective *) {};
0923     return doForAllLoops(CurStmt, TryImperfectlyNestedLoops, NumLoops, Callback,
0924                          TransformCb);
0925   }
0926   static bool
0927   doForAllLoops(const Stmt *CurStmt, bool TryImperfectlyNestedLoops,
0928                 unsigned NumLoops,
0929                 llvm::function_ref<bool(unsigned, const Stmt *)> Callback) {
0930     auto &&NewCallback = [Callback](unsigned Cnt, const Stmt *CurStmt) {
0931       return Callback(Cnt, CurStmt);
0932     };
0933     return doForAllLoops(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
0934                          NumLoops, NewCallback);
0935   }
0936 
0937   /// Calls the specified callback function for all the loop bodies in \p
0938   /// CurStmt, from the outermost loop to the innermost.
0939   static void doForAllLoopsBodies(
0940       Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
0941       llvm::function_ref<void(unsigned, Stmt *, Stmt *)> Callback);
0942   static void doForAllLoopsBodies(
0943       const Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
0944       llvm::function_ref<void(unsigned, const Stmt *, const Stmt *)> Callback) {
0945     auto &&NewCallback = [Callback](unsigned Cnt, Stmt *Loop, Stmt *Body) {
0946       Callback(Cnt, Loop, Body);
0947     };
0948     doForAllLoopsBodies(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
0949                         NumLoops, NewCallback);
0950   }
0951 
0952   static bool classof(const Stmt *T) {
0953     if (auto *D = dyn_cast<OMPExecutableDirective>(T))
0954       return isOpenMPLoopDirective(D->getDirectiveKind());
0955     return false;
0956   }
0957 };
0958 
0959 /// The base class for all loop transformation directives.
0960 class OMPLoopTransformationDirective : public OMPLoopBasedDirective {
0961   friend class ASTStmtReader;
0962 
0963   /// Number of loops generated by this loop transformation.
0964   unsigned NumGeneratedLoops = 0;
0965 
0966 protected:
0967   explicit OMPLoopTransformationDirective(StmtClass SC,
0968                                           OpenMPDirectiveKind Kind,
0969                                           SourceLocation StartLoc,
0970                                           SourceLocation EndLoc,
0971                                           unsigned NumAssociatedLoops)
0972       : OMPLoopBasedDirective(SC, Kind, StartLoc, EndLoc, NumAssociatedLoops) {}
0973 
0974   /// Set the number of loops generated by this loop transformation.
0975   void setNumGeneratedLoops(unsigned Num) { NumGeneratedLoops = Num; }
0976 
0977 public:
0978   /// Return the number of associated (consumed) loops.
0979   unsigned getNumAssociatedLoops() const { return getLoopsNumber(); }
0980 
0981   /// Return the number of loops generated by this loop transformation.
0982   unsigned getNumGeneratedLoops() const { return NumGeneratedLoops; }
0983 
0984   /// Get the de-sugared statements after the loop transformation.
0985   ///
0986   /// Might be nullptr if either the directive generates no loops and is handled
0987   /// directly in CodeGen, or resolving a template-dependence context is
0988   /// required.
0989   Stmt *getTransformedStmt() const;
0990 
0991   /// Return preinits statement.
0992   Stmt *getPreInits() const;
0993 
0994   static bool classof(const Stmt *T) {
0995     Stmt::StmtClass C = T->getStmtClass();
0996     return C == OMPTileDirectiveClass || C == OMPUnrollDirectiveClass ||
0997            C == OMPReverseDirectiveClass || C == OMPInterchangeDirectiveClass;
0998   }
0999 };
1000 
1001 /// This is a common base class for loop directives ('omp simd', 'omp
1002 /// for', 'omp for simd' etc.). It is responsible for the loop code generation.
1003 ///
1004 class OMPLoopDirective : public OMPLoopBasedDirective {
1005   friend class ASTStmtReader;
1006 
1007   /// Offsets to the stored exprs.
1008   /// This enumeration contains offsets to all the pointers to children
1009   /// expressions stored in OMPLoopDirective.
1010   /// The first 9 children are necessary for all the loop directives,
1011   /// the next 8 are specific to the worksharing ones, and the next 11 are
1012   /// used for combined constructs containing two pragmas associated to loops.
1013   /// After the fixed children, three arrays of length NumAssociatedLoops are
1014   /// allocated: loop counters, their updates and final values.
1015   /// PrevLowerBound and PrevUpperBound are used to communicate blocking
1016   /// information in composite constructs which require loop blocking
1017   /// DistInc is used to generate the increment expression for the distribute
1018   /// loop when combined with a further nested loop
1019   /// PrevEnsureUpperBound is used as the EnsureUpperBound expression for the
1020   /// for loop when combined with a previous distribute loop in the same pragma
1021   /// (e.g. 'distribute parallel for')
1022   ///
1023   enum {
1024     IterationVariableOffset = 0,
1025     LastIterationOffset = 1,
1026     CalcLastIterationOffset = 2,
1027     PreConditionOffset = 3,
1028     CondOffset = 4,
1029     InitOffset = 5,
1030     IncOffset = 6,
1031     PreInitsOffset = 7,
1032     // The '...End' enumerators do not correspond to child expressions - they
1033     // specify the offset to the end (and start of the following counters/
1034     // updates/finals/dependent_counters/dependent_inits/finals_conditions
1035     // arrays).
1036     DefaultEnd = 8,
1037     // The following 8 exprs are used by worksharing and distribute loops only.
1038     IsLastIterVariableOffset = 8,
1039     LowerBoundVariableOffset = 9,
1040     UpperBoundVariableOffset = 10,
1041     StrideVariableOffset = 11,
1042     EnsureUpperBoundOffset = 12,
1043     NextLowerBoundOffset = 13,
1044     NextUpperBoundOffset = 14,
1045     NumIterationsOffset = 15,
1046     // Offset to the end for worksharing loop directives.
1047     WorksharingEnd = 16,
1048     PrevLowerBoundVariableOffset = 16,
1049     PrevUpperBoundVariableOffset = 17,
1050     DistIncOffset = 18,
1051     PrevEnsureUpperBoundOffset = 19,
1052     CombinedLowerBoundVariableOffset = 20,
1053     CombinedUpperBoundVariableOffset = 21,
1054     CombinedEnsureUpperBoundOffset = 22,
1055     CombinedInitOffset = 23,
1056     CombinedConditionOffset = 24,
1057     CombinedNextLowerBoundOffset = 25,
1058     CombinedNextUpperBoundOffset = 26,
1059     CombinedDistConditionOffset = 27,
1060     CombinedParForInDistConditionOffset = 28,
1061     // Offset to the end (and start of the following
1062     // counters/updates/finals/dependent_counters/dependent_inits/finals_conditions
1063     // arrays) for combined distribute loop directives.
1064     CombinedDistributeEnd = 29,
1065   };
1066 
1067   /// Get the counters storage.
1068   MutableArrayRef<Expr *> getCounters() {
1069     auto **Storage = reinterpret_cast<Expr **>(
1070         &Data->getChildren()[getArraysOffset(getDirectiveKind())]);
1071     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1072   }
1073 
1074   /// Get the private counters storage.
1075   MutableArrayRef<Expr *> getPrivateCounters() {
1076     auto **Storage = reinterpret_cast<Expr **>(
1077         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1078                              getLoopsNumber()]);
1079     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1080   }
1081 
1082   /// Get the updates storage.
1083   MutableArrayRef<Expr *> getInits() {
1084     auto **Storage = reinterpret_cast<Expr **>(
1085         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1086                              2 * getLoopsNumber()]);
1087     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1088   }
1089 
1090   /// Get the updates storage.
1091   MutableArrayRef<Expr *> getUpdates() {
1092     auto **Storage = reinterpret_cast<Expr **>(
1093         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1094                              3 * getLoopsNumber()]);
1095     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1096   }
1097 
1098   /// Get the final counter updates storage.
1099   MutableArrayRef<Expr *> getFinals() {
1100     auto **Storage = reinterpret_cast<Expr **>(
1101         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1102                              4 * getLoopsNumber()]);
1103     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1104   }
1105 
1106   /// Get the dependent counters storage.
1107   MutableArrayRef<Expr *> getDependentCounters() {
1108     auto **Storage = reinterpret_cast<Expr **>(
1109         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1110                              5 * getLoopsNumber()]);
1111     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1112   }
1113 
1114   /// Get the dependent inits storage.
1115   MutableArrayRef<Expr *> getDependentInits() {
1116     auto **Storage = reinterpret_cast<Expr **>(
1117         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1118                              6 * getLoopsNumber()]);
1119     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1120   }
1121 
1122   /// Get the finals conditions storage.
1123   MutableArrayRef<Expr *> getFinalsConditions() {
1124     auto **Storage = reinterpret_cast<Expr **>(
1125         &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1126                              7 * getLoopsNumber()]);
1127     return llvm::MutableArrayRef(Storage, getLoopsNumber());
1128   }
1129 
1130 protected:
1131   /// Build instance of loop directive of class \a Kind.
1132   ///
1133   /// \param SC Statement class.
1134   /// \param Kind Kind of OpenMP directive.
1135   /// \param StartLoc Starting location of the directive (directive keyword).
1136   /// \param EndLoc Ending location of the directive.
1137   /// \param CollapsedNum Number of collapsed loops from 'collapse' clause.
1138   ///
1139   OMPLoopDirective(StmtClass SC, OpenMPDirectiveKind Kind,
1140                    SourceLocation StartLoc, SourceLocation EndLoc,
1141                    unsigned CollapsedNum)
1142       : OMPLoopBasedDirective(SC, Kind, StartLoc, EndLoc, CollapsedNum) {}
1143 
1144   /// Offset to the start of children expression arrays.
1145   static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
1146     if (isOpenMPLoopBoundSharingDirective(Kind))
1147       return CombinedDistributeEnd;
1148     if (isOpenMPWorksharingDirective(Kind) || isOpenMPTaskLoopDirective(Kind) ||
1149         isOpenMPGenericLoopDirective(Kind) || isOpenMPDistributeDirective(Kind))
1150       return WorksharingEnd;
1151     return DefaultEnd;
1152   }
1153 
1154   /// Children number.
1155   static unsigned numLoopChildren(unsigned CollapsedNum,
1156                                   OpenMPDirectiveKind Kind) {
1157     return getArraysOffset(Kind) +
1158            8 * CollapsedNum; // Counters, PrivateCounters, Inits,
1159                              // Updates, Finals, DependentCounters,
1160                              // DependentInits, FinalsConditions.
1161   }
1162 
1163   void setIterationVariable(Expr *IV) {
1164     Data->getChildren()[IterationVariableOffset] = IV;
1165   }
1166   void setLastIteration(Expr *LI) {
1167     Data->getChildren()[LastIterationOffset] = LI;
1168   }
1169   void setCalcLastIteration(Expr *CLI) {
1170     Data->getChildren()[CalcLastIterationOffset] = CLI;
1171   }
1172   void setPreCond(Expr *PC) { Data->getChildren()[PreConditionOffset] = PC; }
1173   void setCond(Expr *Cond) { Data->getChildren()[CondOffset] = Cond; }
1174   void setInit(Expr *Init) { Data->getChildren()[InitOffset] = Init; }
1175   void setInc(Expr *Inc) { Data->getChildren()[IncOffset] = Inc; }
1176   void setPreInits(Stmt *PreInits) {
1177     Data->getChildren()[PreInitsOffset] = PreInits;
1178   }
1179   void setIsLastIterVariable(Expr *IL) {
1180     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1181             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1182             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1183             isOpenMPDistributeDirective(getDirectiveKind())) &&
1184            "expected worksharing loop directive");
1185     Data->getChildren()[IsLastIterVariableOffset] = IL;
1186   }
1187   void setLowerBoundVariable(Expr *LB) {
1188     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1189             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1190             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1191             isOpenMPDistributeDirective(getDirectiveKind())) &&
1192            "expected worksharing loop directive");
1193     Data->getChildren()[LowerBoundVariableOffset] = LB;
1194   }
1195   void setUpperBoundVariable(Expr *UB) {
1196     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1197             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1198             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1199             isOpenMPDistributeDirective(getDirectiveKind())) &&
1200            "expected worksharing loop directive");
1201     Data->getChildren()[UpperBoundVariableOffset] = UB;
1202   }
1203   void setStrideVariable(Expr *ST) {
1204     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1205             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1206             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1207             isOpenMPDistributeDirective(getDirectiveKind())) &&
1208            "expected worksharing loop directive");
1209     Data->getChildren()[StrideVariableOffset] = ST;
1210   }
1211   void setEnsureUpperBound(Expr *EUB) {
1212     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1213             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1214             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1215             isOpenMPDistributeDirective(getDirectiveKind())) &&
1216            "expected worksharing loop directive");
1217     Data->getChildren()[EnsureUpperBoundOffset] = EUB;
1218   }
1219   void setNextLowerBound(Expr *NLB) {
1220     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1221             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1222             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1223             isOpenMPDistributeDirective(getDirectiveKind())) &&
1224            "expected worksharing loop directive");
1225     Data->getChildren()[NextLowerBoundOffset] = NLB;
1226   }
1227   void setNextUpperBound(Expr *NUB) {
1228     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1229             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1230             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1231             isOpenMPDistributeDirective(getDirectiveKind())) &&
1232            "expected worksharing loop directive");
1233     Data->getChildren()[NextUpperBoundOffset] = NUB;
1234   }
1235   void setNumIterations(Expr *NI) {
1236     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1237             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1238             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1239             isOpenMPDistributeDirective(getDirectiveKind())) &&
1240            "expected worksharing loop directive");
1241     Data->getChildren()[NumIterationsOffset] = NI;
1242   }
1243   void setPrevLowerBoundVariable(Expr *PrevLB) {
1244     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1245            "expected loop bound sharing directive");
1246     Data->getChildren()[PrevLowerBoundVariableOffset] = PrevLB;
1247   }
1248   void setPrevUpperBoundVariable(Expr *PrevUB) {
1249     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1250            "expected loop bound sharing directive");
1251     Data->getChildren()[PrevUpperBoundVariableOffset] = PrevUB;
1252   }
1253   void setDistInc(Expr *DistInc) {
1254     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1255            "expected loop bound sharing directive");
1256     Data->getChildren()[DistIncOffset] = DistInc;
1257   }
1258   void setPrevEnsureUpperBound(Expr *PrevEUB) {
1259     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1260            "expected loop bound sharing directive");
1261     Data->getChildren()[PrevEnsureUpperBoundOffset] = PrevEUB;
1262   }
1263   void setCombinedLowerBoundVariable(Expr *CombLB) {
1264     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1265            "expected loop bound sharing directive");
1266     Data->getChildren()[CombinedLowerBoundVariableOffset] = CombLB;
1267   }
1268   void setCombinedUpperBoundVariable(Expr *CombUB) {
1269     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1270            "expected loop bound sharing directive");
1271     Data->getChildren()[CombinedUpperBoundVariableOffset] = CombUB;
1272   }
1273   void setCombinedEnsureUpperBound(Expr *CombEUB) {
1274     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1275            "expected loop bound sharing directive");
1276     Data->getChildren()[CombinedEnsureUpperBoundOffset] = CombEUB;
1277   }
1278   void setCombinedInit(Expr *CombInit) {
1279     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1280            "expected loop bound sharing directive");
1281     Data->getChildren()[CombinedInitOffset] = CombInit;
1282   }
1283   void setCombinedCond(Expr *CombCond) {
1284     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1285            "expected loop bound sharing directive");
1286     Data->getChildren()[CombinedConditionOffset] = CombCond;
1287   }
1288   void setCombinedNextLowerBound(Expr *CombNLB) {
1289     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1290            "expected loop bound sharing directive");
1291     Data->getChildren()[CombinedNextLowerBoundOffset] = CombNLB;
1292   }
1293   void setCombinedNextUpperBound(Expr *CombNUB) {
1294     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1295            "expected loop bound sharing directive");
1296     Data->getChildren()[CombinedNextUpperBoundOffset] = CombNUB;
1297   }
1298   void setCombinedDistCond(Expr *CombDistCond) {
1299     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1300            "expected loop bound distribute sharing directive");
1301     Data->getChildren()[CombinedDistConditionOffset] = CombDistCond;
1302   }
1303   void setCombinedParForInDistCond(Expr *CombParForInDistCond) {
1304     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1305            "expected loop bound distribute sharing directive");
1306     Data->getChildren()[CombinedParForInDistConditionOffset] =
1307         CombParForInDistCond;
1308   }
1309   void setCounters(ArrayRef<Expr *> A);
1310   void setPrivateCounters(ArrayRef<Expr *> A);
1311   void setInits(ArrayRef<Expr *> A);
1312   void setUpdates(ArrayRef<Expr *> A);
1313   void setFinals(ArrayRef<Expr *> A);
1314   void setDependentCounters(ArrayRef<Expr *> A);
1315   void setDependentInits(ArrayRef<Expr *> A);
1316   void setFinalsConditions(ArrayRef<Expr *> A);
1317 
1318 public:
1319   Expr *getIterationVariable() const {
1320     return cast<Expr>(Data->getChildren()[IterationVariableOffset]);
1321   }
1322   Expr *getLastIteration() const {
1323     return cast<Expr>(Data->getChildren()[LastIterationOffset]);
1324   }
1325   Expr *getCalcLastIteration() const {
1326     return cast<Expr>(Data->getChildren()[CalcLastIterationOffset]);
1327   }
1328   Expr *getPreCond() const {
1329     return cast<Expr>(Data->getChildren()[PreConditionOffset]);
1330   }
1331   Expr *getCond() const { return cast<Expr>(Data->getChildren()[CondOffset]); }
1332   Expr *getInit() const { return cast<Expr>(Data->getChildren()[InitOffset]); }
1333   Expr *getInc() const { return cast<Expr>(Data->getChildren()[IncOffset]); }
1334   const Stmt *getPreInits() const {
1335     return Data->getChildren()[PreInitsOffset];
1336   }
1337   Stmt *getPreInits() { return Data->getChildren()[PreInitsOffset]; }
1338   Expr *getIsLastIterVariable() const {
1339     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1340             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1341             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1342             isOpenMPDistributeDirective(getDirectiveKind())) &&
1343            "expected worksharing loop directive");
1344     return cast<Expr>(Data->getChildren()[IsLastIterVariableOffset]);
1345   }
1346   Expr *getLowerBoundVariable() const {
1347     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1348             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1349             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1350             isOpenMPDistributeDirective(getDirectiveKind())) &&
1351            "expected worksharing loop directive");
1352     return cast<Expr>(Data->getChildren()[LowerBoundVariableOffset]);
1353   }
1354   Expr *getUpperBoundVariable() const {
1355     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1356             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1357             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1358             isOpenMPDistributeDirective(getDirectiveKind())) &&
1359            "expected worksharing loop directive");
1360     return cast<Expr>(Data->getChildren()[UpperBoundVariableOffset]);
1361   }
1362   Expr *getStrideVariable() const {
1363     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1364             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1365             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1366             isOpenMPDistributeDirective(getDirectiveKind())) &&
1367            "expected worksharing loop directive");
1368     return cast<Expr>(Data->getChildren()[StrideVariableOffset]);
1369   }
1370   Expr *getEnsureUpperBound() const {
1371     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1372             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1373             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1374             isOpenMPDistributeDirective(getDirectiveKind())) &&
1375            "expected worksharing loop directive");
1376     return cast<Expr>(Data->getChildren()[EnsureUpperBoundOffset]);
1377   }
1378   Expr *getNextLowerBound() const {
1379     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1380             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1381             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1382             isOpenMPDistributeDirective(getDirectiveKind())) &&
1383            "expected worksharing loop directive");
1384     return cast<Expr>(Data->getChildren()[NextLowerBoundOffset]);
1385   }
1386   Expr *getNextUpperBound() const {
1387     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1388             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1389             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1390             isOpenMPDistributeDirective(getDirectiveKind())) &&
1391            "expected worksharing loop directive");
1392     return cast<Expr>(Data->getChildren()[NextUpperBoundOffset]);
1393   }
1394   Expr *getNumIterations() const {
1395     assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1396             isOpenMPGenericLoopDirective(getDirectiveKind()) ||
1397             isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1398             isOpenMPDistributeDirective(getDirectiveKind())) &&
1399            "expected worksharing loop directive");
1400     return cast<Expr>(Data->getChildren()[NumIterationsOffset]);
1401   }
1402   Expr *getPrevLowerBoundVariable() const {
1403     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1404            "expected loop bound sharing directive");
1405     return cast<Expr>(Data->getChildren()[PrevLowerBoundVariableOffset]);
1406   }
1407   Expr *getPrevUpperBoundVariable() const {
1408     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1409            "expected loop bound sharing directive");
1410     return cast<Expr>(Data->getChildren()[PrevUpperBoundVariableOffset]);
1411   }
1412   Expr *getDistInc() const {
1413     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1414            "expected loop bound sharing directive");
1415     return cast<Expr>(Data->getChildren()[DistIncOffset]);
1416   }
1417   Expr *getPrevEnsureUpperBound() const {
1418     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1419            "expected loop bound sharing directive");
1420     return cast<Expr>(Data->getChildren()[PrevEnsureUpperBoundOffset]);
1421   }
1422   Expr *getCombinedLowerBoundVariable() const {
1423     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1424            "expected loop bound sharing directive");
1425     return cast<Expr>(Data->getChildren()[CombinedLowerBoundVariableOffset]);
1426   }
1427   Expr *getCombinedUpperBoundVariable() const {
1428     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1429            "expected loop bound sharing directive");
1430     return cast<Expr>(Data->getChildren()[CombinedUpperBoundVariableOffset]);
1431   }
1432   Expr *getCombinedEnsureUpperBound() const {
1433     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1434            "expected loop bound sharing directive");
1435     return cast<Expr>(Data->getChildren()[CombinedEnsureUpperBoundOffset]);
1436   }
1437   Expr *getCombinedInit() const {
1438     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1439            "expected loop bound sharing directive");
1440     return cast<Expr>(Data->getChildren()[CombinedInitOffset]);
1441   }
1442   Expr *getCombinedCond() const {
1443     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1444            "expected loop bound sharing directive");
1445     return cast<Expr>(Data->getChildren()[CombinedConditionOffset]);
1446   }
1447   Expr *getCombinedNextLowerBound() const {
1448     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1449            "expected loop bound sharing directive");
1450     return cast<Expr>(Data->getChildren()[CombinedNextLowerBoundOffset]);
1451   }
1452   Expr *getCombinedNextUpperBound() const {
1453     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1454            "expected loop bound sharing directive");
1455     return cast<Expr>(Data->getChildren()[CombinedNextUpperBoundOffset]);
1456   }
1457   Expr *getCombinedDistCond() const {
1458     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1459            "expected loop bound distribute sharing directive");
1460     return cast<Expr>(Data->getChildren()[CombinedDistConditionOffset]);
1461   }
1462   Expr *getCombinedParForInDistCond() const {
1463     assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1464            "expected loop bound distribute sharing directive");
1465     return cast<Expr>(Data->getChildren()[CombinedParForInDistConditionOffset]);
1466   }
1467   Stmt *getBody();
1468   const Stmt *getBody() const {
1469     return const_cast<OMPLoopDirective *>(this)->getBody();
1470   }
1471 
1472   ArrayRef<Expr *> counters() { return getCounters(); }
1473 
1474   ArrayRef<Expr *> counters() const {
1475     return const_cast<OMPLoopDirective *>(this)->getCounters();
1476   }
1477 
1478   ArrayRef<Expr *> private_counters() { return getPrivateCounters(); }
1479 
1480   ArrayRef<Expr *> private_counters() const {
1481     return const_cast<OMPLoopDirective *>(this)->getPrivateCounters();
1482   }
1483 
1484   ArrayRef<Expr *> inits() { return getInits(); }
1485 
1486   ArrayRef<Expr *> inits() const {
1487     return const_cast<OMPLoopDirective *>(this)->getInits();
1488   }
1489 
1490   ArrayRef<Expr *> updates() { return getUpdates(); }
1491 
1492   ArrayRef<Expr *> updates() const {
1493     return const_cast<OMPLoopDirective *>(this)->getUpdates();
1494   }
1495 
1496   ArrayRef<Expr *> finals() { return getFinals(); }
1497 
1498   ArrayRef<Expr *> finals() const {
1499     return const_cast<OMPLoopDirective *>(this)->getFinals();
1500   }
1501 
1502   ArrayRef<Expr *> dependent_counters() { return getDependentCounters(); }
1503 
1504   ArrayRef<Expr *> dependent_counters() const {
1505     return const_cast<OMPLoopDirective *>(this)->getDependentCounters();
1506   }
1507 
1508   ArrayRef<Expr *> dependent_inits() { return getDependentInits(); }
1509 
1510   ArrayRef<Expr *> dependent_inits() const {
1511     return const_cast<OMPLoopDirective *>(this)->getDependentInits();
1512   }
1513 
1514   ArrayRef<Expr *> finals_conditions() { return getFinalsConditions(); }
1515 
1516   ArrayRef<Expr *> finals_conditions() const {
1517     return const_cast<OMPLoopDirective *>(this)->getFinalsConditions();
1518   }
1519 
1520   static bool classof(const Stmt *T) {
1521     return T->getStmtClass() == OMPSimdDirectiveClass ||
1522            T->getStmtClass() == OMPForDirectiveClass ||
1523            T->getStmtClass() == OMPForSimdDirectiveClass ||
1524            T->getStmtClass() == OMPParallelForDirectiveClass ||
1525            T->getStmtClass() == OMPParallelForSimdDirectiveClass ||
1526            T->getStmtClass() == OMPTaskLoopDirectiveClass ||
1527            T->getStmtClass() == OMPTaskLoopSimdDirectiveClass ||
1528            T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass ||
1529            T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass ||
1530            T->getStmtClass() == OMPMasterTaskLoopDirectiveClass ||
1531            T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass ||
1532            T->getStmtClass() == OMPGenericLoopDirectiveClass ||
1533            T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass ||
1534            T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass ||
1535            T->getStmtClass() == OMPParallelGenericLoopDirectiveClass ||
1536            T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass ||
1537            T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass ||
1538            T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass ||
1539            T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass ||
1540            T->getStmtClass() == OMPParallelMasterTaskLoopSimdDirectiveClass ||
1541            T->getStmtClass() == OMPDistributeDirectiveClass ||
1542            T->getStmtClass() == OMPTargetParallelForDirectiveClass ||
1543            T->getStmtClass() == OMPDistributeParallelForDirectiveClass ||
1544            T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass ||
1545            T->getStmtClass() == OMPDistributeSimdDirectiveClass ||
1546            T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass ||
1547            T->getStmtClass() == OMPTargetSimdDirectiveClass ||
1548            T->getStmtClass() == OMPTeamsDistributeDirectiveClass ||
1549            T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass ||
1550            T->getStmtClass() ==
1551                OMPTeamsDistributeParallelForSimdDirectiveClass ||
1552            T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass ||
1553            T->getStmtClass() ==
1554                OMPTargetTeamsDistributeParallelForDirectiveClass ||
1555            T->getStmtClass() ==
1556                OMPTargetTeamsDistributeParallelForSimdDirectiveClass ||
1557            T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass ||
1558            T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass;
1559   }
1560 };
1561 
1562 /// This represents '#pragma omp simd' directive.
1563 ///
1564 /// \code
1565 /// #pragma omp simd private(a,b) linear(i,j:s) reduction(+:c,d)
1566 /// \endcode
1567 /// In this example directive '#pragma omp simd' has clauses 'private'
1568 /// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
1569 /// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
1570 ///
1571 class OMPSimdDirective : public OMPLoopDirective {
1572   friend class ASTStmtReader;
1573   friend class OMPExecutableDirective;
1574   /// Build directive with the given start and end location.
1575   ///
1576   /// \param StartLoc Starting location of the directive kind.
1577   /// \param EndLoc Ending location of the directive.
1578   /// \param CollapsedNum Number of collapsed nested loops.
1579   ///
1580   OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
1581                    unsigned CollapsedNum)
1582       : OMPLoopDirective(OMPSimdDirectiveClass, llvm::omp::OMPD_simd, StartLoc,
1583                          EndLoc, CollapsedNum) {}
1584 
1585   /// Build an empty directive.
1586   ///
1587   /// \param CollapsedNum Number of collapsed nested loops.
1588   ///
1589   explicit OMPSimdDirective(unsigned CollapsedNum)
1590       : OMPLoopDirective(OMPSimdDirectiveClass, llvm::omp::OMPD_simd,
1591                          SourceLocation(), SourceLocation(), CollapsedNum) {}
1592 
1593 public:
1594   /// Creates directive with a list of \a Clauses.
1595   ///
1596   /// \param C AST context.
1597   /// \param StartLoc Starting location of the directive kind.
1598   /// \param EndLoc Ending Location of the directive.
1599   /// \param CollapsedNum Number of collapsed loops.
1600   /// \param Clauses List of clauses.
1601   /// \param AssociatedStmt Statement, associated with the directive.
1602   /// \param Exprs Helper expressions for CodeGen.
1603   ///
1604   static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc,
1605                                   SourceLocation EndLoc, unsigned CollapsedNum,
1606                                   ArrayRef<OMPClause *> Clauses,
1607                                   Stmt *AssociatedStmt,
1608                                   const HelperExprs &Exprs);
1609 
1610   /// Creates an empty directive with the place
1611   /// for \a NumClauses clauses.
1612   ///
1613   /// \param C AST context.
1614   /// \param CollapsedNum Number of collapsed nested loops.
1615   /// \param NumClauses Number of clauses.
1616   ///
1617   static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
1618                                        unsigned CollapsedNum, EmptyShell);
1619 
1620   static bool classof(const Stmt *T) {
1621     return T->getStmtClass() == OMPSimdDirectiveClass;
1622   }
1623 };
1624 
1625 /// This represents '#pragma omp for' directive.
1626 ///
1627 /// \code
1628 /// #pragma omp for private(a,b) reduction(+:c,d)
1629 /// \endcode
1630 /// In this example directive '#pragma omp for' has clauses 'private' with the
1631 /// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c'
1632 /// and 'd'.
1633 ///
1634 class OMPForDirective : public OMPLoopDirective {
1635   friend class ASTStmtReader;
1636   friend class OMPExecutableDirective;
1637   /// true if current directive has inner cancel directive.
1638   bool HasCancel = false;
1639 
1640   /// Build directive with the given start and end location.
1641   ///
1642   /// \param StartLoc Starting location of the directive kind.
1643   /// \param EndLoc Ending location of the directive.
1644   /// \param CollapsedNum Number of collapsed nested loops.
1645   ///
1646   OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
1647                   unsigned CollapsedNum)
1648       : OMPLoopDirective(OMPForDirectiveClass, llvm::omp::OMPD_for, StartLoc,
1649                          EndLoc, CollapsedNum) {}
1650 
1651   /// Build an empty directive.
1652   ///
1653   /// \param CollapsedNum Number of collapsed nested loops.
1654   ///
1655   explicit OMPForDirective(unsigned CollapsedNum)
1656       : OMPLoopDirective(OMPForDirectiveClass, llvm::omp::OMPD_for,
1657                          SourceLocation(), SourceLocation(), CollapsedNum) {}
1658 
1659   /// Sets special task reduction descriptor.
1660   void setTaskReductionRefExpr(Expr *E) {
1661     Data->getChildren()[numLoopChildren(getLoopsNumber(),
1662                                         llvm::omp::OMPD_for)] = E;
1663   }
1664 
1665   /// Set cancel state.
1666   void setHasCancel(bool Has) { HasCancel = Has; }
1667 
1668 public:
1669   /// Creates directive with a list of \a Clauses.
1670   ///
1671   /// \param C AST context.
1672   /// \param StartLoc Starting location of the directive kind.
1673   /// \param EndLoc Ending Location of the directive.
1674   /// \param CollapsedNum Number of collapsed loops.
1675   /// \param Clauses List of clauses.
1676   /// \param AssociatedStmt Statement, associated with the directive.
1677   /// \param Exprs Helper expressions for CodeGen.
1678   /// \param TaskRedRef Task reduction special reference expression to handle
1679   /// taskgroup descriptor.
1680   /// \param HasCancel true if current directive has inner cancel directive.
1681   ///
1682   static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
1683                                  SourceLocation EndLoc, unsigned CollapsedNum,
1684                                  ArrayRef<OMPClause *> Clauses,
1685                                  Stmt *AssociatedStmt, const HelperExprs &Exprs,
1686                                  Expr *TaskRedRef, bool HasCancel);
1687 
1688   /// Creates an empty directive with the place
1689   /// for \a NumClauses clauses.
1690   ///
1691   /// \param C AST context.
1692   /// \param CollapsedNum Number of collapsed nested loops.
1693   /// \param NumClauses Number of clauses.
1694   ///
1695   static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
1696                                       unsigned CollapsedNum, EmptyShell);
1697 
1698   /// Returns special task reduction reference expression.
1699   Expr *getTaskReductionRefExpr() {
1700     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
1701         getLoopsNumber(), llvm::omp::OMPD_for)]);
1702   }
1703   const Expr *getTaskReductionRefExpr() const {
1704     return const_cast<OMPForDirective *>(this)->getTaskReductionRefExpr();
1705   }
1706 
1707   /// Return true if current directive has inner cancel directive.
1708   bool hasCancel() const { return HasCancel; }
1709 
1710   static bool classof(const Stmt *T) {
1711     return T->getStmtClass() == OMPForDirectiveClass;
1712   }
1713 };
1714 
1715 /// This represents '#pragma omp for simd' directive.
1716 ///
1717 /// \code
1718 /// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d)
1719 /// \endcode
1720 /// In this example directive '#pragma omp for simd' has clauses 'private'
1721 /// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
1722 /// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
1723 ///
1724 class OMPForSimdDirective : public OMPLoopDirective {
1725   friend class ASTStmtReader;
1726   friend class OMPExecutableDirective;
1727   /// Build directive with the given start and end location.
1728   ///
1729   /// \param StartLoc Starting location of the directive kind.
1730   /// \param EndLoc Ending location of the directive.
1731   /// \param CollapsedNum Number of collapsed nested loops.
1732   ///
1733   OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
1734                       unsigned CollapsedNum)
1735       : OMPLoopDirective(OMPForSimdDirectiveClass, llvm::omp::OMPD_for_simd,
1736                          StartLoc, EndLoc, CollapsedNum) {}
1737 
1738   /// Build an empty directive.
1739   ///
1740   /// \param CollapsedNum Number of collapsed nested loops.
1741   ///
1742   explicit OMPForSimdDirective(unsigned CollapsedNum)
1743       : OMPLoopDirective(OMPForSimdDirectiveClass, llvm::omp::OMPD_for_simd,
1744                          SourceLocation(), SourceLocation(), CollapsedNum) {}
1745 
1746 public:
1747   /// Creates directive with a list of \a Clauses.
1748   ///
1749   /// \param C AST context.
1750   /// \param StartLoc Starting location of the directive kind.
1751   /// \param EndLoc Ending Location of the directive.
1752   /// \param CollapsedNum Number of collapsed loops.
1753   /// \param Clauses List of clauses.
1754   /// \param AssociatedStmt Statement, associated with the directive.
1755   /// \param Exprs Helper expressions for CodeGen.
1756   ///
1757   static OMPForSimdDirective *
1758   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
1759          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
1760          Stmt *AssociatedStmt, const HelperExprs &Exprs);
1761 
1762   /// Creates an empty directive with the place
1763   /// for \a NumClauses clauses.
1764   ///
1765   /// \param C AST context.
1766   /// \param CollapsedNum Number of collapsed nested loops.
1767   /// \param NumClauses Number of clauses.
1768   ///
1769   static OMPForSimdDirective *CreateEmpty(const ASTContext &C,
1770                                           unsigned NumClauses,
1771                                           unsigned CollapsedNum, EmptyShell);
1772 
1773   static bool classof(const Stmt *T) {
1774     return T->getStmtClass() == OMPForSimdDirectiveClass;
1775   }
1776 };
1777 
1778 /// This represents '#pragma omp sections' directive.
1779 ///
1780 /// \code
1781 /// #pragma omp sections private(a,b) reduction(+:c,d)
1782 /// \endcode
1783 /// In this example directive '#pragma omp sections' has clauses 'private' with
1784 /// the variables 'a' and 'b' and 'reduction' with operator '+' and variables
1785 /// 'c' and 'd'.
1786 ///
1787 class OMPSectionsDirective : public OMPExecutableDirective {
1788   friend class ASTStmtReader;
1789   friend class OMPExecutableDirective;
1790 
1791   /// true if current directive has inner cancel directive.
1792   bool HasCancel = false;
1793 
1794   /// Build directive with the given start and end location.
1795   ///
1796   /// \param StartLoc Starting location of the directive kind.
1797   /// \param EndLoc Ending location of the directive.
1798   ///
1799   OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1800       : OMPExecutableDirective(OMPSectionsDirectiveClass,
1801                                llvm::omp::OMPD_sections, StartLoc, EndLoc) {}
1802 
1803   /// Build an empty directive.
1804   ///
1805   explicit OMPSectionsDirective()
1806       : OMPExecutableDirective(OMPSectionsDirectiveClass,
1807                                llvm::omp::OMPD_sections, SourceLocation(),
1808                                SourceLocation()) {}
1809 
1810   /// Sets special task reduction descriptor.
1811   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
1812 
1813   /// Set cancel state.
1814   void setHasCancel(bool Has) { HasCancel = Has; }
1815 
1816 public:
1817   /// Creates directive with a list of \a Clauses.
1818   ///
1819   /// \param C AST context.
1820   /// \param StartLoc Starting location of the directive kind.
1821   /// \param EndLoc Ending Location of the directive.
1822   /// \param Clauses List of clauses.
1823   /// \param AssociatedStmt Statement, associated with the directive.
1824   /// \param TaskRedRef Task reduction special reference expression to handle
1825   /// taskgroup descriptor.
1826   /// \param HasCancel true if current directive has inner directive.
1827   ///
1828   static OMPSectionsDirective *
1829   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
1830          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
1831          bool HasCancel);
1832 
1833   /// Creates an empty directive with the place for \a NumClauses
1834   /// clauses.
1835   ///
1836   /// \param C AST context.
1837   /// \param NumClauses Number of clauses.
1838   ///
1839   static OMPSectionsDirective *CreateEmpty(const ASTContext &C,
1840                                            unsigned NumClauses, EmptyShell);
1841 
1842   /// Returns special task reduction reference expression.
1843   Expr *getTaskReductionRefExpr() {
1844     return cast_or_null<Expr>(Data->getChildren()[0]);
1845   }
1846   const Expr *getTaskReductionRefExpr() const {
1847     return const_cast<OMPSectionsDirective *>(this)->getTaskReductionRefExpr();
1848   }
1849 
1850   /// Return true if current directive has inner cancel directive.
1851   bool hasCancel() const { return HasCancel; }
1852 
1853   static bool classof(const Stmt *T) {
1854     return T->getStmtClass() == OMPSectionsDirectiveClass;
1855   }
1856 };
1857 
1858 /// This represents '#pragma omp section' directive.
1859 ///
1860 /// \code
1861 /// #pragma omp section
1862 /// \endcode
1863 ///
1864 class OMPSectionDirective : public OMPExecutableDirective {
1865   friend class ASTStmtReader;
1866   friend class OMPExecutableDirective;
1867 
1868   /// true if current directive has inner cancel directive.
1869   bool HasCancel = false;
1870 
1871   /// Build directive with the given start and end location.
1872   ///
1873   /// \param StartLoc Starting location of the directive kind.
1874   /// \param EndLoc Ending location of the directive.
1875   ///
1876   OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1877       : OMPExecutableDirective(OMPSectionDirectiveClass,
1878                                llvm::omp::OMPD_section, StartLoc, EndLoc) {}
1879 
1880   /// Build an empty directive.
1881   ///
1882   explicit OMPSectionDirective()
1883       : OMPExecutableDirective(OMPSectionDirectiveClass,
1884                                llvm::omp::OMPD_section, SourceLocation(),
1885                                SourceLocation()) {}
1886 
1887 public:
1888   /// Creates directive.
1889   ///
1890   /// \param C AST context.
1891   /// \param StartLoc Starting location of the directive kind.
1892   /// \param EndLoc Ending Location of the directive.
1893   /// \param AssociatedStmt Statement, associated with the directive.
1894   /// \param HasCancel true if current directive has inner directive.
1895   ///
1896   static OMPSectionDirective *Create(const ASTContext &C,
1897                                      SourceLocation StartLoc,
1898                                      SourceLocation EndLoc,
1899                                      Stmt *AssociatedStmt, bool HasCancel);
1900 
1901   /// Creates an empty directive.
1902   ///
1903   /// \param C AST context.
1904   ///
1905   static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell);
1906 
1907   /// Set cancel state.
1908   void setHasCancel(bool Has) { HasCancel = Has; }
1909 
1910   /// Return true if current directive has inner cancel directive.
1911   bool hasCancel() const { return HasCancel; }
1912 
1913   static bool classof(const Stmt *T) {
1914     return T->getStmtClass() == OMPSectionDirectiveClass;
1915   }
1916 };
1917 
1918 /// This represents '#pragma omp scope' directive.
1919 /// \code
1920 /// #pragma omp scope private(a,b) nowait
1921 /// \endcode
1922 /// In this example directive '#pragma omp scope' has clauses 'private' with
1923 /// the variables 'a' and 'b' and nowait.
1924 ///
1925 class OMPScopeDirective final : public OMPExecutableDirective {
1926   friend class ASTStmtReader;
1927   friend class OMPExecutableDirective;
1928 
1929   /// Build directive with the given start and end location.
1930   ///
1931   /// \param StartLoc Starting location of the directive kind.
1932   /// \param EndLoc Ending location of the directive.
1933   ///
1934   OMPScopeDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1935       : OMPExecutableDirective(OMPScopeDirectiveClass, llvm::omp::OMPD_scope,
1936                                StartLoc, EndLoc) {}
1937 
1938   /// Build an empty directive.
1939   ///
1940   explicit OMPScopeDirective()
1941       : OMPExecutableDirective(OMPScopeDirectiveClass, llvm::omp::OMPD_scope,
1942                                SourceLocation(), SourceLocation()) {}
1943 
1944 public:
1945   /// Creates directive.
1946   ///
1947   /// \param C AST context.
1948   /// \param StartLoc Starting location of the directive kind.
1949   /// \param EndLoc Ending Location of the directive.
1950   /// \param AssociatedStmt Statement, associated with the directive.
1951   ///
1952   static OMPScopeDirective *Create(const ASTContext &C, SourceLocation StartLoc,
1953                                    SourceLocation EndLoc,
1954                                    ArrayRef<OMPClause *> Clauses,
1955                                    Stmt *AssociatedStmt);
1956 
1957   /// Creates an empty directive.
1958   ///
1959   /// \param C AST context.
1960   ///
1961   static OMPScopeDirective *CreateEmpty(const ASTContext &C,
1962                                         unsigned NumClauses, EmptyShell);
1963 
1964   static bool classof(const Stmt *T) {
1965     return T->getStmtClass() == OMPScopeDirectiveClass;
1966   }
1967 };
1968 
1969 /// This represents '#pragma omp single' directive.
1970 ///
1971 /// \code
1972 /// #pragma omp single private(a,b) copyprivate(c,d)
1973 /// \endcode
1974 /// In this example directive '#pragma omp single' has clauses 'private' with
1975 /// the variables 'a' and 'b' and 'copyprivate' with variables 'c' and 'd'.
1976 ///
1977 class OMPSingleDirective : public OMPExecutableDirective {
1978   friend class ASTStmtReader;
1979   friend class OMPExecutableDirective;
1980   /// Build directive with the given start and end location.
1981   ///
1982   /// \param StartLoc Starting location of the directive kind.
1983   /// \param EndLoc Ending location of the directive.
1984   ///
1985   OMPSingleDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1986       : OMPExecutableDirective(OMPSingleDirectiveClass, llvm::omp::OMPD_single,
1987                                StartLoc, EndLoc) {}
1988 
1989   /// Build an empty directive.
1990   ///
1991   explicit OMPSingleDirective()
1992       : OMPExecutableDirective(OMPSingleDirectiveClass, llvm::omp::OMPD_single,
1993                                SourceLocation(), SourceLocation()) {}
1994 
1995 public:
1996   /// Creates directive with a list of \a Clauses.
1997   ///
1998   /// \param C AST context.
1999   /// \param StartLoc Starting location of the directive kind.
2000   /// \param EndLoc Ending Location of the directive.
2001   /// \param Clauses List of clauses.
2002   /// \param AssociatedStmt Statement, associated with the directive.
2003   ///
2004   static OMPSingleDirective *
2005   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2006          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
2007 
2008   /// Creates an empty directive with the place for \a NumClauses
2009   /// clauses.
2010   ///
2011   /// \param C AST context.
2012   /// \param NumClauses Number of clauses.
2013   ///
2014   static OMPSingleDirective *CreateEmpty(const ASTContext &C,
2015                                          unsigned NumClauses, EmptyShell);
2016 
2017   static bool classof(const Stmt *T) {
2018     return T->getStmtClass() == OMPSingleDirectiveClass;
2019   }
2020 };
2021 
2022 /// This represents '#pragma omp master' directive.
2023 ///
2024 /// \code
2025 /// #pragma omp master
2026 /// \endcode
2027 ///
2028 class OMPMasterDirective : public OMPExecutableDirective {
2029   friend class ASTStmtReader;
2030   friend class OMPExecutableDirective;
2031   /// Build directive with the given start and end location.
2032   ///
2033   /// \param StartLoc Starting location of the directive kind.
2034   /// \param EndLoc Ending location of the directive.
2035   ///
2036   OMPMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2037       : OMPExecutableDirective(OMPMasterDirectiveClass, llvm::omp::OMPD_master,
2038                                StartLoc, EndLoc) {}
2039 
2040   /// Build an empty directive.
2041   ///
2042   explicit OMPMasterDirective()
2043       : OMPExecutableDirective(OMPMasterDirectiveClass, llvm::omp::OMPD_master,
2044                                SourceLocation(), SourceLocation()) {}
2045 
2046 public:
2047   /// Creates directive.
2048   ///
2049   /// \param C AST context.
2050   /// \param StartLoc Starting location of the directive kind.
2051   /// \param EndLoc Ending Location of the directive.
2052   /// \param AssociatedStmt Statement, associated with the directive.
2053   ///
2054   static OMPMasterDirective *Create(const ASTContext &C,
2055                                     SourceLocation StartLoc,
2056                                     SourceLocation EndLoc,
2057                                     Stmt *AssociatedStmt);
2058 
2059   /// Creates an empty directive.
2060   ///
2061   /// \param C AST context.
2062   ///
2063   static OMPMasterDirective *CreateEmpty(const ASTContext &C, EmptyShell);
2064 
2065   static bool classof(const Stmt *T) {
2066     return T->getStmtClass() == OMPMasterDirectiveClass;
2067   }
2068 };
2069 
2070 /// This represents '#pragma omp critical' directive.
2071 ///
2072 /// \code
2073 /// #pragma omp critical
2074 /// \endcode
2075 ///
2076 class OMPCriticalDirective : public OMPExecutableDirective {
2077   friend class ASTStmtReader;
2078   friend class OMPExecutableDirective;
2079   /// Name of the directive.
2080   DeclarationNameInfo DirName;
2081   /// Build directive with the given start and end location.
2082   ///
2083   /// \param Name Name of the directive.
2084   /// \param StartLoc Starting location of the directive kind.
2085   /// \param EndLoc Ending location of the directive.
2086   ///
2087   OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc,
2088                        SourceLocation EndLoc)
2089       : OMPExecutableDirective(OMPCriticalDirectiveClass,
2090                                llvm::omp::OMPD_critical, StartLoc, EndLoc),
2091         DirName(Name) {}
2092 
2093   /// Build an empty directive.
2094   ///
2095   explicit OMPCriticalDirective()
2096       : OMPExecutableDirective(OMPCriticalDirectiveClass,
2097                                llvm::omp::OMPD_critical, SourceLocation(),
2098                                SourceLocation()) {}
2099 
2100   /// Set name of the directive.
2101   ///
2102   /// \param Name Name of the directive.
2103   ///
2104   void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; }
2105 
2106 public:
2107   /// Creates directive.
2108   ///
2109   /// \param C AST context.
2110   /// \param Name Name of the directive.
2111   /// \param StartLoc Starting location of the directive kind.
2112   /// \param EndLoc Ending Location of the directive.
2113   /// \param Clauses List of clauses.
2114   /// \param AssociatedStmt Statement, associated with the directive.
2115   ///
2116   static OMPCriticalDirective *
2117   Create(const ASTContext &C, const DeclarationNameInfo &Name,
2118          SourceLocation StartLoc, SourceLocation EndLoc,
2119          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
2120 
2121   /// Creates an empty directive.
2122   ///
2123   /// \param C AST context.
2124   /// \param NumClauses Number of clauses.
2125   ///
2126   static OMPCriticalDirective *CreateEmpty(const ASTContext &C,
2127                                            unsigned NumClauses, EmptyShell);
2128 
2129   /// Return name of the directive.
2130   ///
2131   DeclarationNameInfo getDirectiveName() const { return DirName; }
2132 
2133   static bool classof(const Stmt *T) {
2134     return T->getStmtClass() == OMPCriticalDirectiveClass;
2135   }
2136 };
2137 
2138 /// This represents '#pragma omp parallel for' directive.
2139 ///
2140 /// \code
2141 /// #pragma omp parallel for private(a,b) reduction(+:c,d)
2142 /// \endcode
2143 /// In this example directive '#pragma omp parallel for' has clauses 'private'
2144 /// with the variables 'a' and 'b' and 'reduction' with operator '+' and
2145 /// variables 'c' and 'd'.
2146 ///
2147 class OMPParallelForDirective : public OMPLoopDirective {
2148   friend class ASTStmtReader;
2149   friend class OMPExecutableDirective;
2150 
2151   /// true if current region has inner cancel directive.
2152   bool HasCancel = false;
2153 
2154   /// Build directive with the given start and end location.
2155   ///
2156   /// \param StartLoc Starting location of the directive kind.
2157   /// \param EndLoc Ending location of the directive.
2158   /// \param CollapsedNum Number of collapsed nested loops.
2159   ///
2160   OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
2161                           unsigned CollapsedNum)
2162       : OMPLoopDirective(OMPParallelForDirectiveClass,
2163                          llvm::omp::OMPD_parallel_for, StartLoc, EndLoc,
2164                          CollapsedNum) {}
2165 
2166   /// Build an empty directive.
2167   ///
2168   /// \param CollapsedNum Number of collapsed nested loops.
2169   ///
2170   explicit OMPParallelForDirective(unsigned CollapsedNum)
2171       : OMPLoopDirective(OMPParallelForDirectiveClass,
2172                          llvm::omp::OMPD_parallel_for, SourceLocation(),
2173                          SourceLocation(), CollapsedNum) {}
2174 
2175   /// Sets special task reduction descriptor.
2176   void setTaskReductionRefExpr(Expr *E) {
2177     Data->getChildren()[numLoopChildren(getLoopsNumber(),
2178                                         llvm::omp::OMPD_parallel_for)] = E;
2179   }
2180 
2181   /// Set cancel state.
2182   void setHasCancel(bool Has) { HasCancel = Has; }
2183 
2184 public:
2185   /// Creates directive with a list of \a Clauses.
2186   ///
2187   /// \param C AST context.
2188   /// \param StartLoc Starting location of the directive kind.
2189   /// \param EndLoc Ending Location of the directive.
2190   /// \param CollapsedNum Number of collapsed loops.
2191   /// \param Clauses List of clauses.
2192   /// \param AssociatedStmt Statement, associated with the directive.
2193   /// \param Exprs Helper expressions for CodeGen.
2194   /// \param TaskRedRef Task reduction special reference expression to handle
2195   /// taskgroup descriptor.
2196   /// \param HasCancel true if current directive has inner cancel directive.
2197   ///
2198   static OMPParallelForDirective *
2199   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2200          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
2201          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
2202          bool HasCancel);
2203 
2204   /// Creates an empty directive with the place
2205   /// for \a NumClauses clauses.
2206   ///
2207   /// \param C AST context.
2208   /// \param CollapsedNum Number of collapsed nested loops.
2209   /// \param NumClauses Number of clauses.
2210   ///
2211   static OMPParallelForDirective *CreateEmpty(const ASTContext &C,
2212                                               unsigned NumClauses,
2213                                               unsigned CollapsedNum,
2214                                               EmptyShell);
2215 
2216   /// Returns special task reduction reference expression.
2217   Expr *getTaskReductionRefExpr() {
2218     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
2219         getLoopsNumber(), llvm::omp::OMPD_parallel_for)]);
2220   }
2221   const Expr *getTaskReductionRefExpr() const {
2222     return const_cast<OMPParallelForDirective *>(this)
2223         ->getTaskReductionRefExpr();
2224   }
2225 
2226   /// Return true if current directive has inner cancel directive.
2227   bool hasCancel() const { return HasCancel; }
2228 
2229   static bool classof(const Stmt *T) {
2230     return T->getStmtClass() == OMPParallelForDirectiveClass;
2231   }
2232 };
2233 
2234 /// This represents '#pragma omp parallel for simd' directive.
2235 ///
2236 /// \code
2237 /// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d)
2238 /// \endcode
2239 /// In this example directive '#pragma omp parallel for simd' has clauses
2240 /// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j'
2241 /// and linear step 's', 'reduction' with operator '+' and variables 'c' and
2242 /// 'd'.
2243 ///
2244 class OMPParallelForSimdDirective : public OMPLoopDirective {
2245   friend class ASTStmtReader;
2246   friend class OMPExecutableDirective;
2247   /// Build directive with the given start and end location.
2248   ///
2249   /// \param StartLoc Starting location of the directive kind.
2250   /// \param EndLoc Ending location of the directive.
2251   /// \param CollapsedNum Number of collapsed nested loops.
2252   ///
2253   OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
2254                               unsigned CollapsedNum)
2255       : OMPLoopDirective(OMPParallelForSimdDirectiveClass,
2256                          llvm::omp::OMPD_parallel_for_simd, StartLoc, EndLoc,
2257                          CollapsedNum) {}
2258 
2259   /// Build an empty directive.
2260   ///
2261   /// \param CollapsedNum Number of collapsed nested loops.
2262   ///
2263   explicit OMPParallelForSimdDirective(unsigned CollapsedNum)
2264       : OMPLoopDirective(OMPParallelForSimdDirectiveClass,
2265                          llvm::omp::OMPD_parallel_for_simd, SourceLocation(),
2266                          SourceLocation(), CollapsedNum) {}
2267 
2268 public:
2269   /// Creates directive with a list of \a Clauses.
2270   ///
2271   /// \param C AST context.
2272   /// \param StartLoc Starting location of the directive kind.
2273   /// \param EndLoc Ending Location of the directive.
2274   /// \param CollapsedNum Number of collapsed loops.
2275   /// \param Clauses List of clauses.
2276   /// \param AssociatedStmt Statement, associated with the directive.
2277   /// \param Exprs Helper expressions for CodeGen.
2278   ///
2279   static OMPParallelForSimdDirective *
2280   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2281          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
2282          Stmt *AssociatedStmt, const HelperExprs &Exprs);
2283 
2284   /// Creates an empty directive with the place
2285   /// for \a NumClauses clauses.
2286   ///
2287   /// \param C AST context.
2288   /// \param CollapsedNum Number of collapsed nested loops.
2289   /// \param NumClauses Number of clauses.
2290   ///
2291   static OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C,
2292                                                   unsigned NumClauses,
2293                                                   unsigned CollapsedNum,
2294                                                   EmptyShell);
2295 
2296   static bool classof(const Stmt *T) {
2297     return T->getStmtClass() == OMPParallelForSimdDirectiveClass;
2298   }
2299 };
2300 
2301 /// This represents '#pragma omp parallel master' directive.
2302 ///
2303 /// \code
2304 /// #pragma omp parallel master private(a,b)
2305 /// \endcode
2306 /// In this example directive '#pragma omp parallel master' has clauses
2307 /// 'private' with the variables 'a' and 'b'
2308 ///
2309 class OMPParallelMasterDirective : public OMPExecutableDirective {
2310   friend class ASTStmtReader;
2311   friend class OMPExecutableDirective;
2312 
2313   OMPParallelMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2314       : OMPExecutableDirective(OMPParallelMasterDirectiveClass,
2315                                llvm::omp::OMPD_parallel_master, StartLoc,
2316                                EndLoc) {}
2317 
2318   explicit OMPParallelMasterDirective()
2319       : OMPExecutableDirective(OMPParallelMasterDirectiveClass,
2320                                llvm::omp::OMPD_parallel_master,
2321                                SourceLocation(), SourceLocation()) {}
2322 
2323   /// Sets special task reduction descriptor.
2324   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
2325 
2326 public:
2327   /// Creates directive with a list of \a Clauses.
2328   ///
2329   /// \param C AST context.
2330   /// \param StartLoc Starting location of the directive kind.
2331   /// \param EndLoc Ending Location of the directive.
2332   /// \param Clauses List of clauses.
2333   /// \param AssociatedStmt Statement, associated with the directive.
2334   /// \param TaskRedRef Task reduction special reference expression to handle
2335   /// taskgroup descriptor.
2336   ///
2337   static OMPParallelMasterDirective *
2338   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2339          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef);
2340 
2341   /// Creates an empty directive with the place for \a NumClauses
2342   /// clauses.
2343   ///
2344   /// \param C AST context.
2345   /// \param NumClauses Number of clauses.
2346   ///
2347   static OMPParallelMasterDirective *
2348   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
2349 
2350   /// Returns special task reduction reference expression.
2351   Expr *getTaskReductionRefExpr() {
2352     return cast_or_null<Expr>(Data->getChildren()[0]);
2353   }
2354   const Expr *getTaskReductionRefExpr() const {
2355     return const_cast<OMPParallelMasterDirective *>(this)
2356         ->getTaskReductionRefExpr();
2357   }
2358 
2359   static bool classof(const Stmt *T) {
2360     return T->getStmtClass() == OMPParallelMasterDirectiveClass;
2361   }
2362 };
2363 
2364 /// This represents '#pragma omp parallel masked' directive.
2365 ///
2366 /// \code
2367 /// #pragma omp parallel masked filter(tid)
2368 /// \endcode
2369 /// In this example directive '#pragma omp parallel masked' has a clause
2370 /// 'filter' with the variable tid
2371 ///
2372 class OMPParallelMaskedDirective final : public OMPExecutableDirective {
2373   friend class ASTStmtReader;
2374   friend class OMPExecutableDirective;
2375 
2376   OMPParallelMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2377       : OMPExecutableDirective(OMPParallelMaskedDirectiveClass,
2378                                llvm::omp::OMPD_parallel_masked, StartLoc,
2379                                EndLoc) {}
2380 
2381   explicit OMPParallelMaskedDirective()
2382       : OMPExecutableDirective(OMPParallelMaskedDirectiveClass,
2383                                llvm::omp::OMPD_parallel_masked,
2384                                SourceLocation(), SourceLocation()) {}
2385 
2386   /// Sets special task reduction descriptor.
2387   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
2388 
2389 public:
2390   /// Creates directive with a list of \a Clauses.
2391   ///
2392   /// \param C AST context.
2393   /// \param StartLoc Starting location of the directive kind.
2394   /// \param EndLoc Ending Location of the directive.
2395   /// \param Clauses List of clauses.
2396   /// \param AssociatedStmt Statement, associated with the directive.
2397   /// \param TaskRedRef Task reduction special reference expression to handle
2398   /// taskgroup descriptor.
2399   ///
2400   static OMPParallelMaskedDirective *
2401   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2402          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef);
2403 
2404   /// Creates an empty directive with the place for \a NumClauses
2405   /// clauses.
2406   ///
2407   /// \param C AST context.
2408   /// \param NumClauses Number of clauses.
2409   ///
2410   static OMPParallelMaskedDirective *
2411   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
2412 
2413   /// Returns special task reduction reference expression.
2414   Expr *getTaskReductionRefExpr() {
2415     return cast_or_null<Expr>(Data->getChildren()[0]);
2416   }
2417   const Expr *getTaskReductionRefExpr() const {
2418     return const_cast<OMPParallelMaskedDirective *>(this)
2419         ->getTaskReductionRefExpr();
2420   }
2421 
2422   static bool classof(const Stmt *T) {
2423     return T->getStmtClass() == OMPParallelMaskedDirectiveClass;
2424   }
2425 };
2426 
2427 /// This represents '#pragma omp parallel sections' directive.
2428 ///
2429 /// \code
2430 /// #pragma omp parallel sections private(a,b) reduction(+:c,d)
2431 /// \endcode
2432 /// In this example directive '#pragma omp parallel sections' has clauses
2433 /// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+'
2434 /// and variables 'c' and 'd'.
2435 ///
2436 class OMPParallelSectionsDirective : public OMPExecutableDirective {
2437   friend class ASTStmtReader;
2438   friend class OMPExecutableDirective;
2439 
2440   /// true if current directive has inner cancel directive.
2441   bool HasCancel = false;
2442 
2443   /// Build directive with the given start and end location.
2444   ///
2445   /// \param StartLoc Starting location of the directive kind.
2446   /// \param EndLoc Ending location of the directive.
2447   ///
2448   OMPParallelSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2449       : OMPExecutableDirective(OMPParallelSectionsDirectiveClass,
2450                                llvm::omp::OMPD_parallel_sections, StartLoc,
2451                                EndLoc) {}
2452 
2453   /// Build an empty directive.
2454   ///
2455   explicit OMPParallelSectionsDirective()
2456       : OMPExecutableDirective(OMPParallelSectionsDirectiveClass,
2457                                llvm::omp::OMPD_parallel_sections,
2458                                SourceLocation(), SourceLocation()) {}
2459 
2460   /// Sets special task reduction descriptor.
2461   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
2462 
2463   /// Set cancel state.
2464   void setHasCancel(bool Has) { HasCancel = Has; }
2465 
2466 public:
2467   /// Creates directive with a list of \a Clauses.
2468   ///
2469   /// \param C AST context.
2470   /// \param StartLoc Starting location of the directive kind.
2471   /// \param EndLoc Ending Location of the directive.
2472   /// \param Clauses List of clauses.
2473   /// \param AssociatedStmt Statement, associated with the directive.
2474   /// \param TaskRedRef Task reduction special reference expression to handle
2475   /// taskgroup descriptor.
2476   /// \param HasCancel true if current directive has inner cancel directive.
2477   ///
2478   static OMPParallelSectionsDirective *
2479   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2480          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
2481          bool HasCancel);
2482 
2483   /// Creates an empty directive with the place for \a NumClauses
2484   /// clauses.
2485   ///
2486   /// \param C AST context.
2487   /// \param NumClauses Number of clauses.
2488   ///
2489   static OMPParallelSectionsDirective *
2490   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
2491 
2492   /// Returns special task reduction reference expression.
2493   Expr *getTaskReductionRefExpr() {
2494     return cast_or_null<Expr>(Data->getChildren()[0]);
2495   }
2496   const Expr *getTaskReductionRefExpr() const {
2497     return const_cast<OMPParallelSectionsDirective *>(this)
2498         ->getTaskReductionRefExpr();
2499   }
2500 
2501   /// Return true if current directive has inner cancel directive.
2502   bool hasCancel() const { return HasCancel; }
2503 
2504   static bool classof(const Stmt *T) {
2505     return T->getStmtClass() == OMPParallelSectionsDirectiveClass;
2506   }
2507 };
2508 
2509 /// This represents '#pragma omp task' directive.
2510 ///
2511 /// \code
2512 /// #pragma omp task private(a,b) final(d)
2513 /// \endcode
2514 /// In this example directive '#pragma omp task' has clauses 'private' with the
2515 /// variables 'a' and 'b' and 'final' with condition 'd'.
2516 ///
2517 class OMPTaskDirective : public OMPExecutableDirective {
2518   friend class ASTStmtReader;
2519   friend class OMPExecutableDirective;
2520   /// true if this directive has inner cancel directive.
2521   bool HasCancel = false;
2522 
2523   /// Build directive with the given start and end location.
2524   ///
2525   /// \param StartLoc Starting location of the directive kind.
2526   /// \param EndLoc Ending location of the directive.
2527   ///
2528   OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2529       : OMPExecutableDirective(OMPTaskDirectiveClass, llvm::omp::OMPD_task,
2530                                StartLoc, EndLoc) {}
2531 
2532   /// Build an empty directive.
2533   ///
2534   explicit OMPTaskDirective()
2535       : OMPExecutableDirective(OMPTaskDirectiveClass, llvm::omp::OMPD_task,
2536                                SourceLocation(), SourceLocation()) {}
2537 
2538   /// Set cancel state.
2539   void setHasCancel(bool Has) { HasCancel = Has; }
2540 
2541 public:
2542   /// Creates directive with a list of \a Clauses.
2543   ///
2544   /// \param C AST context.
2545   /// \param StartLoc Starting location of the directive kind.
2546   /// \param EndLoc Ending Location of the directive.
2547   /// \param Clauses List of clauses.
2548   /// \param AssociatedStmt Statement, associated with the directive.
2549   /// \param HasCancel true, if current directive has inner cancel directive.
2550   ///
2551   static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc,
2552                                   SourceLocation EndLoc,
2553                                   ArrayRef<OMPClause *> Clauses,
2554                                   Stmt *AssociatedStmt, bool HasCancel);
2555 
2556   /// Creates an empty directive with the place for \a NumClauses
2557   /// clauses.
2558   ///
2559   /// \param C AST context.
2560   /// \param NumClauses Number of clauses.
2561   ///
2562   static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
2563                                        EmptyShell);
2564 
2565   /// Return true if current directive has inner cancel directive.
2566   bool hasCancel() const { return HasCancel; }
2567 
2568   static bool classof(const Stmt *T) {
2569     return T->getStmtClass() == OMPTaskDirectiveClass;
2570   }
2571 };
2572 
2573 /// This represents '#pragma omp taskyield' directive.
2574 ///
2575 /// \code
2576 /// #pragma omp taskyield
2577 /// \endcode
2578 ///
2579 class OMPTaskyieldDirective : public OMPExecutableDirective {
2580   friend class ASTStmtReader;
2581   friend class OMPExecutableDirective;
2582   /// Build directive with the given start and end location.
2583   ///
2584   /// \param StartLoc Starting location of the directive kind.
2585   /// \param EndLoc Ending location of the directive.
2586   ///
2587   OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2588       : OMPExecutableDirective(OMPTaskyieldDirectiveClass,
2589                                llvm::omp::OMPD_taskyield, StartLoc, EndLoc) {}
2590 
2591   /// Build an empty directive.
2592   ///
2593   explicit OMPTaskyieldDirective()
2594       : OMPExecutableDirective(OMPTaskyieldDirectiveClass,
2595                                llvm::omp::OMPD_taskyield, SourceLocation(),
2596                                SourceLocation()) {}
2597 
2598 public:
2599   /// Creates directive.
2600   ///
2601   /// \param C AST context.
2602   /// \param StartLoc Starting location of the directive kind.
2603   /// \param EndLoc Ending Location of the directive.
2604   ///
2605   static OMPTaskyieldDirective *
2606   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
2607 
2608   /// Creates an empty directive.
2609   ///
2610   /// \param C AST context.
2611   ///
2612   static OMPTaskyieldDirective *CreateEmpty(const ASTContext &C, EmptyShell);
2613 
2614   static bool classof(const Stmt *T) {
2615     return T->getStmtClass() == OMPTaskyieldDirectiveClass;
2616   }
2617 };
2618 
2619 /// This represents '#pragma omp barrier' directive.
2620 ///
2621 /// \code
2622 /// #pragma omp barrier
2623 /// \endcode
2624 ///
2625 class OMPBarrierDirective : public OMPExecutableDirective {
2626   friend class ASTStmtReader;
2627   friend class OMPExecutableDirective;
2628   /// Build directive with the given start and end location.
2629   ///
2630   /// \param StartLoc Starting location of the directive kind.
2631   /// \param EndLoc Ending location of the directive.
2632   ///
2633   OMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2634       : OMPExecutableDirective(OMPBarrierDirectiveClass,
2635                                llvm::omp::OMPD_barrier, StartLoc, EndLoc) {}
2636 
2637   /// Build an empty directive.
2638   ///
2639   explicit OMPBarrierDirective()
2640       : OMPExecutableDirective(OMPBarrierDirectiveClass,
2641                                llvm::omp::OMPD_barrier, SourceLocation(),
2642                                SourceLocation()) {}
2643 
2644 public:
2645   /// Creates directive.
2646   ///
2647   /// \param C AST context.
2648   /// \param StartLoc Starting location of the directive kind.
2649   /// \param EndLoc Ending Location of the directive.
2650   ///
2651   static OMPBarrierDirective *
2652   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
2653 
2654   /// Creates an empty directive.
2655   ///
2656   /// \param C AST context.
2657   ///
2658   static OMPBarrierDirective *CreateEmpty(const ASTContext &C, EmptyShell);
2659 
2660   static bool classof(const Stmt *T) {
2661     return T->getStmtClass() == OMPBarrierDirectiveClass;
2662   }
2663 };
2664 
2665 /// This represents '#pragma omp taskwait' directive.
2666 ///
2667 /// \code
2668 /// #pragma omp taskwait
2669 /// \endcode
2670 ///
2671 class OMPTaskwaitDirective : public OMPExecutableDirective {
2672   friend class ASTStmtReader;
2673   friend class OMPExecutableDirective;
2674   /// Build directive with the given start and end location.
2675   ///
2676   /// \param StartLoc Starting location of the directive kind.
2677   /// \param EndLoc Ending location of the directive.
2678   ///
2679   OMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2680       : OMPExecutableDirective(OMPTaskwaitDirectiveClass,
2681                                llvm::omp::OMPD_taskwait, StartLoc, EndLoc) {}
2682 
2683   /// Build an empty directive.
2684   ///
2685   explicit OMPTaskwaitDirective()
2686       : OMPExecutableDirective(OMPTaskwaitDirectiveClass,
2687                                llvm::omp::OMPD_taskwait, SourceLocation(),
2688                                SourceLocation()) {}
2689 
2690 public:
2691   /// Creates directive.
2692   ///
2693   /// \param C AST context.
2694   /// \param StartLoc Starting location of the directive kind.
2695   /// \param EndLoc Ending Location of the directive.
2696   /// \param Clauses List of clauses.
2697   ///
2698   static OMPTaskwaitDirective *Create(const ASTContext &C,
2699                                       SourceLocation StartLoc,
2700                                       SourceLocation EndLoc,
2701                                       ArrayRef<OMPClause *> Clauses);
2702 
2703   /// Creates an empty directive.
2704   ///
2705   /// \param C AST context.
2706   /// \param NumClauses Number of clauses.
2707   ///
2708   static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C,
2709                                            unsigned NumClauses, EmptyShell);
2710 
2711   static bool classof(const Stmt *T) {
2712     return T->getStmtClass() == OMPTaskwaitDirectiveClass;
2713   }
2714 };
2715 
2716 /// This represents '#pragma omp taskgroup' directive.
2717 ///
2718 /// \code
2719 /// #pragma omp taskgroup
2720 /// \endcode
2721 ///
2722 class OMPTaskgroupDirective : public OMPExecutableDirective {
2723   friend class ASTStmtReader;
2724   friend class OMPExecutableDirective;
2725   /// Build directive with the given start and end location.
2726   ///
2727   /// \param StartLoc Starting location of the directive kind.
2728   /// \param EndLoc Ending location of the directive.
2729   ///
2730   OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2731       : OMPExecutableDirective(OMPTaskgroupDirectiveClass,
2732                                llvm::omp::OMPD_taskgroup, StartLoc, EndLoc) {}
2733 
2734   /// Build an empty directive.
2735   ///
2736   explicit OMPTaskgroupDirective()
2737       : OMPExecutableDirective(OMPTaskgroupDirectiveClass,
2738                                llvm::omp::OMPD_taskgroup, SourceLocation(),
2739                                SourceLocation()) {}
2740 
2741   /// Sets the task_reduction return variable.
2742   void setReductionRef(Expr *RR) { Data->getChildren()[0] = RR; }
2743 
2744 public:
2745   /// Creates directive.
2746   ///
2747   /// \param C AST context.
2748   /// \param StartLoc Starting location of the directive kind.
2749   /// \param EndLoc Ending Location of the directive.
2750   /// \param Clauses List of clauses.
2751   /// \param AssociatedStmt Statement, associated with the directive.
2752   /// \param ReductionRef Reference to the task_reduction return variable.
2753   ///
2754   static OMPTaskgroupDirective *
2755   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2756          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
2757          Expr *ReductionRef);
2758 
2759   /// Creates an empty directive.
2760   ///
2761   /// \param C AST context.
2762   /// \param NumClauses Number of clauses.
2763   ///
2764   static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C,
2765                                             unsigned NumClauses, EmptyShell);
2766 
2767 
2768   /// Returns reference to the task_reduction return variable.
2769   const Expr *getReductionRef() const {
2770     return const_cast<OMPTaskgroupDirective *>(this)->getReductionRef();
2771   }
2772   Expr *getReductionRef() { return cast_or_null<Expr>(Data->getChildren()[0]); }
2773 
2774   static bool classof(const Stmt *T) {
2775     return T->getStmtClass() == OMPTaskgroupDirectiveClass;
2776   }
2777 };
2778 
2779 /// This represents '#pragma omp flush' directive.
2780 ///
2781 /// \code
2782 /// #pragma omp flush(a,b)
2783 /// \endcode
2784 /// In this example directive '#pragma omp flush' has 2 arguments- variables 'a'
2785 /// and 'b'.
2786 /// 'omp flush' directive does not have clauses but have an optional list of
2787 /// variables to flush. This list of variables is stored within some fake clause
2788 /// FlushClause.
2789 class OMPFlushDirective : public OMPExecutableDirective {
2790   friend class ASTStmtReader;
2791   friend class OMPExecutableDirective;
2792   /// Build directive with the given start and end location.
2793   ///
2794   /// \param StartLoc Starting location of the directive kind.
2795   /// \param EndLoc Ending location of the directive.
2796   ///
2797   OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2798       : OMPExecutableDirective(OMPFlushDirectiveClass, llvm::omp::OMPD_flush,
2799                                StartLoc, EndLoc) {}
2800 
2801   /// Build an empty directive.
2802   ///
2803   explicit OMPFlushDirective()
2804       : OMPExecutableDirective(OMPFlushDirectiveClass, llvm::omp::OMPD_flush,
2805                                SourceLocation(), SourceLocation()) {}
2806 
2807 public:
2808   /// Creates directive with a list of \a Clauses.
2809   ///
2810   /// \param C AST context.
2811   /// \param StartLoc Starting location of the directive kind.
2812   /// \param EndLoc Ending Location of the directive.
2813   /// \param Clauses List of clauses (only single OMPFlushClause clause is
2814   /// allowed).
2815   ///
2816   static OMPFlushDirective *Create(const ASTContext &C, SourceLocation StartLoc,
2817                                    SourceLocation EndLoc,
2818                                    ArrayRef<OMPClause *> Clauses);
2819 
2820   /// Creates an empty directive with the place for \a NumClauses
2821   /// clauses.
2822   ///
2823   /// \param C AST context.
2824   /// \param NumClauses Number of clauses.
2825   ///
2826   static OMPFlushDirective *CreateEmpty(const ASTContext &C,
2827                                         unsigned NumClauses, EmptyShell);
2828 
2829   static bool classof(const Stmt *T) {
2830     return T->getStmtClass() == OMPFlushDirectiveClass;
2831   }
2832 };
2833 
2834 /// This represents '#pragma omp depobj' directive.
2835 ///
2836 /// \code
2837 /// #pragma omp depobj(a) depend(in:x,y)
2838 /// \endcode
2839 /// In this example directive '#pragma omp  depobj' initializes a depobj object
2840 /// 'a' with dependence type 'in' and a list with 'x' and 'y' locators.
2841 class OMPDepobjDirective final : public OMPExecutableDirective {
2842   friend class ASTStmtReader;
2843   friend class OMPExecutableDirective;
2844 
2845   /// Build directive with the given start and end location.
2846   ///
2847   /// \param StartLoc Starting location of the directive kind.
2848   /// \param EndLoc Ending location of the directive.
2849   ///
2850   OMPDepobjDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2851       : OMPExecutableDirective(OMPDepobjDirectiveClass, llvm::omp::OMPD_depobj,
2852                                StartLoc, EndLoc) {}
2853 
2854   /// Build an empty directive.
2855   ///
2856   explicit OMPDepobjDirective()
2857       : OMPExecutableDirective(OMPDepobjDirectiveClass, llvm::omp::OMPD_depobj,
2858                                SourceLocation(), SourceLocation()) {}
2859 
2860 public:
2861   /// Creates directive with a list of \a Clauses.
2862   ///
2863   /// \param C AST context.
2864   /// \param StartLoc Starting location of the directive kind.
2865   /// \param EndLoc Ending Location of the directive.
2866   /// \param Clauses List of clauses.
2867   ///
2868   static OMPDepobjDirective *Create(const ASTContext &C,
2869                                     SourceLocation StartLoc,
2870                                     SourceLocation EndLoc,
2871                                     ArrayRef<OMPClause *> Clauses);
2872 
2873   /// Creates an empty directive with the place for \a NumClauses
2874   /// clauses.
2875   ///
2876   /// \param C AST context.
2877   /// \param NumClauses Number of clauses.
2878   ///
2879   static OMPDepobjDirective *CreateEmpty(const ASTContext &C,
2880                                          unsigned NumClauses, EmptyShell);
2881 
2882   static bool classof(const Stmt *T) {
2883     return T->getStmtClass() == OMPDepobjDirectiveClass;
2884   }
2885 };
2886 
2887 /// This represents '#pragma omp ordered' directive.
2888 ///
2889 /// \code
2890 /// #pragma omp ordered
2891 /// \endcode
2892 ///
2893 class OMPOrderedDirective : public OMPExecutableDirective {
2894   friend class ASTStmtReader;
2895   friend class OMPExecutableDirective;
2896   /// Build directive with the given start and end location.
2897   ///
2898   /// \param StartLoc Starting location of the directive kind.
2899   /// \param EndLoc Ending location of the directive.
2900   ///
2901   OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2902       : OMPExecutableDirective(OMPOrderedDirectiveClass,
2903                                llvm::omp::OMPD_ordered, StartLoc, EndLoc) {}
2904 
2905   /// Build an empty directive.
2906   ///
2907   explicit OMPOrderedDirective()
2908       : OMPExecutableDirective(OMPOrderedDirectiveClass,
2909                                llvm::omp::OMPD_ordered, SourceLocation(),
2910                                SourceLocation()) {}
2911 
2912 public:
2913   /// Creates directive.
2914   ///
2915   /// \param C AST context.
2916   /// \param StartLoc Starting location of the directive kind.
2917   /// \param EndLoc Ending Location of the directive.
2918   /// \param Clauses List of clauses.
2919   /// \param AssociatedStmt Statement, associated with the directive.
2920   ///
2921   static OMPOrderedDirective *
2922   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2923          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
2924 
2925   /// Creates an empty directive.
2926   ///
2927   /// \param C AST context.
2928   /// \param NumClauses Number of clauses.
2929   /// \param IsStandalone true, if the standalone directive is created.
2930   ///
2931   static OMPOrderedDirective *CreateEmpty(const ASTContext &C,
2932                                           unsigned NumClauses,
2933                                           bool IsStandalone, EmptyShell);
2934 
2935   static bool classof(const Stmt *T) {
2936     return T->getStmtClass() == OMPOrderedDirectiveClass;
2937   }
2938 };
2939 
2940 /// This represents '#pragma omp atomic' directive.
2941 ///
2942 /// \code
2943 /// #pragma omp atomic capture
2944 /// \endcode
2945 /// In this example directive '#pragma omp atomic' has clause 'capture'.
2946 ///
2947 class OMPAtomicDirective : public OMPExecutableDirective {
2948   friend class ASTStmtReader;
2949   friend class OMPExecutableDirective;
2950 
2951   struct FlagTy {
2952     /// Used for 'atomic update' or 'atomic capture' constructs. They may
2953     /// have atomic expressions of forms:
2954     /// \code
2955     /// x = x binop expr;
2956     /// x = expr binop x;
2957     /// \endcode
2958     /// This field is 1 for the first form of the expression and 0 for the
2959     /// second. Required for correct codegen of non-associative operations (like
2960     /// << or >>).
2961     LLVM_PREFERRED_TYPE(bool)
2962     uint8_t IsXLHSInRHSPart : 1;
2963     /// Used for 'atomic update' or 'atomic capture' constructs. They may
2964     /// have atomic expressions of forms:
2965     /// \code
2966     /// v = x; <update x>;
2967     /// <update x>; v = x;
2968     /// \endcode
2969     /// This field is 1 for the first(postfix) form of the expression and 0
2970     /// otherwise.
2971     LLVM_PREFERRED_TYPE(bool)
2972     uint8_t IsPostfixUpdate : 1;
2973     /// 1 if 'v' is updated only when the condition is false (compare capture
2974     /// only).
2975     LLVM_PREFERRED_TYPE(bool)
2976     uint8_t IsFailOnly : 1;
2977   } Flags;
2978 
2979   /// Build directive with the given start and end location.
2980   ///
2981   /// \param StartLoc Starting location of the directive kind.
2982   /// \param EndLoc Ending location of the directive.
2983   ///
2984   OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2985       : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
2986                                StartLoc, EndLoc) {}
2987 
2988   /// Build an empty directive.
2989   ///
2990   explicit OMPAtomicDirective()
2991       : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
2992                                SourceLocation(), SourceLocation()) {}
2993 
2994   enum DataPositionTy : size_t {
2995     POS_X = 0,
2996     POS_V,
2997     POS_E,
2998     POS_UpdateExpr,
2999     POS_D,
3000     POS_Cond,
3001     POS_R,
3002   };
3003 
3004   /// Set 'x' part of the associated expression/statement.
3005   void setX(Expr *X) { Data->getChildren()[DataPositionTy::POS_X] = X; }
3006   /// Set helper expression of the form
3007   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
3008   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
3009   void setUpdateExpr(Expr *UE) {
3010     Data->getChildren()[DataPositionTy::POS_UpdateExpr] = UE;
3011   }
3012   /// Set 'v' part of the associated expression/statement.
3013   void setV(Expr *V) { Data->getChildren()[DataPositionTy::POS_V] = V; }
3014   /// Set 'r' part of the associated expression/statement.
3015   void setR(Expr *R) { Data->getChildren()[DataPositionTy::POS_R] = R; }
3016   /// Set 'expr' part of the associated expression/statement.
3017   void setExpr(Expr *E) { Data->getChildren()[DataPositionTy::POS_E] = E; }
3018   /// Set 'd' part of the associated expression/statement.
3019   void setD(Expr *D) { Data->getChildren()[DataPositionTy::POS_D] = D; }
3020   /// Set conditional expression in `atomic compare`.
3021   void setCond(Expr *C) { Data->getChildren()[DataPositionTy::POS_Cond] = C; }
3022 
3023 public:
3024   struct Expressions {
3025     /// 'x' part of the associated expression/statement.
3026     Expr *X = nullptr;
3027     /// 'v' part of the associated expression/statement.
3028     Expr *V = nullptr;
3029     // 'r' part of the associated expression/statement.
3030     Expr *R = nullptr;
3031     /// 'expr' part of the associated expression/statement.
3032     Expr *E = nullptr;
3033     /// UE Helper expression of the form:
3034     /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
3035     /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
3036     Expr *UE = nullptr;
3037     /// 'd' part of the associated expression/statement.
3038     Expr *D = nullptr;
3039     /// Conditional expression in `atomic compare` construct.
3040     Expr *Cond = nullptr;
3041     /// True if UE has the first form and false if the second.
3042     bool IsXLHSInRHSPart;
3043     /// True if original value of 'x' must be stored in 'v', not an updated one.
3044     bool IsPostfixUpdate;
3045     /// True if 'v' is updated only when the condition is false (compare capture
3046     /// only).
3047     bool IsFailOnly;
3048   };
3049 
3050   /// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
3051   /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for
3052   /// detailed description of 'x', 'v' and 'expr').
3053   ///
3054   /// \param C AST context.
3055   /// \param StartLoc Starting location of the directive kind.
3056   /// \param EndLoc Ending Location of the directive.
3057   /// \param Clauses List of clauses.
3058   /// \param AssociatedStmt Statement, associated with the directive.
3059   /// \param Exprs Associated expressions or statements.
3060   static OMPAtomicDirective *Create(const ASTContext &C,
3061                                     SourceLocation StartLoc,
3062                                     SourceLocation EndLoc,
3063                                     ArrayRef<OMPClause *> Clauses,
3064                                     Stmt *AssociatedStmt, Expressions Exprs);
3065 
3066   /// Creates an empty directive with the place for \a NumClauses
3067   /// clauses.
3068   ///
3069   /// \param C AST context.
3070   /// \param NumClauses Number of clauses.
3071   ///
3072   static OMPAtomicDirective *CreateEmpty(const ASTContext &C,
3073                                          unsigned NumClauses, EmptyShell);
3074 
3075   /// Get 'x' part of the associated expression/statement.
3076   Expr *getX() {
3077     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_X]);
3078   }
3079   const Expr *getX() const {
3080     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_X]);
3081   }
3082   /// Get helper expression of the form
3083   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
3084   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
3085   Expr *getUpdateExpr() {
3086     return cast_or_null<Expr>(
3087         Data->getChildren()[DataPositionTy::POS_UpdateExpr]);
3088   }
3089   const Expr *getUpdateExpr() const {
3090     return cast_or_null<Expr>(
3091         Data->getChildren()[DataPositionTy::POS_UpdateExpr]);
3092   }
3093   /// Return true if helper update expression has form
3094   /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form
3095   /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
3096   bool isXLHSInRHSPart() const { return Flags.IsXLHSInRHSPart; }
3097   /// Return true if 'v' expression must be updated to original value of
3098   /// 'x', false if 'v' must be updated to the new value of 'x'.
3099   bool isPostfixUpdate() const { return Flags.IsPostfixUpdate; }
3100   /// Return true if 'v' is updated only when the condition is evaluated false
3101   /// (compare capture only).
3102   bool isFailOnly() const { return Flags.IsFailOnly; }
3103   /// Get 'v' part of the associated expression/statement.
3104   Expr *getV() {
3105     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]);
3106   }
3107   const Expr *getV() const {
3108     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]);
3109   }
3110   /// Get 'r' part of the associated expression/statement.
3111   Expr *getR() {
3112     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]);
3113   }
3114   const Expr *getR() const {
3115     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]);
3116   }
3117   /// Get 'expr' part of the associated expression/statement.
3118   Expr *getExpr() {
3119     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
3120   }
3121   const Expr *getExpr() const {
3122     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
3123   }
3124   /// Get 'd' part of the associated expression/statement.
3125   Expr *getD() {
3126     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
3127   }
3128   Expr *getD() const {
3129     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
3130   }
3131   /// Get the 'cond' part of the source atomic expression.
3132   Expr *getCondExpr() {
3133     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
3134   }
3135   Expr *getCondExpr() const {
3136     return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
3137   }
3138 
3139   static bool classof(const Stmt *T) {
3140     return T->getStmtClass() == OMPAtomicDirectiveClass;
3141   }
3142 };
3143 
3144 /// This represents '#pragma omp target' directive.
3145 ///
3146 /// \code
3147 /// #pragma omp target if(a)
3148 /// \endcode
3149 /// In this example directive '#pragma omp target' has clause 'if' with
3150 /// condition 'a'.
3151 ///
3152 class OMPTargetDirective : public OMPExecutableDirective {
3153   friend class ASTStmtReader;
3154   friend class OMPExecutableDirective;
3155   /// Build directive with the given start and end location.
3156   ///
3157   /// \param StartLoc Starting location of the directive kind.
3158   /// \param EndLoc Ending location of the directive.
3159   ///
3160   OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3161       : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
3162                                StartLoc, EndLoc) {}
3163 
3164   /// Build an empty directive.
3165   ///
3166   explicit OMPTargetDirective()
3167       : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
3168                                SourceLocation(), SourceLocation()) {}
3169 
3170 public:
3171   /// Creates directive with a list of \a Clauses.
3172   ///
3173   /// \param C AST context.
3174   /// \param StartLoc Starting location of the directive kind.
3175   /// \param EndLoc Ending Location of the directive.
3176   /// \param Clauses List of clauses.
3177   /// \param AssociatedStmt Statement, associated with the directive.
3178   ///
3179   static OMPTargetDirective *
3180   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3181          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3182 
3183   /// Creates an empty directive with the place for \a NumClauses
3184   /// clauses.
3185   ///
3186   /// \param C AST context.
3187   /// \param NumClauses Number of clauses.
3188   ///
3189   static OMPTargetDirective *CreateEmpty(const ASTContext &C,
3190                                          unsigned NumClauses, EmptyShell);
3191 
3192   static bool classof(const Stmt *T) {
3193     return T->getStmtClass() == OMPTargetDirectiveClass;
3194   }
3195 };
3196 
3197 /// This represents '#pragma omp target data' directive.
3198 ///
3199 /// \code
3200 /// #pragma omp target data device(0) if(a) map(b[:])
3201 /// \endcode
3202 /// In this example directive '#pragma omp target data' has clauses 'device'
3203 /// with the value '0', 'if' with condition 'a' and 'map' with array
3204 /// section 'b[:]'.
3205 ///
3206 class OMPTargetDataDirective : public OMPExecutableDirective {
3207   friend class ASTStmtReader;
3208   friend class OMPExecutableDirective;
3209   /// Build directive with the given start and end location.
3210   ///
3211   /// \param StartLoc Starting location of the directive kind.
3212   /// \param EndLoc Ending Location of the directive.
3213   ///
3214   OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3215       : OMPExecutableDirective(OMPTargetDataDirectiveClass,
3216                                llvm::omp::OMPD_target_data, StartLoc, EndLoc) {}
3217 
3218   /// Build an empty directive.
3219   ///
3220   explicit OMPTargetDataDirective()
3221       : OMPExecutableDirective(OMPTargetDataDirectiveClass,
3222                                llvm::omp::OMPD_target_data, SourceLocation(),
3223                                SourceLocation()) {}
3224 
3225 public:
3226   /// Creates directive with a list of \a Clauses.
3227   ///
3228   /// \param C AST context.
3229   /// \param StartLoc Starting location of the directive kind.
3230   /// \param EndLoc Ending Location of the directive.
3231   /// \param Clauses List of clauses.
3232   /// \param AssociatedStmt Statement, associated with the directive.
3233   ///
3234   static OMPTargetDataDirective *
3235   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3236          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3237 
3238   /// Creates an empty directive with the place for \a N clauses.
3239   ///
3240   /// \param C AST context.
3241   /// \param N The number of clauses.
3242   ///
3243   static OMPTargetDataDirective *CreateEmpty(const ASTContext &C, unsigned N,
3244                                              EmptyShell);
3245 
3246   static bool classof(const Stmt *T) {
3247     return T->getStmtClass() == OMPTargetDataDirectiveClass;
3248   }
3249 };
3250 
3251 /// This represents '#pragma omp target enter data' directive.
3252 ///
3253 /// \code
3254 /// #pragma omp target enter data device(0) if(a) map(b[:])
3255 /// \endcode
3256 /// In this example directive '#pragma omp target enter data' has clauses
3257 /// 'device' with the value '0', 'if' with condition 'a' and 'map' with array
3258 /// section 'b[:]'.
3259 ///
3260 class OMPTargetEnterDataDirective : public OMPExecutableDirective {
3261   friend class ASTStmtReader;
3262   friend class OMPExecutableDirective;
3263   /// Build directive with the given start and end location.
3264   ///
3265   /// \param StartLoc Starting location of the directive kind.
3266   /// \param EndLoc Ending Location of the directive.
3267   ///
3268   OMPTargetEnterDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3269       : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
3270                                llvm::omp::OMPD_target_enter_data, StartLoc,
3271                                EndLoc) {}
3272 
3273   /// Build an empty directive.
3274   ///
3275   explicit OMPTargetEnterDataDirective()
3276       : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
3277                                llvm::omp::OMPD_target_enter_data,
3278                                SourceLocation(), SourceLocation()) {}
3279 
3280 public:
3281   /// Creates directive with a list of \a Clauses.
3282   ///
3283   /// \param C AST context.
3284   /// \param StartLoc Starting location of the directive kind.
3285   /// \param EndLoc Ending Location of the directive.
3286   /// \param Clauses List of clauses.
3287   /// \param AssociatedStmt Statement, associated with the directive.
3288   ///
3289   static OMPTargetEnterDataDirective *
3290   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3291          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3292 
3293   /// Creates an empty directive with the place for \a N clauses.
3294   ///
3295   /// \param C AST context.
3296   /// \param N The number of clauses.
3297   ///
3298   static OMPTargetEnterDataDirective *CreateEmpty(const ASTContext &C,
3299                                                   unsigned N, EmptyShell);
3300 
3301   static bool classof(const Stmt *T) {
3302     return T->getStmtClass() == OMPTargetEnterDataDirectiveClass;
3303   }
3304 };
3305 
3306 /// This represents '#pragma omp target exit data' directive.
3307 ///
3308 /// \code
3309 /// #pragma omp target exit data device(0) if(a) map(b[:])
3310 /// \endcode
3311 /// In this example directive '#pragma omp target exit data' has clauses
3312 /// 'device' with the value '0', 'if' with condition 'a' and 'map' with array
3313 /// section 'b[:]'.
3314 ///
3315 class OMPTargetExitDataDirective : public OMPExecutableDirective {
3316   friend class ASTStmtReader;
3317   friend class OMPExecutableDirective;
3318   /// Build directive with the given start and end location.
3319   ///
3320   /// \param StartLoc Starting location of the directive kind.
3321   /// \param EndLoc Ending Location of the directive.
3322   ///
3323   OMPTargetExitDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3324       : OMPExecutableDirective(OMPTargetExitDataDirectiveClass,
3325                                llvm::omp::OMPD_target_exit_data, StartLoc,
3326                                EndLoc) {}
3327 
3328   /// Build an empty directive.
3329   ///
3330   explicit OMPTargetExitDataDirective()
3331       : OMPExecutableDirective(OMPTargetExitDataDirectiveClass,
3332                                llvm::omp::OMPD_target_exit_data,
3333                                SourceLocation(), SourceLocation()) {}
3334 
3335 public:
3336   /// Creates directive with a list of \a Clauses.
3337   ///
3338   /// \param C AST context.
3339   /// \param StartLoc Starting location of the directive kind.
3340   /// \param EndLoc Ending Location of the directive.
3341   /// \param Clauses List of clauses.
3342   /// \param AssociatedStmt Statement, associated with the directive.
3343   ///
3344   static OMPTargetExitDataDirective *
3345   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3346          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
3347 
3348   /// Creates an empty directive with the place for \a N clauses.
3349   ///
3350   /// \param C AST context.
3351   /// \param N The number of clauses.
3352   ///
3353   static OMPTargetExitDataDirective *CreateEmpty(const ASTContext &C,
3354                                                  unsigned N, EmptyShell);
3355 
3356   static bool classof(const Stmt *T) {
3357     return T->getStmtClass() == OMPTargetExitDataDirectiveClass;
3358   }
3359 };
3360 
3361 /// This represents '#pragma omp target parallel' directive.
3362 ///
3363 /// \code
3364 /// #pragma omp target parallel if(a)
3365 /// \endcode
3366 /// In this example directive '#pragma omp target parallel' has clause 'if' with
3367 /// condition 'a'.
3368 ///
3369 class OMPTargetParallelDirective : public OMPExecutableDirective {
3370   friend class ASTStmtReader;
3371   friend class OMPExecutableDirective;
3372   /// true if the construct has inner cancel directive.
3373   bool HasCancel = false;
3374 
3375   /// Build directive with the given start and end location.
3376   ///
3377   /// \param StartLoc Starting location of the directive kind.
3378   /// \param EndLoc Ending location of the directive.
3379   ///
3380   OMPTargetParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3381       : OMPExecutableDirective(OMPTargetParallelDirectiveClass,
3382                                llvm::omp::OMPD_target_parallel, StartLoc,
3383                                EndLoc) {}
3384 
3385   /// Build an empty directive.
3386   ///
3387   explicit OMPTargetParallelDirective()
3388       : OMPExecutableDirective(OMPTargetParallelDirectiveClass,
3389                                llvm::omp::OMPD_target_parallel,
3390                                SourceLocation(), SourceLocation()) {}
3391 
3392   /// Sets special task reduction descriptor.
3393   void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
3394   /// Set cancel state.
3395   void setHasCancel(bool Has) { HasCancel = Has; }
3396 
3397 public:
3398   /// Creates directive with a list of \a Clauses.
3399   ///
3400   /// \param C AST context.
3401   /// \param StartLoc Starting location of the directive kind.
3402   /// \param EndLoc Ending Location of the directive.
3403   /// \param Clauses List of clauses.
3404   /// \param AssociatedStmt Statement, associated with the directive.
3405   /// \param TaskRedRef Task reduction special reference expression to handle
3406   /// taskgroup descriptor.
3407   /// \param HasCancel true if this directive has inner cancel directive.
3408   ///
3409   static OMPTargetParallelDirective *
3410   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3411          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
3412          bool HasCancel);
3413 
3414   /// Creates an empty directive with the place for \a NumClauses
3415   /// clauses.
3416   ///
3417   /// \param C AST context.
3418   /// \param NumClauses Number of clauses.
3419   ///
3420   static OMPTargetParallelDirective *
3421   CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
3422 
3423   /// Returns special task reduction reference expression.
3424   Expr *getTaskReductionRefExpr() {
3425     return cast_or_null<Expr>(Data->getChildren()[0]);
3426   }
3427   const Expr *getTaskReductionRefExpr() const {
3428     return const_cast<OMPTargetParallelDirective *>(this)
3429         ->getTaskReductionRefExpr();
3430   }
3431 
3432   /// Return true if current directive has inner cancel directive.
3433   bool hasCancel() const { return HasCancel; }
3434 
3435   static bool classof(const Stmt *T) {
3436     return T->getStmtClass() == OMPTargetParallelDirectiveClass;
3437   }
3438 };
3439 
3440 /// This represents '#pragma omp target parallel for' directive.
3441 ///
3442 /// \code
3443 /// #pragma omp target parallel for private(a,b) reduction(+:c,d)
3444 /// \endcode
3445 /// In this example directive '#pragma omp target parallel for' has clauses
3446 /// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+'
3447 /// and variables 'c' and 'd'.
3448 ///
3449 class OMPTargetParallelForDirective : public OMPLoopDirective {
3450   friend class ASTStmtReader;
3451   friend class OMPExecutableDirective;
3452 
3453   /// true if current region has inner cancel directive.
3454   bool HasCancel = false;
3455 
3456   /// Build directive with the given start and end location.
3457   ///
3458   /// \param StartLoc Starting location of the directive kind.
3459   /// \param EndLoc Ending location of the directive.
3460   /// \param CollapsedNum Number of collapsed nested loops.
3461   ///
3462   OMPTargetParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3463                                 unsigned CollapsedNum)
3464       : OMPLoopDirective(OMPTargetParallelForDirectiveClass,
3465                          llvm::omp::OMPD_target_parallel_for, StartLoc, EndLoc,
3466                          CollapsedNum) {}
3467 
3468   /// Build an empty directive.
3469   ///
3470   /// \param CollapsedNum Number of collapsed nested loops.
3471   ///
3472   explicit OMPTargetParallelForDirective(unsigned CollapsedNum)
3473       : OMPLoopDirective(OMPTargetParallelForDirectiveClass,
3474                          llvm::omp::OMPD_target_parallel_for, SourceLocation(),
3475                          SourceLocation(), CollapsedNum) {}
3476 
3477   /// Sets special task reduction descriptor.
3478   void setTaskReductionRefExpr(Expr *E) {
3479     Data->getChildren()[numLoopChildren(
3480         getLoopsNumber(), llvm::omp::OMPD_target_parallel_for)] = E;
3481   }
3482 
3483   /// Set cancel state.
3484   void setHasCancel(bool Has) { HasCancel = Has; }
3485 
3486 public:
3487   /// Creates directive with a list of \a Clauses.
3488   ///
3489   /// \param C AST context.
3490   /// \param StartLoc Starting location of the directive kind.
3491   /// \param EndLoc Ending Location of the directive.
3492   /// \param CollapsedNum Number of collapsed loops.
3493   /// \param Clauses List of clauses.
3494   /// \param AssociatedStmt Statement, associated with the directive.
3495   /// \param Exprs Helper expressions for CodeGen.
3496   /// \param TaskRedRef Task reduction special reference expression to handle
3497   /// taskgroup descriptor.
3498   /// \param HasCancel true if current directive has inner cancel directive.
3499   ///
3500   static OMPTargetParallelForDirective *
3501   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3502          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3503          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
3504          bool HasCancel);
3505 
3506   /// Creates an empty directive with the place
3507   /// for \a NumClauses clauses.
3508   ///
3509   /// \param C AST context.
3510   /// \param CollapsedNum Number of collapsed nested loops.
3511   /// \param NumClauses Number of clauses.
3512   ///
3513   static OMPTargetParallelForDirective *CreateEmpty(const ASTContext &C,
3514                                                     unsigned NumClauses,
3515                                                     unsigned CollapsedNum,
3516                                                     EmptyShell);
3517 
3518   /// Returns special task reduction reference expression.
3519   Expr *getTaskReductionRefExpr() {
3520     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
3521         getLoopsNumber(), llvm::omp::OMPD_target_parallel_for)]);
3522   }
3523   const Expr *getTaskReductionRefExpr() const {
3524     return const_cast<OMPTargetParallelForDirective *>(this)
3525         ->getTaskReductionRefExpr();
3526   }
3527 
3528   /// Return true if current directive has inner cancel directive.
3529   bool hasCancel() const { return HasCancel; }
3530 
3531   static bool classof(const Stmt *T) {
3532     return T->getStmtClass() == OMPTargetParallelForDirectiveClass;
3533   }
3534 };
3535 
3536 /// This represents '#pragma omp teams' directive.
3537 ///
3538 /// \code
3539 /// #pragma omp teams if(a)
3540 /// \endcode
3541 /// In this example directive '#pragma omp teams' has clause 'if' with
3542 /// condition 'a'.
3543 ///
3544 class OMPTeamsDirective : public OMPExecutableDirective {
3545   friend class ASTStmtReader;
3546   friend class OMPExecutableDirective;
3547   /// Build directive with the given start and end location.
3548   ///
3549   /// \param StartLoc Starting location of the directive kind.
3550   /// \param EndLoc Ending location of the directive.
3551   ///
3552   OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3553       : OMPExecutableDirective(OMPTeamsDirectiveClass, llvm::omp::OMPD_teams,
3554                                StartLoc, EndLoc) {}
3555 
3556   /// Build an empty directive.
3557   ///
3558   explicit OMPTeamsDirective()
3559       : OMPExecutableDirective(OMPTeamsDirectiveClass, llvm::omp::OMPD_teams,
3560                                SourceLocation(), SourceLocation()) {}
3561 
3562 public:
3563   /// Creates directive with a list of \a Clauses.
3564   ///
3565   /// \param C AST context.
3566   /// \param StartLoc Starting location of the directive kind.
3567   /// \param EndLoc Ending Location of the directive.
3568   /// \param Clauses List of clauses.
3569   /// \param AssociatedStmt Statement, associated with the directive.
3570   ///
3571   static OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc,
3572                                    SourceLocation EndLoc,
3573                                    ArrayRef<OMPClause *> Clauses,
3574                                    Stmt *AssociatedStmt);
3575 
3576   /// Creates an empty directive with the place for \a NumClauses
3577   /// clauses.
3578   ///
3579   /// \param C AST context.
3580   /// \param NumClauses Number of clauses.
3581   ///
3582   static OMPTeamsDirective *CreateEmpty(const ASTContext &C,
3583                                         unsigned NumClauses, EmptyShell);
3584 
3585   static bool classof(const Stmt *T) {
3586     return T->getStmtClass() == OMPTeamsDirectiveClass;
3587   }
3588 };
3589 
3590 /// This represents '#pragma omp cancellation point' directive.
3591 ///
3592 /// \code
3593 /// #pragma omp cancellation point for
3594 /// \endcode
3595 ///
3596 /// In this example a cancellation point is created for innermost 'for' region.
3597 class OMPCancellationPointDirective : public OMPExecutableDirective {
3598   friend class ASTStmtReader;
3599   friend class OMPExecutableDirective;
3600   OpenMPDirectiveKind CancelRegion = llvm::omp::OMPD_unknown;
3601   /// Build directive with the given start and end location.
3602   ///
3603   /// \param StartLoc Starting location of the directive kind.
3604   /// \param EndLoc Ending location of the directive.
3605   /// statements and child expressions.
3606   ///
3607   OMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3608       : OMPExecutableDirective(OMPCancellationPointDirectiveClass,
3609                                llvm::omp::OMPD_cancellation_point, StartLoc,
3610                                EndLoc) {}
3611 
3612   /// Build an empty directive.
3613   explicit OMPCancellationPointDirective()
3614       : OMPExecutableDirective(OMPCancellationPointDirectiveClass,
3615                                llvm::omp::OMPD_cancellation_point,
3616                                SourceLocation(), SourceLocation()) {}
3617 
3618   /// Set cancel region for current cancellation point.
3619   /// \param CR Cancellation region.
3620   void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
3621 
3622 public:
3623   /// Creates directive.
3624   ///
3625   /// \param C AST context.
3626   /// \param StartLoc Starting location of the directive kind.
3627   /// \param EndLoc Ending Location of the directive.
3628   ///
3629   static OMPCancellationPointDirective *
3630   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3631          OpenMPDirectiveKind CancelRegion);
3632 
3633   /// Creates an empty directive.
3634   ///
3635   /// \param C AST context.
3636   ///
3637   static OMPCancellationPointDirective *CreateEmpty(const ASTContext &C,
3638                                                     EmptyShell);
3639 
3640   /// Get cancellation region for the current cancellation point.
3641   OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
3642 
3643   static bool classof(const Stmt *T) {
3644     return T->getStmtClass() == OMPCancellationPointDirectiveClass;
3645   }
3646 };
3647 
3648 /// This represents '#pragma omp cancel' directive.
3649 ///
3650 /// \code
3651 /// #pragma omp cancel for
3652 /// \endcode
3653 ///
3654 /// In this example a cancel is created for innermost 'for' region.
3655 class OMPCancelDirective : public OMPExecutableDirective {
3656   friend class ASTStmtReader;
3657   friend class OMPExecutableDirective;
3658   OpenMPDirectiveKind CancelRegion = llvm::omp::OMPD_unknown;
3659   /// Build directive with the given start and end location.
3660   ///
3661   /// \param StartLoc Starting location of the directive kind.
3662   /// \param EndLoc Ending location of the directive.
3663   ///
3664   OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
3665       : OMPExecutableDirective(OMPCancelDirectiveClass, llvm::omp::OMPD_cancel,
3666                                StartLoc, EndLoc) {}
3667 
3668   /// Build an empty directive.
3669   ///
3670   explicit OMPCancelDirective()
3671       : OMPExecutableDirective(OMPCancelDirectiveClass, llvm::omp::OMPD_cancel,
3672                                SourceLocation(), SourceLocation()) {}
3673 
3674   /// Set cancel region for current cancellation point.
3675   /// \param CR Cancellation region.
3676   void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
3677 
3678 public:
3679   /// Creates directive.
3680   ///
3681   /// \param C AST context.
3682   /// \param StartLoc Starting location of the directive kind.
3683   /// \param EndLoc Ending Location of the directive.
3684   /// \param Clauses List of clauses.
3685   ///
3686   static OMPCancelDirective *
3687   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3688          ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion);
3689 
3690   /// Creates an empty directive.
3691   ///
3692   /// \param C AST context.
3693   /// \param NumClauses Number of clauses.
3694   ///
3695   static OMPCancelDirective *CreateEmpty(const ASTContext &C,
3696                                          unsigned NumClauses, EmptyShell);
3697 
3698   /// Get cancellation region for the current cancellation point.
3699   OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
3700 
3701   static bool classof(const Stmt *T) {
3702     return T->getStmtClass() == OMPCancelDirectiveClass;
3703   }
3704 };
3705 
3706 /// This represents '#pragma omp taskloop' directive.
3707 ///
3708 /// \code
3709 /// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num)
3710 /// \endcode
3711 /// In this example directive '#pragma omp taskloop' has clauses 'private'
3712 /// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
3713 /// 'num_tasks' with expression 'num'.
3714 ///
3715 class OMPTaskLoopDirective : public OMPLoopDirective {
3716   friend class ASTStmtReader;
3717   friend class OMPExecutableDirective;
3718   /// true if the construct has inner cancel directive.
3719   bool HasCancel = false;
3720 
3721   /// Build directive with the given start and end location.
3722   ///
3723   /// \param StartLoc Starting location of the directive kind.
3724   /// \param EndLoc Ending location of the directive.
3725   /// \param CollapsedNum Number of collapsed nested loops.
3726   ///
3727   OMPTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3728                        unsigned CollapsedNum)
3729       : OMPLoopDirective(OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop,
3730                          StartLoc, EndLoc, CollapsedNum) {}
3731 
3732   /// Build an empty directive.
3733   ///
3734   /// \param CollapsedNum Number of collapsed nested loops.
3735   ///
3736   explicit OMPTaskLoopDirective(unsigned CollapsedNum)
3737       : OMPLoopDirective(OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop,
3738                          SourceLocation(), SourceLocation(), CollapsedNum) {}
3739 
3740   /// Set cancel state.
3741   void setHasCancel(bool Has) { HasCancel = Has; }
3742 
3743 public:
3744   /// Creates directive with a list of \a Clauses.
3745   ///
3746   /// \param C AST context.
3747   /// \param StartLoc Starting location of the directive kind.
3748   /// \param EndLoc Ending Location of the directive.
3749   /// \param CollapsedNum Number of collapsed loops.
3750   /// \param Clauses List of clauses.
3751   /// \param AssociatedStmt Statement, associated with the directive.
3752   /// \param Exprs Helper expressions for CodeGen.
3753   /// \param HasCancel true if this directive has inner cancel directive.
3754   ///
3755   static OMPTaskLoopDirective *
3756   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3757          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3758          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
3759 
3760   /// Creates an empty directive with the place
3761   /// for \a NumClauses clauses.
3762   ///
3763   /// \param C AST context.
3764   /// \param CollapsedNum Number of collapsed nested loops.
3765   /// \param NumClauses Number of clauses.
3766   ///
3767   static OMPTaskLoopDirective *CreateEmpty(const ASTContext &C,
3768                                            unsigned NumClauses,
3769                                            unsigned CollapsedNum, EmptyShell);
3770 
3771   /// Return true if current directive has inner cancel directive.
3772   bool hasCancel() const { return HasCancel; }
3773 
3774   static bool classof(const Stmt *T) {
3775     return T->getStmtClass() == OMPTaskLoopDirectiveClass;
3776   }
3777 };
3778 
3779 /// This represents '#pragma omp taskloop simd' directive.
3780 ///
3781 /// \code
3782 /// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num)
3783 /// \endcode
3784 /// In this example directive '#pragma omp taskloop simd' has clauses 'private'
3785 /// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
3786 /// 'num_tasks' with expression 'num'.
3787 ///
3788 class OMPTaskLoopSimdDirective : public OMPLoopDirective {
3789   friend class ASTStmtReader;
3790   friend class OMPExecutableDirective;
3791   /// Build directive with the given start and end location.
3792   ///
3793   /// \param StartLoc Starting location of the directive kind.
3794   /// \param EndLoc Ending location of the directive.
3795   /// \param CollapsedNum Number of collapsed nested loops.
3796   ///
3797   OMPTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3798                            unsigned CollapsedNum)
3799       : OMPLoopDirective(OMPTaskLoopSimdDirectiveClass,
3800                          llvm::omp::OMPD_taskloop_simd, StartLoc, EndLoc,
3801                          CollapsedNum) {}
3802 
3803   /// Build an empty directive.
3804   ///
3805   /// \param CollapsedNum Number of collapsed nested loops.
3806   ///
3807   explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum)
3808       : OMPLoopDirective(OMPTaskLoopSimdDirectiveClass,
3809                          llvm::omp::OMPD_taskloop_simd, SourceLocation(),
3810                          SourceLocation(), CollapsedNum) {}
3811 
3812 public:
3813   /// Creates directive with a list of \a Clauses.
3814   ///
3815   /// \param C AST context.
3816   /// \param StartLoc Starting location of the directive kind.
3817   /// \param EndLoc Ending Location of the directive.
3818   /// \param CollapsedNum Number of collapsed loops.
3819   /// \param Clauses List of clauses.
3820   /// \param AssociatedStmt Statement, associated with the directive.
3821   /// \param Exprs Helper expressions for CodeGen.
3822   ///
3823   static OMPTaskLoopSimdDirective *
3824   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3825          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3826          Stmt *AssociatedStmt, const HelperExprs &Exprs);
3827 
3828   /// Creates an empty directive with the place
3829   /// for \a NumClauses clauses.
3830   ///
3831   /// \param C AST context.
3832   /// \param CollapsedNum Number of collapsed nested loops.
3833   /// \param NumClauses Number of clauses.
3834   ///
3835   static OMPTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
3836                                                unsigned NumClauses,
3837                                                unsigned CollapsedNum,
3838                                                EmptyShell);
3839 
3840   static bool classof(const Stmt *T) {
3841     return T->getStmtClass() == OMPTaskLoopSimdDirectiveClass;
3842   }
3843 };
3844 
3845 /// This represents '#pragma omp master taskloop' directive.
3846 ///
3847 /// \code
3848 /// #pragma omp master taskloop private(a,b) grainsize(val) num_tasks(num)
3849 /// \endcode
3850 /// In this example directive '#pragma omp master taskloop' has clauses
3851 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
3852 /// and 'num_tasks' with expression 'num'.
3853 ///
3854 class OMPMasterTaskLoopDirective : public OMPLoopDirective {
3855   friend class ASTStmtReader;
3856   friend class OMPExecutableDirective;
3857   /// true if the construct has inner cancel directive.
3858   bool HasCancel = false;
3859 
3860   /// Build directive with the given start and end location.
3861   ///
3862   /// \param StartLoc Starting location of the directive kind.
3863   /// \param EndLoc Ending location of the directive.
3864   /// \param CollapsedNum Number of collapsed nested loops.
3865   ///
3866   OMPMasterTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3867                              unsigned CollapsedNum)
3868       : OMPLoopDirective(OMPMasterTaskLoopDirectiveClass,
3869                          llvm::omp::OMPD_master_taskloop, StartLoc, EndLoc,
3870                          CollapsedNum) {}
3871 
3872   /// Build an empty directive.
3873   ///
3874   /// \param CollapsedNum Number of collapsed nested loops.
3875   ///
3876   explicit OMPMasterTaskLoopDirective(unsigned CollapsedNum)
3877       : OMPLoopDirective(OMPMasterTaskLoopDirectiveClass,
3878                          llvm::omp::OMPD_master_taskloop, SourceLocation(),
3879                          SourceLocation(), CollapsedNum) {}
3880 
3881   /// Set cancel state.
3882   void setHasCancel(bool Has) { HasCancel = Has; }
3883 
3884 public:
3885   /// Creates directive with a list of \a Clauses.
3886   ///
3887   /// \param C AST context.
3888   /// \param StartLoc Starting location of the directive kind.
3889   /// \param EndLoc Ending Location of the directive.
3890   /// \param CollapsedNum Number of collapsed loops.
3891   /// \param Clauses List of clauses.
3892   /// \param AssociatedStmt Statement, associated with the directive.
3893   /// \param Exprs Helper expressions for CodeGen.
3894   /// \param HasCancel true if this directive has inner cancel directive.
3895   ///
3896   static OMPMasterTaskLoopDirective *
3897   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3898          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3899          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
3900 
3901   /// Creates an empty directive with the place
3902   /// for \a NumClauses clauses.
3903   ///
3904   /// \param C AST context.
3905   /// \param CollapsedNum Number of collapsed nested loops.
3906   /// \param NumClauses Number of clauses.
3907   ///
3908   static OMPMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
3909                                                  unsigned NumClauses,
3910                                                  unsigned CollapsedNum,
3911                                                  EmptyShell);
3912 
3913   /// Return true if current directive has inner cancel directive.
3914   bool hasCancel() const { return HasCancel; }
3915 
3916   static bool classof(const Stmt *T) {
3917     return T->getStmtClass() == OMPMasterTaskLoopDirectiveClass;
3918   }
3919 };
3920 
3921 /// This represents '#pragma omp masked taskloop' directive.
3922 ///
3923 /// \code
3924 /// #pragma omp masked taskloop private(a,b) grainsize(val) num_tasks(num)
3925 /// \endcode
3926 /// In this example directive '#pragma omp masked taskloop' has clauses
3927 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
3928 /// and 'num_tasks' with expression 'num'.
3929 ///
3930 class OMPMaskedTaskLoopDirective final : public OMPLoopDirective {
3931   friend class ASTStmtReader;
3932   friend class OMPExecutableDirective;
3933   /// true if the construct has inner cancel directive.
3934   bool HasCancel = false;
3935 
3936   /// Build directive with the given start and end location.
3937   ///
3938   /// \param StartLoc Starting location of the directive kind.
3939   /// \param EndLoc Ending location of the directive.
3940   /// \param CollapsedNum Number of collapsed nested loops.
3941   ///
3942   OMPMaskedTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
3943                              unsigned CollapsedNum)
3944       : OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass,
3945                          llvm::omp::OMPD_masked_taskloop, StartLoc, EndLoc,
3946                          CollapsedNum) {}
3947 
3948   /// Build an empty directive.
3949   ///
3950   /// \param CollapsedNum Number of collapsed nested loops.
3951   ///
3952   explicit OMPMaskedTaskLoopDirective(unsigned CollapsedNum)
3953       : OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass,
3954                          llvm::omp::OMPD_masked_taskloop, SourceLocation(),
3955                          SourceLocation(), CollapsedNum) {}
3956 
3957   /// Set cancel state.
3958   void setHasCancel(bool Has) { HasCancel = Has; }
3959 
3960 public:
3961   /// Creates directive with a list of \a Clauses.
3962   ///
3963   /// \param C AST context.
3964   /// \param StartLoc Starting location of the directive kind.
3965   /// \param EndLoc Ending Location of the directive.
3966   /// \param CollapsedNum Number of collapsed loops.
3967   /// \param Clauses List of clauses.
3968   /// \param AssociatedStmt Statement, associated with the directive.
3969   /// \param Exprs Helper expressions for CodeGen.
3970   /// \param HasCancel true if this directive has inner cancel directive.
3971   ///
3972   static OMPMaskedTaskLoopDirective *
3973   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
3974          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
3975          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
3976 
3977   /// Creates an empty directive with the place
3978   /// for \a NumClauses clauses.
3979   ///
3980   /// \param C AST context.
3981   /// \param CollapsedNum Number of collapsed nested loops.
3982   /// \param NumClauses Number of clauses.
3983   ///
3984   static OMPMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C,
3985                                                  unsigned NumClauses,
3986                                                  unsigned CollapsedNum,
3987                                                  EmptyShell);
3988 
3989   /// Return true if current directive has inner cancel directive.
3990   bool hasCancel() const { return HasCancel; }
3991 
3992   static bool classof(const Stmt *T) {
3993     return T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass;
3994   }
3995 };
3996 
3997 /// This represents '#pragma omp master taskloop simd' directive.
3998 ///
3999 /// \code
4000 /// #pragma omp master taskloop simd private(a,b) grainsize(val) num_tasks(num)
4001 /// \endcode
4002 /// In this example directive '#pragma omp master taskloop simd' has clauses
4003 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4004 /// and 'num_tasks' with expression 'num'.
4005 ///
4006 class OMPMasterTaskLoopSimdDirective : public OMPLoopDirective {
4007   friend class ASTStmtReader;
4008   friend class OMPExecutableDirective;
4009   /// Build directive with the given start and end location.
4010   ///
4011   /// \param StartLoc Starting location of the directive kind.
4012   /// \param EndLoc Ending location of the directive.
4013   /// \param CollapsedNum Number of collapsed nested loops.
4014   ///
4015   OMPMasterTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4016                                  unsigned CollapsedNum)
4017       : OMPLoopDirective(OMPMasterTaskLoopSimdDirectiveClass,
4018                          llvm::omp::OMPD_master_taskloop_simd, StartLoc, EndLoc,
4019                          CollapsedNum) {}
4020 
4021   /// Build an empty directive.
4022   ///
4023   /// \param CollapsedNum Number of collapsed nested loops.
4024   ///
4025   explicit OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum)
4026       : OMPLoopDirective(OMPMasterTaskLoopSimdDirectiveClass,
4027                          llvm::omp::OMPD_master_taskloop_simd, SourceLocation(),
4028                          SourceLocation(), CollapsedNum) {}
4029 
4030 public:
4031   /// Creates directive with a list of \p Clauses.
4032   ///
4033   /// \param C AST context.
4034   /// \param StartLoc Starting location of the directive kind.
4035   /// \param EndLoc Ending Location of the directive.
4036   /// \param CollapsedNum Number of collapsed loops.
4037   /// \param Clauses List of clauses.
4038   /// \param AssociatedStmt Statement, associated with the directive.
4039   /// \param Exprs Helper expressions for CodeGen.
4040   ///
4041   static OMPMasterTaskLoopSimdDirective *
4042   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4043          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4044          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4045 
4046   /// Creates an empty directive with the place for \p NumClauses clauses.
4047   ///
4048   /// \param C AST context.
4049   /// \param CollapsedNum Number of collapsed nested loops.
4050   /// \param NumClauses Number of clauses.
4051   ///
4052   static OMPMasterTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
4053                                                      unsigned NumClauses,
4054                                                      unsigned CollapsedNum,
4055                                                      EmptyShell);
4056 
4057   static bool classof(const Stmt *T) {
4058     return T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass;
4059   }
4060 };
4061 
4062 /// This represents '#pragma omp masked taskloop simd' directive.
4063 ///
4064 /// \code
4065 /// #pragma omp masked taskloop simd private(a,b) grainsize(val) num_tasks(num)
4066 /// \endcode
4067 /// In this example directive '#pragma omp masked taskloop simd' has clauses
4068 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4069 /// and 'num_tasks' with expression 'num'.
4070 ///
4071 class OMPMaskedTaskLoopSimdDirective final : public OMPLoopDirective {
4072   friend class ASTStmtReader;
4073   friend class OMPExecutableDirective;
4074   /// Build directive with the given start and end location.
4075   ///
4076   /// \param StartLoc Starting location of the directive kind.
4077   /// \param EndLoc Ending location of the directive.
4078   /// \param CollapsedNum Number of collapsed nested loops.
4079   ///
4080   OMPMaskedTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4081                                  unsigned CollapsedNum)
4082       : OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass,
4083                          llvm::omp::OMPD_masked_taskloop_simd, StartLoc, EndLoc,
4084                          CollapsedNum) {}
4085 
4086   /// Build an empty directive.
4087   ///
4088   /// \param CollapsedNum Number of collapsed nested loops.
4089   ///
4090   explicit OMPMaskedTaskLoopSimdDirective(unsigned CollapsedNum)
4091       : OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass,
4092                          llvm::omp::OMPD_masked_taskloop_simd, SourceLocation(),
4093                          SourceLocation(), CollapsedNum) {}
4094 
4095 public:
4096   /// Creates directive with a list of \p Clauses.
4097   ///
4098   /// \param C AST context.
4099   /// \param StartLoc Starting location of the directive kind.
4100   /// \param EndLoc Ending Location of the directive.
4101   /// \param CollapsedNum Number of collapsed loops.
4102   /// \param Clauses List of clauses.
4103   /// \param AssociatedStmt Statement, associated with the directive.
4104   /// \param Exprs Helper expressions for CodeGen.
4105   ///
4106   static OMPMaskedTaskLoopSimdDirective *
4107   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4108          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4109          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4110 
4111   /// Creates an empty directive with the place for \p NumClauses clauses.
4112   ///
4113   /// \param C AST context.
4114   /// \param CollapsedNum Number of collapsed nested loops.
4115   /// \param NumClauses Number of clauses.
4116   ///
4117   static OMPMaskedTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
4118                                                      unsigned NumClauses,
4119                                                      unsigned CollapsedNum,
4120                                                      EmptyShell);
4121 
4122   static bool classof(const Stmt *T) {
4123     return T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass;
4124   }
4125 };
4126 
4127 /// This represents '#pragma omp parallel master taskloop' directive.
4128 ///
4129 /// \code
4130 /// #pragma omp parallel master taskloop private(a,b) grainsize(val)
4131 /// num_tasks(num)
4132 /// \endcode
4133 /// In this example directive '#pragma omp parallel master taskloop' has clauses
4134 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4135 /// and 'num_tasks' with expression 'num'.
4136 ///
4137 class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
4138   friend class ASTStmtReader;
4139   friend class OMPExecutableDirective;
4140   /// true if the construct has inner cancel directive.
4141   bool HasCancel = false;
4142 
4143   /// Build directive with the given start and end location.
4144   ///
4145   /// \param StartLoc Starting location of the directive kind.
4146   /// \param EndLoc Ending location of the directive.
4147   /// \param CollapsedNum Number of collapsed nested loops.
4148   ///
4149   OMPParallelMasterTaskLoopDirective(SourceLocation StartLoc,
4150                                      SourceLocation EndLoc,
4151                                      unsigned CollapsedNum)
4152       : OMPLoopDirective(OMPParallelMasterTaskLoopDirectiveClass,
4153                          llvm::omp::OMPD_parallel_master_taskloop, StartLoc,
4154                          EndLoc, CollapsedNum) {}
4155 
4156   /// Build an empty directive.
4157   ///
4158   /// \param CollapsedNum Number of collapsed nested loops.
4159   ///
4160   explicit OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum)
4161       : OMPLoopDirective(OMPParallelMasterTaskLoopDirectiveClass,
4162                          llvm::omp::OMPD_parallel_master_taskloop,
4163                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4164 
4165   /// Set cancel state.
4166   void setHasCancel(bool Has) { HasCancel = Has; }
4167 
4168 public:
4169   /// Creates directive with a list of \a Clauses.
4170   ///
4171   /// \param C AST context.
4172   /// \param StartLoc Starting location of the directive kind.
4173   /// \param EndLoc Ending Location of the directive.
4174   /// \param CollapsedNum Number of collapsed loops.
4175   /// \param Clauses List of clauses.
4176   /// \param AssociatedStmt Statement, associated with the directive.
4177   /// \param Exprs Helper expressions for CodeGen.
4178   /// \param HasCancel true if this directive has inner cancel directive.
4179   ///
4180   static OMPParallelMasterTaskLoopDirective *
4181   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4182          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4183          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
4184 
4185   /// Creates an empty directive with the place
4186   /// for \a NumClauses clauses.
4187   ///
4188   /// \param C AST context.
4189   /// \param CollapsedNum Number of collapsed nested loops.
4190   /// \param NumClauses Number of clauses.
4191   ///
4192   static OMPParallelMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
4193                                                          unsigned NumClauses,
4194                                                          unsigned CollapsedNum,
4195                                                          EmptyShell);
4196 
4197   /// Return true if current directive has inner cancel directive.
4198   bool hasCancel() const { return HasCancel; }
4199 
4200   static bool classof(const Stmt *T) {
4201     return T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass;
4202   }
4203 };
4204 
4205 /// This represents '#pragma omp parallel masked taskloop' directive.
4206 ///
4207 /// \code
4208 /// #pragma omp parallel masked taskloop private(a,b) grainsize(val)
4209 /// num_tasks(num)
4210 /// \endcode
4211 /// In this example directive '#pragma omp parallel masked taskloop' has clauses
4212 /// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
4213 /// and 'num_tasks' with expression 'num'.
4214 ///
4215 class OMPParallelMaskedTaskLoopDirective final : public OMPLoopDirective {
4216   friend class ASTStmtReader;
4217   friend class OMPExecutableDirective;
4218   /// true if the construct has inner cancel directive.
4219   bool HasCancel = false;
4220 
4221   /// Build directive with the given start and end location.
4222   ///
4223   /// \param StartLoc Starting location of the directive kind.
4224   /// \param EndLoc Ending location of the directive.
4225   /// \param CollapsedNum Number of collapsed nested loops.
4226   ///
4227   OMPParallelMaskedTaskLoopDirective(SourceLocation StartLoc,
4228                                      SourceLocation EndLoc,
4229                                      unsigned CollapsedNum)
4230       : OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass,
4231                          llvm::omp::OMPD_parallel_masked_taskloop, StartLoc,
4232                          EndLoc, CollapsedNum) {}
4233 
4234   /// Build an empty directive.
4235   ///
4236   /// \param CollapsedNum Number of collapsed nested loops.
4237   ///
4238   explicit OMPParallelMaskedTaskLoopDirective(unsigned CollapsedNum)
4239       : OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass,
4240                          llvm::omp::OMPD_parallel_masked_taskloop,
4241                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4242 
4243   /// Set cancel state.
4244   void setHasCancel(bool Has) { HasCancel = Has; }
4245 
4246 public:
4247   /// Creates directive with a list of \a Clauses.
4248   ///
4249   /// \param C AST context.
4250   /// \param StartLoc Starting location of the directive kind.
4251   /// \param EndLoc Ending Location of the directive.
4252   /// \param CollapsedNum Number of collapsed loops.
4253   /// \param Clauses List of clauses.
4254   /// \param AssociatedStmt Statement, associated with the directive.
4255   /// \param Exprs Helper expressions for CodeGen.
4256   /// \param HasCancel true if this directive has inner cancel directive.
4257   ///
4258   static OMPParallelMaskedTaskLoopDirective *
4259   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4260          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4261          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
4262 
4263   /// Creates an empty directive with the place
4264   /// for \a NumClauses clauses.
4265   ///
4266   /// \param C AST context.
4267   /// \param CollapsedNum Number of collapsed nested loops.
4268   /// \param NumClauses Number of clauses.
4269   ///
4270   static OMPParallelMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C,
4271                                                          unsigned NumClauses,
4272                                                          unsigned CollapsedNum,
4273                                                          EmptyShell);
4274 
4275   /// Return true if current directive has inner cancel directive.
4276   bool hasCancel() const { return HasCancel; }
4277 
4278   static bool classof(const Stmt *T) {
4279     return T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass;
4280   }
4281 };
4282 
4283 /// This represents '#pragma omp parallel master taskloop simd' directive.
4284 ///
4285 /// \code
4286 /// #pragma omp parallel master taskloop simd private(a,b) grainsize(val)
4287 /// num_tasks(num)
4288 /// \endcode
4289 /// In this example directive '#pragma omp parallel master taskloop simd' has
4290 /// clauses 'private' with the variables 'a' and 'b', 'grainsize' with
4291 /// expression 'val' and 'num_tasks' with expression 'num'.
4292 ///
4293 class OMPParallelMasterTaskLoopSimdDirective : public OMPLoopDirective {
4294   friend class ASTStmtReader;
4295   friend class OMPExecutableDirective;
4296   /// Build directive with the given start and end location.
4297   ///
4298   /// \param StartLoc Starting location of the directive kind.
4299   /// \param EndLoc Ending location of the directive.
4300   /// \param CollapsedNum Number of collapsed nested loops.
4301   ///
4302   OMPParallelMasterTaskLoopSimdDirective(SourceLocation StartLoc,
4303                                          SourceLocation EndLoc,
4304                                          unsigned CollapsedNum)
4305       : OMPLoopDirective(OMPParallelMasterTaskLoopSimdDirectiveClass,
4306                          llvm::omp::OMPD_parallel_master_taskloop_simd,
4307                          StartLoc, EndLoc, CollapsedNum) {}
4308 
4309   /// Build an empty directive.
4310   ///
4311   /// \param CollapsedNum Number of collapsed nested loops.
4312   ///
4313   explicit OMPParallelMasterTaskLoopSimdDirective(unsigned CollapsedNum)
4314       : OMPLoopDirective(OMPParallelMasterTaskLoopSimdDirectiveClass,
4315                          llvm::omp::OMPD_parallel_master_taskloop_simd,
4316                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4317 
4318 public:
4319   /// Creates directive with a list of \p Clauses.
4320   ///
4321   /// \param C AST context.
4322   /// \param StartLoc Starting location of the directive kind.
4323   /// \param EndLoc Ending Location of the directive.
4324   /// \param CollapsedNum Number of collapsed loops.
4325   /// \param Clauses List of clauses.
4326   /// \param AssociatedStmt Statement, associated with the directive.
4327   /// \param Exprs Helper expressions for CodeGen.
4328   ///
4329   static OMPParallelMasterTaskLoopSimdDirective *
4330   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4331          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4332          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4333 
4334   /// Creates an empty directive with the place
4335   /// for \a NumClauses clauses.
4336   ///
4337   /// \param C AST context.
4338   /// \param CollapsedNum Number of collapsed nested loops.
4339   /// \param NumClauses Number of clauses.
4340   ///
4341   static OMPParallelMasterTaskLoopSimdDirective *
4342   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
4343               EmptyShell);
4344 
4345   static bool classof(const Stmt *T) {
4346     return T->getStmtClass() == OMPParallelMasterTaskLoopSimdDirectiveClass;
4347   }
4348 };
4349 
4350 /// This represents '#pragma omp parallel masked taskloop simd' directive.
4351 ///
4352 /// \code
4353 /// #pragma omp parallel masked taskloop simd private(a,b) grainsize(val)
4354 /// num_tasks(num)
4355 /// \endcode
4356 /// In this example directive '#pragma omp parallel masked taskloop simd' has
4357 /// clauses 'private' with the variables 'a' and 'b', 'grainsize' with
4358 /// expression 'val' and 'num_tasks' with expression 'num'.
4359 ///
4360 class OMPParallelMaskedTaskLoopSimdDirective final : public OMPLoopDirective {
4361   friend class ASTStmtReader;
4362   friend class OMPExecutableDirective;
4363   /// Build directive with the given start and end location.
4364   ///
4365   /// \param StartLoc Starting location of the directive kind.
4366   /// \param EndLoc Ending location of the directive.
4367   /// \param CollapsedNum Number of collapsed nested loops.
4368   ///
4369   OMPParallelMaskedTaskLoopSimdDirective(SourceLocation StartLoc,
4370                                          SourceLocation EndLoc,
4371                                          unsigned CollapsedNum)
4372       : OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass,
4373                          llvm::omp::OMPD_parallel_masked_taskloop_simd,
4374                          StartLoc, EndLoc, CollapsedNum) {}
4375 
4376   /// Build an empty directive.
4377   ///
4378   /// \param CollapsedNum Number of collapsed nested loops.
4379   ///
4380   explicit OMPParallelMaskedTaskLoopSimdDirective(unsigned CollapsedNum)
4381       : OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass,
4382                          llvm::omp::OMPD_parallel_masked_taskloop_simd,
4383                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4384 
4385 public:
4386   /// Creates directive with a list of \p Clauses.
4387   ///
4388   /// \param C AST context.
4389   /// \param StartLoc Starting location of the directive kind.
4390   /// \param EndLoc Ending Location of the directive.
4391   /// \param CollapsedNum Number of collapsed loops.
4392   /// \param Clauses List of clauses.
4393   /// \param AssociatedStmt Statement, associated with the directive.
4394   /// \param Exprs Helper expressions for CodeGen.
4395   ///
4396   static OMPParallelMaskedTaskLoopSimdDirective *
4397   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4398          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4399          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4400 
4401   /// Creates an empty directive with the place
4402   /// for \a NumClauses clauses.
4403   ///
4404   /// \param C AST context.
4405   /// \param CollapsedNum Number of collapsed nested loops.
4406   /// \param NumClauses Number of clauses.
4407   ///
4408   static OMPParallelMaskedTaskLoopSimdDirective *
4409   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
4410               EmptyShell);
4411 
4412   static bool classof(const Stmt *T) {
4413     return T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass;
4414   }
4415 };
4416 
4417 /// This represents '#pragma omp distribute' directive.
4418 ///
4419 /// \code
4420 /// #pragma omp distribute private(a,b)
4421 /// \endcode
4422 /// In this example directive '#pragma omp distribute' has clauses 'private'
4423 /// with the variables 'a' and 'b'
4424 ///
4425 class OMPDistributeDirective : public OMPLoopDirective {
4426   friend class ASTStmtReader;
4427   friend class OMPExecutableDirective;
4428 
4429   /// Build directive with the given start and end location.
4430   ///
4431   /// \param StartLoc Starting location of the directive kind.
4432   /// \param EndLoc Ending location of the directive.
4433   /// \param CollapsedNum Number of collapsed nested loops.
4434   ///
4435   OMPDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4436                          unsigned CollapsedNum)
4437       : OMPLoopDirective(OMPDistributeDirectiveClass,
4438                          llvm::omp::OMPD_distribute, StartLoc, EndLoc,
4439                          CollapsedNum) {}
4440 
4441   /// Build an empty directive.
4442   ///
4443   /// \param CollapsedNum Number of collapsed nested loops.
4444   ///
4445   explicit OMPDistributeDirective(unsigned CollapsedNum)
4446       : OMPLoopDirective(OMPDistributeDirectiveClass,
4447                          llvm::omp::OMPD_distribute, SourceLocation(),
4448                          SourceLocation(), CollapsedNum) {}
4449 
4450 public:
4451   /// Creates directive with a list of \a Clauses.
4452   ///
4453   /// \param C AST context.
4454   /// \param StartLoc Starting location of the directive kind.
4455   /// \param EndLoc Ending Location of the directive.
4456   /// \param CollapsedNum Number of collapsed loops.
4457   /// \param Clauses List of clauses.
4458   /// \param AssociatedStmt Statement, associated with the directive.
4459   /// \param Exprs Helper expressions for CodeGen.
4460   ///
4461   static OMPDistributeDirective *
4462   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4463          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4464          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4465 
4466   /// Creates an empty directive with the place
4467   /// for \a NumClauses clauses.
4468   ///
4469   /// \param C AST context.
4470   /// \param CollapsedNum Number of collapsed nested loops.
4471   /// \param NumClauses Number of clauses.
4472   ///
4473   static OMPDistributeDirective *CreateEmpty(const ASTContext &C,
4474                                              unsigned NumClauses,
4475                                              unsigned CollapsedNum, EmptyShell);
4476 
4477   static bool classof(const Stmt *T) {
4478     return T->getStmtClass() == OMPDistributeDirectiveClass;
4479   }
4480 };
4481 
4482 /// This represents '#pragma omp target update' directive.
4483 ///
4484 /// \code
4485 /// #pragma omp target update to(a) from(b) device(1)
4486 /// \endcode
4487 /// In this example directive '#pragma omp target update' has clause 'to' with
4488 /// argument 'a', clause 'from' with argument 'b' and clause 'device' with
4489 /// argument '1'.
4490 ///
4491 class OMPTargetUpdateDirective : public OMPExecutableDirective {
4492   friend class ASTStmtReader;
4493   friend class OMPExecutableDirective;
4494   /// Build directive with the given start and end location.
4495   ///
4496   /// \param StartLoc Starting location of the directive kind.
4497   /// \param EndLoc Ending Location of the directive.
4498   ///
4499   OMPTargetUpdateDirective(SourceLocation StartLoc, SourceLocation EndLoc)
4500       : OMPExecutableDirective(OMPTargetUpdateDirectiveClass,
4501                                llvm::omp::OMPD_target_update, StartLoc,
4502                                EndLoc) {}
4503 
4504   /// Build an empty directive.
4505   ///
4506   explicit OMPTargetUpdateDirective()
4507       : OMPExecutableDirective(OMPTargetUpdateDirectiveClass,
4508                                llvm::omp::OMPD_target_update, SourceLocation(),
4509                                SourceLocation()) {}
4510 
4511 public:
4512   /// Creates directive with a list of \a Clauses.
4513   ///
4514   /// \param C AST context.
4515   /// \param StartLoc Starting location of the directive kind.
4516   /// \param EndLoc Ending Location of the directive.
4517   /// \param Clauses List of clauses.
4518   /// \param AssociatedStmt Statement, associated with the directive.
4519   ///
4520   static OMPTargetUpdateDirective *
4521   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4522          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
4523 
4524   /// Creates an empty directive with the place for \a NumClauses
4525   /// clauses.
4526   ///
4527   /// \param C AST context.
4528   /// \param NumClauses The number of clauses.
4529   ///
4530   static OMPTargetUpdateDirective *CreateEmpty(const ASTContext &C,
4531                                                unsigned NumClauses, EmptyShell);
4532 
4533   static bool classof(const Stmt *T) {
4534     return T->getStmtClass() == OMPTargetUpdateDirectiveClass;
4535   }
4536 };
4537 
4538 /// This represents '#pragma omp distribute parallel for' composite
4539 ///  directive.
4540 ///
4541 /// \code
4542 /// #pragma omp distribute parallel for private(a,b)
4543 /// \endcode
4544 /// In this example directive '#pragma omp distribute parallel for' has clause
4545 /// 'private' with the variables 'a' and 'b'
4546 ///
4547 class OMPDistributeParallelForDirective : public OMPLoopDirective {
4548   friend class ASTStmtReader;
4549   friend class OMPExecutableDirective;
4550   /// true if the construct has inner cancel directive.
4551   bool HasCancel = false;
4552 
4553   /// Build directive with the given start and end location.
4554   ///
4555   /// \param StartLoc Starting location of the directive kind.
4556   /// \param EndLoc Ending location of the directive.
4557   /// \param CollapsedNum Number of collapsed nested loops.
4558   ///
4559   OMPDistributeParallelForDirective(SourceLocation StartLoc,
4560                                     SourceLocation EndLoc,
4561                                     unsigned CollapsedNum)
4562       : OMPLoopDirective(OMPDistributeParallelForDirectiveClass,
4563                          llvm::omp::OMPD_distribute_parallel_for, StartLoc,
4564                          EndLoc, CollapsedNum) {}
4565 
4566   /// Build an empty directive.
4567   ///
4568   /// \param CollapsedNum Number of collapsed nested loops.
4569   ///
4570   explicit OMPDistributeParallelForDirective(unsigned CollapsedNum)
4571       : OMPLoopDirective(OMPDistributeParallelForDirectiveClass,
4572                          llvm::omp::OMPD_distribute_parallel_for,
4573                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4574 
4575   /// Sets special task reduction descriptor.
4576   void setTaskReductionRefExpr(Expr *E) {
4577     Data->getChildren()[numLoopChildren(
4578         getLoopsNumber(), llvm::omp::OMPD_distribute_parallel_for)] = E;
4579   }
4580 
4581   /// Set cancel state.
4582   void setHasCancel(bool Has) { HasCancel = Has; }
4583 
4584 public:
4585   /// Creates directive with a list of \a Clauses.
4586   ///
4587   /// \param C AST context.
4588   /// \param StartLoc Starting location of the directive kind.
4589   /// \param EndLoc Ending Location of the directive.
4590   /// \param CollapsedNum Number of collapsed loops.
4591   /// \param Clauses List of clauses.
4592   /// \param AssociatedStmt Statement, associated with the directive.
4593   /// \param Exprs Helper expressions for CodeGen.
4594   /// \param TaskRedRef Task reduction special reference expression to handle
4595   /// taskgroup descriptor.
4596   /// \param HasCancel true if this directive has inner cancel directive.
4597   ///
4598   static OMPDistributeParallelForDirective *
4599   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4600          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4601          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
4602          bool HasCancel);
4603 
4604   /// Creates an empty directive with the place
4605   /// for \a NumClauses clauses.
4606   ///
4607   /// \param C AST context.
4608   /// \param CollapsedNum Number of collapsed nested loops.
4609   /// \param NumClauses Number of clauses.
4610   ///
4611   static OMPDistributeParallelForDirective *CreateEmpty(const ASTContext &C,
4612                                                         unsigned NumClauses,
4613                                                         unsigned CollapsedNum,
4614                                                         EmptyShell);
4615 
4616   /// Returns special task reduction reference expression.
4617   Expr *getTaskReductionRefExpr() {
4618     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
4619         getLoopsNumber(), llvm::omp::OMPD_distribute_parallel_for)]);
4620   }
4621   const Expr *getTaskReductionRefExpr() const {
4622     return const_cast<OMPDistributeParallelForDirective *>(this)
4623         ->getTaskReductionRefExpr();
4624   }
4625 
4626   /// Return true if current directive has inner cancel directive.
4627   bool hasCancel() const { return HasCancel; }
4628 
4629   static bool classof(const Stmt *T) {
4630     return T->getStmtClass() == OMPDistributeParallelForDirectiveClass;
4631   }
4632 };
4633 
4634 /// This represents '#pragma omp distribute parallel for simd' composite
4635 /// directive.
4636 ///
4637 /// \code
4638 /// #pragma omp distribute parallel for simd private(x)
4639 /// \endcode
4640 /// In this example directive '#pragma omp distribute parallel for simd' has
4641 /// clause 'private' with the variables 'x'
4642 ///
4643 class OMPDistributeParallelForSimdDirective final : public OMPLoopDirective {
4644   friend class ASTStmtReader;
4645   friend class OMPExecutableDirective;
4646 
4647   /// Build directive with the given start and end location.
4648   ///
4649   /// \param StartLoc Starting location of the directive kind.
4650   /// \param EndLoc Ending location of the directive.
4651   /// \param CollapsedNum Number of collapsed nested loops.
4652   ///
4653   OMPDistributeParallelForSimdDirective(SourceLocation StartLoc,
4654                                         SourceLocation EndLoc,
4655                                         unsigned CollapsedNum)
4656       : OMPLoopDirective(OMPDistributeParallelForSimdDirectiveClass,
4657                          llvm::omp::OMPD_distribute_parallel_for_simd, StartLoc,
4658                          EndLoc, CollapsedNum) {}
4659 
4660   /// Build an empty directive.
4661   ///
4662   /// \param CollapsedNum Number of collapsed nested loops.
4663   ///
4664   explicit OMPDistributeParallelForSimdDirective(unsigned CollapsedNum)
4665       : OMPLoopDirective(OMPDistributeParallelForSimdDirectiveClass,
4666                          llvm::omp::OMPD_distribute_parallel_for_simd,
4667                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4668 
4669 public:
4670   /// Creates directive with a list of \a Clauses.
4671   ///
4672   /// \param C AST context.
4673   /// \param StartLoc Starting location of the directive kind.
4674   /// \param EndLoc Ending Location of the directive.
4675   /// \param CollapsedNum Number of collapsed loops.
4676   /// \param Clauses List of clauses.
4677   /// \param AssociatedStmt Statement, associated with the directive.
4678   /// \param Exprs Helper expressions for CodeGen.
4679   ///
4680   static OMPDistributeParallelForSimdDirective *Create(
4681       const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4682       unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4683       Stmt *AssociatedStmt, const HelperExprs &Exprs);
4684 
4685   /// Creates an empty directive with the place for \a NumClauses clauses.
4686   ///
4687   /// \param C AST context.
4688   /// \param CollapsedNum Number of collapsed nested loops.
4689   /// \param NumClauses Number of clauses.
4690   ///
4691   static OMPDistributeParallelForSimdDirective *CreateEmpty(
4692       const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
4693       EmptyShell);
4694 
4695   static bool classof(const Stmt *T) {
4696     return T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass;
4697   }
4698 };
4699 
4700 /// This represents '#pragma omp distribute simd' composite directive.
4701 ///
4702 /// \code
4703 /// #pragma omp distribute simd private(x)
4704 /// \endcode
4705 /// In this example directive '#pragma omp distribute simd' has clause
4706 /// 'private' with the variables 'x'
4707 ///
4708 class OMPDistributeSimdDirective final : public OMPLoopDirective {
4709   friend class ASTStmtReader;
4710   friend class OMPExecutableDirective;
4711 
4712   /// Build directive with the given start and end location.
4713   ///
4714   /// \param StartLoc Starting location of the directive kind.
4715   /// \param EndLoc Ending location of the directive.
4716   /// \param CollapsedNum Number of collapsed nested loops.
4717   ///
4718   OMPDistributeSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4719                              unsigned CollapsedNum)
4720       : OMPLoopDirective(OMPDistributeSimdDirectiveClass,
4721                          llvm::omp::OMPD_distribute_simd, StartLoc, EndLoc,
4722                          CollapsedNum) {}
4723 
4724   /// Build an empty directive.
4725   ///
4726   /// \param CollapsedNum Number of collapsed nested loops.
4727   ///
4728   explicit OMPDistributeSimdDirective(unsigned CollapsedNum)
4729       : OMPLoopDirective(OMPDistributeSimdDirectiveClass,
4730                          llvm::omp::OMPD_distribute_simd, SourceLocation(),
4731                          SourceLocation(), CollapsedNum) {}
4732 
4733 public:
4734   /// Creates directive with a list of \a Clauses.
4735   ///
4736   /// \param C AST context.
4737   /// \param StartLoc Starting location of the directive kind.
4738   /// \param EndLoc Ending Location of the directive.
4739   /// \param CollapsedNum Number of collapsed loops.
4740   /// \param Clauses List of clauses.
4741   /// \param AssociatedStmt Statement, associated with the directive.
4742   /// \param Exprs Helper expressions for CodeGen.
4743   ///
4744   static OMPDistributeSimdDirective *
4745   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4746          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4747          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4748 
4749   /// Creates an empty directive with the place for \a NumClauses clauses.
4750   ///
4751   /// \param C AST context.
4752   /// \param CollapsedNum Number of collapsed nested loops.
4753   /// \param NumClauses Number of clauses.
4754   ///
4755   static OMPDistributeSimdDirective *CreateEmpty(const ASTContext &C,
4756                                                  unsigned NumClauses,
4757                                                  unsigned CollapsedNum,
4758                                                  EmptyShell);
4759 
4760   static bool classof(const Stmt *T) {
4761     return T->getStmtClass() == OMPDistributeSimdDirectiveClass;
4762   }
4763 };
4764 
4765 /// This represents '#pragma omp target parallel for simd' directive.
4766 ///
4767 /// \code
4768 /// #pragma omp target parallel for simd private(a) map(b) safelen(c)
4769 /// \endcode
4770 /// In this example directive '#pragma omp target parallel for simd' has clauses
4771 /// 'private' with the variable 'a', 'map' with the variable 'b' and 'safelen'
4772 /// with the variable 'c'.
4773 ///
4774 class OMPTargetParallelForSimdDirective final : public OMPLoopDirective {
4775   friend class ASTStmtReader;
4776   friend class OMPExecutableDirective;
4777 
4778   /// Build directive with the given start and end location.
4779   ///
4780   /// \param StartLoc Starting location of the directive kind.
4781   /// \param EndLoc Ending location of the directive.
4782   /// \param CollapsedNum Number of collapsed nested loops.
4783   ///
4784   OMPTargetParallelForSimdDirective(SourceLocation StartLoc,
4785                                     SourceLocation EndLoc,
4786                                     unsigned CollapsedNum)
4787       : OMPLoopDirective(OMPTargetParallelForSimdDirectiveClass,
4788                          llvm::omp::OMPD_target_parallel_for_simd, StartLoc,
4789                          EndLoc, CollapsedNum) {}
4790 
4791   /// Build an empty directive.
4792   ///
4793   /// \param CollapsedNum Number of collapsed nested loops.
4794   ///
4795   explicit OMPTargetParallelForSimdDirective(unsigned CollapsedNum)
4796       : OMPLoopDirective(OMPTargetParallelForSimdDirectiveClass,
4797                          llvm::omp::OMPD_target_parallel_for_simd,
4798                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4799 
4800 public:
4801   /// Creates directive with a list of \a Clauses.
4802   ///
4803   /// \param C AST context.
4804   /// \param StartLoc Starting location of the directive kind.
4805   /// \param EndLoc Ending Location of the directive.
4806   /// \param CollapsedNum Number of collapsed loops.
4807   /// \param Clauses List of clauses.
4808   /// \param AssociatedStmt Statement, associated with the directive.
4809   /// \param Exprs Helper expressions for CodeGen.
4810   ///
4811   static OMPTargetParallelForSimdDirective *
4812   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4813          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4814          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4815 
4816   /// Creates an empty directive with the place for \a NumClauses clauses.
4817   ///
4818   /// \param C AST context.
4819   /// \param CollapsedNum Number of collapsed nested loops.
4820   /// \param NumClauses Number of clauses.
4821   ///
4822   static OMPTargetParallelForSimdDirective *CreateEmpty(const ASTContext &C,
4823                                                         unsigned NumClauses,
4824                                                         unsigned CollapsedNum,
4825                                                         EmptyShell);
4826 
4827   static bool classof(const Stmt *T) {
4828     return T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass;
4829   }
4830 };
4831 
4832 /// This represents '#pragma omp target simd' directive.
4833 ///
4834 /// \code
4835 /// #pragma omp target simd private(a) map(b) safelen(c)
4836 /// \endcode
4837 /// In this example directive '#pragma omp target simd' has clauses 'private'
4838 /// with the variable 'a', 'map' with the variable 'b' and 'safelen' with
4839 /// the variable 'c'.
4840 ///
4841 class OMPTargetSimdDirective final : public OMPLoopDirective {
4842   friend class ASTStmtReader;
4843   friend class OMPExecutableDirective;
4844 
4845   /// Build directive with the given start and end location.
4846   ///
4847   /// \param StartLoc Starting location of the directive kind.
4848   /// \param EndLoc Ending location of the directive.
4849   /// \param CollapsedNum Number of collapsed nested loops.
4850   ///
4851   OMPTargetSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4852                          unsigned CollapsedNum)
4853       : OMPLoopDirective(OMPTargetSimdDirectiveClass,
4854                          llvm::omp::OMPD_target_simd, StartLoc, EndLoc,
4855                          CollapsedNum) {}
4856 
4857   /// Build an empty directive.
4858   ///
4859   /// \param CollapsedNum Number of collapsed nested loops.
4860   ///
4861   explicit OMPTargetSimdDirective(unsigned CollapsedNum)
4862       : OMPLoopDirective(OMPTargetSimdDirectiveClass,
4863                          llvm::omp::OMPD_target_simd, SourceLocation(),
4864                          SourceLocation(), CollapsedNum) {}
4865 
4866 public:
4867   /// Creates directive with a list of \a Clauses.
4868   ///
4869   /// \param C AST context.
4870   /// \param StartLoc Starting location of the directive kind.
4871   /// \param EndLoc Ending Location of the directive.
4872   /// \param CollapsedNum Number of collapsed loops.
4873   /// \param Clauses List of clauses.
4874   /// \param AssociatedStmt Statement, associated with the directive.
4875   /// \param Exprs Helper expressions for CodeGen.
4876   ///
4877   static OMPTargetSimdDirective *
4878   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4879          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4880          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4881 
4882   /// Creates an empty directive with the place for \a NumClauses clauses.
4883   ///
4884   /// \param C AST context.
4885   /// \param CollapsedNum Number of collapsed nested loops.
4886   /// \param NumClauses Number of clauses.
4887   ///
4888   static OMPTargetSimdDirective *CreateEmpty(const ASTContext &C,
4889                                              unsigned NumClauses,
4890                                              unsigned CollapsedNum,
4891                                              EmptyShell);
4892 
4893   static bool classof(const Stmt *T) {
4894     return T->getStmtClass() == OMPTargetSimdDirectiveClass;
4895   }
4896 };
4897 
4898 /// This represents '#pragma omp teams distribute' directive.
4899 ///
4900 /// \code
4901 /// #pragma omp teams distribute private(a,b)
4902 /// \endcode
4903 /// In this example directive '#pragma omp teams distribute' has clauses
4904 /// 'private' with the variables 'a' and 'b'
4905 ///
4906 class OMPTeamsDistributeDirective final : public OMPLoopDirective {
4907   friend class ASTStmtReader;
4908   friend class OMPExecutableDirective;
4909 
4910   /// Build directive with the given start and end location.
4911   ///
4912   /// \param StartLoc Starting location of the directive kind.
4913   /// \param EndLoc Ending location of the directive.
4914   /// \param CollapsedNum Number of collapsed nested loops.
4915   ///
4916   OMPTeamsDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
4917                               unsigned CollapsedNum)
4918       : OMPLoopDirective(OMPTeamsDistributeDirectiveClass,
4919                          llvm::omp::OMPD_teams_distribute, StartLoc, EndLoc,
4920                          CollapsedNum) {}
4921 
4922   /// Build an empty directive.
4923   ///
4924   /// \param CollapsedNum Number of collapsed nested loops.
4925   ///
4926   explicit OMPTeamsDistributeDirective(unsigned CollapsedNum)
4927       : OMPLoopDirective(OMPTeamsDistributeDirectiveClass,
4928                          llvm::omp::OMPD_teams_distribute, SourceLocation(),
4929                          SourceLocation(), CollapsedNum) {}
4930 
4931 public:
4932   /// Creates directive with a list of \a Clauses.
4933   ///
4934   /// \param C AST context.
4935   /// \param StartLoc Starting location of the directive kind.
4936   /// \param EndLoc Ending Location of the directive.
4937   /// \param CollapsedNum Number of collapsed loops.
4938   /// \param Clauses List of clauses.
4939   /// \param AssociatedStmt Statement, associated with the directive.
4940   /// \param Exprs Helper expressions for CodeGen.
4941   ///
4942   static OMPTeamsDistributeDirective *
4943   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
4944          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
4945          Stmt *AssociatedStmt, const HelperExprs &Exprs);
4946 
4947   /// Creates an empty directive with the place for \a NumClauses clauses.
4948   ///
4949   /// \param C AST context.
4950   /// \param CollapsedNum Number of collapsed nested loops.
4951   /// \param NumClauses Number of clauses.
4952   ///
4953   static OMPTeamsDistributeDirective *CreateEmpty(const ASTContext &C,
4954                                                   unsigned NumClauses,
4955                                                   unsigned CollapsedNum,
4956                                                   EmptyShell);
4957 
4958   static bool classof(const Stmt *T) {
4959     return T->getStmtClass() == OMPTeamsDistributeDirectiveClass;
4960   }
4961 };
4962 
4963 /// This represents '#pragma omp teams distribute simd'
4964 /// combined directive.
4965 ///
4966 /// \code
4967 /// #pragma omp teams distribute simd private(a,b)
4968 /// \endcode
4969 /// In this example directive '#pragma omp teams distribute simd'
4970 /// has clause 'private' with the variables 'a' and 'b'
4971 ///
4972 class OMPTeamsDistributeSimdDirective final : public OMPLoopDirective {
4973   friend class ASTStmtReader;
4974   friend class OMPExecutableDirective;
4975 
4976   /// Build directive with the given start and end location.
4977   ///
4978   /// \param StartLoc Starting location of the directive kind.
4979   /// \param EndLoc Ending location of the directive.
4980   /// \param CollapsedNum Number of collapsed nested loops.
4981   ///
4982   OMPTeamsDistributeSimdDirective(SourceLocation StartLoc,
4983                                   SourceLocation EndLoc, unsigned CollapsedNum)
4984       : OMPLoopDirective(OMPTeamsDistributeSimdDirectiveClass,
4985                          llvm::omp::OMPD_teams_distribute_simd, StartLoc,
4986                          EndLoc, CollapsedNum) {}
4987 
4988   /// Build an empty directive.
4989   ///
4990   /// \param CollapsedNum Number of collapsed nested loops.
4991   ///
4992   explicit OMPTeamsDistributeSimdDirective(unsigned CollapsedNum)
4993       : OMPLoopDirective(OMPTeamsDistributeSimdDirectiveClass,
4994                          llvm::omp::OMPD_teams_distribute_simd,
4995                          SourceLocation(), SourceLocation(), CollapsedNum) {}
4996 
4997 public:
4998   /// Creates directive with a list of \a Clauses.
4999   ///
5000   /// \param C AST context.
5001   /// \param StartLoc Starting location of the directive kind.
5002   /// \param EndLoc Ending Location of the directive.
5003   /// \param CollapsedNum Number of collapsed loops.
5004   /// \param Clauses List of clauses.
5005   /// \param AssociatedStmt Statement, associated with the directive.
5006   /// \param Exprs Helper expressions for CodeGen.
5007   ///
5008   static OMPTeamsDistributeSimdDirective *
5009   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5010          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5011          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5012 
5013   /// Creates an empty directive with the place
5014   /// for \a NumClauses clauses.
5015   ///
5016   /// \param C AST context.
5017   /// \param CollapsedNum Number of collapsed nested loops.
5018   /// \param NumClauses Number of clauses.
5019   ///
5020   static OMPTeamsDistributeSimdDirective *CreateEmpty(const ASTContext &C,
5021                                                       unsigned NumClauses,
5022                                                       unsigned CollapsedNum,
5023                                                       EmptyShell);
5024 
5025   static bool classof(const Stmt *T) {
5026     return T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass;
5027   }
5028 };
5029 
5030 /// This represents '#pragma omp teams distribute parallel for simd' composite
5031 /// directive.
5032 ///
5033 /// \code
5034 /// #pragma omp teams distribute parallel for simd private(x)
5035 /// \endcode
5036 /// In this example directive '#pragma omp teams distribute parallel for simd'
5037 /// has clause 'private' with the variables 'x'
5038 ///
5039 class OMPTeamsDistributeParallelForSimdDirective final
5040     : public OMPLoopDirective {
5041   friend class ASTStmtReader;
5042   friend class OMPExecutableDirective;
5043 
5044   /// Build directive with the given start and end location.
5045   ///
5046   /// \param StartLoc Starting location of the directive kind.
5047   /// \param EndLoc Ending location of the directive.
5048   /// \param CollapsedNum Number of collapsed nested loops.
5049   ///
5050   OMPTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
5051                                              SourceLocation EndLoc,
5052                                              unsigned CollapsedNum)
5053       : OMPLoopDirective(OMPTeamsDistributeParallelForSimdDirectiveClass,
5054                          llvm::omp::OMPD_teams_distribute_parallel_for_simd,
5055                          StartLoc, EndLoc, CollapsedNum) {}
5056 
5057   /// Build an empty directive.
5058   ///
5059   /// \param CollapsedNum Number of collapsed nested loops.
5060   ///
5061   explicit OMPTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum)
5062       : OMPLoopDirective(OMPTeamsDistributeParallelForSimdDirectiveClass,
5063                          llvm::omp::OMPD_teams_distribute_parallel_for_simd,
5064                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5065 
5066 public:
5067   /// Creates directive with a list of \a Clauses.
5068   ///
5069   /// \param C AST context.
5070   /// \param StartLoc Starting location of the directive kind.
5071   /// \param EndLoc Ending Location of the directive.
5072   /// \param CollapsedNum Number of collapsed loops.
5073   /// \param Clauses List of clauses.
5074   /// \param AssociatedStmt Statement, associated with the directive.
5075   /// \param Exprs Helper expressions for CodeGen.
5076   ///
5077   static OMPTeamsDistributeParallelForSimdDirective *
5078   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5079          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5080          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5081 
5082   /// Creates an empty directive with the place for \a NumClauses clauses.
5083   ///
5084   /// \param C AST context.
5085   /// \param CollapsedNum Number of collapsed nested loops.
5086   /// \param NumClauses Number of clauses.
5087   ///
5088   static OMPTeamsDistributeParallelForSimdDirective *
5089   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5090               EmptyShell);
5091 
5092   static bool classof(const Stmt *T) {
5093     return T->getStmtClass() == OMPTeamsDistributeParallelForSimdDirectiveClass;
5094   }
5095 };
5096 
5097 /// This represents '#pragma omp teams distribute parallel for' composite
5098 /// directive.
5099 ///
5100 /// \code
5101 /// #pragma omp teams distribute parallel for private(x)
5102 /// \endcode
5103 /// In this example directive '#pragma omp teams distribute parallel for'
5104 /// has clause 'private' with the variables 'x'
5105 ///
5106 class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
5107   friend class ASTStmtReader;
5108   friend class OMPExecutableDirective;
5109   /// true if the construct has inner cancel directive.
5110   bool HasCancel = false;
5111 
5112   /// Build directive with the given start and end location.
5113   ///
5114   /// \param StartLoc Starting location of the directive kind.
5115   /// \param EndLoc Ending location of the directive.
5116   /// \param CollapsedNum Number of collapsed nested loops.
5117   ///
5118   OMPTeamsDistributeParallelForDirective(SourceLocation StartLoc,
5119                                          SourceLocation EndLoc,
5120                                          unsigned CollapsedNum)
5121       : OMPLoopDirective(OMPTeamsDistributeParallelForDirectiveClass,
5122                          llvm::omp::OMPD_teams_distribute_parallel_for,
5123                          StartLoc, EndLoc, CollapsedNum) {}
5124 
5125   /// Build an empty directive.
5126   ///
5127   /// \param CollapsedNum Number of collapsed nested loops.
5128   ///
5129   explicit OMPTeamsDistributeParallelForDirective(unsigned CollapsedNum)
5130       : OMPLoopDirective(OMPTeamsDistributeParallelForDirectiveClass,
5131                          llvm::omp::OMPD_teams_distribute_parallel_for,
5132                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5133 
5134   /// Sets special task reduction descriptor.
5135   void setTaskReductionRefExpr(Expr *E) {
5136     Data->getChildren()[numLoopChildren(
5137         getLoopsNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)] = E;
5138   }
5139 
5140   /// Set cancel state.
5141   void setHasCancel(bool Has) { HasCancel = Has; }
5142 
5143 public:
5144   /// Creates directive with a list of \a Clauses.
5145   ///
5146   /// \param C AST context.
5147   /// \param StartLoc Starting location of the directive kind.
5148   /// \param EndLoc Ending Location of the directive.
5149   /// \param CollapsedNum Number of collapsed loops.
5150   /// \param Clauses List of clauses.
5151   /// \param AssociatedStmt Statement, associated with the directive.
5152   /// \param Exprs Helper expressions for CodeGen.
5153   /// \param TaskRedRef Task reduction special reference expression to handle
5154   /// taskgroup descriptor.
5155   /// \param HasCancel true if this directive has inner cancel directive.
5156   ///
5157   static OMPTeamsDistributeParallelForDirective *
5158   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5159          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5160          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
5161          bool HasCancel);
5162 
5163   /// Creates an empty directive with the place for \a NumClauses clauses.
5164   ///
5165   /// \param C AST context.
5166   /// \param CollapsedNum Number of collapsed nested loops.
5167   /// \param NumClauses Number of clauses.
5168   ///
5169   static OMPTeamsDistributeParallelForDirective *
5170   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5171               EmptyShell);
5172 
5173   /// Returns special task reduction reference expression.
5174   Expr *getTaskReductionRefExpr() {
5175     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
5176         getLoopsNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)]);
5177   }
5178   const Expr *getTaskReductionRefExpr() const {
5179     return const_cast<OMPTeamsDistributeParallelForDirective *>(this)
5180         ->getTaskReductionRefExpr();
5181   }
5182 
5183   /// Return true if current directive has inner cancel directive.
5184   bool hasCancel() const { return HasCancel; }
5185 
5186   static bool classof(const Stmt *T) {
5187     return T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass;
5188   }
5189 };
5190 
5191 /// This represents '#pragma omp target teams' directive.
5192 ///
5193 /// \code
5194 /// #pragma omp target teams if(a>0)
5195 /// \endcode
5196 /// In this example directive '#pragma omp target teams' has clause 'if' with
5197 /// condition 'a>0'.
5198 ///
5199 class OMPTargetTeamsDirective final : public OMPExecutableDirective {
5200   friend class ASTStmtReader;
5201   friend class OMPExecutableDirective;
5202   /// Build directive with the given start and end location.
5203   ///
5204   /// \param StartLoc Starting location of the directive kind.
5205   /// \param EndLoc Ending location of the directive.
5206   ///
5207   OMPTargetTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5208       : OMPExecutableDirective(OMPTargetTeamsDirectiveClass,
5209                                llvm::omp::OMPD_target_teams, StartLoc, EndLoc) {
5210   }
5211 
5212   /// Build an empty directive.
5213   ///
5214   explicit OMPTargetTeamsDirective()
5215       : OMPExecutableDirective(OMPTargetTeamsDirectiveClass,
5216                                llvm::omp::OMPD_target_teams, SourceLocation(),
5217                                SourceLocation()) {}
5218 
5219 public:
5220   /// Creates directive with a list of \a Clauses.
5221   ///
5222   /// \param C AST context.
5223   /// \param StartLoc Starting location of the directive kind.
5224   /// \param EndLoc Ending Location of the directive.
5225   /// \param Clauses List of clauses.
5226   /// \param AssociatedStmt Statement, associated with the directive.
5227   ///
5228   static OMPTargetTeamsDirective *Create(const ASTContext &C,
5229                                          SourceLocation StartLoc,
5230                                          SourceLocation EndLoc,
5231                                          ArrayRef<OMPClause *> Clauses,
5232                                          Stmt *AssociatedStmt);
5233 
5234   /// Creates an empty directive with the place for \a NumClauses clauses.
5235   ///
5236   /// \param C AST context.
5237   /// \param NumClauses Number of clauses.
5238   ///
5239   static OMPTargetTeamsDirective *CreateEmpty(const ASTContext &C,
5240                                               unsigned NumClauses, EmptyShell);
5241 
5242   static bool classof(const Stmt *T) {
5243     return T->getStmtClass() == OMPTargetTeamsDirectiveClass;
5244   }
5245 };
5246 
5247 /// This represents '#pragma omp target teams distribute' combined directive.
5248 ///
5249 /// \code
5250 /// #pragma omp target teams distribute private(x)
5251 /// \endcode
5252 /// In this example directive '#pragma omp target teams distribute' has clause
5253 /// 'private' with the variables 'x'
5254 ///
5255 class OMPTargetTeamsDistributeDirective final : public OMPLoopDirective {
5256   friend class ASTStmtReader;
5257   friend class OMPExecutableDirective;
5258 
5259   /// Build directive with the given start and end location.
5260   ///
5261   /// \param StartLoc Starting location of the directive kind.
5262   /// \param EndLoc Ending location of the directive.
5263   /// \param CollapsedNum Number of collapsed nested loops.
5264   ///
5265   OMPTargetTeamsDistributeDirective(SourceLocation StartLoc,
5266                                     SourceLocation EndLoc,
5267                                     unsigned CollapsedNum)
5268       : OMPLoopDirective(OMPTargetTeamsDistributeDirectiveClass,
5269                          llvm::omp::OMPD_target_teams_distribute, StartLoc,
5270                          EndLoc, CollapsedNum) {}
5271 
5272   /// Build an empty directive.
5273   ///
5274   /// \param CollapsedNum Number of collapsed nested loops.
5275   ///
5276   explicit OMPTargetTeamsDistributeDirective(unsigned CollapsedNum)
5277       : OMPLoopDirective(OMPTargetTeamsDistributeDirectiveClass,
5278                          llvm::omp::OMPD_target_teams_distribute,
5279                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5280 
5281 public:
5282   /// Creates directive with a list of \a Clauses.
5283   ///
5284   /// \param C AST context.
5285   /// \param StartLoc Starting location of the directive kind.
5286   /// \param EndLoc Ending Location of the directive.
5287   /// \param CollapsedNum Number of collapsed loops.
5288   /// \param Clauses List of clauses.
5289   /// \param AssociatedStmt Statement, associated with the directive.
5290   /// \param Exprs Helper expressions for CodeGen.
5291   ///
5292   static OMPTargetTeamsDistributeDirective *
5293   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5294          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5295          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5296 
5297   /// Creates an empty directive with the place for \a NumClauses clauses.
5298   ///
5299   /// \param C AST context.
5300   /// \param CollapsedNum Number of collapsed nested loops.
5301   /// \param NumClauses Number of clauses.
5302   ///
5303   static OMPTargetTeamsDistributeDirective *
5304   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5305               EmptyShell);
5306 
5307   static bool classof(const Stmt *T) {
5308     return T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass;
5309   }
5310 };
5311 
5312 /// This represents '#pragma omp target teams distribute parallel for' combined
5313 /// directive.
5314 ///
5315 /// \code
5316 /// #pragma omp target teams distribute parallel for private(x)
5317 /// \endcode
5318 /// In this example directive '#pragma omp target teams distribute parallel
5319 /// for' has clause 'private' with the variables 'x'
5320 ///
5321 class OMPTargetTeamsDistributeParallelForDirective final
5322     : public OMPLoopDirective {
5323   friend class ASTStmtReader;
5324   friend class OMPExecutableDirective;
5325   /// true if the construct has inner cancel directive.
5326   bool HasCancel = false;
5327 
5328   /// Build directive with the given start and end location.
5329   ///
5330   /// \param StartLoc Starting location of the directive kind.
5331   /// \param EndLoc Ending location of the directive.
5332   /// \param CollapsedNum Number of collapsed nested loops.
5333   ///
5334   OMPTargetTeamsDistributeParallelForDirective(SourceLocation StartLoc,
5335                                                SourceLocation EndLoc,
5336                                                unsigned CollapsedNum)
5337       : OMPLoopDirective(OMPTargetTeamsDistributeParallelForDirectiveClass,
5338                          llvm::omp::OMPD_target_teams_distribute_parallel_for,
5339                          StartLoc, EndLoc, CollapsedNum) {}
5340 
5341   /// Build an empty directive.
5342   ///
5343   /// \param CollapsedNum Number of collapsed nested loops.
5344   ///
5345   explicit OMPTargetTeamsDistributeParallelForDirective(unsigned CollapsedNum)
5346       : OMPLoopDirective(OMPTargetTeamsDistributeParallelForDirectiveClass,
5347                          llvm::omp::OMPD_target_teams_distribute_parallel_for,
5348                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5349 
5350   /// Sets special task reduction descriptor.
5351   void setTaskReductionRefExpr(Expr *E) {
5352     Data->getChildren()[numLoopChildren(
5353         getLoopsNumber(),
5354         llvm::omp::OMPD_target_teams_distribute_parallel_for)] = E;
5355   }
5356 
5357   /// Set cancel state.
5358   void setHasCancel(bool Has) { HasCancel = Has; }
5359 
5360 public:
5361   /// Creates directive with a list of \a Clauses.
5362   ///
5363   /// \param C AST context.
5364   /// \param StartLoc Starting location of the directive kind.
5365   /// \param EndLoc Ending Location of the directive.
5366   /// \param CollapsedNum Number of collapsed loops.
5367   /// \param Clauses List of clauses.
5368   /// \param AssociatedStmt Statement, associated with the directive.
5369   /// \param Exprs Helper expressions for CodeGen.
5370   /// \param TaskRedRef Task reduction special reference expression to handle
5371   /// taskgroup descriptor.
5372   /// \param HasCancel true if this directive has inner cancel directive.
5373   ///
5374   static OMPTargetTeamsDistributeParallelForDirective *
5375   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5376          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5377          Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
5378          bool HasCancel);
5379 
5380   /// Creates an empty directive with the place for \a NumClauses clauses.
5381   ///
5382   /// \param C AST context.
5383   /// \param CollapsedNum Number of collapsed nested loops.
5384   /// \param NumClauses Number of clauses.
5385   ///
5386   static OMPTargetTeamsDistributeParallelForDirective *
5387   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5388               EmptyShell);
5389 
5390   /// Returns special task reduction reference expression.
5391   Expr *getTaskReductionRefExpr() {
5392     return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
5393         getLoopsNumber(),
5394         llvm::omp::OMPD_target_teams_distribute_parallel_for)]);
5395   }
5396   const Expr *getTaskReductionRefExpr() const {
5397     return const_cast<OMPTargetTeamsDistributeParallelForDirective *>(this)
5398         ->getTaskReductionRefExpr();
5399   }
5400 
5401   /// Return true if current directive has inner cancel directive.
5402   bool hasCancel() const { return HasCancel; }
5403 
5404   static bool classof(const Stmt *T) {
5405     return T->getStmtClass() ==
5406            OMPTargetTeamsDistributeParallelForDirectiveClass;
5407   }
5408 };
5409 
5410 /// This represents '#pragma omp target teams distribute parallel for simd'
5411 /// combined directive.
5412 ///
5413 /// \code
5414 /// #pragma omp target teams distribute parallel for simd private(x)
5415 /// \endcode
5416 /// In this example directive '#pragma omp target teams distribute parallel
5417 /// for simd' has clause 'private' with the variables 'x'
5418 ///
5419 class OMPTargetTeamsDistributeParallelForSimdDirective final
5420     : public OMPLoopDirective {
5421   friend class ASTStmtReader;
5422   friend class OMPExecutableDirective;
5423 
5424   /// Build directive with the given start and end location.
5425   ///
5426   /// \param StartLoc Starting location of the directive kind.
5427   /// \param EndLoc Ending location of the directive.
5428   /// \param CollapsedNum Number of collapsed nested loops.
5429   ///
5430   OMPTargetTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
5431                                                    SourceLocation EndLoc,
5432                                                    unsigned CollapsedNum)
5433       : OMPLoopDirective(
5434             OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
5435             llvm::omp::OMPD_target_teams_distribute_parallel_for_simd, StartLoc,
5436             EndLoc, CollapsedNum) {}
5437 
5438   /// Build an empty directive.
5439   ///
5440   /// \param CollapsedNum Number of collapsed nested loops.
5441   ///
5442   explicit OMPTargetTeamsDistributeParallelForSimdDirective(
5443       unsigned CollapsedNum)
5444       : OMPLoopDirective(
5445             OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
5446             llvm::omp::OMPD_target_teams_distribute_parallel_for_simd,
5447             SourceLocation(), SourceLocation(), CollapsedNum) {}
5448 
5449 public:
5450   /// Creates directive with a list of \a Clauses.
5451   ///
5452   /// \param C AST context.
5453   /// \param StartLoc Starting location of the directive kind.
5454   /// \param EndLoc Ending Location of the directive.
5455   /// \param CollapsedNum Number of collapsed loops.
5456   /// \param Clauses List of clauses.
5457   /// \param AssociatedStmt Statement, associated with the directive.
5458   /// \param Exprs Helper expressions for CodeGen.
5459   ///
5460   static OMPTargetTeamsDistributeParallelForSimdDirective *
5461   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5462          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5463          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5464 
5465   /// Creates an empty directive with the place for \a NumClauses clauses.
5466   ///
5467   /// \param C AST context.
5468   /// \param CollapsedNum Number of collapsed nested loops.
5469   /// \param NumClauses Number of clauses.
5470   ///
5471   static OMPTargetTeamsDistributeParallelForSimdDirective *
5472   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5473               EmptyShell);
5474 
5475   static bool classof(const Stmt *T) {
5476     return T->getStmtClass() ==
5477            OMPTargetTeamsDistributeParallelForSimdDirectiveClass;
5478   }
5479 };
5480 
5481 /// This represents '#pragma omp target teams distribute simd' combined
5482 /// directive.
5483 ///
5484 /// \code
5485 /// #pragma omp target teams distribute simd private(x)
5486 /// \endcode
5487 /// In this example directive '#pragma omp target teams distribute simd'
5488 /// has clause 'private' with the variables 'x'
5489 ///
5490 class OMPTargetTeamsDistributeSimdDirective final : public OMPLoopDirective {
5491   friend class ASTStmtReader;
5492   friend class OMPExecutableDirective;
5493 
5494   /// Build directive with the given start and end location.
5495   ///
5496   /// \param StartLoc Starting location of the directive kind.
5497   /// \param EndLoc Ending location of the directive.
5498   /// \param CollapsedNum Number of collapsed nested loops.
5499   ///
5500   OMPTargetTeamsDistributeSimdDirective(SourceLocation StartLoc,
5501                                         SourceLocation EndLoc,
5502                                         unsigned CollapsedNum)
5503       : OMPLoopDirective(OMPTargetTeamsDistributeSimdDirectiveClass,
5504                          llvm::omp::OMPD_target_teams_distribute_simd, StartLoc,
5505                          EndLoc, CollapsedNum) {}
5506 
5507   /// Build an empty directive.
5508   ///
5509   /// \param CollapsedNum Number of collapsed nested loops.
5510   ///
5511   explicit OMPTargetTeamsDistributeSimdDirective(unsigned CollapsedNum)
5512       : OMPLoopDirective(OMPTargetTeamsDistributeSimdDirectiveClass,
5513                          llvm::omp::OMPD_target_teams_distribute_simd,
5514                          SourceLocation(), SourceLocation(), CollapsedNum) {}
5515 
5516 public:
5517   /// Creates directive with a list of \a Clauses.
5518   ///
5519   /// \param C AST context.
5520   /// \param StartLoc Starting location of the directive kind.
5521   /// \param EndLoc Ending Location of the directive.
5522   /// \param CollapsedNum Number of collapsed loops.
5523   /// \param Clauses List of clauses.
5524   /// \param AssociatedStmt Statement, associated with the directive.
5525   /// \param Exprs Helper expressions for CodeGen.
5526   ///
5527   static OMPTargetTeamsDistributeSimdDirective *
5528   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5529          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
5530          Stmt *AssociatedStmt, const HelperExprs &Exprs);
5531 
5532   /// Creates an empty directive with the place for \a NumClauses clauses.
5533   ///
5534   /// \param C AST context.
5535   /// \param CollapsedNum Number of collapsed nested loops.
5536   /// \param NumClauses Number of clauses.
5537   ///
5538   static OMPTargetTeamsDistributeSimdDirective *
5539   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
5540               EmptyShell);
5541 
5542   static bool classof(const Stmt *T) {
5543     return T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass;
5544   }
5545 };
5546 
5547 /// This represents the '#pragma omp tile' loop transformation directive.
5548 class OMPTileDirective final : public OMPLoopTransformationDirective {
5549   friend class ASTStmtReader;
5550   friend class OMPExecutableDirective;
5551 
5552   /// Default list of offsets.
5553   enum {
5554     PreInitsOffset = 0,
5555     TransformedStmtOffset,
5556   };
5557 
5558   explicit OMPTileDirective(SourceLocation StartLoc, SourceLocation EndLoc,
5559                             unsigned NumLoops)
5560       : OMPLoopTransformationDirective(OMPTileDirectiveClass,
5561                                        llvm::omp::OMPD_tile, StartLoc, EndLoc,
5562                                        NumLoops) {
5563     setNumGeneratedLoops(3 * NumLoops);
5564   }
5565 
5566   void setPreInits(Stmt *PreInits) {
5567     Data->getChildren()[PreInitsOffset] = PreInits;
5568   }
5569 
5570   void setTransformedStmt(Stmt *S) {
5571     Data->getChildren()[TransformedStmtOffset] = S;
5572   }
5573 
5574 public:
5575   /// Create a new AST node representation for '#pragma omp tile'.
5576   ///
5577   /// \param C         Context of the AST.
5578   /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
5579   /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
5580   /// \param Clauses   The directive's clauses.
5581   /// \param NumLoops  Number of associated loops (number of items in the
5582   ///                  'sizes' clause).
5583   /// \param AssociatedStmt The outermost associated loop.
5584   /// \param TransformedStmt The loop nest after tiling, or nullptr in
5585   ///                        dependent contexts.
5586   /// \param PreInits Helper preinits statements for the loop nest.
5587   static OMPTileDirective *Create(const ASTContext &C, SourceLocation StartLoc,
5588                                   SourceLocation EndLoc,
5589                                   ArrayRef<OMPClause *> Clauses,
5590                                   unsigned NumLoops, Stmt *AssociatedStmt,
5591                                   Stmt *TransformedStmt, Stmt *PreInits);
5592 
5593   /// Build an empty '#pragma omp tile' AST node for deserialization.
5594   ///
5595   /// \param C          Context of the AST.
5596   /// \param NumClauses Number of clauses to allocate.
5597   /// \param NumLoops   Number of associated loops to allocate.
5598   static OMPTileDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
5599                                        unsigned NumLoops);
5600 
5601   /// Gets/sets the associated loops after tiling.
5602   ///
5603   /// This is in de-sugared format stored as a CompoundStmt.
5604   ///
5605   /// \code
5606   ///   for (...)
5607   ///     ...
5608   /// \endcode
5609   ///
5610   /// Note that if the generated loops a become associated loops of another
5611   /// directive, they may need to be hoisted before them.
5612   Stmt *getTransformedStmt() const {
5613     return Data->getChildren()[TransformedStmtOffset];
5614   }
5615 
5616   /// Return preinits statement.
5617   Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
5618 
5619   static bool classof(const Stmt *T) {
5620     return T->getStmtClass() == OMPTileDirectiveClass;
5621   }
5622 };
5623 
5624 /// This represents the '#pragma omp unroll' loop transformation directive.
5625 ///
5626 /// \code
5627 /// #pragma omp unroll
5628 /// for (int i = 0; i < 64; ++i)
5629 /// \endcode
5630 class OMPUnrollDirective final : public OMPLoopTransformationDirective {
5631   friend class ASTStmtReader;
5632   friend class OMPExecutableDirective;
5633 
5634   /// Default list of offsets.
5635   enum {
5636     PreInitsOffset = 0,
5637     TransformedStmtOffset,
5638   };
5639 
5640   explicit OMPUnrollDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5641       : OMPLoopTransformationDirective(OMPUnrollDirectiveClass,
5642                                        llvm::omp::OMPD_unroll, StartLoc, EndLoc,
5643                                        1) {}
5644 
5645   /// Set the pre-init statements.
5646   void setPreInits(Stmt *PreInits) {
5647     Data->getChildren()[PreInitsOffset] = PreInits;
5648   }
5649 
5650   /// Set the de-sugared statement.
5651   void setTransformedStmt(Stmt *S) {
5652     Data->getChildren()[TransformedStmtOffset] = S;
5653   }
5654 
5655 public:
5656   /// Create a new AST node representation for '#pragma omp unroll'.
5657   ///
5658   /// \param C         Context of the AST.
5659   /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
5660   /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
5661   /// \param Clauses   The directive's clauses.
5662   /// \param AssociatedStmt The outermost associated loop.
5663   /// \param TransformedStmt The loop nest after tiling, or nullptr in
5664   ///                        dependent contexts.
5665   /// \param PreInits   Helper preinits statements for the loop nest.
5666   static OMPUnrollDirective *
5667   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5668          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
5669          unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits);
5670 
5671   /// Build an empty '#pragma omp unroll' AST node for deserialization.
5672   ///
5673   /// \param C          Context of the AST.
5674   /// \param NumClauses Number of clauses to allocate.
5675   static OMPUnrollDirective *CreateEmpty(const ASTContext &C,
5676                                          unsigned NumClauses);
5677 
5678   /// Get the de-sugared associated loops after unrolling.
5679   ///
5680   /// This is only used if the unrolled loop becomes an associated loop of
5681   /// another directive, otherwise the loop is emitted directly using loop
5682   /// transformation metadata. When the unrolled loop cannot be used by another
5683   /// directive (e.g. because of the full clause), the transformed stmt can also
5684   /// be nullptr.
5685   Stmt *getTransformedStmt() const {
5686     return Data->getChildren()[TransformedStmtOffset];
5687   }
5688 
5689   /// Return the pre-init statements.
5690   Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
5691 
5692   static bool classof(const Stmt *T) {
5693     return T->getStmtClass() == OMPUnrollDirectiveClass;
5694   }
5695 };
5696 
5697 /// Represents the '#pragma omp reverse' loop transformation directive.
5698 ///
5699 /// \code
5700 /// #pragma omp reverse
5701 /// for (int i = 0; i < n; ++i)
5702 ///   ...
5703 /// \endcode
5704 class OMPReverseDirective final : public OMPLoopTransformationDirective {
5705   friend class ASTStmtReader;
5706   friend class OMPExecutableDirective;
5707 
5708   /// Offsets of child members.
5709   enum {
5710     PreInitsOffset = 0,
5711     TransformedStmtOffset,
5712   };
5713 
5714   explicit OMPReverseDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5715       : OMPLoopTransformationDirective(OMPReverseDirectiveClass,
5716                                        llvm::omp::OMPD_reverse, StartLoc,
5717                                        EndLoc, 1) {}
5718 
5719   void setPreInits(Stmt *PreInits) {
5720     Data->getChildren()[PreInitsOffset] = PreInits;
5721   }
5722 
5723   void setTransformedStmt(Stmt *S) {
5724     Data->getChildren()[TransformedStmtOffset] = S;
5725   }
5726 
5727 public:
5728   /// Create a new AST node representation for '#pragma omp reverse'.
5729   ///
5730   /// \param C         Context of the AST.
5731   /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
5732   /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
5733   /// \param AssociatedStmt  The outermost associated loop.
5734   /// \param TransformedStmt The loop nest after tiling, or nullptr in
5735   ///                        dependent contexts.
5736   /// \param PreInits   Helper preinits statements for the loop nest.
5737   static OMPReverseDirective *
5738   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5739          Stmt *AssociatedStmt, Stmt *TransformedStmt, Stmt *PreInits);
5740 
5741   /// Build an empty '#pragma omp reverse' AST node for deserialization.
5742   ///
5743   /// \param C          Context of the AST.
5744   /// \param NumClauses Number of clauses to allocate.
5745   static OMPReverseDirective *CreateEmpty(const ASTContext &C);
5746 
5747   /// Gets/sets the associated loops after the transformation, i.e. after
5748   /// de-sugaring.
5749   Stmt *getTransformedStmt() const {
5750     return Data->getChildren()[TransformedStmtOffset];
5751   }
5752 
5753   /// Return preinits statement.
5754   Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
5755 
5756   static bool classof(const Stmt *T) {
5757     return T->getStmtClass() == OMPReverseDirectiveClass;
5758   }
5759 };
5760 
5761 /// Represents the '#pragma omp interchange' loop transformation directive.
5762 ///
5763 /// \code{c}
5764 ///   #pragma omp interchange
5765 ///   for (int i = 0; i < m; ++i)
5766 ///     for (int j = 0; j < n; ++j)
5767 ///       ..
5768 /// \endcode
5769 class OMPInterchangeDirective final : public OMPLoopTransformationDirective {
5770   friend class ASTStmtReader;
5771   friend class OMPExecutableDirective;
5772 
5773   /// Offsets of child members.
5774   enum {
5775     PreInitsOffset = 0,
5776     TransformedStmtOffset,
5777   };
5778 
5779   explicit OMPInterchangeDirective(SourceLocation StartLoc,
5780                                    SourceLocation EndLoc, unsigned NumLoops)
5781       : OMPLoopTransformationDirective(OMPInterchangeDirectiveClass,
5782                                        llvm::omp::OMPD_interchange, StartLoc,
5783                                        EndLoc, NumLoops) {
5784     setNumGeneratedLoops(3 * NumLoops);
5785   }
5786 
5787   void setPreInits(Stmt *PreInits) {
5788     Data->getChildren()[PreInitsOffset] = PreInits;
5789   }
5790 
5791   void setTransformedStmt(Stmt *S) {
5792     Data->getChildren()[TransformedStmtOffset] = S;
5793   }
5794 
5795 public:
5796   /// Create a new AST node representation for '#pragma omp interchange'.
5797   ///
5798   /// \param C         Context of the AST.
5799   /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
5800   /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
5801   /// \param Clauses   The directive's clauses.
5802   /// \param NumLoops  Number of affected loops
5803   ///                  (number of items in the 'permutation' clause if present).
5804   /// \param AssociatedStmt  The outermost associated loop.
5805   /// \param TransformedStmt The loop nest after tiling, or nullptr in
5806   ///                        dependent contexts.
5807   /// \param PreInits  Helper preinits statements for the loop nest.
5808   static OMPInterchangeDirective *
5809   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5810          ArrayRef<OMPClause *> Clauses, unsigned NumLoops, Stmt *AssociatedStmt,
5811          Stmt *TransformedStmt, Stmt *PreInits);
5812 
5813   /// Build an empty '#pragma omp interchange' AST node for deserialization.
5814   ///
5815   /// \param C          Context of the AST.
5816   /// \param NumClauses Number of clauses to allocate.
5817   /// \param NumLoops   Number of associated loops to allocate.
5818   static OMPInterchangeDirective *
5819   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned NumLoops);
5820 
5821   /// Gets the associated loops after the transformation. This is the de-sugared
5822   /// replacement or nullptr in dependent contexts.
5823   Stmt *getTransformedStmt() const {
5824     return Data->getChildren()[TransformedStmtOffset];
5825   }
5826 
5827   /// Return preinits statement.
5828   Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
5829 
5830   static bool classof(const Stmt *T) {
5831     return T->getStmtClass() == OMPInterchangeDirectiveClass;
5832   }
5833 };
5834 
5835 /// This represents '#pragma omp scan' directive.
5836 ///
5837 /// \code
5838 /// #pragma omp scan inclusive(a)
5839 /// \endcode
5840 /// In this example directive '#pragma omp scan' has clause 'inclusive' with
5841 /// list item 'a'.
5842 class OMPScanDirective final : public OMPExecutableDirective {
5843   friend class ASTStmtReader;
5844   friend class OMPExecutableDirective;
5845   /// Build directive with the given start and end location.
5846   ///
5847   /// \param StartLoc Starting location of the directive kind.
5848   /// \param EndLoc Ending location of the directive.
5849   ///
5850   OMPScanDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5851       : OMPExecutableDirective(OMPScanDirectiveClass, llvm::omp::OMPD_scan,
5852                                StartLoc, EndLoc) {}
5853 
5854   /// Build an empty directive.
5855   ///
5856   explicit OMPScanDirective()
5857       : OMPExecutableDirective(OMPScanDirectiveClass, llvm::omp::OMPD_scan,
5858                                SourceLocation(), SourceLocation()) {}
5859 
5860 public:
5861   /// Creates directive with a list of \a Clauses.
5862   ///
5863   /// \param C AST context.
5864   /// \param StartLoc Starting location of the directive kind.
5865   /// \param EndLoc Ending Location of the directive.
5866   /// \param Clauses List of clauses (only single OMPFlushClause clause is
5867   /// allowed).
5868   ///
5869   static OMPScanDirective *Create(const ASTContext &C, SourceLocation StartLoc,
5870                                   SourceLocation EndLoc,
5871                                   ArrayRef<OMPClause *> Clauses);
5872 
5873   /// Creates an empty directive with the place for \a NumClauses
5874   /// clauses.
5875   ///
5876   /// \param C AST context.
5877   /// \param NumClauses Number of clauses.
5878   ///
5879   static OMPScanDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
5880                                        EmptyShell);
5881 
5882   static bool classof(const Stmt *T) {
5883     return T->getStmtClass() == OMPScanDirectiveClass;
5884   }
5885 };
5886 
5887 /// This represents '#pragma omp interop' directive.
5888 ///
5889 /// \code
5890 /// #pragma omp interop init(target:obj) device(x) depend(inout:y) nowait
5891 /// \endcode
5892 /// In this example directive '#pragma omp interop' has
5893 /// clauses 'init', 'device', 'depend' and 'nowait'.
5894 ///
5895 class OMPInteropDirective final : public OMPExecutableDirective {
5896   friend class ASTStmtReader;
5897   friend class OMPExecutableDirective;
5898 
5899   /// Build directive with the given start and end location.
5900   ///
5901   /// \param StartLoc Starting location of the directive.
5902   /// \param EndLoc Ending location of the directive.
5903   ///
5904   OMPInteropDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5905       : OMPExecutableDirective(OMPInteropDirectiveClass,
5906                                llvm::omp::OMPD_interop, StartLoc, EndLoc) {}
5907 
5908   /// Build an empty directive.
5909   ///
5910   explicit OMPInteropDirective()
5911       : OMPExecutableDirective(OMPInteropDirectiveClass,
5912                                llvm::omp::OMPD_interop, SourceLocation(),
5913                                SourceLocation()) {}
5914 
5915 public:
5916   /// Creates directive.
5917   ///
5918   /// \param C AST context.
5919   /// \param StartLoc Starting location of the directive.
5920   /// \param EndLoc Ending Location of the directive.
5921   /// \param Clauses The directive's clauses.
5922   ///
5923   static OMPInteropDirective *Create(const ASTContext &C,
5924                                      SourceLocation StartLoc,
5925                                      SourceLocation EndLoc,
5926                                      ArrayRef<OMPClause *> Clauses);
5927 
5928   /// Creates an empty directive.
5929   ///
5930   /// \param C AST context.
5931   ///
5932   static OMPInteropDirective *CreateEmpty(const ASTContext &C,
5933                                           unsigned NumClauses, EmptyShell);
5934 
5935   static bool classof(const Stmt *T) {
5936     return T->getStmtClass() == OMPInteropDirectiveClass;
5937   }
5938 };
5939 
5940 /// This represents '#pragma omp dispatch' directive.
5941 ///
5942 /// \code
5943 /// #pragma omp dispatch device(dnum)
5944 /// \endcode
5945 /// This example shows a directive '#pragma omp dispatch' with a
5946 /// device clause with variable 'dnum'.
5947 ///
5948 class OMPDispatchDirective final : public OMPExecutableDirective {
5949   friend class ASTStmtReader;
5950   friend class OMPExecutableDirective;
5951 
5952   /// The location of the target-call.
5953   SourceLocation TargetCallLoc;
5954 
5955   /// Set the location of the target-call.
5956   void setTargetCallLoc(SourceLocation Loc) { TargetCallLoc = Loc; }
5957 
5958   /// Build directive with the given start and end location.
5959   ///
5960   /// \param StartLoc Starting location of the directive kind.
5961   /// \param EndLoc Ending location of the directive.
5962   ///
5963   OMPDispatchDirective(SourceLocation StartLoc, SourceLocation EndLoc)
5964       : OMPExecutableDirective(OMPDispatchDirectiveClass,
5965                                llvm::omp::OMPD_dispatch, StartLoc, EndLoc) {}
5966 
5967   /// Build an empty directive.
5968   ///
5969   explicit OMPDispatchDirective()
5970       : OMPExecutableDirective(OMPDispatchDirectiveClass,
5971                                llvm::omp::OMPD_dispatch, SourceLocation(),
5972                                SourceLocation()) {}
5973 
5974 public:
5975   /// Creates directive with a list of \a Clauses.
5976   ///
5977   /// \param C AST context.
5978   /// \param StartLoc Starting location of the directive kind.
5979   /// \param EndLoc Ending Location of the directive.
5980   /// \param Clauses List of clauses.
5981   /// \param AssociatedStmt Statement, associated with the directive.
5982   /// \param TargetCallLoc Location of the target-call.
5983   ///
5984   static OMPDispatchDirective *
5985   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
5986          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
5987          SourceLocation TargetCallLoc);
5988 
5989   /// Creates an empty directive with the place for \a NumClauses
5990   /// clauses.
5991   ///
5992   /// \param C AST context.
5993   /// \param NumClauses Number of clauses.
5994   ///
5995   static OMPDispatchDirective *CreateEmpty(const ASTContext &C,
5996                                            unsigned NumClauses, EmptyShell);
5997 
5998   /// Return location of target-call.
5999   SourceLocation getTargetCallLoc() const { return TargetCallLoc; }
6000 
6001   static bool classof(const Stmt *T) {
6002     return T->getStmtClass() == OMPDispatchDirectiveClass;
6003   }
6004 };
6005 
6006 /// This represents '#pragma omp masked' directive.
6007 /// \code
6008 /// #pragma omp masked filter(tid)
6009 /// \endcode
6010 /// This example shows a directive '#pragma omp masked' with a filter clause
6011 /// with variable 'tid'.
6012 ///
6013 class OMPMaskedDirective final : public OMPExecutableDirective {
6014   friend class ASTStmtReader;
6015   friend class OMPExecutableDirective;
6016 
6017   /// Build directive with the given start and end location.
6018   ///
6019   /// \param StartLoc Starting location of the directive kind.
6020   /// \param EndLoc Ending location of the directive.
6021   ///
6022   OMPMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
6023       : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
6024                                StartLoc, EndLoc) {}
6025 
6026   /// Build an empty directive.
6027   ///
6028   explicit OMPMaskedDirective()
6029       : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
6030                                SourceLocation(), SourceLocation()) {}
6031 
6032 public:
6033   /// Creates directive.
6034   ///
6035   /// \param C AST context.
6036   /// \param StartLoc Starting location of the directive kind.
6037   /// \param EndLoc Ending Location of the directive.
6038   /// \param AssociatedStmt Statement, associated with the directive.
6039   ///
6040   static OMPMaskedDirective *
6041   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6042          ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
6043 
6044   /// Creates an empty directive.
6045   ///
6046   /// \param C AST context.
6047   ///
6048   static OMPMaskedDirective *CreateEmpty(const ASTContext &C,
6049                                          unsigned NumClauses, EmptyShell);
6050 
6051   static bool classof(const Stmt *T) {
6052     return T->getStmtClass() == OMPMaskedDirectiveClass;
6053   }
6054 };
6055 
6056 /// This represents '#pragma omp metadirective' directive.
6057 ///
6058 /// \code
6059 /// #pragma omp metadirective when(user={condition(N>10)}: parallel for)
6060 /// \endcode
6061 /// In this example directive '#pragma omp metadirective' has clauses 'when'
6062 /// with a dynamic user condition to check if a variable 'N > 10'
6063 ///
6064 class OMPMetaDirective final : public OMPExecutableDirective {
6065   friend class ASTStmtReader;
6066   friend class OMPExecutableDirective;
6067   Stmt *IfStmt;
6068 
6069   OMPMetaDirective(SourceLocation StartLoc, SourceLocation EndLoc)
6070       : OMPExecutableDirective(OMPMetaDirectiveClass,
6071                                llvm::omp::OMPD_metadirective, StartLoc,
6072                                EndLoc) {}
6073   explicit OMPMetaDirective()
6074       : OMPExecutableDirective(OMPMetaDirectiveClass,
6075                                llvm::omp::OMPD_metadirective, SourceLocation(),
6076                                SourceLocation()) {}
6077 
6078   void setIfStmt(Stmt *S) { IfStmt = S; }
6079 
6080 public:
6081   static OMPMetaDirective *Create(const ASTContext &C, SourceLocation StartLoc,
6082                                   SourceLocation EndLoc,
6083                                   ArrayRef<OMPClause *> Clauses,
6084                                   Stmt *AssociatedStmt, Stmt *IfStmt);
6085   static OMPMetaDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
6086                                        EmptyShell);
6087   Stmt *getIfStmt() const { return IfStmt; }
6088 
6089   static bool classof(const Stmt *T) {
6090     return T->getStmtClass() == OMPMetaDirectiveClass;
6091   }
6092 };
6093 
6094 /// This represents '#pragma omp loop' directive.
6095 ///
6096 /// \code
6097 /// #pragma omp loop private(a,b) binding(parallel) order(concurrent)
6098 /// \endcode
6099 /// In this example directive '#pragma omp loop' has
6100 /// clauses 'private' with the variables 'a' and 'b', 'binding' with
6101 /// modifier 'parallel' and 'order(concurrent).
6102 ///
6103 class OMPGenericLoopDirective final : public OMPLoopDirective {
6104   friend class ASTStmtReader;
6105   friend class OMPExecutableDirective;
6106   /// Build directive with the given start and end location.
6107   ///
6108   /// \param StartLoc Starting location of the directive kind.
6109   /// \param EndLoc Ending location of the directive.
6110   /// \param CollapsedNum Number of collapsed nested loops.
6111   ///
6112   OMPGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
6113                           unsigned CollapsedNum)
6114       : OMPLoopDirective(OMPGenericLoopDirectiveClass, llvm::omp::OMPD_loop,
6115                          StartLoc, EndLoc, CollapsedNum) {}
6116 
6117   /// Build an empty directive.
6118   ///
6119   /// \param CollapsedNum Number of collapsed nested loops.
6120   ///
6121   explicit OMPGenericLoopDirective(unsigned CollapsedNum)
6122       : OMPLoopDirective(OMPGenericLoopDirectiveClass, llvm::omp::OMPD_loop,
6123                          SourceLocation(), SourceLocation(), CollapsedNum) {}
6124 
6125 public:
6126   /// Creates directive with a list of \p Clauses.
6127   ///
6128   /// \param C AST context.
6129   /// \param StartLoc Starting location of the directive kind.
6130   /// \param EndLoc Ending Location of the directive.
6131   /// \param CollapsedNum Number of collapsed loops.
6132   /// \param Clauses List of clauses.
6133   /// \param AssociatedStmt Statement, associated with the directive.
6134   /// \param Exprs Helper expressions for CodeGen.
6135   ///
6136   static OMPGenericLoopDirective *
6137   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6138          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6139          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6140 
6141   /// Creates an empty directive with a place for \a NumClauses clauses.
6142   ///
6143   /// \param C AST context.
6144   /// \param NumClauses Number of clauses.
6145   /// \param CollapsedNum Number of collapsed nested loops.
6146   ///
6147   static OMPGenericLoopDirective *CreateEmpty(const ASTContext &C,
6148                                               unsigned NumClauses,
6149                                               unsigned CollapsedNum,
6150                                               EmptyShell);
6151 
6152   static bool classof(const Stmt *T) {
6153     return T->getStmtClass() == OMPGenericLoopDirectiveClass;
6154   }
6155 };
6156 
6157 /// This represents '#pragma omp teams loop' directive.
6158 ///
6159 /// \code
6160 /// #pragma omp teams loop private(a,b) order(concurrent)
6161 /// \endcode
6162 /// In this example directive '#pragma omp teams loop' has
6163 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6164 ///
6165 class OMPTeamsGenericLoopDirective final : public OMPLoopDirective {
6166   friend class ASTStmtReader;
6167   friend class OMPExecutableDirective;
6168   /// Build directive with the given start and end location.
6169   ///
6170   /// \param StartLoc Starting location of the directive kind.
6171   /// \param EndLoc Ending location of the directive.
6172   /// \param CollapsedNum Number of collapsed nested loops.
6173   ///
6174   OMPTeamsGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
6175                                unsigned CollapsedNum)
6176       : OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass,
6177                          llvm::omp::OMPD_teams_loop, StartLoc, EndLoc,
6178                          CollapsedNum) {}
6179 
6180   /// Build an empty directive.
6181   ///
6182   /// \param CollapsedNum Number of collapsed nested loops.
6183   ///
6184   explicit OMPTeamsGenericLoopDirective(unsigned CollapsedNum)
6185       : OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass,
6186                          llvm::omp::OMPD_teams_loop, SourceLocation(),
6187                          SourceLocation(), CollapsedNum) {}
6188 
6189 public:
6190   /// Creates directive with a list of \p Clauses.
6191   ///
6192   /// \param C AST context.
6193   /// \param StartLoc Starting location of the directive kind.
6194   /// \param EndLoc Ending Location of the directive.
6195   /// \param CollapsedNum Number of collapsed loops.
6196   /// \param Clauses List of clauses.
6197   /// \param AssociatedStmt Statement, associated with the directive.
6198   /// \param Exprs Helper expressions for CodeGen.
6199   ///
6200   static OMPTeamsGenericLoopDirective *
6201   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6202          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6203          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6204 
6205   /// Creates an empty directive with the place
6206   /// for \a NumClauses clauses.
6207   ///
6208   /// \param C AST context.
6209   /// \param CollapsedNum Number of collapsed nested loops.
6210   /// \param NumClauses Number of clauses.
6211   ///
6212   static OMPTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C,
6213                                                    unsigned NumClauses,
6214                                                    unsigned CollapsedNum,
6215                                                    EmptyShell);
6216 
6217   static bool classof(const Stmt *T) {
6218     return T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass;
6219   }
6220 };
6221 
6222 /// This represents '#pragma omp target teams loop' directive.
6223 ///
6224 /// \code
6225 /// #pragma omp target teams loop private(a,b) order(concurrent)
6226 /// \endcode
6227 /// In this example directive '#pragma omp target teams loop' has
6228 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6229 ///
6230 class OMPTargetTeamsGenericLoopDirective final : public OMPLoopDirective {
6231   friend class ASTStmtReader;
6232   friend class OMPExecutableDirective;
6233   /// true if loop directive's associated loop can be a parallel for.
6234   bool CanBeParallelFor = false;
6235   /// Build directive with the given start and end location.
6236   ///
6237   /// \param StartLoc Starting location of the directive kind.
6238   /// \param EndLoc Ending location of the directive.
6239   /// \param CollapsedNum Number of collapsed nested loops.
6240   ///
6241   OMPTargetTeamsGenericLoopDirective(SourceLocation StartLoc,
6242                                      SourceLocation EndLoc,
6243                                      unsigned CollapsedNum)
6244       : OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass,
6245                          llvm::omp::OMPD_target_teams_loop, StartLoc, EndLoc,
6246                          CollapsedNum) {}
6247 
6248   /// Build an empty directive.
6249   ///
6250   /// \param CollapsedNum Number of collapsed nested loops.
6251   ///
6252   explicit OMPTargetTeamsGenericLoopDirective(unsigned CollapsedNum)
6253       : OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass,
6254                          llvm::omp::OMPD_target_teams_loop, SourceLocation(),
6255                          SourceLocation(), CollapsedNum) {}
6256 
6257   /// Set whether associated loop can be a parallel for.
6258   void setCanBeParallelFor(bool ParFor) { CanBeParallelFor = ParFor; }
6259 
6260 public:
6261   /// Creates directive with a list of \p Clauses.
6262   ///
6263   /// \param C AST context.
6264   /// \param StartLoc Starting location of the directive kind.
6265   /// \param EndLoc Ending Location of the directive.
6266   /// \param CollapsedNum Number of collapsed loops.
6267   /// \param Clauses List of clauses.
6268   /// \param AssociatedStmt Statement, associated with the directive.
6269   /// \param Exprs Helper expressions for CodeGen.
6270   ///
6271   static OMPTargetTeamsGenericLoopDirective *
6272   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6273          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6274          Stmt *AssociatedStmt, const HelperExprs &Exprs, bool CanBeParallelFor);
6275 
6276   /// Creates an empty directive with the place
6277   /// for \a NumClauses clauses.
6278   ///
6279   /// \param C AST context.
6280   /// \param CollapsedNum Number of collapsed nested loops.
6281   /// \param NumClauses Number of clauses.
6282   ///
6283   static OMPTargetTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C,
6284                                                          unsigned NumClauses,
6285                                                          unsigned CollapsedNum,
6286                                                          EmptyShell);
6287 
6288   /// Return true if current loop directive's associated loop can be a
6289   /// parallel for.
6290   bool canBeParallelFor() const { return CanBeParallelFor; }
6291 
6292   static bool classof(const Stmt *T) {
6293     return T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass;
6294   }
6295 };
6296 
6297 /// This represents '#pragma omp parallel loop' directive.
6298 ///
6299 /// \code
6300 /// #pragma omp parallel loop private(a,b) order(concurrent)
6301 /// \endcode
6302 /// In this example directive '#pragma omp parallel loop' has
6303 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6304 ///
6305 class OMPParallelGenericLoopDirective final : public OMPLoopDirective {
6306   friend class ASTStmtReader;
6307   friend class OMPExecutableDirective;
6308   /// Build directive with the given start and end location.
6309   ///
6310   /// \param StartLoc Starting location of the directive kind.
6311   /// \param EndLoc Ending location of the directive.
6312   /// \param CollapsedNum Number of collapsed nested loops.
6313   ///
6314   OMPParallelGenericLoopDirective(SourceLocation StartLoc,
6315                                   SourceLocation EndLoc, unsigned CollapsedNum)
6316       : OMPLoopDirective(OMPParallelGenericLoopDirectiveClass,
6317                          llvm::omp::OMPD_parallel_loop, StartLoc, EndLoc,
6318                          CollapsedNum) {}
6319 
6320   /// Build an empty directive.
6321   ///
6322   /// \param CollapsedNum Number of collapsed nested loops.
6323   ///
6324   explicit OMPParallelGenericLoopDirective(unsigned CollapsedNum)
6325       : OMPLoopDirective(OMPParallelGenericLoopDirectiveClass,
6326                          llvm::omp::OMPD_parallel_loop, SourceLocation(),
6327                          SourceLocation(), CollapsedNum) {}
6328 
6329 public:
6330   /// Creates directive with a list of \p Clauses.
6331   ///
6332   /// \param C AST context.
6333   /// \param StartLoc Starting location of the directive kind.
6334   /// \param EndLoc Ending Location of the directive.
6335   /// \param CollapsedNum Number of collapsed loops.
6336   /// \param Clauses List of clauses.
6337   /// \param AssociatedStmt Statement, associated with the directive.
6338   /// \param Exprs Helper expressions for CodeGen.
6339   ///
6340   static OMPParallelGenericLoopDirective *
6341   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6342          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6343          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6344 
6345   /// Creates an empty directive with the place
6346   /// for \a NumClauses clauses.
6347   ///
6348   /// \param C AST context.
6349   /// \param CollapsedNum Number of collapsed nested loops.
6350   /// \param NumClauses Number of clauses.
6351   ///
6352   static OMPParallelGenericLoopDirective *CreateEmpty(const ASTContext &C,
6353                                                       unsigned NumClauses,
6354                                                       unsigned CollapsedNum,
6355                                                       EmptyShell);
6356 
6357   static bool classof(const Stmt *T) {
6358     return T->getStmtClass() == OMPParallelGenericLoopDirectiveClass;
6359   }
6360 };
6361 
6362 /// This represents '#pragma omp target parallel loop' directive.
6363 ///
6364 /// \code
6365 /// #pragma omp target parallel loop private(a,b) order(concurrent)
6366 /// \endcode
6367 /// In this example directive '#pragma omp target parallel loop' has
6368 /// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
6369 ///
6370 class OMPTargetParallelGenericLoopDirective final : public OMPLoopDirective {
6371   friend class ASTStmtReader;
6372   friend class OMPExecutableDirective;
6373   /// Build directive with the given start and end location.
6374   ///
6375   /// \param StartLoc Starting location of the directive kind.
6376   /// \param EndLoc Ending location of the directive.
6377   /// \param CollapsedNum Number of collapsed nested loops.
6378   ///
6379   OMPTargetParallelGenericLoopDirective(SourceLocation StartLoc,
6380                                         SourceLocation EndLoc,
6381                                         unsigned CollapsedNum)
6382       : OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass,
6383                          llvm::omp::OMPD_target_parallel_loop, StartLoc, EndLoc,
6384                          CollapsedNum) {}
6385 
6386   /// Build an empty directive.
6387   ///
6388   /// \param CollapsedNum Number of collapsed nested loops.
6389   ///
6390   explicit OMPTargetParallelGenericLoopDirective(unsigned CollapsedNum)
6391       : OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass,
6392                          llvm::omp::OMPD_target_parallel_loop, SourceLocation(),
6393                          SourceLocation(), CollapsedNum) {}
6394 
6395 public:
6396   /// Creates directive with a list of \p Clauses.
6397   ///
6398   /// \param C AST context.
6399   /// \param StartLoc Starting location of the directive kind.
6400   /// \param EndLoc Ending Location of the directive.
6401   /// \param CollapsedNum Number of collapsed loops.
6402   /// \param Clauses List of clauses.
6403   /// \param AssociatedStmt Statement, associated with the directive.
6404   /// \param Exprs Helper expressions for CodeGen.
6405   ///
6406   static OMPTargetParallelGenericLoopDirective *
6407   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
6408          unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
6409          Stmt *AssociatedStmt, const HelperExprs &Exprs);
6410 
6411   /// Creates an empty directive with the place
6412   /// for \a NumClauses clauses.
6413   ///
6414   /// \param C AST context.
6415   /// \param CollapsedNum Number of collapsed nested loops.
6416   /// \param NumClauses Number of clauses.
6417   ///
6418   static OMPTargetParallelGenericLoopDirective *
6419   CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
6420               EmptyShell);
6421 
6422   static bool classof(const Stmt *T) {
6423     return T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass;
6424   }
6425 };
6426 
6427 /// This represents '#pragma omp error' directive.
6428 ///
6429 /// \code
6430 /// #pragma omp error
6431 /// \endcode
6432 class OMPErrorDirective final : public OMPExecutableDirective {
6433   friend class ASTStmtReader;
6434   friend class OMPExecutableDirective;
6435   /// Build directive with the given start and end location.
6436   ///
6437   /// \param StartLoc Starting location of the directive kind.
6438   /// \param EndLoc Ending location of the directive.
6439   ///
6440   OMPErrorDirective(SourceLocation StartLoc, SourceLocation EndLoc)
6441       : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error,
6442                                StartLoc, EndLoc) {}
6443   /// Build an empty directive.
6444   ///
6445   explicit OMPErrorDirective()
6446       : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error,
6447                                SourceLocation(), SourceLocation()) {}
6448 
6449 public:
6450   ///
6451   /// \param C AST context.
6452   /// \param StartLoc Starting location of the directive kind.
6453   /// \param EndLoc Ending Location of the directive.
6454   /// \param Clauses List of clauses.
6455   ///
6456   static OMPErrorDirective *Create(const ASTContext &C, SourceLocation StartLoc,
6457                                    SourceLocation EndLoc,
6458                                    ArrayRef<OMPClause *> Clauses);
6459 
6460   /// Creates an empty directive.
6461   ///
6462   /// \param C AST context.
6463   ///
6464   static OMPErrorDirective *CreateEmpty(const ASTContext &C,
6465                                         unsigned NumClauses, EmptyShell);
6466 
6467   static bool classof(const Stmt *T) {
6468     return T->getStmtClass() == OMPErrorDirectiveClass;
6469   }
6470 };
6471 
6472 // It's not really an executable directive, but it seems convenient to use
6473 // that as the parent class.
6474 class OMPAssumeDirective final : public OMPExecutableDirective {
6475   friend class ASTStmtReader;
6476   friend class OMPExecutableDirective;
6477 
6478 private:
6479   OMPAssumeDirective(SourceLocation StartLoc, SourceLocation EndLoc)
6480       : OMPExecutableDirective(OMPAssumeDirectiveClass, llvm::omp::OMPD_assume,
6481                                StartLoc, EndLoc) {}
6482 
6483   explicit OMPAssumeDirective()
6484       : OMPExecutableDirective(OMPAssumeDirectiveClass, llvm::omp::OMPD_assume,
6485                                SourceLocation(), SourceLocation()) {}
6486 
6487 public:
6488   static OMPAssumeDirective *Create(const ASTContext &Ctx,
6489                                     SourceLocation StartLoc,
6490                                     SourceLocation EndLoc,
6491                                     ArrayRef<OMPClause *> Clauses, Stmt *AStmt);
6492 
6493   static OMPAssumeDirective *CreateEmpty(const ASTContext &C,
6494                                          unsigned NumClauses, EmptyShell);
6495 
6496   static bool classof(const Stmt *T) {
6497     return T->getStmtClass() == OMPAssumeDirectiveClass;
6498   }
6499 };
6500 
6501 } // end namespace clang
6502 
6503 #endif