Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //===- StmtOpenACC.h - Classes for OpenACC directives  ----------*- C++ -*-===//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 /// \file
0009 /// This file defines OpenACC AST classes for statement-level contructs.
0010 ///
0011 //===----------------------------------------------------------------------===//
0012 
0013 #ifndef LLVM_CLANG_AST_STMTOPENACC_H
0014 #define LLVM_CLANG_AST_STMTOPENACC_H
0015 
0016 #include "clang/AST/OpenACCClause.h"
0017 #include "clang/AST/Stmt.h"
0018 #include "clang/Basic/OpenACCKinds.h"
0019 #include "clang/Basic/SourceLocation.h"
0020 #include <memory>
0021 
0022 namespace clang {
0023 /// This is the base class for an OpenACC statement-level construct, other
0024 /// construct types are expected to inherit from this.
0025 class OpenACCConstructStmt : public Stmt {
0026   friend class ASTStmtWriter;
0027   friend class ASTStmtReader;
0028   /// The directive kind. Each implementation of this interface should handle
0029   /// specific kinds.
0030   OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
0031   /// The location of the directive statement, from the '#' to the last token of
0032   /// the directive.
0033   SourceRange Range;
0034   /// The location of the directive name.
0035   SourceLocation DirectiveLoc;
0036 
0037   /// The list of clauses.  This is stored here as an ArrayRef, as this is the
0038   /// most convienient place to access the list, however the list itself should
0039   /// be stored in leaf nodes, likely in trailing-storage.
0040   MutableArrayRef<const OpenACCClause *> Clauses;
0041 
0042 protected:
0043   OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K,
0044                        SourceLocation Start, SourceLocation DirectiveLoc,
0045                        SourceLocation End)
0046       : Stmt(SC), Kind(K), Range(Start, End), DirectiveLoc(DirectiveLoc) {}
0047 
0048   // Used only for initialization, the leaf class can initialize this to
0049   // trailing storage.
0050   void setClauseList(MutableArrayRef<const OpenACCClause *> NewClauses) {
0051     assert(Clauses.empty() && "Cannot change clause list");
0052     Clauses = NewClauses;
0053   }
0054 
0055 public:
0056   OpenACCDirectiveKind getDirectiveKind() const { return Kind; }
0057 
0058   static bool classof(const Stmt *S) {
0059     return S->getStmtClass() >= firstOpenACCConstructStmtConstant &&
0060            S->getStmtClass() <= lastOpenACCConstructStmtConstant;
0061   }
0062 
0063   SourceLocation getBeginLoc() const { return Range.getBegin(); }
0064   SourceLocation getEndLoc() const { return Range.getEnd(); }
0065   SourceLocation getDirectiveLoc() const { return DirectiveLoc; }
0066   ArrayRef<const OpenACCClause *> clauses() const { return Clauses; }
0067 
0068   child_range children() {
0069     return child_range(child_iterator(), child_iterator());
0070   }
0071 
0072   const_child_range children() const {
0073     return const_cast<OpenACCConstructStmt *>(this)->children();
0074   }
0075 };
0076 
0077 /// This is a base class for any OpenACC statement-level constructs that have an
0078 /// associated statement. This class is not intended to be instantiated, but is
0079 /// a convenient place to hold the associated statement.
0080 class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt {
0081   friend class ASTStmtWriter;
0082   friend class ASTStmtReader;
0083   template <typename Derived> friend class RecursiveASTVisitor;
0084   Stmt *AssociatedStmt = nullptr;
0085 
0086 protected:
0087   OpenACCAssociatedStmtConstruct(StmtClass SC, OpenACCDirectiveKind K,
0088                                  SourceLocation Start,
0089                                  SourceLocation DirectiveLoc,
0090                                  SourceLocation End, Stmt *AssocStmt)
0091       : OpenACCConstructStmt(SC, K, Start, DirectiveLoc, End),
0092         AssociatedStmt(AssocStmt) {}
0093 
0094   void setAssociatedStmt(Stmt *S) { AssociatedStmt = S; }
0095   Stmt *getAssociatedStmt() { return AssociatedStmt; }
0096   const Stmt *getAssociatedStmt() const {
0097     return const_cast<OpenACCAssociatedStmtConstruct *>(this)
0098         ->getAssociatedStmt();
0099   }
0100 
0101 public:
0102   static bool classof(const Stmt *T) {
0103     return false;
0104   }
0105 
0106   child_range children() {
0107     if (getAssociatedStmt())
0108       return child_range(&AssociatedStmt, &AssociatedStmt + 1);
0109     return child_range(child_iterator(), child_iterator());
0110   }
0111 
0112   const_child_range children() const {
0113     return const_cast<OpenACCAssociatedStmtConstruct *>(this)->children();
0114   }
0115 };
0116 
0117 /// This class represents a compute construct, representing a 'Kind' of
0118 /// `parallel', 'serial', or 'kernel'. These constructs are associated with a
0119 /// 'structured block', defined as:
0120 ///
0121 ///  in C or C++, an executable statement, possibly compound, with a single
0122 ///  entry at the top and a single exit at the bottom
0123 ///
0124 /// At the moment there is no real motivation to have a different AST node for
0125 /// those three, as they are semantically identical, and have only minor
0126 /// differences in the permitted list of clauses, which can be differentiated by
0127 /// the 'Kind'.
0128 class OpenACCComputeConstruct final
0129     : public OpenACCAssociatedStmtConstruct,
0130       private llvm::TrailingObjects<OpenACCComputeConstruct,
0131                                     const OpenACCClause *> {
0132   friend class ASTStmtWriter;
0133   friend class ASTStmtReader;
0134   friend class ASTContext;
0135   friend TrailingObjects;
0136   OpenACCComputeConstruct(unsigned NumClauses)
0137       : OpenACCAssociatedStmtConstruct(
0138             OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid,
0139             SourceLocation{}, SourceLocation{}, SourceLocation{},
0140             /*AssociatedStmt=*/nullptr) {
0141     // We cannot send the TrailingObjects storage to the base class (which holds
0142     // a reference to the data) until it is constructed, so we have to set it
0143     // separately here.
0144     std::uninitialized_value_construct(
0145         getTrailingObjects<const OpenACCClause *>(),
0146         getTrailingObjects<const OpenACCClause *>() + NumClauses);
0147     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0148                                   NumClauses));
0149   }
0150 
0151   OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start,
0152                           SourceLocation DirectiveLoc, SourceLocation End,
0153                           ArrayRef<const OpenACCClause *> Clauses,
0154                           Stmt *StructuredBlock)
0155       : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start,
0156                                        DirectiveLoc, End, StructuredBlock) {
0157     assert(isOpenACCComputeDirectiveKind(K) &&
0158            "Only parallel, serial, and kernels constructs should be "
0159            "represented by this type");
0160 
0161     // Initialize the trailing storage.
0162     std::uninitialized_copy(Clauses.begin(), Clauses.end(),
0163                             getTrailingObjects<const OpenACCClause *>());
0164 
0165     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0166                                   Clauses.size()));
0167   }
0168 
0169   void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
0170 
0171 public:
0172   static bool classof(const Stmt *T) {
0173     return T->getStmtClass() == OpenACCComputeConstructClass;
0174   }
0175 
0176   static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C,
0177                                               unsigned NumClauses);
0178   static OpenACCComputeConstruct *
0179   Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc,
0180          SourceLocation DirectiveLoc, SourceLocation EndLoc,
0181          ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock);
0182 
0183   Stmt *getStructuredBlock() { return getAssociatedStmt(); }
0184   const Stmt *getStructuredBlock() const {
0185     return const_cast<OpenACCComputeConstruct *>(this)->getStructuredBlock();
0186   }
0187 };
0188 /// This class represents a 'loop' construct.  The 'loop' construct applies to a
0189 /// 'for' loop (or range-for loop), and is optionally associated with a Compute
0190 /// Construct.
0191 class OpenACCLoopConstruct final
0192     : public OpenACCAssociatedStmtConstruct,
0193       private llvm::TrailingObjects<OpenACCLoopConstruct,
0194                                    const OpenACCClause *> {
0195   // The compute/combined construct kind this loop is associated with, or
0196   // invalid if this is an orphaned loop construct.
0197   OpenACCDirectiveKind ParentComputeConstructKind =
0198       OpenACCDirectiveKind::Invalid;
0199 
0200   friend class ASTStmtWriter;
0201   friend class ASTStmtReader;
0202   friend class ASTContext;
0203   friend class OpenACCAssociatedStmtConstruct;
0204   friend class OpenACCCombinedConstruct;
0205   friend class OpenACCComputeConstruct;
0206   friend TrailingObjects;
0207 
0208   OpenACCLoopConstruct(unsigned NumClauses);
0209 
0210   OpenACCLoopConstruct(OpenACCDirectiveKind ParentKind, SourceLocation Start,
0211                        SourceLocation DirLoc, SourceLocation End,
0212                        ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop);
0213 
0214 public:
0215   static bool classof(const Stmt *T) {
0216     return T->getStmtClass() == OpenACCLoopConstructClass;
0217   }
0218 
0219   static OpenACCLoopConstruct *CreateEmpty(const ASTContext &C,
0220                                            unsigned NumClauses);
0221 
0222   static OpenACCLoopConstruct *
0223   Create(const ASTContext &C, OpenACCDirectiveKind ParentKind,
0224          SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation EndLoc,
0225          ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop);
0226 
0227   Stmt *getLoop() { return getAssociatedStmt(); }
0228   const Stmt *getLoop() const {
0229     return const_cast<OpenACCLoopConstruct *>(this)->getLoop();
0230   }
0231 
0232   /// OpenACC 3.3 2.9:
0233   /// An orphaned loop construct is a loop construct that is not lexically
0234   /// enclosed within a compute construct. The parent compute construct of a
0235   /// loop construct is the nearest compute construct that lexically contains
0236   /// the loop construct.
0237   bool isOrphanedLoopConstruct() const {
0238     return ParentComputeConstructKind == OpenACCDirectiveKind::Invalid;
0239   }
0240 
0241   OpenACCDirectiveKind getParentComputeConstructKind() const {
0242     return ParentComputeConstructKind;
0243   }
0244 };
0245 
0246 // This class represents a 'combined' construct, which has a bunch of rules
0247 // shared with both loop and compute constructs.
0248 class OpenACCCombinedConstruct final
0249     : public OpenACCAssociatedStmtConstruct,
0250       private llvm::TrailingObjects<OpenACCCombinedConstruct,
0251                                    const OpenACCClause *> {
0252   friend TrailingObjects;
0253   OpenACCCombinedConstruct(unsigned NumClauses)
0254       : OpenACCAssociatedStmtConstruct(
0255             OpenACCCombinedConstructClass, OpenACCDirectiveKind::Invalid,
0256             SourceLocation{}, SourceLocation{}, SourceLocation{},
0257             /*AssociatedStmt=*/nullptr) {
0258     std::uninitialized_value_construct(
0259         getTrailingObjects<const OpenACCClause *>(),
0260         getTrailingObjects<const OpenACCClause *>() + NumClauses);
0261     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0262                                   NumClauses));
0263   }
0264 
0265   OpenACCCombinedConstruct(OpenACCDirectiveKind K, SourceLocation Start,
0266                            SourceLocation DirectiveLoc, SourceLocation End,
0267                            ArrayRef<const OpenACCClause *> Clauses,
0268                            Stmt *StructuredBlock)
0269       : OpenACCAssociatedStmtConstruct(OpenACCCombinedConstructClass, K, Start,
0270                                        DirectiveLoc, End, StructuredBlock) {
0271     assert(isOpenACCCombinedDirectiveKind(K) &&
0272            "Only parallel loop, serial loop, and kernels loop constructs "
0273            "should be represented by this type");
0274 
0275     std::uninitialized_copy(Clauses.begin(), Clauses.end(),
0276                             getTrailingObjects<const OpenACCClause *>());
0277     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0278                                   Clauses.size()));
0279   }
0280   void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
0281 
0282 public:
0283   static bool classof(const Stmt *T) {
0284     return T->getStmtClass() == OpenACCCombinedConstructClass;
0285   }
0286 
0287   static OpenACCCombinedConstruct *CreateEmpty(const ASTContext &C,
0288                                                unsigned NumClauses);
0289   static OpenACCCombinedConstruct *
0290   Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start,
0291          SourceLocation DirectiveLoc, SourceLocation End,
0292          ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock);
0293   Stmt *getLoop() { return getAssociatedStmt(); }
0294   const Stmt *getLoop() const {
0295     return const_cast<OpenACCCombinedConstruct *>(this)->getLoop();
0296   }
0297 };
0298 
0299 // This class represents a 'data' construct, which has an associated statement
0300 // and clauses, but is otherwise pretty simple.
0301 class OpenACCDataConstruct final
0302     : public OpenACCAssociatedStmtConstruct,
0303       private llvm::TrailingObjects<OpenACCDataConstruct,
0304                                    const OpenACCClause *> {
0305   friend TrailingObjects;
0306   OpenACCDataConstruct(unsigned NumClauses)
0307       : OpenACCAssociatedStmtConstruct(
0308             OpenACCDataConstructClass, OpenACCDirectiveKind::Data,
0309             SourceLocation{}, SourceLocation{}, SourceLocation{},
0310             /*AssociatedStmt=*/nullptr) {
0311     std::uninitialized_value_construct(
0312         getTrailingObjects<const OpenACCClause *>(),
0313         getTrailingObjects<const OpenACCClause *>() + NumClauses);
0314     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0315                                   NumClauses));
0316   }
0317 
0318   OpenACCDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
0319                        SourceLocation End,
0320                        ArrayRef<const OpenACCClause *> Clauses,
0321                        Stmt *StructuredBlock)
0322       : OpenACCAssociatedStmtConstruct(OpenACCDataConstructClass,
0323                                        OpenACCDirectiveKind::Data, Start,
0324                                        DirectiveLoc, End, StructuredBlock) {
0325     std::uninitialized_copy(Clauses.begin(), Clauses.end(),
0326                             getTrailingObjects<const OpenACCClause *>());
0327     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0328                                   Clauses.size()));
0329   }
0330   void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
0331 
0332 public:
0333   static bool classof(const Stmt *T) {
0334     return T->getStmtClass() == OpenACCDataConstructClass;
0335   }
0336 
0337   static OpenACCDataConstruct *CreateEmpty(const ASTContext &C,
0338                                            unsigned NumClauses);
0339   static OpenACCDataConstruct *Create(const ASTContext &C, SourceLocation Start,
0340                                       SourceLocation DirectiveLoc,
0341                                       SourceLocation End,
0342                                       ArrayRef<const OpenACCClause *> Clauses,
0343                                       Stmt *StructuredBlock);
0344   Stmt *getStructuredBlock() { return getAssociatedStmt(); }
0345   const Stmt *getStructuredBlock() const {
0346     return const_cast<OpenACCDataConstruct *>(this)->getStructuredBlock();
0347   }
0348 };
0349 // This class represents a 'enter data' construct, which JUST has clauses.
0350 class OpenACCEnterDataConstruct final
0351     : public OpenACCConstructStmt,
0352       private llvm::TrailingObjects<OpenACCEnterDataConstruct,
0353                                    const OpenACCClause *> {
0354   friend TrailingObjects;
0355   OpenACCEnterDataConstruct(unsigned NumClauses)
0356       : OpenACCConstructStmt(OpenACCEnterDataConstructClass,
0357                              OpenACCDirectiveKind::EnterData, SourceLocation{},
0358                              SourceLocation{}, SourceLocation{}) {
0359     std::uninitialized_value_construct(
0360         getTrailingObjects<const OpenACCClause *>(),
0361         getTrailingObjects<const OpenACCClause *>() + NumClauses);
0362     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0363                                   NumClauses));
0364   }
0365   OpenACCEnterDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
0366                             SourceLocation End,
0367                             ArrayRef<const OpenACCClause *> Clauses)
0368       : OpenACCConstructStmt(OpenACCEnterDataConstructClass,
0369                              OpenACCDirectiveKind::EnterData, Start,
0370                              DirectiveLoc, End) {
0371     std::uninitialized_copy(Clauses.begin(), Clauses.end(),
0372                             getTrailingObjects<const OpenACCClause *>());
0373     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0374                                   Clauses.size()));
0375   }
0376 
0377 public:
0378   static bool classof(const Stmt *T) {
0379     return T->getStmtClass() == OpenACCEnterDataConstructClass;
0380   }
0381   static OpenACCEnterDataConstruct *CreateEmpty(const ASTContext &C,
0382                                                 unsigned NumClauses);
0383   static OpenACCEnterDataConstruct *
0384   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
0385          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
0386 };
0387 // This class represents a 'exit data' construct, which JUST has clauses.
0388 class OpenACCExitDataConstruct final
0389     : public OpenACCConstructStmt,
0390       private llvm::TrailingObjects<OpenACCExitDataConstruct,
0391                                    const OpenACCClause *> {
0392   friend TrailingObjects;
0393   OpenACCExitDataConstruct(unsigned NumClauses)
0394       : OpenACCConstructStmt(OpenACCExitDataConstructClass,
0395                              OpenACCDirectiveKind::ExitData, SourceLocation{},
0396                              SourceLocation{}, SourceLocation{}) {
0397     std::uninitialized_value_construct(
0398         getTrailingObjects<const OpenACCClause *>(),
0399         getTrailingObjects<const OpenACCClause *>() + NumClauses);
0400     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0401                                   NumClauses));
0402   }
0403   OpenACCExitDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
0404                            SourceLocation End,
0405                            ArrayRef<const OpenACCClause *> Clauses)
0406       : OpenACCConstructStmt(OpenACCExitDataConstructClass,
0407                              OpenACCDirectiveKind::ExitData, Start,
0408                              DirectiveLoc, End) {
0409     std::uninitialized_copy(Clauses.begin(), Clauses.end(),
0410                             getTrailingObjects<const OpenACCClause *>());
0411     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0412                                   Clauses.size()));
0413   }
0414 
0415 public:
0416   static bool classof(const Stmt *T) {
0417     return T->getStmtClass() == OpenACCExitDataConstructClass;
0418   }
0419   static OpenACCExitDataConstruct *CreateEmpty(const ASTContext &C,
0420                                                unsigned NumClauses);
0421   static OpenACCExitDataConstruct *
0422   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
0423          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
0424 };
0425 // This class represents a 'host_data' construct, which has an associated
0426 // statement and clauses, but is otherwise pretty simple.
0427 class OpenACCHostDataConstruct final
0428     : public OpenACCAssociatedStmtConstruct,
0429       private llvm::TrailingObjects<OpenACCHostDataConstruct,
0430                                    const OpenACCClause *> {
0431   friend TrailingObjects;
0432   OpenACCHostDataConstruct(unsigned NumClauses)
0433       : OpenACCAssociatedStmtConstruct(
0434             OpenACCHostDataConstructClass, OpenACCDirectiveKind::HostData,
0435             SourceLocation{}, SourceLocation{}, SourceLocation{},
0436             /*AssociatedStmt=*/nullptr) {
0437     std::uninitialized_value_construct(
0438         getTrailingObjects<const OpenACCClause *>(),
0439         getTrailingObjects<const OpenACCClause *>() + NumClauses);
0440     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0441                                   NumClauses));
0442   }
0443   OpenACCHostDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
0444                            SourceLocation End,
0445                            ArrayRef<const OpenACCClause *> Clauses,
0446                            Stmt *StructuredBlock)
0447       : OpenACCAssociatedStmtConstruct(OpenACCHostDataConstructClass,
0448                                        OpenACCDirectiveKind::HostData, Start,
0449                                        DirectiveLoc, End, StructuredBlock) {
0450     std::uninitialized_copy(Clauses.begin(), Clauses.end(),
0451                             getTrailingObjects<const OpenACCClause *>());
0452     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0453                                   Clauses.size()));
0454   }
0455   void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
0456 
0457 public:
0458   static bool classof(const Stmt *T) {
0459     return T->getStmtClass() == OpenACCHostDataConstructClass;
0460   }
0461   static OpenACCHostDataConstruct *CreateEmpty(const ASTContext &C,
0462                                                unsigned NumClauses);
0463   static OpenACCHostDataConstruct *
0464   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
0465          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses,
0466          Stmt *StructuredBlock);
0467   Stmt *getStructuredBlock() { return getAssociatedStmt(); }
0468   const Stmt *getStructuredBlock() const {
0469     return const_cast<OpenACCHostDataConstruct *>(this)->getStructuredBlock();
0470   }
0471 };
0472 
0473 // This class represents a 'wait' construct, which has some expressions plus a
0474 // clause list.
0475 class OpenACCWaitConstruct final
0476     : public OpenACCConstructStmt,
0477       private llvm::TrailingObjects<OpenACCWaitConstruct, Expr *,
0478                                     OpenACCClause *> {
0479   // FIXME: We should be storing a `const OpenACCClause *` to be consistent with
0480   // the rest of the constructs, but TrailingObjects doesn't allow for mixing
0481   // constness in its implementation of `getTrailingObjects`.
0482 
0483   friend TrailingObjects;
0484   friend class ASTStmtWriter;
0485   friend class ASTStmtReader;
0486   // Locations of the left and right parens of the 'wait-argument'
0487   // expression-list.
0488   SourceLocation LParenLoc, RParenLoc;
0489   // Location of the 'queues' keyword, if present.
0490   SourceLocation QueuesLoc;
0491 
0492   // Number of the expressions being represented.  Index '0' is always the
0493   // 'devnum' expression, even if it not present.
0494   unsigned NumExprs = 0;
0495 
0496   OpenACCWaitConstruct(unsigned NumExprs, unsigned NumClauses)
0497       : OpenACCConstructStmt(OpenACCWaitConstructClass,
0498                              OpenACCDirectiveKind::Wait, SourceLocation{},
0499                              SourceLocation{}, SourceLocation{}),
0500         NumExprs(NumExprs) {
0501     assert(NumExprs >= 1 &&
0502            "NumExprs should always be >= 1 because the 'devnum' "
0503            "expr is represented by a null if necessary");
0504     std::uninitialized_value_construct(getExprPtr(),
0505                                        getExprPtr() + NumExprs);
0506     std::uninitialized_value_construct(getTrailingObjects<OpenACCClause *>(),
0507                                        getTrailingObjects<OpenACCClause *>() +
0508                                            NumClauses);
0509     setClauseList(MutableArrayRef(const_cast<const OpenACCClause **>(
0510                                       getTrailingObjects<OpenACCClause *>()),
0511                                   NumClauses));
0512   }
0513 
0514   OpenACCWaitConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
0515                        SourceLocation LParenLoc, Expr *DevNumExpr,
0516                        SourceLocation QueuesLoc, ArrayRef<Expr *> QueueIdExprs,
0517                        SourceLocation RParenLoc, SourceLocation End,
0518                        ArrayRef<const OpenACCClause *> Clauses)
0519       : OpenACCConstructStmt(OpenACCWaitConstructClass,
0520                              OpenACCDirectiveKind::Wait, Start, DirectiveLoc,
0521                              End),
0522         LParenLoc(LParenLoc), RParenLoc(RParenLoc), QueuesLoc(QueuesLoc),
0523         NumExprs(QueueIdExprs.size() + 1) {
0524     assert(NumExprs >= 1 &&
0525            "NumExprs should always be >= 1 because the 'devnum' "
0526            "expr is represented by a null if necessary");
0527 
0528     std::uninitialized_copy(&DevNumExpr, &DevNumExpr + 1,
0529                             getExprPtr());
0530     std::uninitialized_copy(QueueIdExprs.begin(), QueueIdExprs.end(),
0531                             getExprPtr() + 1);
0532 
0533     std::uninitialized_copy(const_cast<OpenACCClause **>(Clauses.begin()),
0534                             const_cast<OpenACCClause **>(Clauses.end()),
0535                             getTrailingObjects<OpenACCClause *>());
0536     setClauseList(MutableArrayRef(const_cast<const OpenACCClause **>(
0537                                       getTrailingObjects<OpenACCClause *>()),
0538                                   Clauses.size()));
0539   }
0540 
0541   size_t numTrailingObjects(OverloadToken<Expr *>) const { return NumExprs; }
0542   size_t numTrailingObjects(OverloadToken<const OpenACCClause *>) const {
0543     return clauses().size();
0544   }
0545 
0546   Expr **getExprPtr() const {
0547     return const_cast<Expr**>(getTrailingObjects<Expr *>());
0548   }
0549 
0550   llvm::ArrayRef<Expr *> getExprs() const {
0551     return llvm::ArrayRef<Expr *>(getExprPtr(), NumExprs);
0552   }
0553 
0554   llvm::ArrayRef<Expr *> getExprs() {
0555     return llvm::ArrayRef<Expr *>(getExprPtr(), NumExprs);
0556   }
0557 
0558 public:
0559   static bool classof(const Stmt *T) {
0560     return T->getStmtClass() == OpenACCWaitConstructClass;
0561   }
0562 
0563   static OpenACCWaitConstruct *
0564   CreateEmpty(const ASTContext &C, unsigned NumExprs, unsigned NumClauses);
0565 
0566   static OpenACCWaitConstruct *
0567   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
0568          SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc,
0569          ArrayRef<Expr *> QueueIdExprs, SourceLocation RParenLoc,
0570          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
0571 
0572   SourceLocation getLParenLoc() const { return LParenLoc; }
0573   SourceLocation getRParenLoc() const { return RParenLoc; }
0574   bool hasQueuesTag() const { return !QueuesLoc.isInvalid(); }
0575   SourceLocation getQueuesLoc() const { return QueuesLoc; }
0576 
0577   bool hasDevNumExpr() const { return getExprs()[0]; }
0578   Expr *getDevNumExpr() const { return getExprs()[0]; }
0579   llvm::ArrayRef<Expr *> getQueueIdExprs() { return getExprs().drop_front(); }
0580   llvm::ArrayRef<Expr *> getQueueIdExprs() const {
0581     return getExprs().drop_front();
0582   }
0583 
0584   child_range children() {
0585     Stmt **Begin = reinterpret_cast<Stmt **>(getExprPtr());
0586     return child_range(Begin, Begin + NumExprs);
0587   }
0588 
0589   const_child_range children() const {
0590     Stmt *const *Begin =
0591         reinterpret_cast<Stmt *const *>(getExprPtr());
0592     return const_child_range(Begin, Begin + NumExprs);
0593   }
0594 };
0595 
0596 // This class represents an 'init' construct, which has just a clause list.
0597 class OpenACCInitConstruct final
0598     : public OpenACCConstructStmt,
0599       private llvm::TrailingObjects<OpenACCInitConstruct,
0600                                     const OpenACCClause *> {
0601   friend TrailingObjects;
0602   OpenACCInitConstruct(unsigned NumClauses)
0603       : OpenACCConstructStmt(OpenACCInitConstructClass,
0604                              OpenACCDirectiveKind::Init, SourceLocation{},
0605                              SourceLocation{}, SourceLocation{}) {
0606     std::uninitialized_value_construct(
0607         getTrailingObjects<const OpenACCClause *>(),
0608         getTrailingObjects<const OpenACCClause *>() + NumClauses);
0609     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0610                                   NumClauses));
0611   }
0612   OpenACCInitConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
0613                        SourceLocation End,
0614                        ArrayRef<const OpenACCClause *> Clauses)
0615       : OpenACCConstructStmt(OpenACCInitConstructClass,
0616                              OpenACCDirectiveKind::Init, Start, DirectiveLoc,
0617                              End) {
0618     std::uninitialized_copy(Clauses.begin(), Clauses.end(),
0619                             getTrailingObjects<const OpenACCClause *>());
0620     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0621                                   Clauses.size()));
0622   }
0623 
0624 public:
0625   static bool classof(const Stmt *T) {
0626     return T->getStmtClass() == OpenACCInitConstructClass;
0627   }
0628   static OpenACCInitConstruct *CreateEmpty(const ASTContext &C,
0629                                            unsigned NumClauses);
0630   static OpenACCInitConstruct *Create(const ASTContext &C, SourceLocation Start,
0631                                       SourceLocation DirectiveLoc,
0632                                       SourceLocation End,
0633                                       ArrayRef<const OpenACCClause *> Clauses);
0634 };
0635 
0636 // This class represents a 'shutdown' construct, which has just a clause list.
0637 class OpenACCShutdownConstruct final
0638     : public OpenACCConstructStmt,
0639       private llvm::TrailingObjects<OpenACCShutdownConstruct,
0640                                     const OpenACCClause *> {
0641   friend TrailingObjects;
0642   OpenACCShutdownConstruct(unsigned NumClauses)
0643       : OpenACCConstructStmt(OpenACCShutdownConstructClass,
0644                              OpenACCDirectiveKind::Shutdown, SourceLocation{},
0645                              SourceLocation{}, SourceLocation{}) {
0646     std::uninitialized_value_construct(
0647         getTrailingObjects<const OpenACCClause *>(),
0648         getTrailingObjects<const OpenACCClause *>() + NumClauses);
0649     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0650                                   NumClauses));
0651   }
0652   OpenACCShutdownConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
0653                            SourceLocation End,
0654                            ArrayRef<const OpenACCClause *> Clauses)
0655       : OpenACCConstructStmt(OpenACCShutdownConstructClass,
0656                              OpenACCDirectiveKind::Shutdown, Start,
0657                              DirectiveLoc, End) {
0658     std::uninitialized_copy(Clauses.begin(), Clauses.end(),
0659                             getTrailingObjects<const OpenACCClause *>());
0660     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0661                                   Clauses.size()));
0662   }
0663 
0664 public:
0665   static bool classof(const Stmt *T) {
0666     return T->getStmtClass() == OpenACCShutdownConstructClass;
0667   }
0668   static OpenACCShutdownConstruct *CreateEmpty(const ASTContext &C,
0669                                                unsigned NumClauses);
0670   static OpenACCShutdownConstruct *
0671   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
0672          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
0673 };
0674 
0675 // This class represents a 'set' construct, which has just a clause list.
0676 class OpenACCSetConstruct final
0677     : public OpenACCConstructStmt,
0678       private llvm::TrailingObjects<OpenACCSetConstruct,
0679                                     const OpenACCClause *> {
0680   friend TrailingObjects;
0681   OpenACCSetConstruct(unsigned NumClauses)
0682       : OpenACCConstructStmt(OpenACCSetConstructClass,
0683                              OpenACCDirectiveKind::Set, SourceLocation{},
0684                              SourceLocation{}, SourceLocation{}) {
0685     std::uninitialized_value_construct(
0686         getTrailingObjects<const OpenACCClause *>(),
0687         getTrailingObjects<const OpenACCClause *>() + NumClauses);
0688     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0689                                   NumClauses));
0690   }
0691 
0692   OpenACCSetConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
0693                       SourceLocation End,
0694                       ArrayRef<const OpenACCClause *> Clauses)
0695       : OpenACCConstructStmt(OpenACCSetConstructClass,
0696                              OpenACCDirectiveKind::Set, Start, DirectiveLoc,
0697                              End) {
0698     std::uninitialized_copy(Clauses.begin(), Clauses.end(),
0699                             getTrailingObjects<const OpenACCClause *>());
0700     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0701                                   Clauses.size()));
0702   }
0703 
0704 public:
0705   static bool classof(const Stmt *T) {
0706     return T->getStmtClass() == OpenACCSetConstructClass;
0707   }
0708   static OpenACCSetConstruct *CreateEmpty(const ASTContext &C,
0709                                           unsigned NumClauses);
0710   static OpenACCSetConstruct *Create(const ASTContext &C, SourceLocation Start,
0711                                      SourceLocation DirectiveLoc,
0712                                      SourceLocation End,
0713                                      ArrayRef<const OpenACCClause *> Clauses);
0714 };
0715 // This class represents an 'update' construct, which has just a clause list.
0716 class OpenACCUpdateConstruct final
0717     : public OpenACCConstructStmt,
0718       private llvm::TrailingObjects<OpenACCUpdateConstruct,
0719                                     const OpenACCClause *> {
0720   friend TrailingObjects;
0721   OpenACCUpdateConstruct(unsigned NumClauses)
0722       : OpenACCConstructStmt(OpenACCUpdateConstructClass,
0723                              OpenACCDirectiveKind::Update, SourceLocation{},
0724                              SourceLocation{}, SourceLocation{}) {
0725     std::uninitialized_value_construct(
0726         getTrailingObjects<const OpenACCClause *>(),
0727         getTrailingObjects<const OpenACCClause *>() + NumClauses);
0728     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0729                                   NumClauses));
0730   }
0731 
0732   OpenACCUpdateConstruct(SourceLocation Start, SourceLocation DirectiveLoc,
0733                          SourceLocation End,
0734                          ArrayRef<const OpenACCClause *> Clauses)
0735       : OpenACCConstructStmt(OpenACCUpdateConstructClass,
0736                              OpenACCDirectiveKind::Update, Start, DirectiveLoc,
0737                              End) {
0738     std::uninitialized_copy(Clauses.begin(), Clauses.end(),
0739                             getTrailingObjects<const OpenACCClause *>());
0740     setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
0741                                   Clauses.size()));
0742   }
0743 
0744 public:
0745   static bool classof(const Stmt *T) {
0746     return T->getStmtClass() == OpenACCUpdateConstructClass;
0747   }
0748   static OpenACCUpdateConstruct *CreateEmpty(const ASTContext &C,
0749                                              unsigned NumClauses);
0750   static OpenACCUpdateConstruct *
0751   Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc,
0752          SourceLocation End, ArrayRef<const OpenACCClause *> Clauses);
0753 };
0754 } // namespace clang
0755 #endif // LLVM_CLANG_AST_STMTOPENACC_H