//===- StmtOpenMP.h - Classes for OpenMP directives  ------------*- C++ -*-===//
 
//
 
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 
// See https://llvm.org/LICENSE.txt for license information.
 
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 
//
 
//===----------------------------------------------------------------------===//
 
/// \file
 
/// This file defines OpenMP AST classes for executable directives and
 
/// clauses.
 
///
 
//===----------------------------------------------------------------------===//
 
 
 
#ifndef LLVM_CLANG_AST_STMTOPENMP_H
 
#define LLVM_CLANG_AST_STMTOPENMP_H
 
 
 
#include "clang/AST/ASTContext.h"
 
#include "clang/AST/Expr.h"
 
#include "clang/AST/OpenMPClause.h"
 
#include "clang/AST/Stmt.h"
 
#include "clang/AST/StmtCXX.h"
 
#include "clang/Basic/OpenMPKinds.h"
 
#include "clang/Basic/SourceLocation.h"
 
 
 
namespace clang {
 
 
 
//===----------------------------------------------------------------------===//
 
// AST classes for directives.
 
//===----------------------------------------------------------------------===//
 
 
 
/// Representation of an OpenMP canonical loop.
 
///
 
/// OpenMP 1.0 C/C++, section 2.4.1 for Construct; canonical-shape
 
/// OpenMP 2.0 C/C++, section 2.4.1 for Construct; canonical-shape
 
/// OpenMP 2.5, section 2.5.1 Loop Construct; canonical form
 
/// OpenMP 3.1, section 2.5.1 Loop Construct; canonical form
 
/// OpenMP 4.0, section 2.6 Canonical Loop Form
 
/// OpenMP 4.5, section 2.6 Canonical Loop Form
 
/// OpenMP 5.0, section 2.9.1 Canonical Loop Form
 
/// OpenMP 5.1, section 2.11.1 Canonical Loop Nest Form
 
///
 
/// An OpenMP canonical loop is a for-statement or range-based for-statement
 
/// with additional requirements that ensure that the number of iterations is
 
/// known before entering the loop and allow skipping to an arbitrary iteration.
 
/// The OMPCanonicalLoop AST node wraps a ForStmt or CXXForRangeStmt that is
 
/// known to fulfill OpenMP's canonical loop requirements because of being
 
/// associated to an OMPLoopBasedDirective. That is, the general structure is:
 
///
 
///  OMPLoopBasedDirective
 
/// [`- CapturedStmt   ]
 
/// [   `- CapturedDecl]
 
///        ` OMPCanonicalLoop
 
///          `- ForStmt/CXXForRangeStmt
 
///             `- Stmt
 
///
 
/// One or multiple CapturedStmt/CapturedDecl pairs may be inserted by some
 
/// directives such as OMPParallelForDirective, but others do not need them
 
/// (such as OMPTileDirective). In  The OMPCanonicalLoop and
 
/// ForStmt/CXXForRangeStmt pair is repeated for loop associated with the
 
/// directive. A OMPCanonicalLoop must not appear in the AST unless associated
 
/// with a OMPLoopBasedDirective. In an imperfectly nested loop nest, the
 
/// OMPCanonicalLoop may also be wrapped in a CompoundStmt:
 
///
 
/// [...]
 
///  ` OMPCanonicalLoop
 
///    `- ForStmt/CXXForRangeStmt
 
///       `- CompoundStmt
 
///          |- Leading in-between code (if any)
 
///          |- OMPCanonicalLoop
 
///          |  `- ForStmt/CXXForRangeStmt
 
///          |     `- ...
 
///          `- Trailing in-between code (if any)
 
///
 
/// The leading/trailing in-between code must not itself be a OMPCanonicalLoop
 
/// to avoid confusion which loop belongs to the nesting.
 
///
 
/// There are three different kinds of iteration variables for different
 
/// purposes:
 
/// * Loop user variable: The user-accessible variable with different value for
 
///   each iteration.
 
/// * Loop iteration variable: The variable used to identify a loop iteration;
 
///   for range-based for-statement, this is the hidden iterator '__begin'. For
 
///   other loops, it is identical to the loop user variable. Must be a
 
///   random-access iterator, pointer or integer type.
 
/// * Logical iteration counter: Normalized loop counter starting at 0 and
 
///   incrementing by one at each iteration. Allows abstracting over the type
 
///   of the loop iteration variable and is always an unsigned integer type
 
///   appropriate to represent the range of the loop iteration variable. Its
 
///   value corresponds to the logical iteration number in the OpenMP
 
///   specification.
 
///
 
/// This AST node provides two captured statements:
 
/// * The distance function which computes the number of iterations.
 
/// * The loop user variable function that computes the loop user variable when
 
///   given a logical iteration number.
 
///
 
/// These captured statements provide the link between C/C++ semantics and the
 
/// logical iteration counters used by the OpenMPIRBuilder which is
 
/// language-agnostic and therefore does not know e.g. how to advance a
 
/// random-access iterator. The OpenMPIRBuilder will use this information to
 
/// apply simd, workshare-loop, distribute, taskloop and loop directives to the
 
/// loop. For compatibility with the non-OpenMPIRBuilder codegen path, an
 
/// OMPCanonicalLoop can itself also be wrapped into the CapturedStmts of an
 
/// OMPLoopDirective and skipped when searching for the associated syntactical
 
/// loop.
 
///
 
/// Example:
 
/// <code>
 
///   std::vector<std::string> Container{1,2,3};
 
///   for (std::string Str : Container)
 
///      Body(Str);
 
/// </code>
 
/// which is syntactic sugar for approximately:
 
/// <code>
 
///   auto &&__range = Container;
 
///   auto __begin = std::begin(__range);
 
///   auto __end = std::end(__range);
 
///   for (; __begin != __end; ++__begin) {
 
///     std::String Str = *__begin;
 
///     Body(Str);
 
///   }
 
/// </code>
 
/// In this example, the loop user variable is `Str`, the loop iteration
 
/// variable is `__begin` of type `std::vector<std::string>::iterator` and the
 
/// logical iteration number type is `size_t` (unsigned version of
 
/// `std::vector<std::string>::iterator::difference_type` aka `ptrdiff_t`).
 
/// Therefore, the distance function will be
 
/// <code>
 
///   [&](size_t &Result) { Result = __end - __begin; }
 
/// </code>
 
/// and the loop variable function is
 
/// <code>
 
///   [&,__begin](std::vector<std::string>::iterator &Result, size_t Logical) {
 
///     Result = __begin + Logical;
 
///   }
 
/// </code>
 
/// The variable `__begin`, aka the loop iteration variable, is captured by
 
/// value because it is modified in the loop body, but both functions require
 
/// the initial value. The OpenMP specification explicitly leaves unspecified
 
/// when the loop expressions are evaluated such that a capture by reference is
 
/// sufficient.
 
class OMPCanonicalLoop : public Stmt {
 
  friend class ASTStmtReader;
 
  friend class ASTStmtWriter;
 
 
 
  /// Children of this AST node.
 
  enum {
 
    LOOP_STMT,
 
    DISTANCE_FUNC,
 
    LOOPVAR_FUNC,
 
    LOOPVAR_REF,
 
    LastSubStmt = LOOPVAR_REF
 
  };
 
 
 
private:
 
  /// This AST node's children.
 
  Stmt *SubStmts[LastSubStmt + 1] = {};
 
 
 
  OMPCanonicalLoop() : Stmt(StmtClass::OMPCanonicalLoopClass) {}
 
 
 
public:
 
  /// Create a new OMPCanonicalLoop.
 
  static OMPCanonicalLoop *create(const ASTContext &Ctx, Stmt *LoopStmt,
 
                                  CapturedStmt *DistanceFunc,
 
                                  CapturedStmt *LoopVarFunc,
 
                                  DeclRefExpr *LoopVarRef) {
 
    OMPCanonicalLoop *S = new (Ctx) OMPCanonicalLoop();
 
    S->setLoopStmt(LoopStmt);
 
    S->setDistanceFunc(DistanceFunc);
 
    S->setLoopVarFunc(LoopVarFunc);
 
    S->setLoopVarRef(LoopVarRef);
 
    return S;
 
  }
 
 
 
  /// Create an empty OMPCanonicalLoop for deserialization.
 
  static OMPCanonicalLoop *createEmpty(const ASTContext &Ctx) {
 
    return new (Ctx) OMPCanonicalLoop();
 
  }
 
 
 
  static bool classof(const Stmt *S) {
 
    return S->getStmtClass() == StmtClass::OMPCanonicalLoopClass;
 
  }
 
 
 
  SourceLocation getBeginLoc() const { return getLoopStmt()->getBeginLoc(); }
 
  SourceLocation getEndLoc() const { return getLoopStmt()->getEndLoc(); }
 
 
 
  /// Return this AST node's children.
 
  /// @{
 
  child_range children() {
 
    return child_range(&SubStmts[0], &SubStmts[0] + LastSubStmt + 1);
 
  }
 
  const_child_range children() const {
 
    return const_child_range(&SubStmts[0], &SubStmts[0] + LastSubStmt + 1);
 
  }
 
  /// @}
 
 
 
  /// The wrapped syntactic loop statement (ForStmt or CXXForRangeStmt).
 
  /// @{
 
  Stmt *getLoopStmt() { return SubStmts[LOOP_STMT]; }
 
  const Stmt *getLoopStmt() const { return SubStmts[LOOP_STMT]; }
 
  void setLoopStmt(Stmt *S) {
 
    assert((isa<ForStmt>(S) || isa<CXXForRangeStmt>(S)) &&
 
           "Canonical loop must be a for loop (range-based or otherwise)");
 
    SubStmts[LOOP_STMT] = S;
 
  }
 
  /// @}
 
 
 
  /// The function that computes the number of loop iterations. Can be evaluated
 
  /// before entering the loop but after the syntactical loop's init
 
  /// statement(s).
 
  ///
 
  /// Function signature: void(LogicalTy &Result)
 
  /// Any values necessary to compute the distance are captures of the closure.
 
  /// @{
 
  CapturedStmt *getDistanceFunc() {
 
    return cast<CapturedStmt>(SubStmts[DISTANCE_FUNC]);
 
  }
 
  const CapturedStmt *getDistanceFunc() const {
 
    return cast<CapturedStmt>(SubStmts[DISTANCE_FUNC]);
 
  }
 
  void setDistanceFunc(CapturedStmt *S) {
 
    assert(S && "Expected non-null captured statement");
 
    SubStmts[DISTANCE_FUNC] = S;
 
  }
 
  /// @}
 
 
 
  /// The function that computes the loop user variable from a logical iteration
 
  /// counter. Can be evaluated as first statement in the loop.
 
  ///
 
  /// Function signature: void(LoopVarTy &Result, LogicalTy Number)
 
  /// Any other values required to compute the loop user variable (such as start
 
  /// value, step size) are captured by the closure. In particular, the initial
 
  /// value of loop iteration variable is captured by value to be unaffected by
 
  /// previous iterations.
 
  /// @{
 
  CapturedStmt *getLoopVarFunc() {
 
    return cast<CapturedStmt>(SubStmts[LOOPVAR_FUNC]);
 
  }
 
  const CapturedStmt *getLoopVarFunc() const {
 
    return cast<CapturedStmt>(SubStmts[LOOPVAR_FUNC]);
 
  }
 
  void setLoopVarFunc(CapturedStmt *S) {
 
    assert(S && "Expected non-null captured statement");
 
    SubStmts[LOOPVAR_FUNC] = S;
 
  }
 
  /// @}
 
 
 
  /// Reference to the loop user variable as accessed in the loop body.
 
  /// @{
 
  DeclRefExpr *getLoopVarRef() {
 
    return cast<DeclRefExpr>(SubStmts[LOOPVAR_REF]);
 
  }
 
  const DeclRefExpr *getLoopVarRef() const {
 
    return cast<DeclRefExpr>(SubStmts[LOOPVAR_REF]);
 
  }
 
  void setLoopVarRef(DeclRefExpr *E) {
 
    assert(E && "Expected non-null loop variable");
 
    SubStmts[LOOPVAR_REF] = E;
 
  }
 
  /// @}
 
};
 
 
 
/// This is a basic class for representing single OpenMP executable
 
/// directive.
 
///
 
class OMPExecutableDirective : public Stmt {
 
  friend class ASTStmtReader;
 
  friend class ASTStmtWriter;
 
 
 
  /// Kind of the directive.
 
  OpenMPDirectiveKind Kind = llvm::omp::OMPD_unknown;
 
  /// Starting location of the directive (directive keyword).
 
  SourceLocation StartLoc;
 
  /// Ending location of the directive.
 
  SourceLocation EndLoc;
 
 
 
  /// Get the clauses storage.
 
  MutableArrayRef<OMPClause *> getClauses() {
 
    if (!Data)
 
      return std::nullopt;
 
    return Data->getClauses();
 
  }
 
 
 
protected:
 
  /// Data, associated with the directive.
 
  OMPChildren *Data = nullptr;
 
 
 
  /// Build instance of directive of class \a K.
 
  ///
 
  /// \param SC Statement class.
 
  /// \param K Kind of OpenMP directive.
 
  /// \param StartLoc Starting location of the directive (directive keyword).
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPExecutableDirective(StmtClass SC, OpenMPDirectiveKind K,
 
                         SourceLocation StartLoc, SourceLocation EndLoc)
 
      : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)),
 
        EndLoc(std::move(EndLoc)) {}
 
 
 
  template <typename T, typename... Params>
 
  static T *createDirective(const ASTContext &C, ArrayRef<OMPClause *> Clauses,
 
                            Stmt *AssociatedStmt, unsigned NumChildren,
 
                            Params &&... P) {
 
    void *Mem =
 
        C.Allocate(sizeof(T) + OMPChildren::size(Clauses.size(), AssociatedStmt,
 
                                                 NumChildren),
 
                   alignof(T));
 
 
 
    auto *Data = OMPChildren::Create(reinterpret_cast<T *>(Mem) + 1, Clauses,
 
                                     AssociatedStmt, NumChildren);
 
    auto *Inst = new (Mem) T(std::forward<Params>(P)...);
 
    Inst->Data = Data;
 
    return Inst;
 
  }
 
 
 
  template <typename T, typename... Params>
 
  static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
 
                                 bool HasAssociatedStmt, unsigned NumChildren,
 
                                 Params &&... P) {
 
    void *Mem =
 
        C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
 
                                                 NumChildren),
 
                   alignof(T));
 
    auto *Data =
 
        OMPChildren::CreateEmpty(reinterpret_cast<T *>(Mem) + 1, NumClauses,
 
                                 HasAssociatedStmt, NumChildren);
 
    auto *Inst = new (Mem) T(std::forward<Params>(P)...);
 
    Inst->Data = Data;
 
    return Inst;
 
  }
 
 
 
  template <typename T>
 
  static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
 
                                 bool HasAssociatedStmt = false,
 
                                 unsigned NumChildren = 0) {
 
    void *Mem =
 
        C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
 
                                                 NumChildren),
 
                   alignof(T));
 
    auto *Data =
 
        OMPChildren::CreateEmpty(reinterpret_cast<T *>(Mem) + 1, NumClauses,
 
                                 HasAssociatedStmt, NumChildren);
 
    auto *Inst = new (Mem) T;
 
    Inst->Data = Data;
 
    return Inst;
 
  }
 
 
 
