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