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 llvm::None;
281 return Data->getClauses();
282 }
283
284protected:
285 /// Data, associated with the directive.
286 OMPChildren *Data = nullptr;
287
288 /// Build instance of directive of class \a K.
289 ///
290 /// \param SC Statement class.
291 /// \param K Kind of OpenMP directive.
292 /// \param StartLoc Starting location of the directive (directive keyword).
293 /// \param EndLoc Ending location of the directive.
294 ///
295 OMPExecutableDirective(StmtClass SC, OpenMPDirectiveKind K,
296 SourceLocation StartLoc, SourceLocation EndLoc)
297 : Stmt(SC), Kind(K), StartLoc(std::move(StartLoc)),
298 EndLoc(std::move(EndLoc)) {}
299
300 template <typename T, typename... Params>
301 static T *createDirective(const ASTContext &C, ArrayRef<OMPClause *> Clauses,
302 Stmt *AssociatedStmt, unsigned NumChildren,
303 Params &&... P) {
304 void *Mem =
305 C.Allocate(sizeof(T) + OMPChildren::size(Clauses.size(), AssociatedStmt,
306 NumChildren),
307 alignof(T));
308
309 auto *Data = OMPChildren::Create(reinterpret_cast<T *>(Mem) + 1, Clauses,
310 AssociatedStmt, NumChildren);
311 auto *Inst = new (Mem) T(std::forward<Params>(P)...);
312 Inst->Data = Data;
313 return Inst;
314 }
315
316 template <typename T, typename... Params>
317 static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
318 bool HasAssociatedStmt, unsigned NumChildren,
319 Params &&... P) {
320 void *Mem =
321 C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
322 NumChildren),
323 alignof(T));
324 auto *Data =
325 OMPChildren::CreateEmpty(reinterpret_cast<T *>(Mem) + 1, NumClauses,
326 HasAssociatedStmt, NumChildren);
327 auto *Inst = new (Mem) T(std::forward<Params>(P)...);
328 Inst->Data = Data;
329 return Inst;
330 }
331
332 template <typename T>
333 static T *createEmptyDirective(const ASTContext &C, unsigned NumClauses,
334 bool HasAssociatedStmt = false,
335 unsigned NumChildren = 0) {
336 void *Mem =
337 C.Allocate(sizeof(T) + OMPChildren::size(NumClauses, HasAssociatedStmt,
338 NumChildren),
339 alignof(T));
340 auto *Data =
341 OMPChildren::CreateEmpty(reinterpret_cast<T *>(Mem) + 1, NumClauses,
342 HasAssociatedStmt, NumChildren);
343 auto *Inst = new (Mem) T;
344 Inst->Data = Data;
345 return Inst;
346 }
347
348public:
349 /// Iterates over expressions/statements used in the construct.
350 class used_clauses_child_iterator
351 : public llvm::iterator_adaptor_base<
352 used_clauses_child_iterator, ArrayRef<OMPClause *>::iterator,
353 std::forward_iterator_tag, Stmt *, ptrdiff_t, Stmt *, Stmt *> {
354 ArrayRef<OMPClause *>::iterator End;
355 OMPClause::child_iterator ChildI, ChildEnd;
356
357 void MoveToNext() {
358 if (ChildI != ChildEnd)
359 return;
360 while (this->I != End) {
361 ++this->I;
362 if (this->I != End) {
363 ChildI = (*this->I)->used_children().begin();
364 ChildEnd = (*this->I)->used_children().end();
365 if (ChildI != ChildEnd)
366 return;
367 }
368 }
369 }
370
371 public:
372 explicit used_clauses_child_iterator(ArrayRef<OMPClause *> Clauses)
373 : used_clauses_child_iterator::iterator_adaptor_base(Clauses.begin()),
374 End(Clauses.end()) {
375 if (this->I != End) {
376 ChildI = (*this->I)->used_children().begin();
377 ChildEnd = (*this->I)->used_children().end();
378 MoveToNext();
379 }
380 }
381 Stmt *operator*() const { return *ChildI; }
382 Stmt *operator->() const { return **this; }
383
384 used_clauses_child_iterator &operator++() {
385 ++ChildI;
386 if (ChildI != ChildEnd)
387 return *this;
388 if (this->I != End) {
389 ++this->I;
390 if (this->I != End) {
391 ChildI = (*this->I)->used_children().begin();
392 ChildEnd = (*this->I)->used_children().end();
393 }
394 }
395 MoveToNext();
396 return *this;
397 }
398 };
399
400 static llvm::iterator_range<used_clauses_child_iterator>
401 used_clauses_children(ArrayRef<OMPClause *> Clauses) {
402 return {used_clauses_child_iterator(Clauses),
403 used_clauses_child_iterator(llvm::makeArrayRef(Clauses.end(), 0))};
404 }
405
406 /// Iterates over a filtered subrange of clauses applied to a
407 /// directive.
408 ///
409 /// This iterator visits only clauses of type SpecificClause.
410 template <typename SpecificClause>
411 class specific_clause_iterator
412 : public llvm::iterator_adaptor_base<
413 specific_clause_iterator<SpecificClause>,
414 ArrayRef<OMPClause *>::const_iterator, std::forward_iterator_tag,
415 const SpecificClause *, ptrdiff_t, const SpecificClause *,
416 const SpecificClause *> {
417 ArrayRef<OMPClause *>::const_iterator End;
418
419 void SkipToNextClause() {
420 while (this->I != End && !isa<SpecificClause>(*this->I))
421 ++this->I;
422 }
423
424 public:
425 explicit specific_clause_iterator(ArrayRef<OMPClause *> Clauses)
426 : specific_clause_iterator::iterator_adaptor_base(Clauses.begin()),
427 End(Clauses.end()) {
428 SkipToNextClause();
429 }
430
431 const SpecificClause *operator*() const {
432 return cast<SpecificClause>(*this->I);
433 }
434 const SpecificClause *operator->() const { return **this; }
435
436 specific_clause_iterator &operator++() {
437 ++this->I;
438 SkipToNextClause();
439 return *this;
440 }
441 };
442
443 template <typename SpecificClause>
444 static llvm::iterator_range<specific_clause_iterator<SpecificClause>>
445 getClausesOfKind(ArrayRef<OMPClause *> Clauses) {
446 return {specific_clause_iterator<SpecificClause>(Clauses),
447 specific_clause_iterator<SpecificClause>(
448 llvm::makeArrayRef(Clauses.end(), 0))};
449 }
450
451 template <typename SpecificClause>
452 llvm::iterator_range<specific_clause_iterator<SpecificClause>>
453 getClausesOfKind() const {
454 return getClausesOfKind<SpecificClause>(clauses());
455 }
456
457 /// Gets a single clause of the specified kind associated with the
458 /// current directive iff there is only one clause of this kind (and assertion
459 /// is fired if there is more than one clause is associated with the
460 /// directive). Returns nullptr if no clause of this kind is associated with
461 /// the directive.
462 template <typename SpecificClause>
463 const SpecificClause *getSingleClause() const {
464 auto Clauses = getClausesOfKind<SpecificClause>();
465
466 if (Clauses.begin() != Clauses.end()) {
467 assert(std::next(Clauses.begin()) == Clauses.end() &&
468 "There are at least 2 clauses of the specified kind");
469 return *Clauses.begin();
470 }
471 return nullptr;
472 }
473
474 /// Returns true if the current directive has one or more clauses of a
475 /// specific kind.
476 template <typename SpecificClause>
477 bool hasClausesOfKind() const {
478 auto Clauses = getClausesOfKind<SpecificClause>();
479 return Clauses.begin() != Clauses.end();
480 }
481
482 /// Returns starting location of directive kind.
483 SourceLocation getBeginLoc() const { return StartLoc; }
484 /// Returns ending location of directive.
485 SourceLocation getEndLoc() const { return EndLoc; }
486
487 /// Set starting location of directive kind.
488 ///
489 /// \param Loc New starting location of directive.
490 ///
491 void setLocStart(SourceLocation Loc) { StartLoc = Loc; }
492 /// Set ending location of directive.
493 ///
494 /// \param Loc New ending location of directive.
495 ///
496 void setLocEnd(SourceLocation Loc) { EndLoc = Loc; }
497
498 /// Get number of clauses.
499 unsigned getNumClauses() const {
500 if (!Data)
501 return 0;
502 return Data->getNumClauses();
503 }
504
505 /// Returns specified clause.
506 ///
507 /// \param I Number of clause.
508 ///
509 OMPClause *getClause(unsigned I) const { return clauses()[I]; }
510
511 /// Returns true if directive has associated statement.
512 bool hasAssociatedStmt() const { return Data && Data->hasAssociatedStmt(); }
513
514 /// Returns statement associated with the directive.
515 const Stmt *getAssociatedStmt() const {
516 return const_cast<OMPExecutableDirective *>(this)->getAssociatedStmt();
517 }
518 Stmt *getAssociatedStmt() {
519 assert(hasAssociatedStmt() &&
520 "Expected directive with the associated statement.");
521 return Data->getAssociatedStmt();
522 }
523
524 /// Returns the captured statement associated with the
525 /// component region within the (combined) directive.
526 ///
527 /// \param RegionKind Component region kind.
528 const CapturedStmt *getCapturedStmt(OpenMPDirectiveKind RegionKind) const {
529 assert(hasAssociatedStmt() &&
530 "Expected directive with the associated statement.");
531 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
532 getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
533 return Data->getCapturedStmt(RegionKind, CaptureRegions);
534 }
535
536 /// Get innermost captured statement for the construct.
537 CapturedStmt *getInnermostCapturedStmt() {
538 assert(hasAssociatedStmt() &&
539 "Expected directive with the associated statement.");
540 SmallVector<OpenMPDirectiveKind, 4> CaptureRegions;
541 getOpenMPCaptureRegions(CaptureRegions, getDirectiveKind());
542 return Data->getInnermostCapturedStmt(CaptureRegions);
543 }
544
545 const CapturedStmt *getInnermostCapturedStmt() const {
546 return const_cast<OMPExecutableDirective *>(this)
547 ->getInnermostCapturedStmt();
548 }
549
550 OpenMPDirectiveKind getDirectiveKind() const { return Kind; }
551
552 static bool classof(const Stmt *S) {
553 return S->getStmtClass() >= firstOMPExecutableDirectiveConstant &&
554 S->getStmtClass() <= lastOMPExecutableDirectiveConstant;
555 }
556
557 child_range children() {
558 if (!Data)
559 return child_range(child_iterator(), child_iterator());
560 return Data->getAssociatedStmtAsRange();
561 }
562
563 const_child_range children() const {
564 return const_cast<OMPExecutableDirective *>(this)->children();
565 }
566
567 ArrayRef<OMPClause *> clauses() const {
568 if (!Data)
569 return llvm::None;
570 return Data->getClauses();
571 }
572
573 /// Returns whether or not this is a Standalone directive.
574 ///
575 /// Stand-alone directives are executable directives
576 /// that have no associated user code.
577 bool isStandaloneDirective() const;
578
579 /// Returns the AST node representing OpenMP structured-block of this
580 /// OpenMP executable directive,
581 /// Prerequisite: Executable Directive must not be Standalone directive.
582 const Stmt *getStructuredBlock() const {
583 return const_cast<OMPExecutableDirective *>(this)->getStructuredBlock();
584 }
585 Stmt *getStructuredBlock();
586
587 const Stmt *getRawStmt() const {
588 return const_cast<OMPExecutableDirective *>(this)->getRawStmt();
589 }
590 Stmt *getRawStmt() {
591 assert(hasAssociatedStmt() &&
592 "Expected directive with the associated statement.");
593 return Data->getRawStmt();
594 }
595};
596
597/// This represents '#pragma omp parallel' directive.
598///
599/// \code
600/// #pragma omp parallel private(a,b) reduction(+: c,d)
601/// \endcode
602/// In this example directive '#pragma omp parallel' has clauses 'private'
603/// with the variables 'a' and 'b' and 'reduction' with operator '+' and
604/// variables 'c' and 'd'.
605///
606class OMPParallelDirective : public OMPExecutableDirective {
607 friend class ASTStmtReader;
608 friend class OMPExecutableDirective;
609 /// true if the construct has inner cancel directive.
610 bool HasCancel = false;
611
612 /// Build directive with the given start and end location.
613 ///
614 /// \param StartLoc Starting location of the directive (directive keyword).
615 /// \param EndLoc Ending Location of the directive.
616 ///
617 OMPParallelDirective(SourceLocation StartLoc, SourceLocation EndLoc)
618 : OMPExecutableDirective(OMPParallelDirectiveClass,
619 llvm::omp::OMPD_parallel, StartLoc, EndLoc) {}
620
621 /// Build an empty directive.
622 ///
623 explicit OMPParallelDirective()
624 : OMPExecutableDirective(OMPParallelDirectiveClass,
625 llvm::omp::OMPD_parallel, SourceLocation(),
626 SourceLocation()) {}
627
628 /// Sets special task reduction descriptor.
629 void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
630
631 /// Set cancel state.
632 void setHasCancel(bool Has) { HasCancel = Has; }
633
634public:
635 /// Creates directive with a list of \a Clauses.
636 ///
637 /// \param C AST context.
638 /// \param StartLoc Starting location of the directive kind.
639 /// \param EndLoc Ending Location of the directive.
640 /// \param Clauses List of clauses.
641 /// \param AssociatedStmt Statement associated with the directive.
642 /// \param TaskRedRef Task reduction special reference expression to handle
643 /// taskgroup descriptor.
644 /// \param HasCancel true if this directive has inner cancel directive.
645 ///
646 static OMPParallelDirective *
647 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
648 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
649 bool HasCancel);
650
651 /// Creates an empty directive with the place for \a N clauses.
652 ///
653 /// \param C AST context.
654 /// \param NumClauses Number of clauses.
655 ///
656 static OMPParallelDirective *CreateEmpty(const ASTContext &C,
657 unsigned NumClauses, EmptyShell);
658
659 /// Returns special task reduction reference expression.
660 Expr *getTaskReductionRefExpr() {
661 return cast_or_null<Expr>(Data->getChildren()[0]);
662 }
663 const Expr *getTaskReductionRefExpr() const {
664 return const_cast<OMPParallelDirective *>(this)->getTaskReductionRefExpr();
665 }
666
667 /// Return true if current directive has inner cancel directive.
668 bool hasCancel() const { return HasCancel; }
669
670 static bool classof(const Stmt *T) {
671 return T->getStmtClass() == OMPParallelDirectiveClass;
672 }
673};
674
675/// The base class for all loop-based directives, including loop transformation
676/// directives.
677class OMPLoopBasedDirective : public OMPExecutableDirective {
678 friend class ASTStmtReader;
679
680protected:
681 /// Number of collapsed loops as specified by 'collapse' clause.
682 unsigned NumAssociatedLoops = 0;
683
684 /// Build instance of loop directive of class \a Kind.
685 ///
686 /// \param SC Statement class.
687 /// \param Kind Kind of OpenMP directive.
688 /// \param StartLoc Starting location of the directive (directive keyword).
689 /// \param EndLoc Ending location of the directive.
690 /// \param NumAssociatedLoops Number of loops associated with the construct.
691 ///
692 OMPLoopBasedDirective(StmtClass SC, OpenMPDirectiveKind Kind,
693 SourceLocation StartLoc, SourceLocation EndLoc,
694 unsigned NumAssociatedLoops)
695 : OMPExecutableDirective(SC, Kind, StartLoc, EndLoc),
696 NumAssociatedLoops(NumAssociatedLoops) {}
697
698public:
699 /// The expressions built to support OpenMP loops in combined/composite
700 /// pragmas (e.g. pragma omp distribute parallel for)
701 struct DistCombinedHelperExprs {
702 /// DistributeLowerBound - used when composing 'omp distribute' with
703 /// 'omp for' in a same construct.
704 Expr *LB;
705 /// DistributeUpperBound - used when composing 'omp distribute' with
706 /// 'omp for' in a same construct.
707 Expr *UB;
708 /// DistributeEnsureUpperBound - used when composing 'omp distribute'
709 /// with 'omp for' in a same construct, EUB depends on DistUB
710 Expr *EUB;
711 /// Distribute loop iteration variable init used when composing 'omp
712 /// distribute'
713 /// with 'omp for' in a same construct
714 Expr *Init;
715 /// Distribute Loop condition used when composing 'omp distribute'
716 /// with 'omp for' in a same construct
717 Expr *Cond;
718 /// Update of LowerBound for statically scheduled omp loops for
719 /// outer loop in combined constructs (e.g. 'distribute parallel for')
720 Expr *NLB;
721 /// Update of UpperBound for statically scheduled omp loops for
722 /// outer loop in combined constructs (e.g. 'distribute parallel for')
723 Expr *NUB;
724 /// Distribute Loop condition used when composing 'omp distribute'
725 /// with 'omp for' in a same construct when schedule is chunked.
726 Expr *DistCond;
727 /// 'omp parallel for' loop condition used when composed with
728 /// 'omp distribute' in the same construct and when schedule is
729 /// chunked and the chunk size is 1.
730 Expr *ParForInDistCond;
731 };
732
733 /// The expressions built for the OpenMP loop CodeGen for the
734 /// whole collapsed loop nest.
735 struct HelperExprs {
736 /// Loop iteration variable.
737 Expr *IterationVarRef;
738 /// Loop last iteration number.
739 Expr *LastIteration;
740 /// Loop number of iterations.
741 Expr *NumIterations;
742 /// Calculation of last iteration.
743 Expr *CalcLastIteration;
744 /// Loop pre-condition.
745 Expr *PreCond;
746 /// Loop condition.
747 Expr *Cond;
748 /// Loop iteration variable init.
749 Expr *Init;
750 /// Loop increment.
751 Expr *Inc;
752 /// IsLastIteration - local flag variable passed to runtime.
753 Expr *IL;
754 /// LowerBound - local variable passed to runtime.
755 Expr *LB;
756 /// UpperBound - local variable passed to runtime.
757 Expr *UB;
758 /// Stride - local variable passed to runtime.
759 Expr *ST;
760 /// EnsureUpperBound -- expression UB = min(UB, NumIterations).
761 Expr *EUB;
762 /// Update of LowerBound for statically scheduled 'omp for' loops.
763 Expr *NLB;
764 /// Update of UpperBound for statically scheduled 'omp for' loops.
765 Expr *NUB;
766 /// PreviousLowerBound - local variable passed to runtime in the
767 /// enclosing schedule or null if that does not apply.
768 Expr *PrevLB;
769 /// PreviousUpperBound - local variable passed to runtime in the
770 /// enclosing schedule or null if that does not apply.
771 Expr *PrevUB;
772 /// DistInc - increment expression for distribute loop when found
773 /// combined with a further loop level (e.g. in 'distribute parallel for')
774 /// expression IV = IV + ST
775 Expr *DistInc;
776 /// PrevEUB - expression similar to EUB but to be used when loop
777 /// scheduling uses PrevLB and PrevUB (e.g. in 'distribute parallel for'
778 /// when ensuring that the UB is either the calculated UB by the runtime or
779 /// the end of the assigned distribute chunk)
780 /// expression UB = min (UB, PrevUB)
781 Expr *PrevEUB;
782 /// Counters Loop counters.
783 SmallVector<Expr *, 4> Counters;
784 /// PrivateCounters Loop counters.
785 SmallVector<Expr *, 4> PrivateCounters;
786 /// Expressions for loop counters inits for CodeGen.
787 SmallVector<Expr *, 4> Inits;
788 /// Expressions for loop counters update for CodeGen.
789 SmallVector<Expr *, 4> Updates;
790 /// Final loop counter values for GodeGen.
791 SmallVector<Expr *, 4> Finals;
792 /// List of counters required for the generation of the non-rectangular
793 /// loops.
794 SmallVector<Expr *, 4> DependentCounters;
795 /// List of initializers required for the generation of the non-rectangular
796 /// loops.
797 SmallVector<Expr *, 4> DependentInits;
798 /// List of final conditions required for the generation of the
799 /// non-rectangular loops.
800 SmallVector<Expr *, 4> FinalsConditions;
801 /// Init statement for all captured expressions.
802 Stmt *PreInits;
803
804 /// Expressions used when combining OpenMP loop pragmas
805 DistCombinedHelperExprs DistCombinedFields;
806
807 /// Check if all the expressions are built (does not check the
808 /// worksharing ones).
809 bool builtAll() {
810 return IterationVarRef != nullptr && LastIteration != nullptr &&
811 NumIterations != nullptr && PreCond != nullptr &&
812 Cond != nullptr && Init != nullptr && Inc != nullptr;
813 }
814
815 /// Initialize all the fields to null.
816 /// \param Size Number of elements in the
817 /// counters/finals/updates/dependent_counters/dependent_inits/finals_conditions
818 /// arrays.
819 void clear(unsigned Size) {
820 IterationVarRef = nullptr;
821 LastIteration = nullptr;
822 CalcLastIteration = nullptr;
823 PreCond = nullptr;
824 Cond = nullptr;
825 Init = nullptr;
826 Inc = nullptr;
827 IL = nullptr;
828 LB = nullptr;
829 UB = nullptr;
830 ST = nullptr;
831 EUB = nullptr;
832 NLB = nullptr;
833 NUB = nullptr;
834 NumIterations = nullptr;
835 PrevLB = nullptr;
836 PrevUB = nullptr;
837 DistInc = nullptr;
838 PrevEUB = nullptr;
839 Counters.resize(Size);
840 PrivateCounters.resize(Size);
841 Inits.resize(Size);
842 Updates.resize(Size);
843 Finals.resize(Size);
844 DependentCounters.resize(Size);
845 DependentInits.resize(Size);
846 FinalsConditions.resize(Size);
847 for (unsigned I = 0; I < Size; ++I) {
848 Counters[I] = nullptr;
849 PrivateCounters[I] = nullptr;
850 Inits[I] = nullptr;
851 Updates[I] = nullptr;
852 Finals[I] = nullptr;
853 DependentCounters[I] = nullptr;
854 DependentInits[I] = nullptr;
855 FinalsConditions[I] = nullptr;
856 }
857 PreInits = nullptr;
858 DistCombinedFields.LB = nullptr;
859 DistCombinedFields.UB = nullptr;
860 DistCombinedFields.EUB = nullptr;
861 DistCombinedFields.Init = nullptr;
862 DistCombinedFields.Cond = nullptr;
863 DistCombinedFields.NLB = nullptr;
864 DistCombinedFields.NUB = nullptr;
865 DistCombinedFields.DistCond = nullptr;
866 DistCombinedFields.ParForInDistCond = nullptr;
867 }
868 };
869
870 /// Get number of collapsed loops.
871 unsigned getLoopsNumber() const { return NumAssociatedLoops; }
872
873 /// Try to find the next loop sub-statement in the specified statement \p
874 /// CurStmt.
875 /// \param TryImperfectlyNestedLoops true, if we need to try to look for the
876 /// imperfectly nested loop.
877 static Stmt *tryToFindNextInnerLoop(Stmt *CurStmt,
878 bool TryImperfectlyNestedLoops);
879 static const Stmt *tryToFindNextInnerLoop(const Stmt *CurStmt,
880 bool TryImperfectlyNestedLoops) {
881 return tryToFindNextInnerLoop(const_cast<Stmt *>(CurStmt),
882 TryImperfectlyNestedLoops);
883 }
884
885 /// Calls the specified callback function for all the loops in \p CurStmt,
886 /// from the outermost to the innermost.
887 static bool
888 doForAllLoops(Stmt *CurStmt, bool TryImperfectlyNestedLoops,
889 unsigned NumLoops,
890 llvm::function_ref<bool(unsigned, Stmt *)> Callback);
891 static bool
892 doForAllLoops(const Stmt *CurStmt, bool TryImperfectlyNestedLoops,
893 unsigned NumLoops,
894 llvm::function_ref<bool(unsigned, const Stmt *)> Callback) {
895 auto &&NewCallback = [Callback](unsigned Cnt, Stmt *CurStmt) {
896 return Callback(Cnt, CurStmt);
897 };
898 return doForAllLoops(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
899 NumLoops, NewCallback);
900 }
901
902 /// Calls the specified callback function for all the loop bodies in \p
903 /// CurStmt, from the outermost loop to the innermost.
904 static void doForAllLoopsBodies(
905 Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
906 llvm::function_ref<void(unsigned, Stmt *, Stmt *)> Callback);
907 static void doForAllLoopsBodies(
908 const Stmt *CurStmt, bool TryImperfectlyNestedLoops, unsigned NumLoops,
909 llvm::function_ref<void(unsigned, const Stmt *, const Stmt *)> Callback) {
910 auto &&NewCallback = [Callback](unsigned Cnt, Stmt *Loop, Stmt *Body) {
911 Callback(Cnt, Loop, Body);
912 };
913 doForAllLoopsBodies(const_cast<Stmt *>(CurStmt), TryImperfectlyNestedLoops,
914 NumLoops, NewCallback);
915 }
916
917 static bool classof(const Stmt *T) {
918 if (auto *D = dyn_cast<OMPExecutableDirective>(T))
919 return isOpenMPLoopDirective(D->getDirectiveKind());
920 return false;
921 }
922};
923
924/// This is a common base class for loop directives ('omp simd', 'omp
925/// for', 'omp for simd' etc.). It is responsible for the loop code generation.
926///
927class OMPLoopDirective : public OMPLoopBasedDirective {
928 friend class ASTStmtReader;
929
930 /// Offsets to the stored exprs.
931 /// This enumeration contains offsets to all the pointers to children
932 /// expressions stored in OMPLoopDirective.
933 /// The first 9 children are necessary for all the loop directives,
934 /// the next 8 are specific to the worksharing ones, and the next 11 are
935 /// used for combined constructs containing two pragmas associated to loops.
936 /// After the fixed children, three arrays of length NumAssociatedLoops are
937 /// allocated: loop counters, their updates and final values.
938 /// PrevLowerBound and PrevUpperBound are used to communicate blocking
939 /// information in composite constructs which require loop blocking
940 /// DistInc is used to generate the increment expression for the distribute
941 /// loop when combined with a further nested loop
942 /// PrevEnsureUpperBound is used as the EnsureUpperBound expression for the
943 /// for loop when combined with a previous distribute loop in the same pragma
944 /// (e.g. 'distribute parallel for')
945 ///
946 enum {
947 IterationVariableOffset = 0,
948 LastIterationOffset = 1,
949 CalcLastIterationOffset = 2,
950 PreConditionOffset = 3,
951 CondOffset = 4,
952 InitOffset = 5,
953 IncOffset = 6,
954 PreInitsOffset = 7,
955 // The '...End' enumerators do not correspond to child expressions - they
956 // specify the offset to the end (and start of the following counters/
957 // updates/finals/dependent_counters/dependent_inits/finals_conditions
958 // arrays).
959 DefaultEnd = 8,
960 // The following 8 exprs are used by worksharing and distribute loops only.
961 IsLastIterVariableOffset = 8,
962 LowerBoundVariableOffset = 9,
963 UpperBoundVariableOffset = 10,
964 StrideVariableOffset = 11,
965 EnsureUpperBoundOffset = 12,
966 NextLowerBoundOffset = 13,
967 NextUpperBoundOffset = 14,
968 NumIterationsOffset = 15,
969 // Offset to the end for worksharing loop directives.
970 WorksharingEnd = 16,
971 PrevLowerBoundVariableOffset = 16,
972 PrevUpperBoundVariableOffset = 17,
973 DistIncOffset = 18,
974 PrevEnsureUpperBoundOffset = 19,
975 CombinedLowerBoundVariableOffset = 20,
976 CombinedUpperBoundVariableOffset = 21,
977 CombinedEnsureUpperBoundOffset = 22,
978 CombinedInitOffset = 23,
979 CombinedConditionOffset = 24,
980 CombinedNextLowerBoundOffset = 25,
981 CombinedNextUpperBoundOffset = 26,
982 CombinedDistConditionOffset = 27,
983 CombinedParForInDistConditionOffset = 28,
984 // Offset to the end (and start of the following
985 // counters/updates/finals/dependent_counters/dependent_inits/finals_conditions
986 // arrays) for combined distribute loop directives.
987 CombinedDistributeEnd = 29,
988 };
989
990 /// Get the counters storage.
991 MutableArrayRef<Expr *> getCounters() {
992 auto **Storage = reinterpret_cast<Expr **>(
993 &Data->getChildren()[getArraysOffset(getDirectiveKind())]);
994 return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
995 }
996
997 /// Get the private counters storage.
998 MutableArrayRef<Expr *> getPrivateCounters() {
999 auto **Storage = reinterpret_cast<Expr **>(
1000 &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1001 getLoopsNumber()]);
1002 return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
1003 }
1004
1005 /// Get the updates storage.
1006 MutableArrayRef<Expr *> getInits() {
1007 auto **Storage = reinterpret_cast<Expr **>(
1008 &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1009 2 * getLoopsNumber()]);
1010 return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
1011 }
1012
1013 /// Get the updates storage.
1014 MutableArrayRef<Expr *> getUpdates() {
1015 auto **Storage = reinterpret_cast<Expr **>(
1016 &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1017 3 * getLoopsNumber()]);
1018 return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
1019 }
1020
1021 /// Get the final counter updates storage.
1022 MutableArrayRef<Expr *> getFinals() {
1023 auto **Storage = reinterpret_cast<Expr **>(
1024 &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1025 4 * getLoopsNumber()]);
1026 return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
1027 }
1028
1029 /// Get the dependent counters storage.
1030 MutableArrayRef<Expr *> getDependentCounters() {
1031 auto **Storage = reinterpret_cast<Expr **>(
1032 &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1033 5 * getLoopsNumber()]);
1034 return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
1035 }
1036
1037 /// Get the dependent inits storage.
1038 MutableArrayRef<Expr *> getDependentInits() {
1039 auto **Storage = reinterpret_cast<Expr **>(
1040 &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1041 6 * getLoopsNumber()]);
1042 return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
1043 }
1044
1045 /// Get the finals conditions storage.
1046 MutableArrayRef<Expr *> getFinalsConditions() {
1047 auto **Storage = reinterpret_cast<Expr **>(
1048 &Data->getChildren()[getArraysOffset(getDirectiveKind()) +
1049 7 * getLoopsNumber()]);
1050 return llvm::makeMutableArrayRef(Storage, getLoopsNumber());
1051 }
1052
1053protected:
1054 /// Build instance of loop directive of class \a Kind.
1055 ///
1056 /// \param SC Statement class.
1057 /// \param Kind Kind of OpenMP directive.
1058 /// \param StartLoc Starting location of the directive (directive keyword).
1059 /// \param EndLoc Ending location of the directive.
1060 /// \param CollapsedNum Number of collapsed loops from 'collapse' clause.
1061 ///
1062 OMPLoopDirective(StmtClass SC, OpenMPDirectiveKind Kind,
1063 SourceLocation StartLoc, SourceLocation EndLoc,
1064 unsigned CollapsedNum)
1065 : OMPLoopBasedDirective(SC, Kind, StartLoc, EndLoc, CollapsedNum) {}
1066
1067 /// Offset to the start of children expression arrays.
1068 static unsigned getArraysOffset(OpenMPDirectiveKind Kind) {
1069 if (isOpenMPLoopBoundSharingDirective(Kind))
1070 return CombinedDistributeEnd;
1071 if (isOpenMPWorksharingDirective(Kind) || isOpenMPTaskLoopDirective(Kind) ||
1072 isOpenMPDistributeDirective(Kind))
1073 return WorksharingEnd;
1074 return DefaultEnd;
1075 }
1076
1077 /// Children number.
1078 static unsigned numLoopChildren(unsigned CollapsedNum,
1079 OpenMPDirectiveKind Kind) {
1080 return getArraysOffset(Kind) +
1081 8 * CollapsedNum; // Counters, PrivateCounters, Inits,
1082 // Updates, Finals, DependentCounters,
1083 // DependentInits, FinalsConditions.
1084 }
1085
1086 void setIterationVariable(Expr *IV) {
1087 Data->getChildren()[IterationVariableOffset] = IV;
1088 }
1089 void setLastIteration(Expr *LI) {
1090 Data->getChildren()[LastIterationOffset] = LI;
1091 }
1092 void setCalcLastIteration(Expr *CLI) {
1093 Data->getChildren()[CalcLastIterationOffset] = CLI;
1094 }
1095 void setPreCond(Expr *PC) { Data->getChildren()[PreConditionOffset] = PC; }
1096 void setCond(Expr *Cond) { Data->getChildren()[CondOffset] = Cond; }
1097 void setInit(Expr *Init) { Data->getChildren()[InitOffset] = Init; }
1098 void setInc(Expr *Inc) { Data->getChildren()[IncOffset] = Inc; }
1099 void setPreInits(Stmt *PreInits) {
1100 Data->getChildren()[PreInitsOffset] = PreInits;
1101 }
1102 void setIsLastIterVariable(Expr *IL) {
1103 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1104 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1105 isOpenMPDistributeDirective(getDirectiveKind())) &&
1106 "expected worksharing loop directive");
1107 Data->getChildren()[IsLastIterVariableOffset] = IL;
1108 }
1109 void setLowerBoundVariable(Expr *LB) {
1110 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1111 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1112 isOpenMPDistributeDirective(getDirectiveKind())) &&
1113 "expected worksharing loop directive");
1114 Data->getChildren()[LowerBoundVariableOffset] = LB;
1115 }
1116 void setUpperBoundVariable(Expr *UB) {
1117 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1118 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1119 isOpenMPDistributeDirective(getDirectiveKind())) &&
1120 "expected worksharing loop directive");
1121 Data->getChildren()[UpperBoundVariableOffset] = UB;
1122 }
1123 void setStrideVariable(Expr *ST) {
1124 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1125 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1126 isOpenMPDistributeDirective(getDirectiveKind())) &&
1127 "expected worksharing loop directive");
1128 Data->getChildren()[StrideVariableOffset] = ST;
1129 }
1130 void setEnsureUpperBound(Expr *EUB) {
1131 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1132 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1133 isOpenMPDistributeDirective(getDirectiveKind())) &&
1134 "expected worksharing loop directive");
1135 Data->getChildren()[EnsureUpperBoundOffset] = EUB;
1136 }
1137 void setNextLowerBound(Expr *NLB) {
1138 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1139 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1140 isOpenMPDistributeDirective(getDirectiveKind())) &&
1141 "expected worksharing loop directive");
1142 Data->getChildren()[NextLowerBoundOffset] = NLB;
1143 }
1144 void setNextUpperBound(Expr *NUB) {
1145 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1146 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1147 isOpenMPDistributeDirective(getDirectiveKind())) &&
1148 "expected worksharing loop directive");
1149 Data->getChildren()[NextUpperBoundOffset] = NUB;
1150 }
1151 void setNumIterations(Expr *NI) {
1152 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1153 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1154 isOpenMPDistributeDirective(getDirectiveKind())) &&
1155 "expected worksharing loop directive");
1156 Data->getChildren()[NumIterationsOffset] = NI;
1157 }
1158 void setPrevLowerBoundVariable(Expr *PrevLB) {
1159 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1160 "expected loop bound sharing directive");
1161 Data->getChildren()[PrevLowerBoundVariableOffset] = PrevLB;
1162 }
1163 void setPrevUpperBoundVariable(Expr *PrevUB) {
1164 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1165 "expected loop bound sharing directive");
1166 Data->getChildren()[PrevUpperBoundVariableOffset] = PrevUB;
1167 }
1168 void setDistInc(Expr *DistInc) {
1169 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1170 "expected loop bound sharing directive");
1171 Data->getChildren()[DistIncOffset] = DistInc;
1172 }
1173 void setPrevEnsureUpperBound(Expr *PrevEUB) {
1174 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1175 "expected loop bound sharing directive");
1176 Data->getChildren()[PrevEnsureUpperBoundOffset] = PrevEUB;
1177 }
1178 void setCombinedLowerBoundVariable(Expr *CombLB) {
1179 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1180 "expected loop bound sharing directive");
1181 Data->getChildren()[CombinedLowerBoundVariableOffset] = CombLB;
1182 }
1183 void setCombinedUpperBoundVariable(Expr *CombUB) {
1184 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1185 "expected loop bound sharing directive");
1186 Data->getChildren()[CombinedUpperBoundVariableOffset] = CombUB;
1187 }
1188 void setCombinedEnsureUpperBound(Expr *CombEUB) {
1189 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1190 "expected loop bound sharing directive");
1191 Data->getChildren()[CombinedEnsureUpperBoundOffset] = CombEUB;
1192 }
1193 void setCombinedInit(Expr *CombInit) {
1194 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1195 "expected loop bound sharing directive");
1196 Data->getChildren()[CombinedInitOffset] = CombInit;
1197 }
1198 void setCombinedCond(Expr *CombCond) {
1199 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1200 "expected loop bound sharing directive");
1201 Data->getChildren()[CombinedConditionOffset] = CombCond;
1202 }
1203 void setCombinedNextLowerBound(Expr *CombNLB) {
1204 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1205 "expected loop bound sharing directive");
1206 Data->getChildren()[CombinedNextLowerBoundOffset] = CombNLB;
1207 }
1208 void setCombinedNextUpperBound(Expr *CombNUB) {
1209 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1210 "expected loop bound sharing directive");
1211 Data->getChildren()[CombinedNextUpperBoundOffset] = CombNUB;
1212 }
1213 void setCombinedDistCond(Expr *CombDistCond) {
1214 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1215 "expected loop bound distribute sharing directive");
1216 Data->getChildren()[CombinedDistConditionOffset] = CombDistCond;
1217 }
1218 void setCombinedParForInDistCond(Expr *CombParForInDistCond) {
1219 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1220 "expected loop bound distribute sharing directive");
1221 Data->getChildren()[CombinedParForInDistConditionOffset] =
1222 CombParForInDistCond;
1223 }
1224 void setCounters(ArrayRef<Expr *> A);
1225 void setPrivateCounters(ArrayRef<Expr *> A);
1226 void setInits(ArrayRef<Expr *> A);
1227 void setUpdates(ArrayRef<Expr *> A);
1228 void setFinals(ArrayRef<Expr *> A);
1229 void setDependentCounters(ArrayRef<Expr *> A);
1230 void setDependentInits(ArrayRef<Expr *> A);
1231 void setFinalsConditions(ArrayRef<Expr *> A);
1232
1233public:
1234 Expr *getIterationVariable() const {
1235 return cast<Expr>(Data->getChildren()[IterationVariableOffset]);
1236 }
1237 Expr *getLastIteration() const {
1238 return cast<Expr>(Data->getChildren()[LastIterationOffset]);
1239 }
1240 Expr *getCalcLastIteration() const {
1241 return cast<Expr>(Data->getChildren()[CalcLastIterationOffset]);
1242 }
1243 Expr *getPreCond() const {
1244 return cast<Expr>(Data->getChildren()[PreConditionOffset]);
1245 }
1246 Expr *getCond() const { return cast<Expr>(Data->getChildren()[CondOffset]); }
1247 Expr *getInit() const { return cast<Expr>(Data->getChildren()[InitOffset]); }
1248 Expr *getInc() const { return cast<Expr>(Data->getChildren()[IncOffset]); }
1249 const Stmt *getPreInits() const {
1250 return Data->getChildren()[PreInitsOffset];
1251 }
1252 Stmt *getPreInits() { return Data->getChildren()[PreInitsOffset]; }
1253 Expr *getIsLastIterVariable() const {
1254 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1255 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1256 isOpenMPDistributeDirective(getDirectiveKind())) &&
1257 "expected worksharing loop directive");
1258 return cast<Expr>(Data->getChildren()[IsLastIterVariableOffset]);
1259 }
1260 Expr *getLowerBoundVariable() const {
1261 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1262 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1263 isOpenMPDistributeDirective(getDirectiveKind())) &&
1264 "expected worksharing loop directive");
1265 return cast<Expr>(Data->getChildren()[LowerBoundVariableOffset]);
1266 }
1267 Expr *getUpperBoundVariable() const {
1268 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1269 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1270 isOpenMPDistributeDirective(getDirectiveKind())) &&
1271 "expected worksharing loop directive");
1272 return cast<Expr>(Data->getChildren()[UpperBoundVariableOffset]);
1273 }
1274 Expr *getStrideVariable() const {
1275 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1276 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1277 isOpenMPDistributeDirective(getDirectiveKind())) &&
1278 "expected worksharing loop directive");
1279 return cast<Expr>(Data->getChildren()[StrideVariableOffset]);
1280 }
1281 Expr *getEnsureUpperBound() const {
1282 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1283 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1284 isOpenMPDistributeDirective(getDirectiveKind())) &&
1285 "expected worksharing loop directive");
1286 return cast<Expr>(Data->getChildren()[EnsureUpperBoundOffset]);
1287 }
1288 Expr *getNextLowerBound() const {
1289 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1290 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1291 isOpenMPDistributeDirective(getDirectiveKind())) &&
1292 "expected worksharing loop directive");
1293 return cast<Expr>(Data->getChildren()[NextLowerBoundOffset]);
1294 }
1295 Expr *getNextUpperBound() const {
1296 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1297 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1298 isOpenMPDistributeDirective(getDirectiveKind())) &&
1299 "expected worksharing loop directive");
1300 return cast<Expr>(Data->getChildren()[NextUpperBoundOffset]);
1301 }
1302 Expr *getNumIterations() const {
1303 assert((isOpenMPWorksharingDirective(getDirectiveKind()) ||
1304 isOpenMPTaskLoopDirective(getDirectiveKind()) ||
1305 isOpenMPDistributeDirective(getDirectiveKind())) &&
1306 "expected worksharing loop directive");
1307 return cast<Expr>(Data->getChildren()[NumIterationsOffset]);
1308 }
1309 Expr *getPrevLowerBoundVariable() const {
1310 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1311 "expected loop bound sharing directive");
1312 return cast<Expr>(Data->getChildren()[PrevLowerBoundVariableOffset]);
1313 }
1314 Expr *getPrevUpperBoundVariable() const {
1315 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1316 "expected loop bound sharing directive");
1317 return cast<Expr>(Data->getChildren()[PrevUpperBoundVariableOffset]);
1318 }
1319 Expr *getDistInc() const {
1320 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1321 "expected loop bound sharing directive");
1322 return cast<Expr>(Data->getChildren()[DistIncOffset]);
1323 }
1324 Expr *getPrevEnsureUpperBound() const {
1325 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1326 "expected loop bound sharing directive");
1327 return cast<Expr>(Data->getChildren()[PrevEnsureUpperBoundOffset]);
1328 }
1329 Expr *getCombinedLowerBoundVariable() const {
1330 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1331 "expected loop bound sharing directive");
1332 return cast<Expr>(Data->getChildren()[CombinedLowerBoundVariableOffset]);
1333 }
1334 Expr *getCombinedUpperBoundVariable() const {
1335 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1336 "expected loop bound sharing directive");
1337 return cast<Expr>(Data->getChildren()[CombinedUpperBoundVariableOffset]);
1338 }
1339 Expr *getCombinedEnsureUpperBound() const {
1340 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1341 "expected loop bound sharing directive");
1342 return cast<Expr>(Data->getChildren()[CombinedEnsureUpperBoundOffset]);
1343 }
1344 Expr *getCombinedInit() const {
1345 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1346 "expected loop bound sharing directive");
1347 return cast<Expr>(Data->getChildren()[CombinedInitOffset]);
1348 }
1349 Expr *getCombinedCond() const {
1350 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1351 "expected loop bound sharing directive");
1352 return cast<Expr>(Data->getChildren()[CombinedConditionOffset]);
1353 }
1354 Expr *getCombinedNextLowerBound() const {
1355 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1356 "expected loop bound sharing directive");
1357 return cast<Expr>(Data->getChildren()[CombinedNextLowerBoundOffset]);
1358 }
1359 Expr *getCombinedNextUpperBound() const {
1360 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1361 "expected loop bound sharing directive");
1362 return cast<Expr>(Data->getChildren()[CombinedNextUpperBoundOffset]);
1363 }
1364 Expr *getCombinedDistCond() const {
1365 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1366 "expected loop bound distribute sharing directive");
1367 return cast<Expr>(Data->getChildren()[CombinedDistConditionOffset]);
1368 }
1369 Expr *getCombinedParForInDistCond() const {
1370 assert(isOpenMPLoopBoundSharingDirective(getDirectiveKind()) &&
1371 "expected loop bound distribute sharing directive");
1372 return cast<Expr>(Data->getChildren()[CombinedParForInDistConditionOffset]);
1373 }
1374 Stmt *getBody();
1375 const Stmt *getBody() const {
1376 return const_cast<OMPLoopDirective *>(this)->getBody();
1377 }
1378
1379 ArrayRef<Expr *> counters() { return getCounters(); }
1380
1381 ArrayRef<Expr *> counters() const {
1382 return const_cast<OMPLoopDirective *>(this)->getCounters();
1383 }
1384
1385 ArrayRef<Expr *> private_counters() { return getPrivateCounters(); }
1386
1387 ArrayRef<Expr *> private_counters() const {
1388 return const_cast<OMPLoopDirective *>(this)->getPrivateCounters();
1389 }
1390
1391 ArrayRef<Expr *> inits() { return getInits(); }
1392
1393 ArrayRef<Expr *> inits() const {
1394 return const_cast<OMPLoopDirective *>(this)->getInits();
1395 }
1396
1397 ArrayRef<Expr *> updates() { return getUpdates(); }
1398
1399 ArrayRef<Expr *> updates() const {
1400 return const_cast<OMPLoopDirective *>(this)->getUpdates();
1401 }
1402
1403 ArrayRef<Expr *> finals() { return getFinals(); }
1404
1405 ArrayRef<Expr *> finals() const {
1406 return const_cast<OMPLoopDirective *>(this)->getFinals();
1407 }
1408
1409 ArrayRef<Expr *> dependent_counters() { return getDependentCounters(); }
1410
1411 ArrayRef<Expr *> dependent_counters() const {
1412 return const_cast<OMPLoopDirective *>(this)->getDependentCounters();
1413 }
1414
1415 ArrayRef<Expr *> dependent_inits() { return getDependentInits(); }
1416
1417 ArrayRef<Expr *> dependent_inits() const {
1418 return const_cast<OMPLoopDirective *>(this)->getDependentInits();
1419 }
1420
1421 ArrayRef<Expr *> finals_conditions() { return getFinalsConditions(); }
1422
1423 ArrayRef<Expr *> finals_conditions() const {
1424 return const_cast<OMPLoopDirective *>(this)->getFinalsConditions();
1425 }
1426
1427 static bool classof(const Stmt *T) {
1428 return T->getStmtClass() == OMPSimdDirectiveClass ||
1429 T->getStmtClass() == OMPForDirectiveClass ||
1430 T->getStmtClass() == OMPForSimdDirectiveClass ||
1431 T->getStmtClass() == OMPParallelForDirectiveClass ||
1432 T->getStmtClass() == OMPParallelForSimdDirectiveClass ||
1433 T->getStmtClass() == OMPTaskLoopDirectiveClass ||
1434 T->getStmtClass() == OMPTaskLoopSimdDirectiveClass ||
1435 T->getStmtClass() == OMPMasterTaskLoopDirectiveClass ||
1436 T->getStmtClass() == OMPMasterTaskLoopSimdDirectiveClass ||
1437 T->getStmtClass() == OMPParallelMasterTaskLoopDirectiveClass ||
1438 T->getStmtClass() == OMPParallelMasterTaskLoopSimdDirectiveClass ||
1439 T->getStmtClass() == OMPDistributeDirectiveClass ||
1440 T->getStmtClass() == OMPTargetParallelForDirectiveClass ||
1441 T->getStmtClass() == OMPDistributeParallelForDirectiveClass ||
1442 T->getStmtClass() == OMPDistributeParallelForSimdDirectiveClass ||
1443 T->getStmtClass() == OMPDistributeSimdDirectiveClass ||
1444 T->getStmtClass() == OMPTargetParallelForSimdDirectiveClass ||
1445 T->getStmtClass() == OMPTargetSimdDirectiveClass ||
1446 T->getStmtClass() == OMPTeamsDistributeDirectiveClass ||
1447 T->getStmtClass() == OMPTeamsDistributeSimdDirectiveClass ||
1448 T->getStmtClass() ==
1449 OMPTeamsDistributeParallelForSimdDirectiveClass ||
1450 T->getStmtClass() == OMPTeamsDistributeParallelForDirectiveClass ||
1451 T->getStmtClass() ==
1452 OMPTargetTeamsDistributeParallelForDirectiveClass ||
1453 T->getStmtClass() ==
1454 OMPTargetTeamsDistributeParallelForSimdDirectiveClass ||
1455 T->getStmtClass() == OMPTargetTeamsDistributeDirectiveClass ||
1456 T->getStmtClass() == OMPTargetTeamsDistributeSimdDirectiveClass;
1457 }
1458};
1459
1460/// This represents '#pragma omp simd' directive.
1461///
1462/// \code
1463/// #pragma omp simd private(a,b) linear(i,j:s) reduction(+:c,d)
1464/// \endcode
1465/// In this example directive '#pragma omp simd' has clauses 'private'
1466/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
1467/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
1468///
1469class OMPSimdDirective : public OMPLoopDirective {
1470 friend class ASTStmtReader;
1471 friend class OMPExecutableDirective;
1472 /// Build directive with the given start and end location.
1473 ///
1474 /// \param StartLoc Starting location of the directive kind.
1475 /// \param EndLoc Ending location of the directive.
1476 /// \param CollapsedNum Number of collapsed nested loops.
1477 ///
1478 OMPSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
1479 unsigned CollapsedNum)
1480 : OMPLoopDirective(OMPSimdDirectiveClass, llvm::omp::OMPD_simd, StartLoc,
1481 EndLoc, CollapsedNum) {}
1482
1483 /// Build an empty directive.
1484 ///
1485 /// \param CollapsedNum Number of collapsed nested loops.
1486 ///
1487 explicit OMPSimdDirective(unsigned CollapsedNum)
1488 : OMPLoopDirective(OMPSimdDirectiveClass, llvm::omp::OMPD_simd,
1489 SourceLocation(), SourceLocation(), CollapsedNum) {}
1490
1491public:
1492 /// Creates directive with a list of \a Clauses.
1493 ///
1494 /// \param C AST context.
1495 /// \param StartLoc Starting location of the directive kind.
1496 /// \param EndLoc Ending Location of the directive.
1497 /// \param CollapsedNum Number of collapsed loops.
1498 /// \param Clauses List of clauses.
1499 /// \param AssociatedStmt Statement, associated with the directive.
1500 /// \param Exprs Helper expressions for CodeGen.
1501 ///
1502 static OMPSimdDirective *Create(const ASTContext &C, SourceLocation StartLoc,
1503 SourceLocation EndLoc, unsigned CollapsedNum,
1504 ArrayRef<OMPClause *> Clauses,
1505 Stmt *AssociatedStmt,
1506 const HelperExprs &Exprs);
1507
1508 /// Creates an empty directive with the place
1509 /// for \a NumClauses clauses.
1510 ///
1511 /// \param C AST context.
1512 /// \param CollapsedNum Number of collapsed nested loops.
1513 /// \param NumClauses Number of clauses.
1514 ///
1515 static OMPSimdDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
1516 unsigned CollapsedNum, EmptyShell);
1517
1518 static bool classof(const Stmt *T) {
1519 return T->getStmtClass() == OMPSimdDirectiveClass;
1520 }
1521};
1522
1523/// This represents '#pragma omp for' directive.
1524///
1525/// \code
1526/// #pragma omp for private(a,b) reduction(+:c,d)
1527/// \endcode
1528/// In this example directive '#pragma omp for' has clauses 'private' with the
1529/// variables 'a' and 'b' and 'reduction' with operator '+' and variables 'c'
1530/// and 'd'.
1531///
1532class OMPForDirective : public OMPLoopDirective {
1533 friend class ASTStmtReader;
1534 friend class OMPExecutableDirective;
1535 /// true if current directive has inner cancel directive.
1536 bool HasCancel = false;
1537
1538 /// Build directive with the given start and end location.
1539 ///
1540 /// \param StartLoc Starting location of the directive kind.
1541 /// \param EndLoc Ending location of the directive.
1542 /// \param CollapsedNum Number of collapsed nested loops.
1543 ///
1544 OMPForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
1545 unsigned CollapsedNum)
1546 : OMPLoopDirective(OMPForDirectiveClass, llvm::omp::OMPD_for, StartLoc,
1547 EndLoc, CollapsedNum) {}
1548
1549 /// Build an empty directive.
1550 ///
1551 /// \param CollapsedNum Number of collapsed nested loops.
1552 ///
1553 explicit OMPForDirective(unsigned CollapsedNum)
1554 : OMPLoopDirective(OMPForDirectiveClass, llvm::omp::OMPD_for,
1555 SourceLocation(), SourceLocation(), CollapsedNum) {}
1556
1557 /// Sets special task reduction descriptor.
1558 void setTaskReductionRefExpr(Expr *E) {
1559 Data->getChildren()[numLoopChildren(getLoopsNumber(),
1560 llvm::omp::OMPD_for)] = E;
1561 }
1562
1563 /// Set cancel state.
1564 void setHasCancel(bool Has) { HasCancel = Has; }
1565
1566public:
1567 /// Creates directive with a list of \a Clauses.
1568 ///
1569 /// \param C AST context.
1570 /// \param StartLoc Starting location of the directive kind.
1571 /// \param EndLoc Ending Location of the directive.
1572 /// \param CollapsedNum Number of collapsed loops.
1573 /// \param Clauses List of clauses.
1574 /// \param AssociatedStmt Statement, associated with the directive.
1575 /// \param Exprs Helper expressions for CodeGen.
1576 /// \param TaskRedRef Task reduction special reference expression to handle
1577 /// taskgroup descriptor.
1578 /// \param HasCancel true if current directive has inner cancel directive.
1579 ///
1580 static OMPForDirective *Create(const ASTContext &C, SourceLocation StartLoc,
1581 SourceLocation EndLoc, unsigned CollapsedNum,
1582 ArrayRef<OMPClause *> Clauses,
1583 Stmt *AssociatedStmt, const HelperExprs &Exprs,
1584 Expr *TaskRedRef, bool HasCancel);
1585
1586 /// Creates an empty directive with the place
1587 /// for \a NumClauses clauses.
1588 ///
1589 /// \param C AST context.
1590 /// \param CollapsedNum Number of collapsed nested loops.
1591 /// \param NumClauses Number of clauses.
1592 ///
1593 static OMPForDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
1594 unsigned CollapsedNum, EmptyShell);
1595
1596 /// Returns special task reduction reference expression.
1597 Expr *getTaskReductionRefExpr() {
1598 return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
1599 getLoopsNumber(), llvm::omp::OMPD_for)]);
1600 }
1601 const Expr *getTaskReductionRefExpr() const {
1602 return const_cast<OMPForDirective *>(this)->getTaskReductionRefExpr();
1603 }
1604
1605 /// Return true if current directive has inner cancel directive.
1606 bool hasCancel() const { return HasCancel; }
1607
1608 static bool classof(const Stmt *T) {
1609 return T->getStmtClass() == OMPForDirectiveClass;
1610 }
1611};
1612
1613/// This represents '#pragma omp for simd' directive.
1614///
1615/// \code
1616/// #pragma omp for simd private(a,b) linear(i,j:s) reduction(+:c,d)
1617/// \endcode
1618/// In this example directive '#pragma omp for simd' has clauses 'private'
1619/// with the variables 'a' and 'b', 'linear' with variables 'i', 'j' and
1620/// linear step 's', 'reduction' with operator '+' and variables 'c' and 'd'.
1621///
1622class OMPForSimdDirective : public OMPLoopDirective {
1623 friend class ASTStmtReader;
1624 friend class OMPExecutableDirective;
1625 /// Build directive with the given start and end location.
1626 ///
1627 /// \param StartLoc Starting location of the directive kind.
1628 /// \param EndLoc Ending location of the directive.
1629 /// \param CollapsedNum Number of collapsed nested loops.
1630 ///
1631 OMPForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
1632 unsigned CollapsedNum)
1633 : OMPLoopDirective(OMPForSimdDirectiveClass, llvm::omp::OMPD_for_simd,
1634 StartLoc, EndLoc, CollapsedNum) {}
1635
1636 /// Build an empty directive.
1637 ///
1638 /// \param CollapsedNum Number of collapsed nested loops.
1639 ///
1640 explicit OMPForSimdDirective(unsigned CollapsedNum)
1641 : OMPLoopDirective(OMPForSimdDirectiveClass, llvm::omp::OMPD_for_simd,
1642 SourceLocation(), SourceLocation(), CollapsedNum) {}
1643
1644public:
1645 /// Creates directive with a list of \a Clauses.
1646 ///
1647 /// \param C AST context.
1648 /// \param StartLoc Starting location of the directive kind.
1649 /// \param EndLoc Ending Location of the directive.
1650 /// \param CollapsedNum Number of collapsed loops.
1651 /// \param Clauses List of clauses.
1652 /// \param AssociatedStmt Statement, associated with the directive.
1653 /// \param Exprs Helper expressions for CodeGen.
1654 ///
1655 static OMPForSimdDirective *
1656 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
1657 unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
1658 Stmt *AssociatedStmt, const HelperExprs &Exprs);
1659
1660 /// Creates an empty directive with the place
1661 /// for \a NumClauses clauses.
1662 ///
1663 /// \param C AST context.
1664 /// \param CollapsedNum Number of collapsed nested loops.
1665 /// \param NumClauses Number of clauses.
1666 ///
1667 static OMPForSimdDirective *CreateEmpty(const ASTContext &C,
1668 unsigned NumClauses,
1669 unsigned CollapsedNum, EmptyShell);
1670
1671 static bool classof(const Stmt *T) {
1672 return T->getStmtClass() == OMPForSimdDirectiveClass;
1673 }
1674};
1675
1676/// This represents '#pragma omp sections' directive.
1677///
1678/// \code
1679/// #pragma omp sections private(a,b) reduction(+:c,d)
1680/// \endcode
1681/// In this example directive '#pragma omp sections' has clauses 'private' with
1682/// the variables 'a' and 'b' and 'reduction' with operator '+' and variables
1683/// 'c' and 'd'.
1684///
1685class OMPSectionsDirective : public OMPExecutableDirective {
1686 friend class ASTStmtReader;
1687 friend class OMPExecutableDirective;
1688
1689 /// true if current directive has inner cancel directive.
1690 bool HasCancel = false;
1691
1692 /// Build directive with the given start and end location.
1693 ///
1694 /// \param StartLoc Starting location of the directive kind.
1695 /// \param EndLoc Ending location of the directive.
1696 ///
1697 OMPSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1698 : OMPExecutableDirective(OMPSectionsDirectiveClass,
1699 llvm::omp::OMPD_sections, StartLoc, EndLoc) {}
1700
1701 /// Build an empty directive.
1702 ///
1703 explicit OMPSectionsDirective()
1704 : OMPExecutableDirective(OMPSectionsDirectiveClass,
1705 llvm::omp::OMPD_sections, SourceLocation(),
1706 SourceLocation()) {}
1707
1708 /// Sets special task reduction descriptor.
1709 void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
1710
1711 /// Set cancel state.
1712 void setHasCancel(bool Has) { HasCancel = Has; }
1713
1714public:
1715 /// Creates directive with a list of \a Clauses.
1716 ///
1717 /// \param C AST context.
1718 /// \param StartLoc Starting location of the directive kind.
1719 /// \param EndLoc Ending Location of the directive.
1720 /// \param Clauses List of clauses.
1721 /// \param AssociatedStmt Statement, associated with the directive.
1722 /// \param TaskRedRef Task reduction special reference expression to handle
1723 /// taskgroup descriptor.
1724 /// \param HasCancel true if current directive has inner directive.
1725 ///
1726 static OMPSectionsDirective *
1727 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
1728 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
1729 bool HasCancel);
1730
1731 /// Creates an empty directive with the place for \a NumClauses
1732 /// clauses.
1733 ///
1734 /// \param C AST context.
1735 /// \param NumClauses Number of clauses.
1736 ///
1737 static OMPSectionsDirective *CreateEmpty(const ASTContext &C,
1738 unsigned NumClauses, EmptyShell);
1739
1740 /// Returns special task reduction reference expression.
1741 Expr *getTaskReductionRefExpr() {
1742 return cast_or_null<Expr>(Data->getChildren()[0]);
1743 }
1744 const Expr *getTaskReductionRefExpr() const {
1745 return const_cast<OMPSectionsDirective *>(this)->getTaskReductionRefExpr();
1746 }
1747
1748 /// Return true if current directive has inner cancel directive.
1749 bool hasCancel() const { return HasCancel; }
1750
1751 static bool classof(const Stmt *T) {
1752 return T->getStmtClass() == OMPSectionsDirectiveClass;
1753 }
1754};
1755
1756/// This represents '#pragma omp section' directive.
1757///
1758/// \code
1759/// #pragma omp section
1760/// \endcode
1761///
1762class OMPSectionDirective : public OMPExecutableDirective {
1763 friend class ASTStmtReader;
1764 friend class OMPExecutableDirective;
1765
1766 /// true if current directive has inner cancel directive.
1767 bool HasCancel = false;
1768
1769 /// Build directive with the given start and end location.
1770 ///
1771 /// \param StartLoc Starting location of the directive kind.
1772 /// \param EndLoc Ending location of the directive.
1773 ///
1774 OMPSectionDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1775 : OMPExecutableDirective(OMPSectionDirectiveClass,
1776 llvm::omp::OMPD_section, StartLoc, EndLoc) {}
1777
1778 /// Build an empty directive.
1779 ///
1780 explicit OMPSectionDirective()
1781 : OMPExecutableDirective(OMPSectionDirectiveClass,
1782 llvm::omp::OMPD_section, SourceLocation(),
1783 SourceLocation()) {}
1784
1785public:
1786 /// Creates directive.
1787 ///
1788 /// \param C AST context.
1789 /// \param StartLoc Starting location of the directive kind.
1790 /// \param EndLoc Ending Location of the directive.
1791 /// \param AssociatedStmt Statement, associated with the directive.
1792 /// \param HasCancel true if current directive has inner directive.
1793 ///
1794 static OMPSectionDirective *Create(const ASTContext &C,
1795 SourceLocation StartLoc,
1796 SourceLocation EndLoc,
1797 Stmt *AssociatedStmt, bool HasCancel);
1798
1799 /// Creates an empty directive.
1800 ///
1801 /// \param C AST context.
1802 ///
1803 static OMPSectionDirective *CreateEmpty(const ASTContext &C, EmptyShell);
1804
1805 /// Set cancel state.
1806 void setHasCancel(bool Has) { HasCancel = Has; }
1807
1808 /// Return true if current directive has inner cancel directive.
1809 bool hasCancel() const { return HasCancel; }
1810
1811 static bool classof(const Stmt *T) {
1812 return T->getStmtClass() == OMPSectionDirectiveClass;
1813 }
1814};
1815
1816/// This represents '#pragma omp single' directive.
1817///
1818/// \code
1819/// #pragma omp single private(a,b) copyprivate(c,d)
1820/// \endcode
1821/// In this example directive '#pragma omp single' has clauses 'private' with
1822/// the variables 'a' and 'b' and 'copyprivate' with variables 'c' and 'd'.
1823///
1824class OMPSingleDirective : public OMPExecutableDirective {
1825 friend class ASTStmtReader;
1826 friend class OMPExecutableDirective;
1827 /// Build directive with the given start and end location.
1828 ///
1829 /// \param StartLoc Starting location of the directive kind.
1830 /// \param EndLoc Ending location of the directive.
1831 ///
1832 OMPSingleDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1833 : OMPExecutableDirective(OMPSingleDirectiveClass, llvm::omp::OMPD_single,
1834 StartLoc, EndLoc) {}
1835
1836 /// Build an empty directive.
1837 ///
1838 explicit OMPSingleDirective()
1839 : OMPExecutableDirective(OMPSingleDirectiveClass, llvm::omp::OMPD_single,
1840 SourceLocation(), SourceLocation()) {}
1841
1842public:
1843 /// Creates directive with a list of \a Clauses.
1844 ///
1845 /// \param C AST context.
1846 /// \param StartLoc Starting location of the directive kind.
1847 /// \param EndLoc Ending Location of the directive.
1848 /// \param Clauses List of clauses.
1849 /// \param AssociatedStmt Statement, associated with the directive.
1850 ///
1851 static OMPSingleDirective *
1852 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
1853 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
1854
1855 /// Creates an empty directive with the place for \a NumClauses
1856 /// clauses.
1857 ///
1858 /// \param C AST context.
1859 /// \param NumClauses Number of clauses.
1860 ///
1861 static OMPSingleDirective *CreateEmpty(const ASTContext &C,
1862 unsigned NumClauses, EmptyShell);
1863
1864 static bool classof(const Stmt *T) {
1865 return T->getStmtClass() == OMPSingleDirectiveClass;
1866 }
1867};
1868
1869/// This represents '#pragma omp master' directive.
1870///
1871/// \code
1872/// #pragma omp master
1873/// \endcode
1874///
1875class OMPMasterDirective : public OMPExecutableDirective {
1876 friend class ASTStmtReader;
1877 friend class OMPExecutableDirective;
1878 /// Build directive with the given start and end location.
1879 ///
1880 /// \param StartLoc Starting location of the directive kind.
1881 /// \param EndLoc Ending location of the directive.
1882 ///
1883 OMPMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
1884 : OMPExecutableDirective(OMPMasterDirectiveClass, llvm::omp::OMPD_master,
1885 StartLoc, EndLoc) {}
1886
1887 /// Build an empty directive.
1888 ///
1889 explicit OMPMasterDirective()
1890 : OMPExecutableDirective(OMPMasterDirectiveClass, llvm::omp::OMPD_master,
1891 SourceLocation(), SourceLocation()) {}
1892
1893public:
1894 /// Creates directive.
1895 ///
1896 /// \param C AST context.
1897 /// \param StartLoc Starting location of the directive kind.
1898 /// \param EndLoc Ending Location of the directive.
1899 /// \param AssociatedStmt Statement, associated with the directive.
1900 ///
1901 static OMPMasterDirective *Create(const ASTContext &C,
1902 SourceLocation StartLoc,
1903 SourceLocation EndLoc,
1904 Stmt *AssociatedStmt);
1905
1906 /// Creates an empty directive.
1907 ///
1908 /// \param C AST context.
1909 ///
1910 static OMPMasterDirective *CreateEmpty(const ASTContext &C, EmptyShell);
1911
1912 static bool classof(const Stmt *T) {
1913 return T->getStmtClass() == OMPMasterDirectiveClass;
1914 }
1915};
1916
1917/// This represents '#pragma omp critical' directive.
1918///
1919/// \code
1920/// #pragma omp critical
1921/// \endcode
1922///
1923class OMPCriticalDirective : public OMPExecutableDirective {
1924 friend class ASTStmtReader;
1925 friend class OMPExecutableDirective;
1926 /// Name of the directive.
1927 DeclarationNameInfo DirName;
1928 /// Build directive with the given start and end location.
1929 ///
1930 /// \param Name Name of the directive.
1931 /// \param StartLoc Starting location of the directive kind.
1932 /// \param EndLoc Ending location of the directive.
1933 ///
1934 OMPCriticalDirective(const DeclarationNameInfo &Name, SourceLocation StartLoc,
1935 SourceLocation EndLoc)
1936 : OMPExecutableDirective(OMPCriticalDirectiveClass,
1937 llvm::omp::OMPD_critical, StartLoc, EndLoc),
1938 DirName(Name) {}
1939
1940 /// Build an empty directive.
1941 ///
1942 explicit OMPCriticalDirective()
1943 : OMPExecutableDirective(OMPCriticalDirectiveClass,
1944 llvm::omp::OMPD_critical, SourceLocation(),
1945 SourceLocation()) {}
1946
1947 /// Set name of the directive.
1948 ///
1949 /// \param Name Name of the directive.
1950 ///
1951 void setDirectiveName(const DeclarationNameInfo &Name) { DirName = Name; }
1952
1953public:
1954 /// Creates directive.
1955 ///
1956 /// \param C AST context.
1957 /// \param Name Name of the directive.
1958 /// \param StartLoc Starting location of the directive kind.
1959 /// \param EndLoc Ending Location of the directive.
1960 /// \param Clauses List of clauses.
1961 /// \param AssociatedStmt Statement, associated with the directive.
1962 ///
1963 static OMPCriticalDirective *
1964 Create(const ASTContext &C, const DeclarationNameInfo &Name,
1965 SourceLocation StartLoc, SourceLocation EndLoc,
1966 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
1967
1968 /// Creates an empty directive.
1969 ///
1970 /// \param C AST context.
1971 /// \param NumClauses Number of clauses.
1972 ///
1973 static OMPCriticalDirective *CreateEmpty(const ASTContext &C,
1974 unsigned NumClauses, EmptyShell);
1975
1976 /// Return name of the directive.
1977 ///
1978 DeclarationNameInfo getDirectiveName() const { return DirName; }
1979
1980 static bool classof(const Stmt *T) {
1981 return T->getStmtClass() == OMPCriticalDirectiveClass;
1982 }
1983};
1984
1985/// This represents '#pragma omp parallel for' directive.
1986///
1987/// \code
1988/// #pragma omp parallel for private(a,b) reduction(+:c,d)
1989/// \endcode
1990/// In this example directive '#pragma omp parallel for' has clauses 'private'
1991/// with the variables 'a' and 'b' and 'reduction' with operator '+' and
1992/// variables 'c' and 'd'.
1993///
1994class OMPParallelForDirective : public OMPLoopDirective {
1995 friend class ASTStmtReader;
1996 friend class OMPExecutableDirective;
1997
1998 /// true if current region has inner cancel directive.
1999 bool HasCancel = false;
2000
2001 /// Build directive with the given start and end location.
2002 ///
2003 /// \param StartLoc Starting location of the directive kind.
2004 /// \param EndLoc Ending location of the directive.
2005 /// \param CollapsedNum Number of collapsed nested loops.
2006 ///
2007 OMPParallelForDirective(SourceLocation StartLoc, SourceLocation EndLoc,
2008 unsigned CollapsedNum)
2009 : OMPLoopDirective(OMPParallelForDirectiveClass,
2010 llvm::omp::OMPD_parallel_for, StartLoc, EndLoc,
2011 CollapsedNum) {}
2012
2013 /// Build an empty directive.
2014 ///
2015 /// \param CollapsedNum Number of collapsed nested loops.
2016 ///
2017 explicit OMPParallelForDirective(unsigned CollapsedNum)
2018 : OMPLoopDirective(OMPParallelForDirectiveClass,
2019 llvm::omp::OMPD_parallel_for, SourceLocation(),
2020 SourceLocation(), CollapsedNum) {}
2021
2022 /// Sets special task reduction descriptor.
2023 void setTaskReductionRefExpr(Expr *E) {
2024 Data->getChildren()[numLoopChildren(getLoopsNumber(),
2025 llvm::omp::OMPD_parallel_for)] = E;
2026 }
2027
2028 /// Set cancel state.
2029 void setHasCancel(bool Has) { HasCancel = Has; }
2030
2031public:
2032 /// Creates directive with a list of \a Clauses.
2033 ///
2034 /// \param C AST context.
2035 /// \param StartLoc Starting location of the directive kind.
2036 /// \param EndLoc Ending Location of the directive.
2037 /// \param CollapsedNum Number of collapsed loops.
2038 /// \param Clauses List of clauses.
2039 /// \param AssociatedStmt Statement, associated with the directive.
2040 /// \param Exprs Helper expressions for CodeGen.
2041 /// \param TaskRedRef Task reduction special reference expression to handle
2042 /// taskgroup descriptor.
2043 /// \param HasCancel true if current directive has inner cancel directive.
2044 ///
2045 static OMPParallelForDirective *
2046 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2047 unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
2048 Stmt *AssociatedStmt, const HelperExprs &Exprs, Expr *TaskRedRef,
2049 bool HasCancel);
2050
2051 /// Creates an empty directive with the place
2052 /// for \a NumClauses clauses.
2053 ///
2054 /// \param C AST context.
2055 /// \param CollapsedNum Number of collapsed nested loops.
2056 /// \param NumClauses Number of clauses.
2057 ///
2058 static OMPParallelForDirective *CreateEmpty(const ASTContext &C,
2059 unsigned NumClauses,
2060 unsigned CollapsedNum,
2061 EmptyShell);
2062
2063 /// Returns special task reduction reference expression.
2064 Expr *getTaskReductionRefExpr() {
2065 return cast_or_null<Expr>(Data->getChildren()[numLoopChildren(
2066 getLoopsNumber(), llvm::omp::OMPD_parallel_for)]);
2067 }
2068 const Expr *getTaskReductionRefExpr() const {
2069 return const_cast<OMPParallelForDirective *>(this)
2070 ->getTaskReductionRefExpr();
2071 }
2072
2073 /// Return true if current directive has inner cancel directive.
2074 bool hasCancel() const { return HasCancel; }
2075
2076 static bool classof(const Stmt *T) {
2077 return T->getStmtClass() == OMPParallelForDirectiveClass;
2078 }
2079};
2080
2081/// This represents '#pragma omp parallel for simd' directive.
2082///
2083/// \code
2084/// #pragma omp parallel for simd private(a,b) linear(i,j:s) reduction(+:c,d)
2085/// \endcode
2086/// In this example directive '#pragma omp parallel for simd' has clauses
2087/// 'private' with the variables 'a' and 'b', 'linear' with variables 'i', 'j'
2088/// and linear step 's', 'reduction' with operator '+' and variables 'c' and
2089/// 'd'.
2090///
2091class OMPParallelForSimdDirective : public OMPLoopDirective {
2092 friend class ASTStmtReader;
2093 friend class OMPExecutableDirective;
2094 /// Build directive with the given start and end location.
2095 ///
2096 /// \param StartLoc Starting location of the directive kind.
2097 /// \param EndLoc Ending location of the directive.
2098 /// \param CollapsedNum Number of collapsed nested loops.
2099 ///
2100 OMPParallelForSimdDirective(SourceLocation StartLoc, SourceLocation EndLoc,
2101 unsigned CollapsedNum)
2102 : OMPLoopDirective(OMPParallelForSimdDirectiveClass,
2103 llvm::omp::OMPD_parallel_for_simd, StartLoc, EndLoc,
2104 CollapsedNum) {}
2105
2106 /// Build an empty directive.
2107 ///
2108 /// \param CollapsedNum Number of collapsed nested loops.
2109 ///
2110 explicit OMPParallelForSimdDirective(unsigned CollapsedNum)
2111 : OMPLoopDirective(OMPParallelForSimdDirectiveClass,
2112 llvm::omp::OMPD_parallel_for_simd, SourceLocation(),
2113 SourceLocation(), CollapsedNum) {}
2114
2115public:
2116 /// Creates directive with a list of \a Clauses.
2117 ///
2118 /// \param C AST context.
2119 /// \param StartLoc Starting location of the directive kind.
2120 /// \param EndLoc Ending Location of the directive.
2121 /// \param CollapsedNum Number of collapsed loops.
2122 /// \param Clauses List of clauses.
2123 /// \param AssociatedStmt Statement, associated with the directive.
2124 /// \param Exprs Helper expressions for CodeGen.
2125 ///
2126 static OMPParallelForSimdDirective *
2127 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2128 unsigned CollapsedNum, ArrayRef<OMPClause *> Clauses,
2129 Stmt *AssociatedStmt, const HelperExprs &Exprs);
2130
2131 /// Creates an empty directive with the place
2132 /// for \a NumClauses clauses.
2133 ///
2134 /// \param C AST context.
2135 /// \param CollapsedNum Number of collapsed nested loops.
2136 /// \param NumClauses Number of clauses.
2137 ///
2138 static OMPParallelForSimdDirective *CreateEmpty(const ASTContext &C,
2139 unsigned NumClauses,
2140 unsigned CollapsedNum,
2141 EmptyShell);
2142
2143 static bool classof(const Stmt *T) {
2144 return T->getStmtClass() == OMPParallelForSimdDirectiveClass;
2145 }
2146};
2147
2148/// This represents '#pragma omp parallel master' directive.
2149///
2150/// \code
2151/// #pragma omp parallel master private(a,b)
2152/// \endcode
2153/// In this example directive '#pragma omp parallel master' has clauses
2154/// 'private' with the variables 'a' and 'b'
2155///
2156class OMPParallelMasterDirective : public OMPExecutableDirective {
2157 friend class ASTStmtReader;
2158 friend class OMPExecutableDirective;
2159
2160 OMPParallelMasterDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2161 : OMPExecutableDirective(OMPParallelMasterDirectiveClass,
2162 llvm::omp::OMPD_parallel_master, StartLoc,
2163 EndLoc) {}
2164
2165 explicit OMPParallelMasterDirective()
2166 : OMPExecutableDirective(OMPParallelMasterDirectiveClass,
2167 llvm::omp::OMPD_parallel_master,
2168 SourceLocation(), SourceLocation()) {}
2169
2170 /// Sets special task reduction descriptor.
2171 void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
2172
2173public:
2174 /// Creates directive with a list of \a Clauses.
2175 ///
2176 /// \param C AST context.
2177 /// \param StartLoc Starting location of the directive kind.
2178 /// \param EndLoc Ending Location of the directive.
2179 /// \param Clauses List of clauses.
2180 /// \param AssociatedStmt Statement, associated with the directive.
2181 /// \param TaskRedRef Task reduction special reference expression to handle
2182 /// taskgroup descriptor.
2183 ///
2184 static OMPParallelMasterDirective *
2185 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2186 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef);
2187
2188 /// Creates an empty directive with the place for \a NumClauses
2189 /// clauses.
2190 ///
2191 /// \param C AST context.
2192 /// \param NumClauses Number of clauses.
2193 ///
2194 static OMPParallelMasterDirective *
2195 CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
2196
2197 /// Returns special task reduction reference expression.
2198 Expr *getTaskReductionRefExpr() {
2199 return cast_or_null<Expr>(Data->getChildren()[0]);
2200 }
2201 const Expr *getTaskReductionRefExpr() const {
2202 return const_cast<OMPParallelMasterDirective *>(this)
2203 ->getTaskReductionRefExpr();
2204 }
2205
2206 static bool classof(const Stmt *T) {
2207 return T->getStmtClass() == OMPParallelMasterDirectiveClass;
2208 }
2209};
2210
2211/// This represents '#pragma omp parallel sections' directive.
2212///
2213/// \code
2214/// #pragma omp parallel sections private(a,b) reduction(+:c,d)
2215/// \endcode
2216/// In this example directive '#pragma omp parallel sections' has clauses
2217/// 'private' with the variables 'a' and 'b' and 'reduction' with operator '+'
2218/// and variables 'c' and 'd'.
2219///
2220class OMPParallelSectionsDirective : public OMPExecutableDirective {
2221 friend class ASTStmtReader;
2222 friend class OMPExecutableDirective;
2223
2224 /// true if current directive has inner cancel directive.
2225 bool HasCancel = false;
2226
2227 /// Build directive with the given start and end location.
2228 ///
2229 /// \param StartLoc Starting location of the directive kind.
2230 /// \param EndLoc Ending location of the directive.
2231 ///
2232 OMPParallelSectionsDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2233 : OMPExecutableDirective(OMPParallelSectionsDirectiveClass,
2234 llvm::omp::OMPD_parallel_sections, StartLoc,
2235 EndLoc) {}
2236
2237 /// Build an empty directive.
2238 ///
2239 explicit OMPParallelSectionsDirective()
2240 : OMPExecutableDirective(OMPParallelSectionsDirectiveClass,
2241 llvm::omp::OMPD_parallel_sections,
2242 SourceLocation(), SourceLocation()) {}
2243
2244 /// Sets special task reduction descriptor.
2245 void setTaskReductionRefExpr(Expr *E) { Data->getChildren()[0] = E; }
2246
2247 /// Set cancel state.
2248 void setHasCancel(bool Has) { HasCancel = Has; }
2249
2250public:
2251 /// Creates directive with a list of \a Clauses.
2252 ///
2253 /// \param C AST context.
2254 /// \param StartLoc Starting location of the directive kind.
2255 /// \param EndLoc Ending Location of the directive.
2256 /// \param Clauses List of clauses.
2257 /// \param AssociatedStmt Statement, associated with the directive.
2258 /// \param TaskRedRef Task reduction special reference expression to handle
2259 /// taskgroup descriptor.
2260 /// \param HasCancel true if current directive has inner cancel directive.
2261 ///
2262 static OMPParallelSectionsDirective *
2263 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2264 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *TaskRedRef,
2265 bool HasCancel);
2266
2267 /// Creates an empty directive with the place for \a NumClauses
2268 /// clauses.
2269 ///
2270 /// \param C AST context.
2271 /// \param NumClauses Number of clauses.
2272 ///
2273 static OMPParallelSectionsDirective *
2274 CreateEmpty(const ASTContext &C, unsigned NumClauses, EmptyShell);
2275
2276 /// Returns special task reduction reference expression.
2277 Expr *getTaskReductionRefExpr() {
2278 return cast_or_null<Expr>(Data->getChildren()[0]);
2279 }
2280 const Expr *getTaskReductionRefExpr() const {
2281 return const_cast<OMPParallelSectionsDirective *>(this)
2282 ->getTaskReductionRefExpr();
2283 }
2284
2285 /// Return true if current directive has inner cancel directive.
2286 bool hasCancel() const { return HasCancel; }
2287
2288 static bool classof(const Stmt *T) {
2289 return T->getStmtClass() == OMPParallelSectionsDirectiveClass;
2290 }
2291};
2292
2293/// This represents '#pragma omp task' directive.
2294///
2295/// \code
2296/// #pragma omp task private(a,b) final(d)
2297/// \endcode
2298/// In this example directive '#pragma omp task' has clauses 'private' with the
2299/// variables 'a' and 'b' and 'final' with condition 'd'.
2300///
2301class OMPTaskDirective : public OMPExecutableDirective {
2302 friend class ASTStmtReader;
2303 friend class OMPExecutableDirective;
2304 /// true if this directive has inner cancel directive.
2305 bool HasCancel = false;
2306
2307 /// Build directive with the given start and end location.
2308 ///
2309 /// \param StartLoc Starting location of the directive kind.
2310 /// \param EndLoc Ending location of the directive.
2311 ///
2312 OMPTaskDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2313 : OMPExecutableDirective(OMPTaskDirectiveClass, llvm::omp::OMPD_task,
2314 StartLoc, EndLoc) {}
2315
2316 /// Build an empty directive.
2317 ///
2318 explicit OMPTaskDirective()
2319 : OMPExecutableDirective(OMPTaskDirectiveClass, llvm::omp::OMPD_task,
2320 SourceLocation(), SourceLocation()) {}
2321
2322 /// Set cancel state.
2323 void setHasCancel(bool Has) { HasCancel = Has; }
2324
2325public:
2326 /// Creates directive with a list of \a Clauses.
2327 ///
2328 /// \param C AST context.
2329 /// \param StartLoc Starting location of the directive kind.
2330 /// \param EndLoc Ending Location of the directive.
2331 /// \param Clauses List of clauses.
2332 /// \param AssociatedStmt Statement, associated with the directive.
2333 /// \param HasCancel true, if current directive has inner cancel directive.
2334 ///
2335 static OMPTaskDirective *Create(const ASTContext &C, SourceLocation StartLoc,
2336 SourceLocation EndLoc,
2337 ArrayRef<OMPClause *> Clauses,
2338 Stmt *AssociatedStmt, bool HasCancel);
2339
2340 /// Creates an empty directive with the place for \a NumClauses
2341 /// clauses.
2342 ///
2343 /// \param C AST context.
2344 /// \param NumClauses Number of clauses.
2345 ///
2346 static OMPTaskDirective *CreateEmpty(const ASTContext &C, unsigned NumClauses,
2347 EmptyShell);
2348
2349 /// Return true if current directive has inner cancel directive.
2350 bool hasCancel() const { return HasCancel; }
2351
2352 static bool classof(const Stmt *T) {
2353 return T->getStmtClass() == OMPTaskDirectiveClass;
2354 }
2355};
2356
2357/// This represents '#pragma omp taskyield' directive.
2358///
2359/// \code
2360/// #pragma omp taskyield
2361/// \endcode
2362///
2363class OMPTaskyieldDirective : public OMPExecutableDirective {
2364 friend class ASTStmtReader;
2365 friend class OMPExecutableDirective;
2366 /// Build directive with the given start and end location.
2367 ///
2368 /// \param StartLoc Starting location of the directive kind.
2369 /// \param EndLoc Ending location of the directive.
2370 ///
2371 OMPTaskyieldDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2372 : OMPExecutableDirective(OMPTaskyieldDirectiveClass,
2373 llvm::omp::OMPD_taskyield, StartLoc, EndLoc) {}
2374
2375 /// Build an empty directive.
2376 ///
2377 explicit OMPTaskyieldDirective()
2378 : OMPExecutableDirective(OMPTaskyieldDirectiveClass,
2379 llvm::omp::OMPD_taskyield, SourceLocation(),
2380 SourceLocation()) {}
2381
2382public:
2383 /// Creates directive.
2384 ///
2385 /// \param C AST context.
2386 /// \param StartLoc Starting location of the directive kind.
2387 /// \param EndLoc Ending Location of the directive.
2388 ///
2389 static OMPTaskyieldDirective *
2390 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
2391
2392 /// Creates an empty directive.
2393 ///
2394 /// \param C AST context.
2395 ///
2396 static OMPTaskyieldDirective *CreateEmpty(const ASTContext &C, EmptyShell);
2397
2398 static bool classof(const Stmt *T) {
2399 return T->getStmtClass() == OMPTaskyieldDirectiveClass;
2400 }
2401};
2402
2403/// This represents '#pragma omp barrier' directive.
2404///
2405/// \code
2406/// #pragma omp barrier
2407/// \endcode
2408///
2409class OMPBarrierDirective : public OMPExecutableDirective {
2410 friend class ASTStmtReader;
2411 friend class OMPExecutableDirective;
2412 /// Build directive with the given start and end location.
2413 ///
2414 /// \param StartLoc Starting location of the directive kind.
2415 /// \param EndLoc Ending location of the directive.
2416 ///
2417 OMPBarrierDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2418 : OMPExecutableDirective(OMPBarrierDirectiveClass,
2419 llvm::omp::OMPD_barrier, StartLoc, EndLoc) {}
2420
2421 /// Build an empty directive.
2422 ///
2423 explicit OMPBarrierDirective()
2424 : OMPExecutableDirective(OMPBarrierDirectiveClass,
2425 llvm::omp::OMPD_barrier, SourceLocation(),
2426 SourceLocation()) {}
2427
2428public:
2429 /// Creates directive.
2430 ///
2431 /// \param C AST context.
2432 /// \param StartLoc Starting location of the directive kind.
2433 /// \param EndLoc Ending Location of the directive.
2434 ///
2435 static OMPBarrierDirective *
2436 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
2437
2438 /// Creates an empty directive.
2439 ///
2440 /// \param C AST context.
2441 ///
2442 static OMPBarrierDirective *CreateEmpty(const ASTContext &C, EmptyShell);
2443
2444 static bool classof(const Stmt *T) {
2445 return T->getStmtClass() == OMPBarrierDirectiveClass;
2446 }
2447};
2448
2449/// This represents '#pragma omp taskwait' directive.
2450///
2451/// \code
2452/// #pragma omp taskwait
2453/// \endcode
2454///
2455class OMPTaskwaitDirective : public OMPExecutableDirective {
2456 friend class ASTStmtReader;
2457 friend class OMPExecutableDirective;
2458 /// Build directive with the given start and end location.
2459 ///
2460 /// \param StartLoc Starting location of the directive kind.
2461 /// \param EndLoc Ending location of the directive.
2462 ///
2463 OMPTaskwaitDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2464 : OMPExecutableDirective(OMPTaskwaitDirectiveClass,
2465 llvm::omp::OMPD_taskwait, StartLoc, EndLoc) {}
2466
2467 /// Build an empty directive.
2468 ///
2469 explicit OMPTaskwaitDirective()
2470 : OMPExecutableDirective(OMPTaskwaitDirectiveClass,
2471 llvm::omp::OMPD_taskwait, SourceLocation(),
2472 SourceLocation()) {}
2473
2474public:
2475 /// Creates directive.
2476 ///
2477 /// \param C AST context.
2478 /// \param StartLoc Starting location of the directive kind.
2479 /// \param EndLoc Ending Location of the directive.
2480 ///
2481 static OMPTaskwaitDirective *
2482 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc);
2483
2484 /// Creates an empty directive.
2485 ///
2486 /// \param C AST context.
2487 ///
2488 static OMPTaskwaitDirective *CreateEmpty(const ASTContext &C, EmptyShell);
2489
2490 static bool classof(const Stmt *T) {
2491 return T->getStmtClass() == OMPTaskwaitDirectiveClass;
2492 }
2493};
2494
2495/// This represents '#pragma omp taskgroup' directive.
2496///
2497/// \code
2498/// #pragma omp taskgroup
2499/// \endcode
2500///
2501class OMPTaskgroupDirective : public OMPExecutableDirective {
2502 friend class ASTStmtReader;
2503 friend class OMPExecutableDirective;
2504 /// Build directive with the given start and end location.
2505 ///
2506 /// \param StartLoc Starting location of the directive kind.
2507 /// \param EndLoc Ending location of the directive.
2508 ///
2509 OMPTaskgroupDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2510 : OMPExecutableDirective(OMPTaskgroupDirectiveClass,
2511 llvm::omp::OMPD_taskgroup, StartLoc, EndLoc) {}
2512
2513 /// Build an empty directive.
2514 ///
2515 explicit OMPTaskgroupDirective()
2516 : OMPExecutableDirective(OMPTaskgroupDirectiveClass,
2517 llvm::omp::OMPD_taskgroup, SourceLocation(),
2518 SourceLocation()) {}
2519
2520 /// Sets the task_reduction return variable.
2521 void setReductionRef(Expr *RR) { Data->getChildren()[0] = RR; }
2522
2523public:
2524 /// Creates directive.
2525 ///
2526 /// \param C AST context.
2527 /// \param StartLoc Starting location of the directive kind.
2528 /// \param EndLoc Ending Location of the directive.
2529 /// \param Clauses List of clauses.
2530 /// \param AssociatedStmt Statement, associated with the directive.
2531 /// \param ReductionRef Reference to the task_reduction return variable.
2532 ///
2533 static OMPTaskgroupDirective *
2534 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2535 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt,
2536 Expr *ReductionRef);
2537
2538 /// Creates an empty directive.
2539 ///
2540 /// \param C AST context.
2541 /// \param NumClauses Number of clauses.
2542 ///
2543 static OMPTaskgroupDirective *CreateEmpty(const ASTContext &C,
2544 unsigned NumClauses, EmptyShell);
2545
2546
2547 /// Returns reference to the task_reduction return variable.
2548 const Expr *getReductionRef() const {
2549 return const_cast<OMPTaskgroupDirective *>(this)->getReductionRef();
2550 }
2551 Expr *getReductionRef() { return cast_or_null<Expr>(Data->getChildren()[0]); }
2552
2553 static bool classof(const Stmt *T) {
2554 return T->getStmtClass() == OMPTaskgroupDirectiveClass;
2555 }
2556};
2557
2558/// This represents '#pragma omp flush' directive.
2559///
2560/// \code
2561/// #pragma omp flush(a,b)
2562/// \endcode
2563/// In this example directive '#pragma omp flush' has 2 arguments- variables 'a'
2564/// and 'b'.
2565/// 'omp flush' directive does not have clauses but have an optional list of
2566/// variables to flush. This list of variables is stored within some fake clause
2567/// FlushClause.
2568class OMPFlushDirective : public OMPExecutableDirective {
2569 friend class ASTStmtReader;
2570 friend class OMPExecutableDirective;
2571 /// Build directive with the given start and end location.
2572 ///
2573 /// \param StartLoc Starting location of the directive kind.
2574 /// \param EndLoc Ending location of the directive.
2575 ///
2576 OMPFlushDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2577 : OMPExecutableDirective(OMPFlushDirectiveClass, llvm::omp::OMPD_flush,
2578 StartLoc, EndLoc) {}
2579
2580 /// Build an empty directive.
2581 ///
2582 explicit OMPFlushDirective()
2583 : OMPExecutableDirective(OMPFlushDirectiveClass, llvm::omp::OMPD_flush,
2584 SourceLocation(), SourceLocation()) {}
2585
2586public:
2587 /// Creates directive with a list of \a Clauses.
2588 ///
2589 /// \param C AST context.
2590 /// \param StartLoc Starting location of the directive kind.
2591 /// \param EndLoc Ending Location of the directive.
2592 /// \param Clauses List of clauses (only single OMPFlushClause clause is
2593 /// allowed).
2594 ///
2595 static OMPFlushDirective *Create(const ASTContext &C, SourceLocation StartLoc,
2596 SourceLocation EndLoc,
2597 ArrayRef<OMPClause *> Clauses);
2598
2599 /// Creates an empty directive with the place for \a NumClauses
2600 /// clauses.
2601 ///
2602 /// \param C AST context.
2603 /// \param NumClauses Number of clauses.
2604 ///
2605 static OMPFlushDirective *CreateEmpty(const ASTContext &C,
2606 unsigned NumClauses, EmptyShell);
2607
2608 static bool classof(const Stmt *T) {
2609 return T->getStmtClass() == OMPFlushDirectiveClass;
2610 }
2611};
2612
2613/// This represents '#pragma omp depobj' directive.
2614///
2615/// \code
2616/// #pragma omp depobj(a) depend(in:x,y)
2617/// \endcode
2618/// In this example directive '#pragma omp depobj' initializes a depobj object
2619/// 'a' with dependence type 'in' and a list with 'x' and 'y' locators.
2620class OMPDepobjDirective final : public OMPExecutableDirective {
2621 friend class ASTStmtReader;
2622 friend class OMPExecutableDirective;
2623
2624 /// Build directive with the given start and end location.
2625 ///
2626 /// \param StartLoc Starting location of the directive kind.
2627 /// \param EndLoc Ending location of the directive.
2628 ///
2629 OMPDepobjDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2630 : OMPExecutableDirective(OMPDepobjDirectiveClass, llvm::omp::OMPD_depobj,
2631 StartLoc, EndLoc) {}
2632
2633 /// Build an empty directive.
2634 ///
2635 explicit OMPDepobjDirective()
2636 : OMPExecutableDirective(OMPDepobjDirectiveClass, llvm::omp::OMPD_depobj,
2637 SourceLocation(), SourceLocation()) {}
2638
2639public:
2640 /// Creates directive with a list of \a Clauses.
2641 ///
2642 /// \param C AST context.
2643 /// \param StartLoc Starting location of the directive kind.
2644 /// \param EndLoc Ending Location of the directive.
2645 /// \param Clauses List of clauses.
2646 ///
2647 static OMPDepobjDirective *Create(const ASTContext &C,
2648 SourceLocation StartLoc,
2649 SourceLocation EndLoc,
2650 ArrayRef<OMPClause *> Clauses);
2651
2652 /// Creates an empty directive with the place for \a NumClauses
2653 /// clauses.
2654 ///
2655 /// \param C AST context.
2656 /// \param NumClauses Number of clauses.
2657 ///
2658 static OMPDepobjDirective *CreateEmpty(const ASTContext &C,
2659 unsigned NumClauses, EmptyShell);
2660
2661 static bool classof(const Stmt *T) {
2662 return T->getStmtClass() == OMPDepobjDirectiveClass;
2663 }
2664};
2665
2666/// This represents '#pragma omp ordered' directive.
2667///
2668/// \code
2669/// #pragma omp ordered
2670/// \endcode
2671///
2672class OMPOrderedDirective : public OMPExecutableDirective {
2673 friend class ASTStmtReader;
2674 friend class OMPExecutableDirective;
2675 /// Build directive with the given start and end location.
2676 ///
2677 /// \param StartLoc Starting location of the directive kind.
2678 /// \param EndLoc Ending location of the directive.
2679 ///
2680 OMPOrderedDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2681 : OMPExecutableDirective(OMPOrderedDirectiveClass,
2682 llvm::omp::OMPD_ordered, StartLoc, EndLoc) {}
2683
2684 /// Build an empty directive.
2685 ///
2686 explicit OMPOrderedDirective()
2687 : OMPExecutableDirective(OMPOrderedDirectiveClass,
2688 llvm::omp::OMPD_ordered, SourceLocation(),
2689 SourceLocation()) {}
2690
2691public:
2692 /// Creates directive.
2693 ///
2694 /// \param C AST context.
2695 /// \param StartLoc Starting location of the directive kind.
2696 /// \param EndLoc Ending Location of the directive.
2697 /// \param Clauses List of clauses.
2698 /// \param AssociatedStmt Statement, associated with the directive.
2699 ///
2700 static OMPOrderedDirective *
2701 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2702 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
2703
2704 /// Creates an empty directive.
2705 ///
2706 /// \param C AST context.
2707 /// \param NumClauses Number of clauses.
2708 /// \param IsStandalone true, if the the standalone directive is created.
2709 ///
2710 static OMPOrderedDirective *CreateEmpty(const ASTContext &C,
2711 unsigned NumClauses,
2712 bool IsStandalone, EmptyShell);
2713
2714 static bool classof(const Stmt *T) {
2715 return T->getStmtClass() == OMPOrderedDirectiveClass;
2716 }
2717};
2718
2719/// This represents '#pragma omp atomic' directive.
2720///
2721/// \code
2722/// #pragma omp atomic capture
2723/// \endcode
2724/// In this example directive '#pragma omp atomic' has clause 'capture'.
2725///
2726class OMPAtomicDirective : public OMPExecutableDirective {
2727 friend class ASTStmtReader;
2728 friend class OMPExecutableDirective;
2729 /// Used for 'atomic update' or 'atomic capture' constructs. They may
2730 /// have atomic expressions of forms
2731 /// \code
2732 /// x = x binop expr;
2733 /// x = expr binop x;
2734 /// \endcode
2735 /// This field is true for the first form of the expression and false for the
2736 /// second. Required for correct codegen of non-associative operations (like
2737 /// << or >>).
2738 bool IsXLHSInRHSPart = false;
2739 /// Used for 'atomic update' or 'atomic capture' constructs. They may
2740 /// have atomic expressions of forms
2741 /// \code
2742 /// v = x; <update x>;
2743 /// <update x>; v = x;
2744 /// \endcode
2745 /// This field is true for the first(postfix) form of the expression and false
2746 /// otherwise.
2747 bool IsPostfixUpdate = false;
2748
2749 /// Build directive with the given start and end location.
2750 ///
2751 /// \param StartLoc Starting location of the directive kind.
2752 /// \param EndLoc Ending location of the directive.
2753 ///
2754 OMPAtomicDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2755 : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
2756 StartLoc, EndLoc) {}
2757
2758 /// Build an empty directive.
2759 ///
2760 explicit OMPAtomicDirective()
2761 : OMPExecutableDirective(OMPAtomicDirectiveClass, llvm::omp::OMPD_atomic,
2762 SourceLocation(), SourceLocation()) {}
2763
2764 /// Set 'x' part of the associated expression/statement.
2765 void setX(Expr *X) { Data->getChildren()[0] = X; }
2766 /// Set helper expression of the form
2767 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
2768 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
2769 void setUpdateExpr(Expr *UE) { Data->getChildren()[1] = UE; }
2770 /// Set 'v' part of the associated expression/statement.
2771 void setV(Expr *V) { Data->getChildren()[2] = V; }
2772 /// Set 'expr' part of the associated expression/statement.
2773 void setExpr(Expr *E) { Data->getChildren()[3] = E; }
2774
2775public:
2776 /// Creates directive with a list of \a Clauses and 'x', 'v' and 'expr'
2777 /// parts of the atomic construct (see Section 2.12.6, atomic Construct, for
2778 /// detailed description of 'x', 'v' and 'expr').
2779 ///
2780 /// \param C AST context.
2781 /// \param StartLoc Starting location of the directive kind.
2782 /// \param EndLoc Ending Location of the directive.
2783 /// \param Clauses List of clauses.
2784 /// \param AssociatedStmt Statement, associated with the directive.
2785 /// \param X 'x' part of the associated expression/statement.
2786 /// \param V 'v' part of the associated expression/statement.
2787 /// \param E 'expr' part of the associated expression/statement.
2788 /// \param UE Helper expression of the form
2789 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
2790 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
2791 /// \param IsXLHSInRHSPart true if \a UE has the first form and false if the
2792 /// second.
2793 /// \param IsPostfixUpdate true if original value of 'x' must be stored in
2794 /// 'v', not an updated one.
2795 static OMPAtomicDirective *
2796 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2797 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt, Expr *X, Expr *V,
2798 Expr *E, Expr *UE, bool IsXLHSInRHSPart, bool IsPostfixUpdate);
2799
2800 /// Creates an empty directive with the place for \a NumClauses
2801 /// clauses.
2802 ///
2803 /// \param C AST context.
2804 /// \param NumClauses Number of clauses.
2805 ///
2806 static OMPAtomicDirective *CreateEmpty(const ASTContext &C,
2807 unsigned NumClauses, EmptyShell);
2808
2809 /// Get 'x' part of the associated expression/statement.
2810 Expr *getX() { return cast_or_null<Expr>(Data->getChildren()[0]); }
2811 const Expr *getX() const {
2812 return cast_or_null<Expr>(Data->getChildren()[0]);
2813 }
2814 /// Get helper expression of the form
2815 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' or
2816 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
2817 Expr *getUpdateExpr() { return cast_or_null<Expr>(Data->getChildren()[1]); }
2818 const Expr *getUpdateExpr() const {
2819 return cast_or_null<Expr>(Data->getChildren()[1]);
2820 }
2821 /// Return true if helper update expression has form
2822 /// 'OpaqueValueExpr(x) binop OpaqueValueExpr(expr)' and false if it has form
2823 /// 'OpaqueValueExpr(expr) binop OpaqueValueExpr(x)'.
2824 bool isXLHSInRHSPart() const { return IsXLHSInRHSPart; }
2825 /// Return true if 'v' expression must be updated to original value of
2826 /// 'x', false if 'v' must be updated to the new value of 'x'.
2827 bool isPostfixUpdate() const { return IsPostfixUpdate; }
2828 /// Get 'v' part of the associated expression/statement.
2829 Expr *getV() { return cast_or_null<Expr>(Data->getChildren()[2]); }
2830 const Expr *getV() const {
2831 return cast_or_null<Expr>(Data->getChildren()[2]);
2832 }
2833 /// Get 'expr' part of the associated expression/statement.
2834 Expr *getExpr() { return cast_or_null<Expr>(Data->getChildren()[3]); }
2835 const Expr *getExpr() const {
2836 return cast_or_null<Expr>(Data->getChildren()[3]);
2837 }
2838
2839 static bool classof(const Stmt *T) {
2840 return T->getStmtClass() == OMPAtomicDirectiveClass;
2841 }
2842};
2843
2844/// This represents '#pragma omp target' directive.
2845///
2846/// \code
2847/// #pragma omp target if(a)
2848/// \endcode
2849/// In this example directive '#pragma omp target' has clause 'if' with
2850/// condition 'a'.
2851///
2852class OMPTargetDirective : public OMPExecutableDirective {
2853 friend class ASTStmtReader;
2854 friend class OMPExecutableDirective;
2855 /// Build directive with the given start and end location.
2856 ///
2857 /// \param StartLoc Starting location of the directive kind.
2858 /// \param EndLoc Ending location of the directive.
2859 ///
2860 OMPTargetDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2861 : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
2862 StartLoc, EndLoc) {}
2863
2864 /// Build an empty directive.
2865 ///
2866 explicit OMPTargetDirective()
2867 : OMPExecutableDirective(OMPTargetDirectiveClass, llvm::omp::OMPD_target,
2868 SourceLocation(), SourceLocation()) {}
2869
2870public:
2871 /// Creates directive with a list of \a Clauses.
2872 ///
2873 /// \param C AST context.
2874 /// \param StartLoc Starting location of the directive kind.
2875 /// \param EndLoc Ending Location of the directive.
2876 /// \param Clauses List of clauses.
2877 /// \param AssociatedStmt Statement, associated with the directive.
2878 ///
2879 static OMPTargetDirective *
2880 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2881 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
2882
2883 /// Creates an empty directive with the place for \a NumClauses
2884 /// clauses.
2885 ///
2886 /// \param C AST context.
2887 /// \param NumClauses Number of clauses.
2888 ///
2889 static OMPTargetDirective *CreateEmpty(const ASTContext &C,
2890 unsigned NumClauses, EmptyShell);
2891
2892 static bool classof(const Stmt *T) {
2893 return T->getStmtClass() == OMPTargetDirectiveClass;
2894 }
2895};
2896
2897/// This represents '#pragma omp target data' directive.
2898///
2899/// \code
2900/// #pragma omp target data device(0) if(a) map(b[:])
2901/// \endcode
2902/// In this example directive '#pragma omp target data' has clauses 'device'
2903/// with the value '0', 'if' with condition 'a' and 'map' with array
2904/// section 'b[:]'.
2905///
2906class OMPTargetDataDirective : public OMPExecutableDirective {
2907 friend class ASTStmtReader;
2908 friend class OMPExecutableDirective;
2909 /// Build directive with the given start and end location.
2910 ///
2911 /// \param StartLoc Starting location of the directive kind.
2912 /// \param EndLoc Ending Location of the directive.
2913 ///
2914 OMPTargetDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2915 : OMPExecutableDirective(OMPTargetDataDirectiveClass,
2916 llvm::omp::OMPD_target_data, StartLoc, EndLoc) {}
2917
2918 /// Build an empty directive.
2919 ///
2920 explicit OMPTargetDataDirective()
2921 : OMPExecutableDirective(OMPTargetDataDirectiveClass,
2922 llvm::omp::OMPD_target_data, SourceLocation(),
2923 SourceLocation()) {}
2924
2925public:
2926 /// Creates directive with a list of \a Clauses.
2927 ///
2928 /// \param C AST context.
2929 /// \param StartLoc Starting location of the directive kind.
2930 /// \param EndLoc Ending Location of the directive.
2931 /// \param Clauses List of clauses.
2932 /// \param AssociatedStmt Statement, associated with the directive.
2933 ///
2934 static OMPTargetDataDirective *
2935 Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation EndLoc,
2936 ArrayRef<OMPClause *> Clauses, Stmt *AssociatedStmt);
2937
2938 /// Creates an empty directive with the place for \a N clauses.
2939 ///
2940 /// \param C AST context.
2941 /// \param N The number of clauses.
2942 ///
2943 static OMPTargetDataDirective *CreateEmpty(const ASTContext &C, unsigned N,
2944 EmptyShell);
2945
2946 static bool classof(const Stmt *T) {
2947 return T->getStmtClass() == OMPTargetDataDirectiveClass;
2948 }
2949};
2950
2951/// This represents '#pragma omp target enter data' directive.
2952///
2953/// \code
2954/// #pragma omp target enter data device(0) if(a) map(b[:])
2955/// \endcode
2956/// In this example directive '#pragma omp target enter data' has clauses
2957/// 'device' with the value '0', 'if' with condition 'a' and 'map' with array
2958/// section 'b[:]'.
2959///
2960class OMPTargetEnterDataDirective : public OMPExecutableDirective {
2961 friend class ASTStmtReader;
2962 friend class OMPExecutableDirective;
2963 /// Build directive with the given start and end location.
2964 ///
2965 /// \param StartLoc Starting location of the directive kind.
2966 /// \param EndLoc Ending Location of the directive.
2967 ///
2968 OMPTargetEnterDataDirective(SourceLocation StartLoc, SourceLocation EndLoc)
2969 : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
2970 llvm::omp::OMPD_target_enter_data, StartLoc,
2971 EndLoc) {}
2972
2973 /// Build an empty directive.
2974 ///
2975 explicit OMPTargetEnterDataDirective()
2976 : OMPExecutableDirective(OMPTargetEnterDataDirectiveClass,
2977 llvm::omp::OMPD_target_enter_data,
2978