public:
 
  /// Iterates over expressions/statements used in the construct.
 
  class used_clauses_child_iterator
 
      : public llvm::iterator_adaptor_base<
 
            used_clauses_child_iterator, ArrayRef<OMPClause *>::iterator,
 
            std::forward_iterator_tag, Stmt *, ptrdiff_t, Stmt *, Stmt *> {
 
    ArrayRef<OMPClause *>::iterator End;
 
    OMPClause::child_iterator ChildI, ChildEnd;
 
 
 
    void MoveToNext() {
 
      if (ChildI != ChildEnd)
 
        return;
 
      while (this->I != End) {
 
        ++this->I;
 
        if (this->I != End) {
 
          ChildI = (*this->I)->used_children().begin();
 
          ChildEnd = (*this->I)->used_children().end();
 
          if (ChildI != ChildEnd)
 
            return;
 
        }
 
      }
 
    }
 
 
 
  public:
 
    explicit used_clauses_child_iterator(ArrayRef<OMPClause *> Clauses)
 
        : used_clauses_child_iterator::iterator_adaptor_base(Clauses.begin()),
 
          End(Clauses.end()) {
 
      if (this->I != End) {
 
        ChildI = (*this->I)->used_children().begin();
 
        ChildEnd = (*this->I)->used_children().end();
 
        MoveToNext();
 
      }
 
    }
 
    Stmt *operator*() const { return *ChildI; }
 
    Stmt *operator->() const { return **this; }
 
 
 
    used_clauses_child_iterator &operator++() {
 
      ++ChildI;
 
      if (ChildI != ChildEnd)
 
        return *this;
 
      if (this->I != End) {
 
        ++this->I;
 
        if (this->I != End) {
 
          ChildI = (*this->I)->used_children().begin();
 
          ChildEnd = (*this->I)->used_children().end();
 
        }
 
      }
 
      MoveToNext();
 
      return *this;
 
    }
 
  };
 
 
 
  static llvm::iterator_range<used_clauses_child_iterator>
 
  used_clauses_children(ArrayRef<OMPClause *> Clauses) {
 
    return {
 
        used_clauses_child_iterator(Clauses),
 
        used_clauses_child_iterator(llvm::ArrayRef(Clauses.end(), (size_t)0))};
 
  }
 
 
 
  /// Iterates over a filtered subrange of clauses applied to a
 
  /// directive.
 
  ///
 
  /// This iterator visits only clauses of type SpecificClause.
 
  template <typename SpecificClause>
 
  class specific_clause_iterator
 
      : public llvm::iterator_adaptor_base<
 
            specific_clause_iterator<SpecificClause>,
 
            ArrayRef<OMPClause *>::const_iterator, std::forward_iterator_tag,
 
            const SpecificClause *, ptrdiff_t, const SpecificClause *,
 
            const SpecificClause *> {
 
    ArrayRef<OMPClause *>::const_iterator End;
 
 
 
    void SkipToNextClause() {
 
      while (this->I != End && !isa<SpecificClause>(*this->I))
 
        ++this->I;
 
    }
 
 
 
  public:
 
    explicit specific_clause_iterator(ArrayRef<OMPClause *> Clauses)
 
        : specific_clause_iterator::iterator_adaptor_base(Clauses.begin()),
 
          End(Clauses.end()) {
 
      SkipToNextClause();
 
    }
 
 
 
    const SpecificClause *operator*() const {
 
      return cast<SpecificClause>(*this->I);
 
    }
 
    const SpecificClause *operator->() const { return **this; }
 
 
 
    specific_clause_iterator &operator++() {
 
      ++this->I;
 
      SkipToNextClause();
 
      return *this;
 
    }
 
  };
 
 
 
  template <typename SpecificClause>
 
  static llvm::iterator_range<specific_clause_iterator<SpecificClause>>
 
  getClausesOfKind(ArrayRef<OMPClause *> Clauses) {
 
    return {specific_clause_iterator<SpecificClause>(Clauses),
 
            specific_clause_iterator<SpecificClause>(
 
                llvm::ArrayRef(Clauses.end(), (size_t)0))};
 
  }
 
 
 
  template <typename SpecificClause>
 
  llvm::iterator_range<specific_clause_iterator<SpecificClause>>
 
  getClausesOfKind() const {
 
    return getClausesOfKind<SpecificClause>(clauses());
 
  }
 
 
 
  /// Gets a single clause of the specified kind associated with the
 
  /// current directive iff there is only one clause of this kind (and assertion
 
  /// is fired if there is more than one clause is associated with the
 
  /// directive). Returns nullptr if no clause of this kind is associated with
 
  /// the directive.
 
  template <typename SpecificClause>
 
  static const SpecificClause *getSingleClause(ArrayRef<OMPClause *> Clauses) {
 
    auto ClausesOfKind = getClausesOfKind<SpecificClause>(Clauses);
 
 
 
    if (ClausesOfKind.begin() != ClausesOfKind.end()) {
 
      assert(std::next(ClausesOfKind.begin()) == ClausesOfKind.end() &&
 
             "There are at least 2 clauses of the specified kind");
 
      return *ClausesOfKind.begin();
 
    }
 
    return nullptr;
 
  }
 
 
 
  template <typename SpecificClause>
 
  const SpecificClause *getSingleClause() const {
 
    return getSingleClause<SpecificClause>(clauses());
 
  }
 
 
 
  /// Returns true if the current directive has one or more clauses of a
 
  /// specific kind.
 
  template <typename SpecificClause>
 
  bool hasClausesOfKind() const {
 
    auto Clauses = getClausesOfKind<SpecificClause>();
 
    return Clauses.begin() != Clauses.end();
 
  }
 
 
 
  /// Returns starting location of directive kind.
 
  SourceLocation getBeginLoc() const { return StartLoc; }
 
  /// Returns ending location of directive.
 
  SourceLocation getEndLoc() const { return EndLoc; }
 
 
 
  /// Set starting location of directive kind.
 
  ///
 
  /// \param Loc New starting location of directive.
 
  ///
 
  void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
 
  /// Set ending location of directive.
 
  ///
 
  /// \param Loc New ending location of directive.
 
  ///
 
  void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
 
 
 
  /// Get number of clauses.
 
  unsigned getNumClauses() const {
 
    if (!Data)
 
      return 0;
 
    return Data->getNumClauses();
 
  }
 
 
 
  /// Returns specified clause.
 
  ///
 
  /// \param I Number of clause.
 
  ///
 
  OMPClause *getClause(unsigned I) const { return clauses()[I]; }
 
 
 
  /// Returns true if directive has associated statement.
 
  bool hasAssociatedStmt() const { return Data && Data->hasAssociatedStmt(); }
 
 
 
  /// Returns statement associated with the directive.
 
  const Stmt *getAssociatedStmt() const {
 
    return const_cast<OMPExecutableDirective *>(this)->getAssociatedStmt();
 
  }
 
  Stmt *getAssociatedStmt() {
 
    assert(hasAssociatedStmt() &&
 
           "Expected directive with the associated statement.");
 
    return Data->getAssociatedStmt();
 
  }
 
 
 
  /// Returns the captured statement associated with the
 
  /// component region within the (combined) directive.
 
  ///
 
  /// \param RegionKind Component region kind.
 
  const CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
 
    assert(hasAssociatedStmt() &&
 
           "Expected directive with the associated statement.");
 
    SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
 
    getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
 
    return Data->getCapturedStmt(RegionKind, CaptureRegions);
 
  }
 
 
 
  /// Get innermost captured statement for the construct.
 
  CapturedStmt *getInnermostCapturedStmt() {
 
    assert(hasAssociatedStmt() &&
 
           "Expected directive with the associated statement.");
 
    SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
 
    getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
 
    return Data->getInnermostCapturedStmt(CaptureRegions);
 
  }
 
 
 
  const CapturedStmt *getInnermostCapturedStmt() const {
 
    return const_cast<OMPExecutableDirective *>(this)
 
        ->getInnermostCapturedStmt();
 
  }
 
 
 
  OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
 
 
 
  static bool classof(const Stmt *S) {
 
    return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
 
           S->getStmtClass() <= lastOMPExecutableDirectiveConstant;
 
  }
 
 
 
  child_range children() {
 
    if (!Data)
 
      return child_range(child_iterator(), child_iterator());
 
    return Data->getAssociatedStmtAsRange();
 
  }
 
 
 
  const_child_range children() const {
 
    return const_cast<OMPExecutableDirective *>(this)->children();
 
  }
 
 
 
  ArrayRef<OMPClause *> clauses() const {
 
    if (!Data)
 
      return std::nullopt;
 
    return Data->getClauses();
 
  }
 
 
 
  /// Returns whether or not this is a Standalone directive.
 
  ///
 
  /// Stand-alone directives are executable directives
 
  /// that have no associated user code.
 
  bool isStandaloneDirective() const;
 
 
 
  /// Returns the AST node representing OpenMP structured-block of this
 
  /// OpenMP executable directive,
 
  /// Prerequisite: Executable Directive must not be Standalone directive.
 
  const Stmt *getStructuredBlock() const {
 
    return const_cast<OMPExecutableDirective *>(this)->getStructuredBlock();
 
  }
 
  Stmt *getStructuredBlock();
 
 
 
  const Stmt *getRawStmt() const {
 
    return const_cast<OMPExecutableDirective *>(this)->getRawStmt();
 
  }
 
  Stmt *getRawStmt() {
 
    assert(hasAssociatedStmt() &&
 
           "Expected directive with the associated statement.");
 
    return Data->getRawStmt();
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel' directive.
 
///
 
/// \code
 
/// #pragma omp parallel private(a,b) reduction(+: c,d)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel' has clauses 'private'
 
/// with the variables 'a' and 'b' and 'reduction' with operator '+' and
 
/// variables 'c' and 'd'.
 
///
 
class OMPParallelDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if the construct has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive (directive keyword).
 
  /// \param EndLoc Ending Location of the directive.
 
  ///
 
  OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPParallelDirectiveClass,
 
                               llvm::omp::OMPD_parallel, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPParallelDirective()
 
      : OMPExecutableDirective(OMPParallelDirectiveClass,
 
                               llvm::omp::OMPD_parallel, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement associated with the directive.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  /// \param HasCancel true if this directive has inner cancel directive.
 
  ///
 
  static OMPParallelDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
 
         bool HasCancel);
 
 
 
  /// Creates an empty directive with the place for \a N clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelDirective *CreateEmpty(const ASTContext &C,
 
                                           unsigned NumClauses, EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[0]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPParallelDirective *>(this)->getTaskReductionRefExpr();
 
  }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelDirectiveClass;
 
  }
 
};
 
 
 
/// The base class for all loop-based directives, including loop transformation
 
/// directives.
 
class OMPLoopBasedDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
 
 
protected:
 
  /// Number of collapsed loops as specified by 'collapse' clause.
 
  unsigned NumAssociatedLoops = 0;
 
 
 
  /// Build instance of loop directive of class \a Kind.
 
  ///
 
  /// \param SC Statement class.
 
  /// \param Kind Kind of OpenMP directive.
 
  /// \param StartLoc Starting location of the directive (directive keyword).
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param NumAssociatedLoops Number of loops associated with the construct.
 
  ///
 
  OMPLoopBasedDirective(StmtClass SC, OpenMPDirectiveKind Kind,
 
                        SourceLocation StartLoc, SourceLocation EndLoc,
 
                        unsigned NumAssociatedLoops)
 
      : OMPExecutableDirective(SC, Kind, StartLoc, EndLoc),
 
        NumAssociatedLoops(NumAssociatedLoops) {}
 
 
 
public:
 
  /// The expressions built to support OpenMP loops in combined/composite
 
  /// pragmas (e.g. pragma omp distribute parallel for)
 
  struct DistCombinedHelperExprs {
 
    /// DistributeLowerBound - used when composing 'omp distribute' with
 
    /// 'omp for' in a same construct.
 
    Expr *LB;
 
    /// DistributeUpperBound - used when composing 'omp distribute' with
 
    /// 'omp for' in a same construct.
 
    Expr *UB;
 
    /// DistributeEnsureUpperBound - used when composing 'omp distribute'
 
    ///  with 'omp for' in a same construct, EUB depends on DistUB
 
    Expr *EUB;
 
    /// Distribute loop iteration variable init used when composing 'omp
 
    /// distribute'
 
    ///  with 'omp for' in a same construct
 
    Expr *Init;
 
    /// Distribute Loop condition used when composing 'omp distribute'
 
    ///  with 'omp for' in a same construct
 
    Expr *Cond;
 
    /// Update of LowerBound for statically scheduled omp loops for
 
    /// outer loop in combined constructs (e.g. 'distribute parallel for')
 
    Expr *NLB;
 
    /// Update of UpperBound for statically scheduled omp loops for
 
    /// outer loop in combined constructs (e.g. 'distribute parallel for')
 
    Expr *NUB;
 
    /// Distribute Loop condition used when composing 'omp distribute'
 
    ///  with 'omp for' in a same construct when schedule is chunked.
 
    Expr *DistCond;
 
    /// 'omp parallel for' loop condition used when composed with
 
    /// 'omp distribute' in the same construct and when schedule is
 
    /// chunked and the chunk size is 1.
 
    Expr *ParForInDistCond;
 
  };
 
 
 
  /// The expressions built for the OpenMP loop CodeGen for the
 
  /// whole collapsed loop nest.
 
  struct HelperExprs {
 
    /// Loop iteration variable.
 
    Expr *IterationVarRef;
 
    /// Loop last iteration number.
 
    Expr *LastIteration;
 
    /// Loop number of iterations.
 
    Expr *NumIterations;
 
    /// Calculation of last iteration.
 
    Expr *CalcLastIteration;
 
    /// Loop pre-condition.
 
    Expr *PreCond;
 
    /// Loop condition.
 
    Expr *Cond;
 
    /// Loop iteration variable init.
 
    Expr *Init;
 
    /// Loop increment.
 
    Expr *Inc;
 
    /// IsLastIteration - local flag variable passed to runtime.
 
    Expr *IL;
 
    /// LowerBound - local variable passed to runtime.
 
    Expr *LB;
 
    /// UpperBound - local variable passed to runtime.
 
    Expr *UB;
 
    /// Stride - local variable passed to runtime.
 
    Expr *ST;
 
    /// EnsureUpperBound -- expression UB = min(UB, NumIterations).
 
    Expr *EUB;
 
    /// Update of LowerBound for statically scheduled 'omp for' loops.
 
    Expr *NLB;
 
    /// Update of UpperBound for statically scheduled 'omp for' loops.
 
    Expr *NUB;
 
    /// PreviousLowerBound - local variable passed to runtime in the
 
    /// enclosing schedule or null if that does not apply.
 
    Expr *PrevLB;
 
    /// PreviousUpperBound - local variable passed to runtime in the
 
    /// enclosing schedule or null if that does not apply.
 
    Expr *PrevUB;
 
    /// DistInc - increment expression for distribute loop when found
 
    /// combined with a further loop level (e.g. in 'distribute parallel for')
 
    /// expression IV = IV + ST
 
    Expr *DistInc;
 
    /// PrevEUB - expression similar to EUB but to be used when loop
 
    /// scheduling uses PrevLB and PrevUB (e.g.  in 'distribute parallel for'
 
    /// when ensuring that the UB is either the calculated UB by the runtime or
 
    /// the end of the assigned distribute chunk)
 
    /// expression UB = min (UB, PrevUB)
 
    Expr *PrevEUB;
 
    /// Counters Loop counters.
 
    SmallVector<Expr *, 4> Counters;
 
    /// PrivateCounters Loop counters.
 
    SmallVector<Expr *, 4> PrivateCounters;
 
    /// Expressions for loop counters inits for CodeGen.
 
    SmallVector<Expr *, 4> Inits;
 
    /// Expressions for loop counters update for CodeGen.
 
    SmallVector<Expr *, 4> Updates;
 
    /// Final loop counter values for GodeGen.
 
    SmallVector<Expr *, 4> Finals;
 
    /// List of counters required for the generation of the non-rectangular
 
    /// loops.
 
    SmallVector<Expr *, 4> DependentCounters;
 
    /// List of initializers required for the generation of the non-rectangular
 
    /// loops.
 
    SmallVector<Expr *, 4> DependentInits;
 
    /// List of final conditions required for the generation of the
 
    /// non-rectangular loops.
 
    SmallVector<Expr *, 4> FinalsConditions;
 
    /// Init statement for all captured expressions.
 
    Stmt *PreInits;
 
 
 
    /// Expressions used when combining OpenMP loop pragmas
 
    DistCombinedHelperExprs DistCombinedFields;
 
 
 
    /// Check if all the expressions are built (does not check the
 
    /// worksharing ones).
 
    bool builtAll() {
 
      return IterationVarRef != nullptr && LastIteration != nullptr &&
 
             NumIterations != nullptr && PreCond != nullptr &&
 
             Cond != nullptr && Init != nullptr && Inc != nullptr;
 
    }
 
 
 
    /// Initialize all the fields to null.
 
    /// \param Size Number of elements in the
 
    /// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions
 
    /// arrays.
 
    void clear(unsigned Size) {
 
      IterationVarRef = nullptr;
 
      LastIteration = nullptr;
 
      CalcLastIteration = nullptr;
 
      PreCond = nullptr;
 
      Cond = nullptr;
 
      Init = nullptr;
 
      Inc = nullptr;
 
      IL = nullptr;
 
      LB = nullptr;
 
      UB = nullptr;
 
      ST = nullptr;
 
      EUB = nullptr;
 
      NLB = nullptr;
 
      NUB = nullptr;
 
      NumIterations = nullptr;
 
      PrevLB = nullptr;
 
      PrevUB = nullptr;
 
      DistInc = nullptr;
 
      PrevEUB = nullptr;
 
      Counters.resize(Size);
 
      PrivateCounters.resize(Size);
 
      Inits.resize(Size);
 
      Updates.resize(Size);
 
      Finals.resize(Size);
 
      DependentCounters.resize(Size);
 
      DependentInits.resize(Size);
 
      FinalsConditions.resize(Size);
 
      for (unsigned I = 0; I < Size; ++I) {
 
        Counters[I] = nullptr;
 
        PrivateCounters[I] = nullptr;
 
        Inits[I] = nullptr;
 
        Updates[I] = nullptr;
 
        Finals[I] = nullptr;
 
        DependentCounters[I] = nullptr;
 
        DependentInits[I] = nullptr;
 
        FinalsConditions[I] = nullptr;
 
      }
 
      PreInits = nullptr;
 
      DistCombinedFields.LB = nullptr;
 
      DistCombinedFields.UB = nullptr;
 
      DistCombinedFields.EUB = nullptr;
 
      DistCombinedFields.Init = nullptr;
 
      DistCombinedFields.Cond = nullptr;
 
      DistCombinedFields.NLB = nullptr;
 
      DistCombinedFields.NUB = nullptr;
 
      DistCombinedFields.DistCond = nullptr;
 
      DistCombinedFields.ParForInDistCond = nullptr;
 
    }
 
  };
 
 
 
  /// Get number of collapsed loops.
 
  unsigned getLoopsNumber() const { return NumAssociatedLoops; }
 
 
 
  /// Try to find the next loop sub-statement in the specified statement \p
 
  /// CurStmt.
 
  /// \param TryImperfectlyNestedLoops true, if we need to try to look for the
 
  /// imperfectly nested loop.
 
  static Stmt *tryToFindNextInnerLoop(Stmt *CurStmt,
 
                                      bool TryImperfectlyNestedLoops);
 
  static const Stmt *tryToFindNextInnerLoop(const Stmt *CurStmt,
 
                                            bool TryImperfectlyNestedLoops) {
 
    return tryToFindNextInnerLoop(const_cast<Stmt *>(CurStmt),
 
                                  TryImperfectlyNestedLoops);
 
  }
 
 
 
  /// Calls the specified callback function for all the loops in \p CurStmt,
 
  /// from the outermost to the innermost.
 
  static bool
 
  doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops,
 
                unsigned NumLoops,
 
                llvm::function_ref<bool(unsigned, Stmt *)> Callback,
 
                llvm::function_ref<void(OMPLoopTransformationDirective *)>
 
                    OnTransformationCallback);
 
  static bool
 
  doForAllLoops(const Stmt *CurStmt, bool TryImperfectlyNestedLoops,
 
                unsigned NumLoops,
 
                llvm::function_ref<bool(unsigned, const Stmt *)> Callback,
 
                llvm::function_ref<void(const OMPLoopTransformationDirective *)>
 
                    OnTransformationCallback) {
 
    auto &&NewCallback = [Callback](unsigned Cnt, Stmt *CurStmt) {
 
      return Callback(Cnt, CurStmt);
 
    };
 
    auto &&NewTransformCb =
 
        [OnTransformationCallback](OMPLoopTransformationDirective *A) {
 
          OnTransformationCallback(A);
 
        };
 
    return doForAllLoops(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
 
                         NumLoops, NewCallback, NewTransformCb);
 
  }
 
 
 
  /// Calls the specified callback function for all the loops in \p CurStmt,
 
  /// from the outermost to the innermost.
 
  static bool
 
  doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops,
 
                unsigned NumLoops,
 
                llvm::function_ref<bool(unsigned, Stmt *)> Callback) {
 
    auto &&TransformCb = [](OMPLoopTransformationDirective *) {};
 
    return doForAllLoops(CurStmt, TryImperfectlyNestedLoops, NumLoops, Callback,
 
                         TransformCb);
 
  }
 
  static bool
 
  doForAllLoops(const Stmt *CurStmt, bool TryImperfectlyNestedLoops,
 
                unsigned NumLoops,
 
                llvm::function_ref<bool(unsigned, const Stmt *)> Callback) {
 
    auto &&NewCallback = [Callback](unsigned Cnt, const Stmt *CurStmt) {
 
      return Callback(Cnt, CurStmt);
 
    };
 
    return doForAllLoops(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
 
                         NumLoops, NewCallback);
 
  }
 
 
 
  /// Calls the specified callback function for all the loop bodies in \p
 
  /// CurStmt, from the outermost loop to the innermost.
 
  static void doForAllLoopsBodies(
 
      Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
 
      llvm::function_ref<void(unsigned, Stmt *, Stmt *)> Callback);
 
  static void doForAllLoopsBodies(
 
      const Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
 
      llvm::function_ref<void(unsigned, const Stmt *, const Stmt *)> Callback) {
 
    auto &&NewCallback = [Callback](unsigned Cnt, Stmt *Loop, Stmt *Body) {
 
      Callback(Cnt, Loop, Body);
 
    };
 
    doForAllLoopsBodies(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
 
                        NumLoops, NewCallback);
 
  }
 
 
 
  static bool classof(const Stmt *T) {
 
    if (auto *D = dyn_cast<OMPExecutableDirective>(T))
 
      return isOpenMPLoopDirective(D->getDirectiveKind());
 
    return false;
 
  }
 
};
 
 
 
