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