/// The base class for all loop transformation directives.
 
class OMPLoopTransformationDirective : public OMPLoopBasedDirective {
 
  friend class ASTStmtReader;
 
 
 
  /// Number of loops generated by this loop transformation.
 
  unsigned NumGeneratedLoops = 0;
 
 
 
protected:
 
  explicit OMPLoopTransformationDirective(StmtClass SC,
 
                                          OpenMPDirectiveKind Kind,
 
                                          SourceLocation StartLoc,
 
                                          SourceLocation EndLoc,
 
                                          unsigned NumAssociatedLoops)
 
      : OMPLoopBasedDirective(SC, Kind, StartLoc, EndLoc, NumAssociatedLoops) {}
 
 
 
  /// Set the number of loops generated by this loop transformation.
 
  void setNumGeneratedLoops(unsigned Num) { NumGeneratedLoops = Num; }
 
 
 
public:
 
  /// Return the number of associated (consumed) loops.
 
  unsigned getNumAssociatedLoops() const { return getLoopsNumber(); }
 
 
 
  /// Return the number of loops generated by this loop transformation.
 
  unsigned getNumGeneratedLoops() { return NumGeneratedLoops; }
 
 
 
  /// Get the de-sugared statements after the loop transformation.
 
  ///
 
  /// Might be nullptr if either the directive generates no loops and is handled
 
  /// directly in CodeGen, or resolving a template-dependence context is
 
  /// required.
 
  Stmt *getTransformedStmt() const;
 
 
 
  /// Return preinits statement.
 
  Stmt *getPreInits() const;
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTileDirectiveClass ||
 
           T->getStmtClass() == OMPUnrollDirectiveClass;
 
  }
 
};
 
 
 
/// This is a common base class for loop directives ('omp simd', 'omp
 
/// for', 'omp for simd' etc.). It is responsible for the loop code generation.
 
///
 
class OMPLoopDirective : public OMPLoopBasedDirective {
 
  friend class ASTStmtReader;
 
 
 
  /// Offsets to the stored exprs.
 
  /// This enumeration contains offsets to all the pointers to children
 
  /// expressions stored in OMPLoopDirective.
 
  /// The first 9 children are necessary for all the loop directives,
 
  /// the next 8 are specific to the worksharing ones, and the next 11 are
 
  /// used for combined constructs containing two pragmas associated to loops.
 
  /// After the fixed children, three arrays of length NumAssociatedLoops are
 
  /// allocated: loop counters, their updates and final values.
 
  /// PrevLowerBound and PrevUpperBound are used to communicate blocking
 
  /// information in composite constructs which require loop blocking
 
  /// DistInc is used to generate the increment expression for the distribute
 
  /// loop when combined with a further nested loop
 
  /// PrevEnsureUpperBound is used as the EnsureUpperBound expression for the
 
  /// for loop when combined with a previous distribute loop in the same pragma
 
  /// (e.g. 'distribute parallel for')
 
  ///
 
  enum {
 
    IterationVariableOffset = 0,
 
    LastIterationOffset = 1,
 
    CalcLastIterationOffset = 2,
 
    PreConditionOffset = 3,
 
    CondOffset = 4,
 
    InitOffset = 5,
 
    IncOffset = 6,
 
    PreInitsOffset = 7,
 
    // The '...End' enumerators do not correspond to child expressions - they
 
    // specify the offset to the end (and start of the following counters/
 
    // updates/finals/dependent_counters/dependent_inits/finals_conditions
 
    // arrays).
 
    DefaultEnd = 8,
 
    // The following 8 exprs are used by worksharing and distribute loops only.
 
    IsLastIterVariableOffset = 8,
 
    LowerBoundVariableOffset = 9,
 
    UpperBoundVariableOffset = 10,
 
    StrideVariableOffset = 11,
 
    EnsureUpperBoundOffset = 12,
 
    NextLowerBoundOffset = 13,
 
    NextUpperBoundOffset = 14,
 
    NumIterationsOffset = 15,
 
    // Offset to the end for worksharing loop directives.
 
    WorksharingEnd = 16,
 
    PrevLowerBoundVariableOffset = 16,
 
    PrevUpperBoundVariableOffset = 17,
 
    DistIncOffset = 18,
 
    PrevEnsureUpperBoundOffset = 19,
 
    CombinedLowerBoundVariableOffset = 20,
 
    CombinedUpperBoundVariableOffset = 21,
 
    CombinedEnsureUpperBoundOffset = 22,
 
    CombinedInitOffset = 23,
 
    CombinedConditionOffset = 24,
 
    CombinedNextLowerBoundOffset = 25,
 
    CombinedNextUpperBoundOffset = 26,
 
    CombinedDistConditionOffset = 27,
 
    CombinedParForInDistConditionOffset = 28,
 
    // Offset to the end (and start of the following
 
    // counters/updates/finals/dependent_counters/dependent_inits/finals_conditions
 
    // arrays) for combined distribute loop directives.
 
    CombinedDistributeEnd = 29,
 
  };
 
 
 
  /// Get the counters storage.
 
  MutableArrayRef<Expr *> getCounters() {
 
    auto **Storage = reinterpret_cast<Expr **>(
 
        &Data->getChildren()[getArraysOffset(getDirectiveKind())]);
 
    return llvm::MutableArrayRef(Storage, getLoopsNumber());
 
  }
 
 
 
  /// Get the private counters storage.
 
  MutableArrayRef<Expr *> getPrivateCounters() {
 
    auto **Storage = reinterpret_cast<Expr **>(
 
        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
 
                             getLoopsNumber()]);
 
    return llvm::MutableArrayRef(Storage, getLoopsNumber());
 
  }
 
 
 
  /// Get the updates storage.
 
  MutableArrayRef<Expr *> getInits() {
 
    auto **Storage = reinterpret_cast<Expr **>(
 
        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
 
                             2 * getLoopsNumber()]);
 
    return llvm::MutableArrayRef(Storage, getLoopsNumber());
 
  }
 
 
 
  /// Get the updates storage.
 
  MutableArrayRef<Expr *> getUpdates() {
 
    auto **Storage = reinterpret_cast<Expr **>(
 
        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
 
                             3 * getLoopsNumber()]);
 
    return llvm::MutableArrayRef(Storage, getLoopsNumber());
 
  }
 
 
 
  /// Get the final counter updates storage.
 
  MutableArrayRef<Expr *> getFinals() {
 
    auto **Storage = reinterpret_cast<Expr **>(
 
        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
 
                             4 * getLoopsNumber()]);
 
    return llvm::MutableArrayRef(Storage, getLoopsNumber());
 
  }
 
 
 
  /// Get the dependent counters storage.
 
  MutableArrayRef<Expr *> getDependentCounters() {
 
    auto **Storage = reinterpret_cast<Expr **>(
 
        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
 
                             5 * getLoopsNumber()]);
 
    return llvm::MutableArrayRef(Storage, getLoopsNumber());
 
  }
 
 
 
  /// Get the dependent inits storage.
 
  MutableArrayRef<Expr *> getDependentInits() {
 
    auto **Storage = reinterpret_cast<Expr **>(
 
        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
 
                             6 * getLoopsNumber()]);
 
    return llvm::MutableArrayRef(Storage, getLoopsNumber());
 
  }
 
 
 
  /// Get the finals conditions storage.
 
  MutableArrayRef<Expr *> getFinalsConditions() {
 
    auto **Storage = reinterpret_cast<Expr **>(
 
        &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
 
                             7 * getLoopsNumber()]);
 
    return llvm::MutableArrayRef(Storage, getLoopsNumber());
 
  }
 
 
 
protected:
 
  /// Build instance of loop directive of class \a Kind.
 
  ///
 
  /// \param SC Statement class.
 
  /// \param Kind Kind of OpenMP directive.
 
  /// \param StartLoc Starting location of the directive (directive keyword).
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops from 'collapse' clause.
 
  ///
 
  OMPLoopDirective(StmtClass SC, OpenMPDirectiveKind Kind,
 
                   SourceLocation StartLoc, SourceLocation EndLoc,
 
                   unsigned CollapsedNum)
 
      : OMPLoopBasedDirective(SC, Kind, StartLoc, EndLoc, CollapsedNum) {}
 
 
 
  /// Offset to the start of children expression arrays.
 
  static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
 
    if (isOpenMPLoopBoundSharingDirective(Kind))
 
      return CombinedDistributeEnd;
 
    if (isOpenMPWorksharingDirective(Kind) || isOpenMPTaskLoopDirective(Kind) ||
 
        isOpenMPGenericLoopDirective(Kind) || isOpenMPDistributeDirective(Kind))
 
      return WorksharingEnd;
 
    return DefaultEnd;
 
  }
 
 
 
  /// Children number.
 
  static unsigned numLoopChildren(unsigned CollapsedNum,
 
                                  OpenMPDirectiveKind Kind) {
 
    return getArraysOffset(Kind) +
 
           8 * CollapsedNum; // Counters, PrivateCounters, Inits,
 
                             // Updates, Finals, DependentCounters,
 
                             // DependentInits, FinalsConditions.
 
  }
 
 
 
  void setIterationVariable(Expr *IV) {
 
    Data->getChildren()[IterationVariableOffset] = IV;
 
  }
 
  void setLastIteration(Expr *LI) {
 
    Data->getChildren()[LastIterationOffset] = LI;
 
  }
 
  void setCalcLastIteration(Expr *CLI) {
 
    Data->getChildren()[CalcLastIterationOffset] = CLI;
 
  }
 
  void setPreCond(Expr *PC) { Data->getChildren()[PreConditionOffset] = PC; }
 
  void setCond(Expr *Cond) { Data->getChildren()[CondOffset] = Cond; }
 
  void setInit(Expr *Init) { Data->getChildren()[InitOffset] = Init; }
 
  void setInc(Expr *Inc) { Data->getChildren()[IncOffset] = Inc; }
 
  void setPreInits(Stmt *PreInits) {
 
    Data->getChildren()[PreInitsOffset] = PreInits;
 
  }
 
  void setIsLastIterVariable(Expr *IL) {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    Data->getChildren()[IsLastIterVariableOffset] = IL;
 
  }
 
  void setLowerBoundVariable(Expr *LB) {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    Data->getChildren()[LowerBoundVariableOffset] = LB;
 
  }
 
  void setUpperBoundVariable(Expr *UB) {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    Data->getChildren()[UpperBoundVariableOffset] = UB;
 
  }
 
  void setStrideVariable(Expr *ST) {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    Data->getChildren()[StrideVariableOffset] = ST;
 
  }
 
  void setEnsureUpperBound(Expr *EUB) {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    Data->getChildren()[EnsureUpperBoundOffset] = EUB;
 
  }
 
  void setNextLowerBound(Expr *NLB) {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    Data->getChildren()[NextLowerBoundOffset] = NLB;
 
  }
 
  void setNextUpperBound(Expr *NUB) {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    Data->getChildren()[NextUpperBoundOffset] = NUB;
 
  }
 
  void setNumIterations(Expr *NI) {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    Data->getChildren()[NumIterationsOffset] = NI;
 
  }
 
  void setPrevLowerBoundVariable(Expr *PrevLB) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[PrevLowerBoundVariableOffset] = PrevLB;
 
  }
 
  void setPrevUpperBoundVariable(Expr *PrevUB) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[PrevUpperBoundVariableOffset] = PrevUB;
 
  }
 
  void setDistInc(Expr *DistInc) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[DistIncOffset] = DistInc;
 
  }
 
  void setPrevEnsureUpperBound(Expr *PrevEUB) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[PrevEnsureUpperBoundOffset] = PrevEUB;
 
  }
 
  void setCombinedLowerBoundVariable(Expr *CombLB) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[CombinedLowerBoundVariableOffset] = CombLB;
 
  }
 
  void setCombinedUpperBoundVariable(Expr *CombUB) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[CombinedUpperBoundVariableOffset] = CombUB;
 
  }
 
  void setCombinedEnsureUpperBound(Expr *CombEUB) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[CombinedEnsureUpperBoundOffset] = CombEUB;
 
  }
 
  void setCombinedInit(Expr *CombInit) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[CombinedInitOffset] = CombInit;
 
  }
 
  void setCombinedCond(Expr *CombCond) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[CombinedConditionOffset] = CombCond;
 
  }
 
  void setCombinedNextLowerBound(Expr *CombNLB) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[CombinedNextLowerBoundOffset] = CombNLB;
 
  }
 
  void setCombinedNextUpperBound(Expr *CombNUB) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    Data->getChildren()[CombinedNextUpperBoundOffset] = CombNUB;
 
  }
 
  void setCombinedDistCond(Expr *CombDistCond) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound distribute sharing directive");
 
    Data->getChildren()[CombinedDistConditionOffset] = CombDistCond;
 
  }
 
  void setCombinedParForInDistCond(Expr *CombParForInDistCond) {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound distribute sharing directive");
 
    Data->getChildren()[CombinedParForInDistConditionOffset] =
 
        CombParForInDistCond;
 
  }
 
  void setCounters(ArrayRef<Expr *> A);
 
  void setPrivateCounters(ArrayRef<Expr *> A);
 
  void setInits(ArrayRef<Expr *> A);
 
  void setUpdates(ArrayRef<Expr *> A);
 
  void setFinals(ArrayRef<Expr *> A);
 
  void setDependentCounters(ArrayRef<Expr *> A);
 
  void setDependentInits(ArrayRef<Expr *> A);
 
  void setFinalsConditions(ArrayRef<Expr *> A);
 
 
 
public:
 
  Expr *getIterationVariable() const {
 
    return cast<Expr>(Data->getChildren()[IterationVariableOffset]);
 
  }
 
  Expr *getLastIteration() const {
 
    return cast<Expr>(Data->getChildren()[LastIterationOffset]);
 
  }
 
  Expr *getCalcLastIteration() const {
 
    return cast<Expr>(Data->getChildren()[CalcLastIterationOffset]);
 
  }
 
  Expr *getPreCond() const {
 
    return cast<Expr>(Data->getChildren()[PreConditionOffset]);
 
  }
 
  Expr *getCond() const { return cast<Expr>(Data->getChildren()[CondOffset]); }
 
  Expr *getInit() const { return cast<Expr>(Data->getChildren()[InitOffset]); }
 
  Expr *getInc() const { return cast<Expr>(Data->getChildren()[IncOffset]); }
 
  const Stmt *getPreInits() const {
 
    return Data->getChildren()[PreInitsOffset];
 
  }
 
  Stmt *getPreInits() { return Data->getChildren()[PreInitsOffset]; }
 
  Expr *getIsLastIterVariable() const {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    return cast<Expr>(Data->getChildren()[IsLastIterVariableOffset]);
 
  }
 
  Expr *getLowerBoundVariable() const {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    return cast<Expr>(Data->getChildren()[LowerBoundVariableOffset]);
 
  }
 
  Expr *getUpperBoundVariable() const {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    return cast<Expr>(Data->getChildren()[UpperBoundVariableOffset]);
 
  }
 
  Expr *getStrideVariable() const {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    return cast<Expr>(Data->getChildren()[StrideVariableOffset]);
 
  }
 
  Expr *getEnsureUpperBound() const {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    return cast<Expr>(Data->getChildren()[EnsureUpperBoundOffset]);
 
  }
 
  Expr *getNextLowerBound() const {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    return cast<Expr>(Data->getChildren()[NextLowerBoundOffset]);
 
  }
 
  Expr *getNextUpperBound() const {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    return cast<Expr>(Data->getChildren()[NextUpperBoundOffset]);
 
  }
 
  Expr *getNumIterations() const {
 
    assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
 
            isOpenMPGenericLoopDirective(getDirectiveKind()) ||
 
            isOpenMPTaskLoopDirective(getDirectiveKind()) ||
 
            isOpenMPDistributeDirective(getDirectiveKind())) &&
 
           "expected worksharing loop directive");
 
    return cast<Expr>(Data->getChildren()[NumIterationsOffset]);
 
  }
 
  Expr *getPrevLowerBoundVariable() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[PrevLowerBoundVariableOffset]);
 
  }
 
  Expr *getPrevUpperBoundVariable() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[PrevUpperBoundVariableOffset]);
 
  }
 
  Expr *getDistInc() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[DistIncOffset]);
 
  }
 
  Expr *getPrevEnsureUpperBound() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[PrevEnsureUpperBoundOffset]);
 
  }
 
  Expr *getCombinedLowerBoundVariable() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[CombinedLowerBoundVariableOffset]);
 
  }
 
  Expr *getCombinedUpperBoundVariable() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[CombinedUpperBoundVariableOffset]);
 
  }
 
  Expr *getCombinedEnsureUpperBound() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[CombinedEnsureUpperBoundOffset]);
 
  }
 
  Expr *getCombinedInit() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[CombinedInitOffset]);
 
  }
 
  Expr *getCombinedCond() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[CombinedConditionOffset]);
 
  }
 
  Expr *getCombinedNextLowerBound() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[CombinedNextLowerBoundOffset]);
 
  }
 
  Expr *getCombinedNextUpperBound() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound sharing directive");
 
    return cast<Expr>(Data->getChildren()[CombinedNextUpperBoundOffset]);
 
  }
 
  Expr *getCombinedDistCond() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound distribute sharing directive");
 
    return cast<Expr>(Data->getChildren()[CombinedDistConditionOffset]);
 
  }
 
  Expr *getCombinedParForInDistCond() const {
 
    assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
 
           "expected loop bound distribute sharing directive");
 
    return cast<Expr>(Data->getChildren()[CombinedParForInDistConditionOffset]);
 
  }
 
  Stmt *getBody();
 
  const Stmt *getBody() const {
 
    return const_cast<OMPLoopDirective *>(this)->getBody();
 
  }
 
 
 
  ArrayRef<Expr *> counters() { return getCounters(); }
 
 
 
  ArrayRef<Expr *> counters() const {
 
    return const_cast<OMPLoopDirective *>(this)->getCounters();
 
  }
 
 
 
  ArrayRef<Expr *> private_counters() { return getPrivateCounters(); }
 
 
 
  ArrayRef<Expr *> private_counters() const {
 
    return const_cast<OMPLoopDirective *>(this)->getPrivateCounters();
 
  }
 
 
 
  ArrayRef<Expr *> inits() { return getInits(); }
 
 
 
  ArrayRef<Expr *> inits() const {
 
    return const_cast<OMPLoopDirective *>(this)->getInits();
 
  }
 
 
 
  ArrayRef<Expr *> updates() { return getUpdates(); }
 
 
 
  ArrayRef<Expr *> updates() const {
 
    return const_cast<OMPLoopDirective *>(this)->getUpdates();
 
  }
 
 
 
  ArrayRef<Expr *> finals() { return getFinals(); }
 
 
 
  ArrayRef<Expr *> finals() const {
 
    return const_cast<OMPLoopDirective *>(this)->getFinals();
 
  }
 
 
 
  ArrayRef<Expr *> dependent_counters() { return getDependentCounters(); }
 
 
 
  ArrayRef<Expr *> dependent_counters() const {
 
    return const_cast<OMPLoopDirective *>(this)->getDependentCounters();
 
  }
 
 
 
  ArrayRef<Expr *> dependent_inits() { return getDependentInits(); }
 
 
 
  ArrayRef<Expr *> dependent_inits() const {
 
    return const_cast<OMPLoopDirective *>(this)->getDependentInits();
 
  }
 
 
 
  ArrayRef<Expr *> finals_conditions() { return getFinalsConditions(); }
 
 
 
  ArrayRef<Expr *> finals_conditions() const {
 
    return const_cast<OMPLoopDirective *>(this)->getFinalsConditions();
 
  }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPSimdDirectiveClass ||
 
           T->getStmtClass() == OMPForDirectiveClass ||
 
           T->getStmtClass() == OMPForSimdDirectiveClass ||
 
           T->getStmtClass() == OMPParallelForDirectiveClass ||
 
           T->getStmtClass() == OMPParallelForSimdDirectiveClass ||
 
           T->getStmtClass() == OMPTaskLoopDirectiveClass ||
 
           T->getStmtClass() == OMPTaskLoopSimdDirectiveClass ||
 
           T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass ||
 
           T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass ||
 
           T->getStmtClass() == OMPMasterTaskLoopDirectiveClass ||
 
           T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass ||
 
           T->getStmtClass() == OMPGenericLoopDirectiveClass ||
 
           T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass ||
 
           T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass ||
 
           T->getStmtClass() == OMPParallelGenericLoopDirectiveClass ||
 
           T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass ||
 
           T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass ||
 
           T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass ||
 
           T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass ||
 
           T->getStmtClass() == OMPParallelMasterTaskLoopSimdDirectiveClass ||
 
           T->getStmtClass() == OMPDistributeDirectiveClass ||
 
           T->getStmtClass() == OMPTargetParallelForDirectiveClass ||
 
           T->getStmtClass() == OMPDistributeParallelForDirectiveClass ||
 
           T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass ||
 
           T->getStmtClass() == OMPDistributeSimdDirectiveClass ||
 
           T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass ||
 
           T->getStmtClass() == OMPTargetSimdDirectiveClass ||
 
           T->getStmtClass() == OMPTeamsDistributeDirectiveClass ||
 
           T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass ||
 
           T->getStmtClass() ==
 
               OMPTeamsDistributeParallelForSimdDirectiveClass ||
 
           T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass ||
 
           T->getStmtClass() ==
 
               OMPTargetTeamsDistributeParallelForDirectiveClass ||
 
           T->getStmtClass() ==
 
               OMPTargetTeamsDistributeParallelForSimdDirectiveClass ||
 
           T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass ||
 
           T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp simd' directive.
 
///
 
/// \code
 
/// #pragma omp simd private(a,b) linear(i,j:s) reduction(+:c,d)
 
/// \endcode
 
/// In this example directive '#pragma omp simd' has clauses 'private'
 
/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
 
/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
 
///
 
class OMPSimdDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                   unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPSimdDirectiveClass, llvm::omp::OMPD_simd, StartLoc,
 
                         EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPSimdDirectiveClass, llvm::omp::OMPD_simd,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc,
 
                                  SourceLocation EndLoc, unsigned CollapsedNum,
 
                                  ArrayRef<OMPClause *> Clauses,
 
                                  Stmt *AssociatedStmt,
 
                                  const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
 
                                       unsigned CollapsedNum, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp for' directive.
 
///
 
/// \code
 
/// #pragma omp for private(a,b) reduction(+:c,d)
 
/// \endcode
 
/// In this example directive '#pragma omp for' has clauses 'private' with the
 
/// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c'
 
/// and 'd'.
 
///
 
class OMPForDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if current directive has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                  unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPForDirectiveClass, llvm::omp::OMPD_for, StartLoc,
 
                         EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPForDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPForDirectiveClass, llvm::omp::OMPD_for,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) {
 
    Data->getChildren()[numLoopChildren(getLoopsNumber(),
 
                                        llvm::omp::OMPD_for)] = E;
 
  }
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  /// \param HasCancel true if current directive has inner cancel directive.
 
  ///
 
  static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
 
                                 SourceLocation EndLoc, unsigned CollapsedNum,
 
                                 ArrayRef<OMPClause *> Clauses,
 
                                 Stmt *AssociatedStmt, const HelperExprs &Exprs,
 
                                 Expr *TaskRedRef, bool HasCancel);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
 
                                      unsigned CollapsedNum, EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
 
        getLoopsNumber(), llvm::omp::OMPD_for)]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPForDirective *>(this)->getTaskReductionRefExpr();
 
  }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPForDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp for simd' directive.
 
///
 
/// \code
 
/// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d)
 
/// \endcode
 
/// In this example directive '#pragma omp for simd' has clauses 'private'
 
/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
 
/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
 
///
 
class OMPForSimdDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                      unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPForSimdDirectiveClass, llvm::omp::OMPD_for_simd,
 
                         StartLoc, EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPForSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPForSimdDirectiveClass, llvm::omp::OMPD_for_simd,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPForSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPForSimdDirective *CreateEmpty(const ASTContext &C,
 
                                          unsigned NumClauses,
 
                                          unsigned CollapsedNum, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPForSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp sections' directive.
 
///
 
/// \code
 
/// #pragma omp sections private(a,b) reduction(+:c,d)
 
/// \endcode
 
/// In this example directive '#pragma omp sections' has clauses 'private' with
 
/// the variables 'a' and 'b' and 'reduction' with operator '+' and variables
 
/// 'c' and 'd'.
 
///
 
class OMPSectionsDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// true if current directive has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPSectionsDirectiveClass,
 
                               llvm::omp::OMPD_sections, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPSectionsDirective()
 
      : OMPExecutableDirective(OMPSectionsDirectiveClass,
 
                               llvm::omp::OMPD_sections, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  /// \param HasCancel true if current directive has inner directive.
 
  ///
 
  static OMPSectionsDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
 
         bool HasCancel);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPSectionsDirective *CreateEmpty(const ASTContext &C,
 
                                           unsigned NumClauses, EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[0]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPSectionsDirective *>(this)->getTaskReductionRefExpr();
 
  }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPSectionsDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp section' directive.
 
///
 
/// \code
 
/// #pragma omp section
 
/// \endcode
 
///
 
class OMPSectionDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// true if current directive has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPSectionDirectiveClass,
 
                               llvm::omp::OMPD_section, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPSectionDirective()
 
      : OMPExecutableDirective(OMPSectionDirectiveClass,
 
                               llvm::omp::OMPD_section, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param HasCancel true if current directive has inner directive.
 
  ///
 
  static OMPSectionDirective *Create(const ASTContext &C,
 
                                     SourceLocation StartLoc,
 
                                     SourceLocation EndLoc,
 
                                     Stmt *AssociatedStmt, bool HasCancel);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  ///
 
  static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell);
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPSectionDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp single' directive.
 
///
 
/// \code
 
/// #pragma omp single private(a,b) copyprivate(c,d)
 
/// \endcode
 
/// In this example directive '#pragma omp single' has clauses 'private' with
 
/// the variables 'a' and 'b' and 'copyprivate' with variables 'c' and 'd'.
 
///
 
class OMPSingleDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPSingleDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPSingleDirectiveClass, llvm::omp::OMPD_single,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPSingleDirective()
 
      : OMPExecutableDirective(OMPSingleDirectiveClass, llvm::omp::OMPD_single,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPSingleDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPSingleDirective *CreateEmpty(const ASTContext &C,
 
                                         unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPSingleDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp master' directive.
 
///
 
/// \code
 
/// #pragma omp master
 
/// \endcode
 
///
 
class OMPMasterDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPMasterDirectiveClass, llvm::omp::OMPD_master,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPMasterDirective()
 
      : OMPExecutableDirective(OMPMasterDirectiveClass, llvm::omp::OMPD_master,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPMasterDirective *Create(const ASTContext &C,
 
                                    SourceLocation StartLoc,
 
                                    SourceLocation EndLoc,
 
                                    Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  ///
 
  static OMPMasterDirective *CreateEmpty(const ASTContext &C, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPMasterDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp critical' directive.
 
///
 
/// \code
 
/// #pragma omp critical
 
/// \endcode
 
///
 
class OMPCriticalDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Name of the directive.
 
  DeclarationNameInfo DirName;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param Name Name of the directive.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc,
 
                       SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPCriticalDirectiveClass,
 
                               llvm::omp::OMPD_critical, StartLoc, EndLoc),
 
        DirName(Name) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPCriticalDirective()
 
      : OMPExecutableDirective(OMPCriticalDirectiveClass,
 
                               llvm::omp::OMPD_critical, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
  /// Set name of the directive.
 
  ///
 
  /// \param Name Name of the directive.
 
  ///
 
  void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; }
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param Name Name of the directive.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPCriticalDirective *
 
  Create(const ASTContext &C, const DeclarationNameInfo &Name,
 
         SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPCriticalDirective *CreateEmpty(const ASTContext &C,
 
                                           unsigned NumClauses, EmptyShell);
 
 
 
  /// Return name of the directive.
 
  ///
 
  DeclarationNameInfo getDirectiveName() const { return DirName; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPCriticalDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel for' directive.
 
///
 
/// \code
 
/// #pragma omp parallel for private(a,b) reduction(+:c,d)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel for' has clauses 'private'
 
/// with the variables 'a' and 'b' and 'reduction' with operator '+' and
 
/// variables 'c' and 'd'.
 
///
 
class OMPParallelForDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// true if current region has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                          unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelForDirectiveClass,
 
                         llvm::omp::OMPD_parallel_for, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPParallelForDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelForDirectiveClass,
 
                         llvm::omp::OMPD_parallel_for, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) {
 
    Data->getChildren()[numLoopChildren(getLoopsNumber(),
 
                                        llvm::omp::OMPD_parallel_for)] = E;
 
  }
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  /// \param HasCancel true if current directive has inner cancel directive.
 
  ///
 
  static OMPParallelForDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
 
         bool HasCancel);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelForDirective *CreateEmpty(const ASTContext &C,
 
                                              unsigned NumClauses,
 
                                              unsigned CollapsedNum,
 
                                              EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
 
        getLoopsNumber(), llvm::omp::OMPD_parallel_for)]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPParallelForDirective *>(this)
 
        ->getTaskReductionRefExpr();
 
  }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelForDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel for simd' directive.
 
///
 
/// \code
 
/// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel for simd' has clauses
 
/// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j'
 
/// and linear step 's', 'reduction' with operator '+' and variables 'c' and
 
/// 'd'.
 
///
 
class OMPParallelForSimdDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                              unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelForSimdDirectiveClass,
 
                         llvm::omp::OMPD_parallel_for_simd, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPParallelForSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelForSimdDirectiveClass,
 
                         llvm::omp::OMPD_parallel_for_simd, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPParallelForSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C,
 
                                                  unsigned NumClauses,
 
                                                  unsigned CollapsedNum,
 
                                                  EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelForSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel master' directive.
 
///
 
/// \code
 
/// #pragma omp parallel master private(a,b)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel master' has clauses
 
/// 'private' with the variables 'a' and 'b'
 
///
 
class OMPParallelMasterDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  OMPParallelMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPParallelMasterDirectiveClass,
 
                               llvm::omp::OMPD_parallel_master, StartLoc,
 
                               EndLoc) {}
 
 
 
  explicit OMPParallelMasterDirective()
 
      : OMPExecutableDirective(OMPParallelMasterDirectiveClass,
 
                               llvm::omp::OMPD_parallel_master,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  ///
 
  static OMPParallelMasterDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelMasterDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[0]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPParallelMasterDirective *>(this)
 
        ->getTaskReductionRefExpr();
 
  }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelMasterDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel masked' directive.
 
///
 
/// \code
 
/// #pragma omp parallel masked filter(tid)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel masked' has a clause
 
/// 'filter' with the variable tid
 
///
 
class OMPParallelMaskedDirective final : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  OMPParallelMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPParallelMaskedDirectiveClass,
 
                               llvm::omp::OMPD_parallel_masked, StartLoc,
 
                               EndLoc) {}
 
 
 
  explicit OMPParallelMaskedDirective()
 
      : OMPExecutableDirective(OMPParallelMaskedDirectiveClass,
 
                               llvm::omp::OMPD_parallel_masked,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  ///
 
  static OMPParallelMaskedDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelMaskedDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[0]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPParallelMaskedDirective *>(this)
 
        ->getTaskReductionRefExpr();
 
  }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelMaskedDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel sections' directive.
 
///
 
/// \code
 
/// #pragma omp parallel sections private(a,b) reduction(+:c,d)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel sections' has clauses
 
/// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+'
 
/// and variables 'c' and 'd'.
 
///
 
class OMPParallelSectionsDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// true if current directive has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPParallelSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPParallelSectionsDirectiveClass,
 
                               llvm::omp::OMPD_parallel_sections, StartLoc,
 
                               EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPParallelSectionsDirective()
 
      : OMPExecutableDirective(OMPParallelSectionsDirectiveClass,
 
                               llvm::omp::OMPD_parallel_sections,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  /// \param HasCancel true if current directive has inner cancel directive.
 
  ///
 
  static OMPParallelSectionsDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
 
         bool HasCancel);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelSectionsDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[0]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPParallelSectionsDirective *>(this)
 
        ->getTaskReductionRefExpr();
 
  }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelSectionsDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp task' directive.
 
///
 
/// \code
 
/// #pragma omp task private(a,b) final(d)
 
/// \endcode
 
/// In this example directive '#pragma omp task' has clauses 'private' with the
 
/// variables 'a' and 'b' and 'final' with condition 'd'.
 
///
 
class OMPTaskDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if this directive has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTaskDirectiveClass, llvm::omp::OMPD_task,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTaskDirective()
 
      : OMPExecutableDirective(OMPTaskDirectiveClass, llvm::omp::OMPD_task,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param HasCancel true, if current directive has inner cancel directive.
 
  ///
 
  static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc,
 
                                  SourceLocation EndLoc,
 
                                  ArrayRef<OMPClause *> Clauses,
 
                                  Stmt *AssociatedStmt, bool HasCancel);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
 
                                       EmptyShell);
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTaskDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp taskyield' directive.
 
///
 
/// \code
 
/// #pragma omp taskyield
 
/// \endcode
 
///
 
class OMPTaskyieldDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTaskyieldDirectiveClass,
 
                               llvm::omp::OMPD_taskyield, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTaskyieldDirective()
 
      : OMPExecutableDirective(OMPTaskyieldDirectiveClass,
 
                               llvm::omp::OMPD_taskyield, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  ///
 
  static OMPTaskyieldDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  ///
 
  static OMPTaskyieldDirective *CreateEmpty(const ASTContext &C, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTaskyieldDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp barrier' directive.
 
///
 
/// \code
 
/// #pragma omp barrier
 
/// \endcode
 
///
 
class OMPBarrierDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPBarrierDirectiveClass,
 
                               llvm::omp::OMPD_barrier, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPBarrierDirective()
 
      : OMPExecutableDirective(OMPBarrierDirectiveClass,
 
                               llvm::omp::OMPD_barrier, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  ///
 
  static OMPBarrierDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  ///
 
  static OMPBarrierDirective *CreateEmpty(const ASTContext &C, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPBarrierDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp taskwait' directive.
 
///
 
/// \code
 
/// #pragma omp taskwait
 
/// \endcode
 
///
 
class OMPTaskwaitDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTaskwaitDirectiveClass,
 
                               llvm::omp::OMPD_taskwait, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTaskwaitDirective()
 
      : OMPExecutableDirective(OMPTaskwaitDirectiveClass,
 
                               llvm::omp::OMPD_taskwait, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  ///
 
  static OMPTaskwaitDirective *Create(const ASTContext &C,
 
                                      SourceLocation StartLoc,
 
                                      SourceLocation EndLoc,
 
                                      ArrayRef<OMPClause *> Clauses);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C,
 
                                           unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTaskwaitDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp taskgroup' directive.
 
///
 
/// \code
 
/// #pragma omp taskgroup
 
/// \endcode
 
///
 
class OMPTaskgroupDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTaskgroupDirectiveClass,
 
                               llvm::omp::OMPD_taskgroup, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTaskgroupDirective()
 
      : OMPExecutableDirective(OMPTaskgroupDirectiveClass,
 
                               llvm::omp::OMPD_taskgroup, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
  /// Sets the task_reduction return variable.
 
  void setReductionRef(Expr *RR) { Data->getChildren()[0] = RR; }
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param ReductionRef Reference to the task_reduction return variable.
 
  ///
 
  static OMPTaskgroupDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
 
         Expr *ReductionRef);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C,
 
                                            unsigned NumClauses, EmptyShell);
 
 
 
 
 
  /// Returns reference to the task_reduction return variable.
 
  const Expr *getReductionRef() const {
 
    return const_cast<OMPTaskgroupDirective *>(this)->getReductionRef();
 
  }
 
  Expr *getReductionRef() { return cast_or_null<Expr>(Data->getChildren()[0]); }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTaskgroupDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp flush' directive.
 
///
 
/// \code
 
/// #pragma omp flush(a,b)
 
/// \endcode
 
/// In this example directive '#pragma omp flush' has 2 arguments- variables 'a'
 
/// and 'b'.
 
/// 'omp flush' directive does not have clauses but have an optional list of
 
/// variables to flush. This list of variables is stored within some fake clause
 
/// FlushClause.
 
class OMPFlushDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPFlushDirectiveClass, llvm::omp::OMPD_flush,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPFlushDirective()
 
      : OMPExecutableDirective(OMPFlushDirectiveClass, llvm::omp::OMPD_flush,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses (only single OMPFlushClause clause is
 
  /// allowed).
 
  ///
 
  static OMPFlushDirective *Create(const ASTContext &C, SourceLocation StartLoc,
 
                                   SourceLocation EndLoc,
 
                                   ArrayRef<OMPClause *> Clauses);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPFlushDirective *CreateEmpty(const ASTContext &C,
 
                                        unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPFlushDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp depobj' directive.
 
///
 
/// \code
 
/// #pragma omp depobj(a) depend(in:x,y)
 
/// \endcode
 
/// In this example directive '#pragma omp  depobj' initializes a depobj object
 
/// 'a' with dependence type 'in' and a list with 'x' and 'y' locators.
 
class OMPDepobjDirective final : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPDepobjDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPDepobjDirectiveClass, llvm::omp::OMPD_depobj,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPDepobjDirective()
 
      : OMPExecutableDirective(OMPDepobjDirectiveClass, llvm::omp::OMPD_depobj,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  ///
 
  static OMPDepobjDirective *Create(const ASTContext &C,
 
                                    SourceLocation StartLoc,
 
                                    SourceLocation EndLoc,
 
                                    ArrayRef<OMPClause *> Clauses);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPDepobjDirective *CreateEmpty(const ASTContext &C,
 
                                         unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPDepobjDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp ordered' directive.
 
///
 
/// \code
 
/// #pragma omp ordered
 
/// \endcode
 
///
 
class OMPOrderedDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPOrderedDirectiveClass,
 
                               llvm::omp::OMPD_ordered, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPOrderedDirective()
 
      : OMPExecutableDirective(OMPOrderedDirectiveClass,
 
                               llvm::omp::OMPD_ordered, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPOrderedDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  /// \param IsStandalone true, if the standalone directive is created.
 
  ///
 
  static OMPOrderedDirective *CreateEmpty(const ASTContext &C,
 
                                          unsigned NumClauses,
 
                                          bool IsStandalone, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPOrderedDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp atomic' directive.
 
///
 
/// \code
 
/// #pragma omp atomic capture
 
/// \endcode
 
/// In this example directive '#pragma omp atomic' has clause 'capture'.
 
///
 
class OMPAtomicDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  struct FlagTy {
 
    /// Used for 'atomic update' or 'atomic capture' constructs. They may
 
    /// have atomic expressions of forms:
 
    /// \code
 
    /// x = x binop expr;
 
    /// x = expr binop x;
 
    /// \endcode
 
    /// This field is 1 for the first form of the expression and 0 for the
 
    /// second. Required for correct codegen of non-associative operations (like
 
    /// << or >>).
 
    uint8_t IsXLHSInRHSPart : 1;
 
    /// Used for 'atomic update' or 'atomic capture' constructs. They may
 
    /// have atomic expressions of forms:
 
    /// \code
 
    /// v = x; <update x>;
 
    /// <update x>; v = x;
 
    /// \endcode
 
    /// This field is 1 for the first(postfix) form of the expression and 0
 
    /// otherwise.
 
    uint8_t IsPostfixUpdate : 1;
 
    /// 1 if 'v' is updated only when the condition is false (compare capture
 
    /// only).
 
    uint8_t IsFailOnly : 1;
 
  } Flags;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPAtomicDirective()
 
      : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
  enum DataPositionTy : size_t {
 
    POS_X = 0,
 
    POS_V,
 
    POS_E,
 
    POS_UpdateExpr,
 
    POS_D,
 
    POS_Cond,
 
    POS_R,
 
  };
 
 
 
  /// Set 'x' part of the associated expression/statement.
 
  void setX(Expr *X) { Data->getChildren()[DataPositionTy::POS_X] = X; }
 
  /// Set helper expression of the form
 
  /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
 
  /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
 
  void setUpdateExpr(Expr *UE) {
 
    Data->getChildren()[DataPositionTy::POS_UpdateExpr] = UE;
 
  }
 
  /// Set 'v' part of the associated expression/statement.
 
  void setV(Expr *V) { Data->getChildren()[DataPositionTy::POS_V] = V; }
 
  /// Set 'r' part of the associated expression/statement.
 
  void setR(Expr *R) { Data->getChildren()[DataPositionTy::POS_R] = R; }
 
  /// Set 'expr' part of the associated expression/statement.
 
  void setExpr(Expr *E) { Data->getChildren()[DataPositionTy::POS_E] = E; }
 
  /// Set 'd' part of the associated expression/statement.
 
  void setD(Expr *D) { Data->getChildren()[DataPositionTy::POS_D] = D; }
 
  /// Set conditional expression in `atomic compare`.
 
  void setCond(Expr *C) { Data->getChildren()[DataPositionTy::POS_Cond] = C; }
 
 
 
public:
 
  struct Expressions {
 
    /// 'x' part of the associated expression/statement.
 
    Expr *X = nullptr;
 
    /// 'v' part of the associated expression/statement.
 
    Expr *V = nullptr;
 
    // 'r' part of the associated expression/statement.
 
    Expr *R = nullptr;
 
    /// 'expr' part of the associated expression/statement.
 
    Expr *E = nullptr;
 
    /// UE Helper expression of the form:
 
    /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
 
    /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
 
    Expr *UE = nullptr;
 
    /// 'd' part of the associated expression/statement.
 
    Expr *D = nullptr;
 
    /// Conditional expression in `atomic compare` construct.
 
    Expr *Cond = nullptr;
 
    /// True if UE has the first form and false if the second.
 
    bool IsXLHSInRHSPart;
 
    /// True if original value of 'x' must be stored in 'v', not an updated one.
 
    bool IsPostfixUpdate;
 
    /// True if 'v' is updated only when the condition is false (compare capture
 
    /// only).
 
    bool IsFailOnly;
 
  };
 
 
 
  /// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
 
  /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for
 
  /// detailed description of 'x', 'v' and 'expr').
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Associated expressions or statements.
 
  static OMPAtomicDirective *Create(const ASTContext &C,
 
                                    SourceLocation StartLoc,
 
                                    SourceLocation EndLoc,
 
                                    ArrayRef<OMPClause *> Clauses,
 
                                    Stmt *AssociatedStmt, Expressions Exprs);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPAtomicDirective *CreateEmpty(const ASTContext &C,
 
                                         unsigned NumClauses, EmptyShell);
 
 
 
  /// Get 'x' part of the associated expression/statement.
 
  Expr *getX() {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_X]);
 
  }
 
  const Expr *getX() const {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_X]);
 
  }
 
  /// Get helper expression of the form
 
  /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
 
  /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
 
  Expr *getUpdateExpr() {
 
    return cast_or_null<Expr>(
 
        Data->getChildren()[DataPositionTy::POS_UpdateExpr]);
 
  }
 
  const Expr *getUpdateExpr() const {
 
    return cast_or_null<Expr>(
 
        Data->getChildren()[DataPositionTy::POS_UpdateExpr]);
 
  }
 
  /// Return true if helper update expression has form
 
  /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form
 
  /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
 
  bool isXLHSInRHSPart() const { return Flags.IsXLHSInRHSPart; }
 
  /// Return true if 'v' expression must be updated to original value of
 
  /// 'x', false if 'v' must be updated to the new value of 'x'.
 
  bool isPostfixUpdate() const { return Flags.IsPostfixUpdate; }
 
  /// Return true if 'v' is updated only when the condition is evaluated false
 
  /// (compare capture only).
 
  bool isFailOnly() const { return Flags.IsFailOnly; }
 
  /// Get 'v' part of the associated expression/statement.
 
  Expr *getV() {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]);
 
  }
 
  const Expr *getV() const {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_V]);
 
  }
 
  /// Get 'r' part of the associated expression/statement.
 
  Expr *getR() {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]);
 
  }
 
  const Expr *getR() const {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_R]);
 
  }
 
  /// Get 'expr' part of the associated expression/statement.
 
  Expr *getExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
 
  }
 
  const Expr *getExpr() const {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_E]);
 
  }
 
  /// Get 'd' part of the associated expression/statement.
 
  Expr *getD() {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
 
  }
 
  Expr *getD() const {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_D]);
 
  }
 
  /// Get the 'cond' part of the source atomic expression.
 
  Expr *getCondExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
 
  }
 
  Expr *getCondExpr() const {
 
    return cast_or_null<Expr>(Data->getChildren()[DataPositionTy::POS_Cond]);
 
  }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPAtomicDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target' directive.
 
///
 
/// \code
 
/// #pragma omp target if(a)
 
/// \endcode
 
/// In this example directive '#pragma omp target' has clause 'if' with
 
/// condition 'a'.
 
///
 
class OMPTargetDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTargetDirective()
 
      : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPTargetDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetDirective *CreateEmpty(const ASTContext &C,
 
                                         unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target data' directive.
 
///
 
/// \code
 
/// #pragma omp target data device(0) if(a) map(b[:])
 
/// \endcode
 
/// In this example directive '#pragma omp target data' has clauses 'device'
 
/// with the value '0', 'if' with condition 'a' and 'map' with array
 
/// section 'b[:]'.
 
///
 
class OMPTargetDataDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  ///
 
  OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTargetDataDirectiveClass,
 
                               llvm::omp::OMPD_target_data, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTargetDataDirective()
 
      : OMPExecutableDirective(OMPTargetDataDirectiveClass,
 
                               llvm::omp::OMPD_target_data, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPTargetDataDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive with the place for \a N clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param N The number of clauses.
 
  ///
 
  static OMPTargetDataDirective *CreateEmpty(const ASTContext &C, unsigned N,
 
                                             EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetDataDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target enter data' directive.
 
///
 
/// \code
 
/// #pragma omp target enter data device(0) if(a) map(b[:])
 
/// \endcode
 
/// In this example directive '#pragma omp target enter data' has clauses
 
/// 'device' with the value '0', 'if' with condition 'a' and 'map' with array
 
/// section 'b[:]'.
 
///
 
class OMPTargetEnterDataDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  ///
 
  OMPTargetEnterDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
 
                               llvm::omp::OMPD_target_enter_data, StartLoc,
 
                               EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTargetEnterDataDirective()
 
      : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
 
                               llvm::omp::OMPD_target_enter_data,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPTargetEnterDataDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive with the place for \a N clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param N The number of clauses.
 
  ///
 
  static OMPTargetEnterDataDirective *CreateEmpty(const ASTContext &C,
 
                                                  unsigned N, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetEnterDataDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target exit data' directive.
 
///
 
/// \code
 
/// #pragma omp target exit data device(0) if(a) map(b[:])
 
/// \endcode
 
/// In this example directive '#pragma omp target exit data' has clauses
 
/// 'device' with the value '0', 'if' with condition 'a' and 'map' with array
 
/// section 'b[:]'.
 
///
 
class OMPTargetExitDataDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  ///
 
  OMPTargetExitDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTargetExitDataDirectiveClass,
 
                               llvm::omp::OMPD_target_exit_data, StartLoc,
 
                               EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTargetExitDataDirective()
 
      : OMPExecutableDirective(OMPTargetExitDataDirectiveClass,
 
                               llvm::omp::OMPD_target_exit_data,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPTargetExitDataDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive with the place for \a N clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param N The number of clauses.
 
  ///
 
  static OMPTargetExitDataDirective *CreateEmpty(const ASTContext &C,
 
                                                 unsigned N, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetExitDataDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target parallel' directive.
 
///
 
/// \code
 
/// #pragma omp target parallel if(a)
 
/// \endcode
 
/// In this example directive '#pragma omp target parallel' has clause 'if' with
 
/// condition 'a'.
 
///
 
class OMPTargetParallelDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if the construct has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPTargetParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTargetParallelDirectiveClass,
 
                               llvm::omp::OMPD_target_parallel, StartLoc,
 
                               EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTargetParallelDirective()
 
      : OMPExecutableDirective(OMPTargetParallelDirectiveClass,
 
                               llvm::omp::OMPD_target_parallel,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  /// \param HasCancel true if this directive has inner cancel directive.
 
  ///
 
  static OMPTargetParallelDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
 
         bool HasCancel);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetParallelDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[0]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPTargetParallelDirective *>(this)
 
        ->getTaskReductionRefExpr();
 
  }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetParallelDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target parallel for' directive.
 
///
 
/// \code
 
/// #pragma omp target parallel for private(a,b) reduction(+:c,d)
 
/// \endcode
 
/// In this example directive '#pragma omp target parallel for' has clauses
 
/// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+'
 
/// and variables 'c' and 'd'.
 
///
 
class OMPTargetParallelForDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// true if current region has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTargetParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                                unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetParallelForDirectiveClass,
 
                         llvm::omp::OMPD_target_parallel_for, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTargetParallelForDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetParallelForDirectiveClass,
 
                         llvm::omp::OMPD_target_parallel_for, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) {
 
    Data->getChildren()[numLoopChildren(
 
        getLoopsNumber(), llvm::omp::OMPD_target_parallel_for)] = E;
 
  }
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  /// \param HasCancel true if current directive has inner cancel directive.
 
  ///
 
  static OMPTargetParallelForDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
 
         bool HasCancel);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetParallelForDirective *CreateEmpty(const ASTContext &C,
 
                                                    unsigned NumClauses,
 
                                                    unsigned CollapsedNum,
 
                                                    EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
 
        getLoopsNumber(), llvm::omp::OMPD_target_parallel_for)]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPTargetParallelForDirective *>(this)
 
        ->getTaskReductionRefExpr();
 
  }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetParallelForDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp teams' directive.
 
///
 
/// \code
 
/// #pragma omp teams if(a)
 
/// \endcode
 
/// In this example directive '#pragma omp teams' has clause 'if' with
 
/// condition 'a'.
 
///
 
class OMPTeamsDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTeamsDirectiveClass, llvm::omp::OMPD_teams,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTeamsDirective()
 
      : OMPExecutableDirective(OMPTeamsDirectiveClass, llvm::omp::OMPD_teams,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPTeamsDirective *Create(const ASTContext &C, SourceLocation StartLoc,
 
                                   SourceLocation EndLoc,
 
                                   ArrayRef<OMPClause *> Clauses,
 
                                   Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTeamsDirective *CreateEmpty(const ASTContext &C,
 
                                        unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTeamsDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp cancellation point' directive.
 
///
 
/// \code
 
/// #pragma omp cancellation point for
 
/// \endcode
 
///
 
/// In this example a cancellation point is created for innermost 'for' region.
 
class OMPCancellationPointDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  OpenMPDirectiveKind CancelRegion = llvm::omp::OMPD_unknown;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// statements and child expressions.
 
  ///
 
  OMPCancellationPointDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPCancellationPointDirectiveClass,
 
                               llvm::omp::OMPD_cancellation_point, StartLoc,
 
                               EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  explicit OMPCancellationPointDirective()
 
      : OMPExecutableDirective(OMPCancellationPointDirectiveClass,
 
                               llvm::omp::OMPD_cancellation_point,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
  /// Set cancel region for current cancellation point.
 
  /// \param CR Cancellation region.
 
  void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  ///
 
  static OMPCancellationPointDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         OpenMPDirectiveKind CancelRegion);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  ///
 
  static OMPCancellationPointDirective *CreateEmpty(const ASTContext &C,
 
                                                    EmptyShell);
 
 
 
  /// Get cancellation region for the current cancellation point.
 
  OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPCancellationPointDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp cancel' directive.
 
///
 
/// \code
 
/// #pragma omp cancel for
 
/// \endcode
 
///
 
/// In this example a cancel is created for innermost 'for' region.
 
class OMPCancelDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  OpenMPDirectiveKind CancelRegion = llvm::omp::OMPD_unknown;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPCancelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPCancelDirectiveClass, llvm::omp::OMPD_cancel,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPCancelDirective()
 
      : OMPExecutableDirective(OMPCancelDirectiveClass, llvm::omp::OMPD_cancel,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
  /// Set cancel region for current cancellation point.
 
  /// \param CR Cancellation region.
 
  void setCancelRegion(OpenMPDirectiveKind CR) { CancelRegion = CR; }
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  ///
 
  static OMPCancelDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, OpenMPDirectiveKind CancelRegion);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPCancelDirective *CreateEmpty(const ASTContext &C,
 
                                         unsigned NumClauses, EmptyShell);
 
 
 
  /// Get cancellation region for the current cancellation point.
 
  OpenMPDirectiveKind getCancelRegion() const { return CancelRegion; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPCancelDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp taskloop' directive.
 
///
 
/// \code
 
/// #pragma omp taskloop private(a,b) grainsize(val) num_tasks(num)
 
/// \endcode
 
/// In this example directive '#pragma omp taskloop' has clauses 'private'
 
/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
 
/// 'num_tasks' with expression 'num'.
 
///
 
class OMPTaskLoopDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if the construct has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                       unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop,
 
                         StartLoc, EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTaskLoopDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTaskLoopDirectiveClass, llvm::omp::OMPD_taskloop,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param HasCancel true if this directive has inner cancel directive.
 
  ///
 
  static OMPTaskLoopDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTaskLoopDirective *CreateEmpty(const ASTContext &C,
 
                                           unsigned NumClauses,
 
                                           unsigned CollapsedNum, EmptyShell);
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTaskLoopDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp taskloop simd' directive.
 
///
 
/// \code
 
/// #pragma omp taskloop simd private(a,b) grainsize(val) num_tasks(num)
 
/// \endcode
 
/// In this example directive '#pragma omp taskloop simd' has clauses 'private'
 
/// with the variables 'a' and 'b', 'grainsize' with expression 'val' and
 
/// 'num_tasks' with expression 'num'.
 
///
 
class OMPTaskLoopSimdDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                           unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTaskLoopSimdDirectiveClass,
 
                         llvm::omp::OMPD_taskloop_simd, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTaskLoopSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTaskLoopSimdDirectiveClass,
 
                         llvm::omp::OMPD_taskloop_simd, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTaskLoopSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
 
                                               unsigned NumClauses,
 
                                               unsigned CollapsedNum,
 
                                               EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTaskLoopSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp master taskloop' directive.
 
///
 
/// \code
 
/// #pragma omp master taskloop private(a,b) grainsize(val) num_tasks(num)
 
/// \endcode
 
/// In this example directive '#pragma omp master taskloop' has clauses
 
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
 
/// and 'num_tasks' with expression 'num'.
 
///
 
class OMPMasterTaskLoopDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if the construct has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPMasterTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                             unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPMasterTaskLoopDirectiveClass,
 
                         llvm::omp::OMPD_master_taskloop, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPMasterTaskLoopDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPMasterTaskLoopDirectiveClass,
 
                         llvm::omp::OMPD_master_taskloop, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param HasCancel true if this directive has inner cancel directive.
 
  ///
 
  static OMPMasterTaskLoopDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
 
                                                 unsigned NumClauses,
 
                                                 unsigned CollapsedNum,
 
                                                 EmptyShell);
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPMasterTaskLoopDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp masked taskloop' directive.
 
///
 
/// \code
 
/// #pragma omp masked taskloop private(a,b) grainsize(val) num_tasks(num)
 
/// \endcode
 
/// In this example directive '#pragma omp masked taskloop' has clauses
 
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
 
/// and 'num_tasks' with expression 'num'.
 
///
 
class OMPMaskedTaskLoopDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if the construct has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPMaskedTaskLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                             unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass,
 
                         llvm::omp::OMPD_masked_taskloop, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPMaskedTaskLoopDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPMaskedTaskLoopDirectiveClass,
 
                         llvm::omp::OMPD_masked_taskloop, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param HasCancel true if this directive has inner cancel directive.
 
  ///
 
  static OMPMaskedTaskLoopDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C,
 
                                                 unsigned NumClauses,
 
                                                 unsigned CollapsedNum,
 
                                                 EmptyShell);
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPMaskedTaskLoopDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp master taskloop simd' directive.
 
///
 
/// \code
 
/// #pragma omp master taskloop simd private(a,b) grainsize(val) num_tasks(num)
 
/// \endcode
 
/// In this example directive '#pragma omp master taskloop simd' has clauses
 
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
 
/// and 'num_tasks' with expression 'num'.
 
///
 
class OMPMasterTaskLoopSimdDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPMasterTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                                 unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPMasterTaskLoopSimdDirectiveClass,
 
                         llvm::omp::OMPD_master_taskloop_simd, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPMasterTaskLoopSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPMasterTaskLoopSimdDirectiveClass,
 
                         llvm::omp::OMPD_master_taskloop_simd, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \p Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPMasterTaskLoopSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \p NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPMasterTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
 
                                                     unsigned NumClauses,
 
                                                     unsigned CollapsedNum,
 
                                                     EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp masked taskloop simd' directive.
 
///
 
/// \code
 
/// #pragma omp masked taskloop simd private(a,b) grainsize(val) num_tasks(num)
 
/// \endcode
 
/// In this example directive '#pragma omp masked taskloop simd' has clauses
 
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
 
/// and 'num_tasks' with expression 'num'.
 
///
 
class OMPMaskedTaskLoopSimdDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPMaskedTaskLoopSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                                 unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass,
 
                         llvm::omp::OMPD_masked_taskloop_simd, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPMaskedTaskLoopSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPMaskedTaskLoopSimdDirectiveClass,
 
                         llvm::omp::OMPD_masked_taskloop_simd, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \p Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPMaskedTaskLoopSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \p NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPMaskedTaskLoopSimdDirective *CreateEmpty(const ASTContext &C,
 
                                                     unsigned NumClauses,
 
                                                     unsigned CollapsedNum,
 
                                                     EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPMaskedTaskLoopSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel master taskloop' directive.
 
///
 
/// \code
 
/// #pragma omp parallel master taskloop private(a,b) grainsize(val)
 
/// num_tasks(num)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel master taskloop' has clauses
 
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
 
/// and 'num_tasks' with expression 'num'.
 
///
 
class OMPParallelMasterTaskLoopDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if the construct has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPParallelMasterTaskLoopDirective(SourceLocation StartLoc,
 
                                     SourceLocation EndLoc,
 
                                     unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelMasterTaskLoopDirectiveClass,
 
                         llvm::omp::OMPD_parallel_master_taskloop, StartLoc,
 
                         EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPParallelMasterTaskLoopDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelMasterTaskLoopDirectiveClass,
 
                         llvm::omp::OMPD_parallel_master_taskloop,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param HasCancel true if this directive has inner cancel directive.
 
  ///
 
  static OMPParallelMasterTaskLoopDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelMasterTaskLoopDirective *CreateEmpty(const ASTContext &C,
 
                                                         unsigned NumClauses,
 
                                                         unsigned CollapsedNum,
 
                                                         EmptyShell);
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel masked taskloop' directive.
 
///
 
/// \code
 
/// #pragma omp parallel masked taskloop private(a,b) grainsize(val)
 
/// num_tasks(num)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel masked taskloop' has clauses
 
/// 'private' with the variables 'a' and 'b', 'grainsize' with expression 'val'
 
/// and 'num_tasks' with expression 'num'.
 
///
 
class OMPParallelMaskedTaskLoopDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if the construct has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPParallelMaskedTaskLoopDirective(SourceLocation StartLoc,
 
                                     SourceLocation EndLoc,
 
                                     unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass,
 
                         llvm::omp::OMPD_parallel_masked_taskloop, StartLoc,
 
                         EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPParallelMaskedTaskLoopDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelMaskedTaskLoopDirectiveClass,
 
                         llvm::omp::OMPD_parallel_masked_taskloop,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param HasCancel true if this directive has inner cancel directive.
 
  ///
 
  static OMPParallelMaskedTaskLoopDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs, bool HasCancel);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelMaskedTaskLoopDirective *CreateEmpty(const ASTContext &C,
 
                                                         unsigned NumClauses,
 
                                                         unsigned CollapsedNum,
 
                                                         EmptyShell);
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelMaskedTaskLoopDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel master taskloop simd' directive.
 
///
 
/// \code
 
/// #pragma omp parallel master taskloop simd private(a,b) grainsize(val)
 
/// num_tasks(num)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel master taskloop simd' has
 
/// clauses 'private' with the variables 'a' and 'b', 'grainsize' with
 
/// expression 'val' and 'num_tasks' with expression 'num'.
 
///
 
class OMPParallelMasterTaskLoopSimdDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPParallelMasterTaskLoopSimdDirective(SourceLocation StartLoc,
 
                                         SourceLocation EndLoc,
 
                                         unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelMasterTaskLoopSimdDirectiveClass,
 
                         llvm::omp::OMPD_parallel_master_taskloop_simd,
 
                         StartLoc, EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPParallelMasterTaskLoopSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelMasterTaskLoopSimdDirectiveClass,
 
                         llvm::omp::OMPD_parallel_master_taskloop_simd,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \p Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPParallelMasterTaskLoopSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelMasterTaskLoopSimdDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
 
              EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelMasterTaskLoopSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel masked taskloop simd' directive.
 
///
 
/// \code
 
/// #pragma omp parallel masked taskloop simd private(a,b) grainsize(val)
 
/// num_tasks(num)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel masked taskloop simd' has
 
/// clauses 'private' with the variables 'a' and 'b', 'grainsize' with
 
/// expression 'val' and 'num_tasks' with expression 'num'.
 
///
 
class OMPParallelMaskedTaskLoopSimdDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPParallelMaskedTaskLoopSimdDirective(SourceLocation StartLoc,
 
                                         SourceLocation EndLoc,
 
                                         unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass,
 
                         llvm::omp::OMPD_parallel_masked_taskloop_simd,
 
                         StartLoc, EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPParallelMaskedTaskLoopSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelMaskedTaskLoopSimdDirectiveClass,
 
                         llvm::omp::OMPD_parallel_masked_taskloop_simd,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \p Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPParallelMaskedTaskLoopSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelMaskedTaskLoopSimdDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
 
              EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelMaskedTaskLoopSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp distribute' directive.
 
///
 
/// \code
 
/// #pragma omp distribute private(a,b)
 
/// \endcode
 
/// In this example directive '#pragma omp distribute' has clauses 'private'
 
/// with the variables 'a' and 'b'
 
///
 
class OMPDistributeDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                         unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPDistributeDirectiveClass,
 
                         llvm::omp::OMPD_distribute, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPDistributeDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPDistributeDirectiveClass,
 
                         llvm::omp::OMPD_distribute, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPDistributeDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPDistributeDirective *CreateEmpty(const ASTContext &C,
 
                                             unsigned NumClauses,
 
                                             unsigned CollapsedNum, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPDistributeDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target update' directive.
 
///
 
/// \code
 
/// #pragma omp target update to(a) from(b) device(1)
 
/// \endcode
 
/// In this example directive '#pragma omp target update' has clause 'to' with
 
/// argument 'a', clause 'from' with argument 'b' and clause 'device' with
 
/// argument '1'.
 
///
 
class OMPTargetUpdateDirective : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  ///
 
  OMPTargetUpdateDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTargetUpdateDirectiveClass,
 
                               llvm::omp::OMPD_target_update, StartLoc,
 
                               EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTargetUpdateDirective()
 
      : OMPExecutableDirective(OMPTargetUpdateDirectiveClass,
 
                               llvm::omp::OMPD_target_update, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPTargetUpdateDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses The number of clauses.
 
  ///
 
  static OMPTargetUpdateDirective *CreateEmpty(const ASTContext &C,
 
                                               unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetUpdateDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp distribute parallel for' composite
 
///  directive.
 
///
 
/// \code
 
/// #pragma omp distribute parallel for private(a,b)
 
/// \endcode
 
/// In this example directive '#pragma omp distribute parallel for' has clause
 
/// 'private' with the variables 'a' and 'b'
 
///
 
class OMPDistributeParallelForDirective : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if the construct has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPDistributeParallelForDirective(SourceLocation StartLoc,
 
                                    SourceLocation EndLoc,
 
                                    unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPDistributeParallelForDirectiveClass,
 
                         llvm::omp::OMPD_distribute_parallel_for, StartLoc,
 
                         EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPDistributeParallelForDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPDistributeParallelForDirectiveClass,
 
                         llvm::omp::OMPD_distribute_parallel_for,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) {
 
    Data->getChildren()[numLoopChildren(
 
        getLoopsNumber(), llvm::omp::OMPD_distribute_parallel_for)] = E;
 
  }
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  /// \param HasCancel true if this directive has inner cancel directive.
 
  ///
 
  static OMPDistributeParallelForDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
 
         bool HasCancel);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPDistributeParallelForDirective *CreateEmpty(const ASTContext &C,
 
                                                        unsigned NumClauses,
 
                                                        unsigned CollapsedNum,
 
                                                        EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
 
        getLoopsNumber(), llvm::omp::OMPD_distribute_parallel_for)]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPDistributeParallelForDirective *>(this)
 
        ->getTaskReductionRefExpr();
 
  }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPDistributeParallelForDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp distribute parallel for simd' composite
 
/// directive.
 
///
 
/// \code
 
/// #pragma omp distribute parallel for simd private(x)
 
/// \endcode
 
/// In this example directive '#pragma omp distribute parallel for simd' has
 
/// clause 'private' with the variables 'x'
 
///
 
class OMPDistributeParallelForSimdDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPDistributeParallelForSimdDirective(SourceLocation StartLoc,
 
                                        SourceLocation EndLoc,
 
                                        unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPDistributeParallelForSimdDirectiveClass,
 
                         llvm::omp::OMPD_distribute_parallel_for_simd, StartLoc,
 
                         EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPDistributeParallelForSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPDistributeParallelForSimdDirectiveClass,
 
                         llvm::omp::OMPD_distribute_parallel_for_simd,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPDistributeParallelForSimdDirective *Create(
 
      const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
      unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
      Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPDistributeParallelForSimdDirective *CreateEmpty(
 
      const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
 
      EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp distribute simd' composite directive.
 
///
 
/// \code
 
/// #pragma omp distribute simd private(x)
 
/// \endcode
 
/// In this example directive '#pragma omp distribute simd' has clause
 
/// 'private' with the variables 'x'
 
///
 
class OMPDistributeSimdDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPDistributeSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                             unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPDistributeSimdDirectiveClass,
 
                         llvm::omp::OMPD_distribute_simd, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPDistributeSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPDistributeSimdDirectiveClass,
 
                         llvm::omp::OMPD_distribute_simd, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPDistributeSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPDistributeSimdDirective *CreateEmpty(const ASTContext &C,
 
                                                 unsigned NumClauses,
 
                                                 unsigned CollapsedNum,
 
                                                 EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPDistributeSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target parallel for simd' directive.
 
///
 
/// \code
 
/// #pragma omp target parallel for simd private(a) map(b) safelen(c)
 
/// \endcode
 
/// In this example directive '#pragma omp target parallel for simd' has clauses
 
/// 'private' with the variable 'a', 'map' with the variable 'b' and 'safelen'
 
/// with the variable 'c'.
 
///
 
class OMPTargetParallelForSimdDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTargetParallelForSimdDirective(SourceLocation StartLoc,
 
                                    SourceLocation EndLoc,
 
                                    unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetParallelForSimdDirectiveClass,
 
                         llvm::omp::OMPD_target_parallel_for_simd, StartLoc,
 
                         EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTargetParallelForSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetParallelForSimdDirectiveClass,
 
                         llvm::omp::OMPD_target_parallel_for_simd,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTargetParallelForSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetParallelForSimdDirective *CreateEmpty(const ASTContext &C,
 
                                                        unsigned NumClauses,
 
                                                        unsigned CollapsedNum,
 
                                                        EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target simd' directive.
 
///
 
/// \code
 
/// #pragma omp target simd private(a) map(b) safelen(c)
 
/// \endcode
 
/// In this example directive '#pragma omp target simd' has clauses 'private'
 
/// with the variable 'a', 'map' with the variable 'b' and 'safelen' with
 
/// the variable 'c'.
 
///
 
class OMPTargetSimdDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTargetSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                         unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetSimdDirectiveClass,
 
                         llvm::omp::OMPD_target_simd, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTargetSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetSimdDirectiveClass,
 
                         llvm::omp::OMPD_target_simd, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTargetSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetSimdDirective *CreateEmpty(const ASTContext &C,
 
                                             unsigned NumClauses,
 
                                             unsigned CollapsedNum,
 
                                             EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp teams distribute' directive.
 
///
 
/// \code
 
/// #pragma omp teams distribute private(a,b)
 
/// \endcode
 
/// In this example directive '#pragma omp teams distribute' has clauses
 
/// 'private' with the variables 'a' and 'b'
 
///
 
class OMPTeamsDistributeDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTeamsDistributeDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                              unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTeamsDistributeDirectiveClass,
 
                         llvm::omp::OMPD_teams_distribute, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTeamsDistributeDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTeamsDistributeDirectiveClass,
 
                         llvm::omp::OMPD_teams_distribute, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTeamsDistributeDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTeamsDistributeDirective *CreateEmpty(const ASTContext &C,
 
                                                  unsigned NumClauses,
 
                                                  unsigned CollapsedNum,
 
                                                  EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTeamsDistributeDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp teams distribute simd'
 
/// combined directive.
 
///
 
/// \code
 
/// #pragma omp teams distribute simd private(a,b)
 
/// \endcode
 
/// In this example directive '#pragma omp teams distribute simd'
 
/// has clause 'private' with the variables 'a' and 'b'
 
///
 
class OMPTeamsDistributeSimdDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTeamsDistributeSimdDirective(SourceLocation StartLoc,
 
                                  SourceLocation EndLoc, unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTeamsDistributeSimdDirectiveClass,
 
                         llvm::omp::OMPD_teams_distribute_simd, StartLoc,
 
                         EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTeamsDistributeSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTeamsDistributeSimdDirectiveClass,
 
                         llvm::omp::OMPD_teams_distribute_simd,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTeamsDistributeSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTeamsDistributeSimdDirective *CreateEmpty(const ASTContext &C,
 
                                                      unsigned NumClauses,
 
                                                      unsigned CollapsedNum,
 
                                                      EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp teams distribute parallel for simd' composite
 
/// directive.
 
///
 
/// \code
 
/// #pragma omp teams distribute parallel for simd private(x)
 
/// \endcode
 
/// In this example directive '#pragma omp teams distribute parallel for simd'
 
/// has clause 'private' with the variables 'x'
 
///
 
class OMPTeamsDistributeParallelForSimdDirective final
 
    : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
 
                                             SourceLocation EndLoc,
 
                                             unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTeamsDistributeParallelForSimdDirectiveClass,
 
                         llvm::omp::OMPD_teams_distribute_parallel_for_simd,
 
                         StartLoc, EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTeamsDistributeParallelForSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTeamsDistributeParallelForSimdDirectiveClass,
 
                         llvm::omp::OMPD_teams_distribute_parallel_for_simd,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTeamsDistributeParallelForSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTeamsDistributeParallelForSimdDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
 
              EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTeamsDistributeParallelForSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp teams distribute parallel for' composite
 
/// directive.
 
///
 
/// \code
 
/// #pragma omp teams distribute parallel for private(x)
 
/// \endcode
 
/// In this example directive '#pragma omp teams distribute parallel for'
 
/// has clause 'private' with the variables 'x'
 
///
 
class OMPTeamsDistributeParallelForDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if the construct has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTeamsDistributeParallelForDirective(SourceLocation StartLoc,
 
                                         SourceLocation EndLoc,
 
                                         unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTeamsDistributeParallelForDirectiveClass,
 
                         llvm::omp::OMPD_teams_distribute_parallel_for,
 
                         StartLoc, EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTeamsDistributeParallelForDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTeamsDistributeParallelForDirectiveClass,
 
                         llvm::omp::OMPD_teams_distribute_parallel_for,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) {
 
    Data->getChildren()[numLoopChildren(
 
        getLoopsNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)] = E;
 
  }
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  /// \param HasCancel true if this directive has inner cancel directive.
 
  ///
 
  static OMPTeamsDistributeParallelForDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
 
         bool HasCancel);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTeamsDistributeParallelForDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
 
              EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
 
        getLoopsNumber(), llvm::omp::OMPD_teams_distribute_parallel_for)]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPTeamsDistributeParallelForDirective *>(this)
 
        ->getTaskReductionRefExpr();
 
  }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target teams' directive.
 
///
 
/// \code
 
/// #pragma omp target teams if(a>0)
 
/// \endcode
 
/// In this example directive '#pragma omp target teams' has clause 'if' with
 
/// condition 'a>0'.
 
///
 
class OMPTargetTeamsDirective final : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPTargetTeamsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPTargetTeamsDirectiveClass,
 
                               llvm::omp::OMPD_target_teams, StartLoc, EndLoc) {
 
  }
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPTargetTeamsDirective()
 
      : OMPExecutableDirective(OMPTargetTeamsDirectiveClass,
 
                               llvm::omp::OMPD_target_teams, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPTargetTeamsDirective *Create(const ASTContext &C,
 
                                         SourceLocation StartLoc,
 
                                         SourceLocation EndLoc,
 
                                         ArrayRef<OMPClause *> Clauses,
 
                                         Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetTeamsDirective *CreateEmpty(const ASTContext &C,
 
                                              unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetTeamsDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target teams distribute' combined directive.
 
///
 
/// \code
 
/// #pragma omp target teams distribute private(x)
 
/// \endcode
 
/// In this example directive '#pragma omp target teams distribute' has clause
 
/// 'private' with the variables 'x'
 
///
 
class OMPTargetTeamsDistributeDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTargetTeamsDistributeDirective(SourceLocation StartLoc,
 
                                    SourceLocation EndLoc,
 
                                    unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetTeamsDistributeDirectiveClass,
 
                         llvm::omp::OMPD_target_teams_distribute, StartLoc,
 
                         EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTargetTeamsDistributeDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetTeamsDistributeDirectiveClass,
 
                         llvm::omp::OMPD_target_teams_distribute,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTargetTeamsDistributeDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetTeamsDistributeDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
 
              EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target teams distribute parallel for' combined
 
/// directive.
 
///
 
/// \code
 
/// #pragma omp target teams distribute parallel for private(x)
 
/// \endcode
 
/// In this example directive '#pragma omp target teams distribute parallel
 
/// for' has clause 'private' with the variables 'x'
 
///
 
class OMPTargetTeamsDistributeParallelForDirective final
 
    : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// true if the construct has inner cancel directive.
 
  bool HasCancel = false;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTargetTeamsDistributeParallelForDirective(SourceLocation StartLoc,
 
                                               SourceLocation EndLoc,
 
                                               unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetTeamsDistributeParallelForDirectiveClass,
 
                         llvm::omp::OMPD_target_teams_distribute_parallel_for,
 
                         StartLoc, EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTargetTeamsDistributeParallelForDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetTeamsDistributeParallelForDirectiveClass,
 
                         llvm::omp::OMPD_target_teams_distribute_parallel_for,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
  /// Sets special task reduction descriptor.
 
  void setTaskReductionRefExpr(Expr *E) {
 
    Data->getChildren()[numLoopChildren(
 
        getLoopsNumber(),
 
        llvm::omp::OMPD_target_teams_distribute_parallel_for)] = E;
 
  }
 
 
 
  /// Set cancel state.
 
  void setHasCancel(bool Has) { HasCancel = Has; }
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  /// \param TaskRedRef Task reduction special reference expression to handle
 
  /// taskgroup descriptor.
 
  /// \param HasCancel true if this directive has inner cancel directive.
 
  ///
 
  static OMPTargetTeamsDistributeParallelForDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
 
         bool HasCancel);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetTeamsDistributeParallelForDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
 
              EmptyShell);
 
 
 
  /// Returns special task reduction reference expression.
 
  Expr *getTaskReductionRefExpr() {
 
    return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
 
        getLoopsNumber(),
 
        llvm::omp::OMPD_target_teams_distribute_parallel_for)]);
 
  }
 
  const Expr *getTaskReductionRefExpr() const {
 
    return const_cast<OMPTargetTeamsDistributeParallelForDirective *>(this)
 
        ->getTaskReductionRefExpr();
 
  }
 
 
 
  /// Return true if current directive has inner cancel directive.
 
  bool hasCancel() const { return HasCancel; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() ==
 
           OMPTargetTeamsDistributeParallelForDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target teams distribute parallel for simd'
 
/// combined directive.
 
///
 
/// \code
 
/// #pragma omp target teams distribute parallel for simd private(x)
 
/// \endcode
 
/// In this example directive '#pragma omp target teams distribute parallel
 
/// for simd' has clause 'private' with the variables 'x'
 
///
 
class OMPTargetTeamsDistributeParallelForSimdDirective final
 
    : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTargetTeamsDistributeParallelForSimdDirective(SourceLocation StartLoc,
 
                                                   SourceLocation EndLoc,
 
                                                   unsigned CollapsedNum)
 
      : OMPLoopDirective(
 
            OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
 
            llvm::omp::OMPD_target_teams_distribute_parallel_for_simd, StartLoc,
 
            EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTargetTeamsDistributeParallelForSimdDirective(
 
      unsigned CollapsedNum)
 
      : OMPLoopDirective(
 
            OMPTargetTeamsDistributeParallelForSimdDirectiveClass,
 
            llvm::omp::OMPD_target_teams_distribute_parallel_for_simd,
 
            SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTargetTeamsDistributeParallelForSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetTeamsDistributeParallelForSimdDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
 
              EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() ==
 
           OMPTargetTeamsDistributeParallelForSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target teams distribute simd' combined
 
/// directive.
 
///
 
/// \code
 
/// #pragma omp target teams distribute simd private(x)
 
/// \endcode
 
/// In this example directive '#pragma omp target teams distribute simd'
 
/// has clause 'private' with the variables 'x'
 
///
 
class OMPTargetTeamsDistributeSimdDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTargetTeamsDistributeSimdDirective(SourceLocation StartLoc,
 
                                        SourceLocation EndLoc,
 
                                        unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetTeamsDistributeSimdDirectiveClass,
 
                         llvm::omp::OMPD_target_teams_distribute_simd, StartLoc,
 
                         EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTargetTeamsDistributeSimdDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetTeamsDistributeSimdDirectiveClass,
 
                         llvm::omp::OMPD_target_teams_distribute_simd,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTargetTeamsDistributeSimdDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetTeamsDistributeSimdDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
 
              EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass;
 
  }
 
};
 
 
 
/// This represents the '#pragma omp tile' loop transformation directive.
 
class OMPTileDirective final : public OMPLoopTransformationDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Default list of offsets.
 
  enum {
 
    PreInitsOffset = 0,
 
    TransformedStmtOffset,
 
  };
 
 
 
  explicit OMPTileDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                            unsigned NumLoops)
 
      : OMPLoopTransformationDirective(OMPTileDirectiveClass,
 
                                       llvm::omp::OMPD_tile, StartLoc, EndLoc,
 
                                       NumLoops) {
 
    setNumGeneratedLoops(3 * NumLoops);
 
  }
 
 
 
  void setPreInits(Stmt *PreInits) {
 
    Data->getChildren()[PreInitsOffset] = PreInits;
 
  }
 
 
 
  void setTransformedStmt(Stmt *S) {
 
    Data->getChildren()[TransformedStmtOffset] = S;
 
  }
 
 
 
public:
 
  /// Create a new AST node representation for '#pragma omp tile'.
 
  ///
 
  /// \param C         Context of the AST.
 
  /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
 
  /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
 
  /// \param Clauses   The directive's clauses.
 
  /// \param NumLoops  Number of associated loops (number of items in the
 
  ///                  'sizes' clause).
 
  /// \param AssociatedStmt The outermost associated loop.
 
  /// \param TransformedStmt The loop nest after tiling, or nullptr in
 
  ///                        dependent contexts.
 
  /// \param PreInits Helper preinits statements for the loop nest.
 
  static OMPTileDirective *Create(const ASTContext &C, SourceLocation StartLoc,
 
                                  SourceLocation EndLoc,
 
                                  ArrayRef<OMPClause *> Clauses,
 
                                  unsigned NumLoops, Stmt *AssociatedStmt,
 
                                  Stmt *TransformedStmt, Stmt *PreInits);
 
 
 
  /// Build an empty '#pragma omp tile' AST node for deserialization.
 
  ///
 
  /// \param C          Context of the AST.
 
  /// \param NumClauses Number of clauses to allocate.
 
  /// \param NumLoops   Number of associated loops to allocate.
 
  static OMPTileDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
 
                                       unsigned NumLoops);
 
 
 
  /// Gets/sets the associated loops after tiling.
 
  ///
 
  /// This is in de-sugared format stored as a CompoundStmt.
 
  ///
 
  /// \code
 
  ///   for (...)
 
  ///     ...
 
  /// \endcode
 
  ///
 
  /// Note that if the generated loops a become associated loops of another
 
  /// directive, they may need to be hoisted before them.
 
  Stmt *getTransformedStmt() const {
 
    return Data->getChildren()[TransformedStmtOffset];
 
  }
 
 
 
  /// Return preinits statement.
 
  Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTileDirectiveClass;
 
  }
 
};
 
 
 
/// This represents the '#pragma omp unroll' loop transformation directive.
 
///
 
/// \code
 
/// #pragma omp unroll
 
/// for (int i = 0; i < 64; ++i)
 
/// \endcode
 
class OMPUnrollDirective final : public OMPLoopTransformationDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Default list of offsets.
 
  enum {
 
    PreInitsOffset = 0,
 
    TransformedStmtOffset,
 
  };
 
 
 
  explicit OMPUnrollDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPLoopTransformationDirective(OMPUnrollDirectiveClass,
 
                                       llvm::omp::OMPD_unroll, StartLoc, EndLoc,
 
                                       1) {}
 
 
 
  /// Set the pre-init statements.
 
  void setPreInits(Stmt *PreInits) {
 
    Data->getChildren()[PreInitsOffset] = PreInits;
 
  }
 
 
 
  /// Set the de-sugared statement.
 
  void setTransformedStmt(Stmt *S) {
 
    Data->getChildren()[TransformedStmtOffset] = S;
 
  }
 
 
 
public:
 
  /// Create a new AST node representation for '#pragma omp unroll'.
 
  ///
 
  /// \param C         Context of the AST.
 
  /// \param StartLoc  Location of the introducer (e.g. the 'omp' token).
 
  /// \param EndLoc    Location of the directive's end (e.g. the tok::eod).
 
  /// \param Clauses   The directive's clauses.
 
  /// \param AssociatedStmt The outermost associated loop.
 
  /// \param TransformedStmt The loop nest after tiling, or nullptr in
 
  ///                        dependent contexts.
 
  /// \param PreInits   Helper preinits statements for the loop nest.
 
  static OMPUnrollDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
 
         unsigned NumGeneratedLoops, Stmt *TransformedStmt, Stmt *PreInits);
 
 
 
  /// Build an empty '#pragma omp unroll' AST node for deserialization.
 
  ///
 
  /// \param C          Context of the AST.
 
  /// \param NumClauses Number of clauses to allocate.
 
  static OMPUnrollDirective *CreateEmpty(const ASTContext &C,
 
                                         unsigned NumClauses);
 
 
 
  /// Get the de-sugared associated loops after unrolling.
 
  ///
 
  /// This is only used if the unrolled loop becomes an associated loop of
 
  /// another directive, otherwise the loop is emitted directly using loop
 
  /// transformation metadata. When the unrolled loop cannot be used by another
 
  /// directive (e.g. because of the full clause), the transformed stmt can also
 
  /// be nullptr.
 
  Stmt *getTransformedStmt() const {
 
    return Data->getChildren()[TransformedStmtOffset];
 
  }
 
 
 
  /// Return the pre-init statements.
 
  Stmt *getPreInits() const { return Data->getChildren()[PreInitsOffset]; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPUnrollDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp scan' directive.
 
///
 
/// \code
 
/// #pragma omp scan inclusive(a)
 
/// \endcode
 
/// In this example directive '#pragma omp scan' has clause 'inclusive' with
 
/// list item 'a'.
 
class OMPScanDirective final : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPScanDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPScanDirectiveClass, llvm::omp::OMPD_scan,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPScanDirective()
 
      : OMPExecutableDirective(OMPScanDirectiveClass, llvm::omp::OMPD_scan,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses (only single OMPFlushClause clause is
 
  /// allowed).
 
  ///
 
  static OMPScanDirective *Create(const ASTContext &C, SourceLocation StartLoc,
 
                                  SourceLocation EndLoc,
 
                                  ArrayRef<OMPClause *> Clauses);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPScanDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
 
                                       EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPScanDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp interop' directive.
 
///
 
/// \code
 
/// #pragma omp interop init(target:obj) device(x) depend(inout:y) nowait
 
/// \endcode
 
/// In this example directive '#pragma omp interop' has
 
/// clauses 'init', 'device', 'depend' and 'nowait'.
 
///
 
class OMPInteropDirective final : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPInteropDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPInteropDirectiveClass,
 
                               llvm::omp::OMPD_interop, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPInteropDirective()
 
      : OMPExecutableDirective(OMPInteropDirectiveClass,
 
                               llvm::omp::OMPD_interop, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses The directive's clauses.
 
  ///
 
  static OMPInteropDirective *Create(const ASTContext &C,
 
                                     SourceLocation StartLoc,
 
                                     SourceLocation EndLoc,
 
                                     ArrayRef<OMPClause *> Clauses);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  ///
 
  static OMPInteropDirective *CreateEmpty(const ASTContext &C,
 
                                          unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPInteropDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp dispatch' directive.
 
///
 
/// \code
 
/// #pragma omp dispatch device(dnum)
 
/// \endcode
 
/// This example shows a directive '#pragma omp dispatch' with a
 
/// device clause with variable 'dnum'.
 
///
 
class OMPDispatchDirective final : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// The location of the target-call.
 
  SourceLocation TargetCallLoc;
 
 
 
  /// Set the location of the target-call.
 
  void setTargetCallLoc(SourceLocation Loc) { TargetCallLoc = Loc; }
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPDispatchDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPDispatchDirectiveClass,
 
                               llvm::omp::OMPD_dispatch, StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPDispatchDirective()
 
      : OMPExecutableDirective(OMPDispatchDirectiveClass,
 
                               llvm::omp::OMPD_dispatch, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive with a list of \a Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param TargetCallLoc Location of the target-call.
 
  ///
 
  static OMPDispatchDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
 
         SourceLocation TargetCallLoc);
 
 
 
  /// Creates an empty directive with the place for \a NumClauses
 
  /// clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPDispatchDirective *CreateEmpty(const ASTContext &C,
 
                                           unsigned NumClauses, EmptyShell);
 
 
 
  /// Return location of target-call.
 
  SourceLocation getTargetCallLoc() const { return TargetCallLoc; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPDispatchDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp masked' directive.
 
/// \code
 
/// #pragma omp masked filter(tid)
 
/// \endcode
 
/// This example shows a directive '#pragma omp masked' with a filter clause
 
/// with variable 'tid'.
 
///
 
class OMPMaskedDirective final : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
 
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPMaskedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
 
                               StartLoc, EndLoc) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPMaskedDirective()
 
      : OMPExecutableDirective(OMPMaskedDirectiveClass, llvm::omp::OMPD_masked,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  /// Creates directive.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  ///
 
  static OMPMaskedDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  ///
 
  static OMPMaskedDirective *CreateEmpty(const ASTContext &C,
 
                                         unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPMaskedDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp metadirective' directive.
 
///
 
/// \code
 
/// #pragma omp metadirective when(user={condition(N>10)}: parallel for)
 
/// \endcode
 
/// In this example directive '#pragma omp metadirective' has clauses 'when'
 
/// with a dynamic user condition to check if a variable 'N > 10'
 
///
 
class OMPMetaDirective final : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  Stmt *IfStmt;
 
 
 
  OMPMetaDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPMetaDirectiveClass,
 
                               llvm::omp::OMPD_metadirective, StartLoc,
 
                               EndLoc) {}
 
  explicit OMPMetaDirective()
 
      : OMPExecutableDirective(OMPMetaDirectiveClass,
 
                               llvm::omp::OMPD_metadirective, SourceLocation(),
 
                               SourceLocation()) {}
 
 
 
  void setIfStmt(Stmt *S) { IfStmt = S; }
 
 
 
public:
 
  static OMPMetaDirective *Create(const ASTContext &C, SourceLocation StartLoc,
 
                                  SourceLocation EndLoc,
 
                                  ArrayRef<OMPClause *> Clauses,
 
                                  Stmt *AssociatedStmt, Stmt *IfStmt);
 
  static OMPMetaDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
 
                                       EmptyShell);
 
  Stmt *getIfStmt() const { return IfStmt; }
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPMetaDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp loop' directive.
 
///
 
/// \code
 
/// #pragma omp loop private(a,b) binding(parallel) order(concurrent)
 
/// \endcode
 
/// In this example directive '#pragma omp loop' has
 
/// clauses 'private' with the variables 'a' and 'b', 'binding' with
 
/// modifier 'parallel' and 'order(concurrent).
 
///
 
class OMPGenericLoopDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                          unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPGenericLoopDirectiveClass, llvm::omp::OMPD_loop,
 
                         StartLoc, EndLoc, CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPGenericLoopDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPGenericLoopDirectiveClass, llvm::omp::OMPD_loop,
 
                         SourceLocation(), SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \p Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPGenericLoopDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with a place for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param NumClauses Number of clauses.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  static OMPGenericLoopDirective *CreateEmpty(const ASTContext &C,
 
                                              unsigned NumClauses,
 
                                              unsigned CollapsedNum,
 
                                              EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPGenericLoopDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp teams loop' directive.
 
///
 
/// \code
 
/// #pragma omp teams loop private(a,b) order(concurrent)
 
/// \endcode
 
/// In this example directive '#pragma omp teams loop' has
 
/// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
 
///
 
class OMPTeamsGenericLoopDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTeamsGenericLoopDirective(SourceLocation StartLoc, SourceLocation EndLoc,
 
                               unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass,
 
                         llvm::omp::OMPD_teams_loop, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTeamsGenericLoopDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTeamsGenericLoopDirectiveClass,
 
                         llvm::omp::OMPD_teams_loop, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \p Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTeamsGenericLoopDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C,
 
                                                   unsigned NumClauses,
 
                                                   unsigned CollapsedNum,
 
                                                   EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTeamsGenericLoopDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target teams loop' directive.
 
///
 
/// \code
 
/// #pragma omp target teams loop private(a,b) order(concurrent)
 
/// \endcode
 
/// In this example directive '#pragma omp target teams loop' has
 
/// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
 
///
 
class OMPTargetTeamsGenericLoopDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTargetTeamsGenericLoopDirective(SourceLocation StartLoc,
 
                                     SourceLocation EndLoc,
 
                                     unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass,
 
                         llvm::omp::OMPD_target_teams_loop, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTargetTeamsGenericLoopDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetTeamsGenericLoopDirectiveClass,
 
                         llvm::omp::OMPD_target_teams_loop, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \p Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTargetTeamsGenericLoopDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetTeamsGenericLoopDirective *CreateEmpty(const ASTContext &C,
 
                                                         unsigned NumClauses,
 
                                                         unsigned CollapsedNum,
 
                                                         EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetTeamsGenericLoopDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp parallel loop' directive.
 
///
 
/// \code
 
/// #pragma omp parallel loop private(a,b) order(concurrent)
 
/// \endcode
 
/// In this example directive '#pragma omp parallel loop' has
 
/// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
 
///
 
class OMPParallelGenericLoopDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPParallelGenericLoopDirective(SourceLocation StartLoc,
 
                                  SourceLocation EndLoc, unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelGenericLoopDirectiveClass,
 
                         llvm::omp::OMPD_parallel_loop, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPParallelGenericLoopDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPParallelGenericLoopDirectiveClass,
 
                         llvm::omp::OMPD_parallel_loop, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \p Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPParallelGenericLoopDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPParallelGenericLoopDirective *CreateEmpty(const ASTContext &C,
 
                                                      unsigned NumClauses,
 
                                                      unsigned CollapsedNum,
 
                                                      EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPParallelGenericLoopDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp target parallel loop' directive.
 
///
 
/// \code
 
/// #pragma omp target parallel loop private(a,b) order(concurrent)
 
/// \endcode
 
/// In this example directive '#pragma omp target parallel loop' has
 
/// clauses 'private' with the variables 'a' and 'b', and order(concurrent).
 
///
 
class OMPTargetParallelGenericLoopDirective final : public OMPLoopDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  OMPTargetParallelGenericLoopDirective(SourceLocation StartLoc,
 
                                        SourceLocation EndLoc,
 
                                        unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass,
 
                         llvm::omp::OMPD_target_parallel_loop, StartLoc, EndLoc,
 
                         CollapsedNum) {}
 
 
 
  /// Build an empty directive.
 
  ///
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  ///
 
  explicit OMPTargetParallelGenericLoopDirective(unsigned CollapsedNum)
 
      : OMPLoopDirective(OMPTargetParallelGenericLoopDirectiveClass,
 
                         llvm::omp::OMPD_target_parallel_loop, SourceLocation(),
 
                         SourceLocation(), CollapsedNum) {}
 
 
 
public:
 
  /// Creates directive with a list of \p Clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param CollapsedNum Number of collapsed loops.
 
  /// \param Clauses List of clauses.
 
  /// \param AssociatedStmt Statement, associated with the directive.
 
  /// \param Exprs Helper expressions for CodeGen.
 
  ///
 
  static OMPTargetParallelGenericLoopDirective *
 
  Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
 
         unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
 
         Stmt *AssociatedStmt, const HelperExprs &Exprs);
 
 
 
  /// Creates an empty directive with the place
 
  /// for \a NumClauses clauses.
 
  ///
 
  /// \param C AST context.
 
  /// \param CollapsedNum Number of collapsed nested loops.
 
  /// \param NumClauses Number of clauses.
 
  ///
 
  static OMPTargetParallelGenericLoopDirective *
 
  CreateEmpty(const ASTContext &C, unsigned NumClauses, unsigned CollapsedNum,
 
              EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPTargetParallelGenericLoopDirectiveClass;
 
  }
 
};
 
 
 
/// This represents '#pragma omp error' directive.
 
///
 
/// \code
 
/// #pragma omp error
 
/// \endcode
 
class OMPErrorDirective final : public OMPExecutableDirective {
 
  friend class ASTStmtReader;
 
  friend class OMPExecutableDirective;
 
  /// Build directive with the given start and end location.
 
  ///
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending location of the directive.
 
  ///
 
  OMPErrorDirective(SourceLocation StartLoc, SourceLocation EndLoc)
 
      : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error,
 
                               StartLoc, EndLoc) {}
 
  /// Build an empty directive.
 
  ///
 
  explicit OMPErrorDirective()
 
      : OMPExecutableDirective(OMPErrorDirectiveClass, llvm::omp::OMPD_error,
 
                               SourceLocation(), SourceLocation()) {}
 
 
 
public:
 
  ///
 
  /// \param C AST context.
 
  /// \param StartLoc Starting location of the directive kind.
 
  /// \param EndLoc Ending Location of the directive.
 
  /// \param Clauses List of clauses.
 
  ///
 
  static OMPErrorDirective *Create(const ASTContext &C, SourceLocation StartLoc,
 
                                   SourceLocation EndLoc,
 
                                   ArrayRef<OMPClause *> Clauses);
 
 
 
  /// Creates an empty directive.
 
  ///
 
  /// \param C AST context.
 
  ///
 
  static OMPErrorDirective *CreateEmpty(const ASTContext &C,
 
                                        unsigned NumClauses, EmptyShell);
 
 
 
  static bool classof(const Stmt *T) {
 
    return T->getStmtClass() == OMPErrorDirectiveClass;
 
  }
 
};
 
} // end namespace clang
 
 
 
#endif