Back to home page

EIC code displayed by LXR

 
 

    


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

0001 //===- OpenACCClause.h - Classes for OpenACC clauses ------------*- 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 //
0009 // \file
0010 // This file defines OpenACC AST classes for clauses.
0011 //
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H
0015 #define LLVM_CLANG_AST_OPENACCCLAUSE_H
0016 #include "clang/AST/ASTContext.h"
0017 #include "clang/AST/StmtIterator.h"
0018 #include "clang/Basic/OpenACCKinds.h"
0019 
0020 #include <utility>
0021 
0022 namespace clang {
0023 /// This is the base type for all OpenACC Clauses.
0024 class OpenACCClause {
0025   OpenACCClauseKind Kind;
0026   SourceRange Location;
0027 
0028 protected:
0029   OpenACCClause(OpenACCClauseKind K, SourceLocation BeginLoc,
0030                 SourceLocation EndLoc)
0031       : Kind(K), Location(BeginLoc, EndLoc) {
0032     assert(!BeginLoc.isInvalid() && !EndLoc.isInvalid() &&
0033            "Begin and end location must be valid for OpenACCClause");
0034       }
0035 
0036 public:
0037   OpenACCClauseKind getClauseKind() const { return Kind; }
0038   SourceLocation getBeginLoc() const { return Location.getBegin(); }
0039   SourceLocation getEndLoc() const { return Location.getEnd(); }
0040 
0041   static bool classof(const OpenACCClause *) { return true; }
0042 
0043   using child_iterator = StmtIterator;
0044   using const_child_iterator = ConstStmtIterator;
0045   using child_range = llvm::iterator_range<child_iterator>;
0046   using const_child_range = llvm::iterator_range<const_child_iterator>;
0047 
0048   child_range children();
0049   const_child_range children() const {
0050     auto Children = const_cast<OpenACCClause *>(this)->children();
0051     return const_child_range(Children.begin(), Children.end());
0052   }
0053 
0054   virtual ~OpenACCClause() = default;
0055 };
0056 
0057 // Represents the 'auto' clause.
0058 class OpenACCAutoClause : public OpenACCClause {
0059 protected:
0060   OpenACCAutoClause(SourceLocation BeginLoc, SourceLocation EndLoc)
0061       : OpenACCClause(OpenACCClauseKind::Auto, BeginLoc, EndLoc) {}
0062 
0063 public:
0064   static bool classof(const OpenACCClause *C) {
0065     return C->getClauseKind() == OpenACCClauseKind::Auto;
0066   }
0067 
0068   static OpenACCAutoClause *
0069   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
0070 
0071   child_range children() {
0072     return child_range(child_iterator(), child_iterator());
0073   }
0074   const_child_range children() const {
0075     return const_child_range(const_child_iterator(), const_child_iterator());
0076   }
0077 };
0078 
0079 // Represents the 'finalize' clause.
0080 class OpenACCFinalizeClause : public OpenACCClause {
0081 protected:
0082   OpenACCFinalizeClause(SourceLocation BeginLoc, SourceLocation EndLoc)
0083       : OpenACCClause(OpenACCClauseKind::Finalize, BeginLoc, EndLoc) {}
0084 
0085 public:
0086   static bool classof(const OpenACCClause *C) {
0087     return C->getClauseKind() == OpenACCClauseKind::Finalize;
0088   }
0089 
0090   static OpenACCFinalizeClause *
0091   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
0092 
0093   child_range children() {
0094     return child_range(child_iterator(), child_iterator());
0095   }
0096   const_child_range children() const {
0097     return const_child_range(const_child_iterator(), const_child_iterator());
0098   }
0099 };
0100 
0101 // Represents the 'if_present' clause.
0102 class OpenACCIfPresentClause : public OpenACCClause {
0103 protected:
0104   OpenACCIfPresentClause(SourceLocation BeginLoc, SourceLocation EndLoc)
0105       : OpenACCClause(OpenACCClauseKind::IfPresent, BeginLoc, EndLoc) {}
0106 
0107 public:
0108   static bool classof(const OpenACCClause *C) {
0109     return C->getClauseKind() == OpenACCClauseKind::IfPresent;
0110   }
0111 
0112   static OpenACCIfPresentClause *
0113   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
0114 
0115   child_range children() {
0116     return child_range(child_iterator(), child_iterator());
0117   }
0118   const_child_range children() const {
0119     return const_child_range(const_child_iterator(), const_child_iterator());
0120   }
0121 };
0122 
0123 // Represents the 'independent' clause.
0124 class OpenACCIndependentClause : public OpenACCClause {
0125 protected:
0126   OpenACCIndependentClause(SourceLocation BeginLoc, SourceLocation EndLoc)
0127       : OpenACCClause(OpenACCClauseKind::Independent, BeginLoc, EndLoc) {}
0128 
0129 public:
0130   static bool classof(const OpenACCClause *C) {
0131     return C->getClauseKind() == OpenACCClauseKind::Independent;
0132   }
0133 
0134   static OpenACCIndependentClause *
0135   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
0136 
0137   child_range children() {
0138     return child_range(child_iterator(), child_iterator());
0139   }
0140   const_child_range children() const {
0141     return const_child_range(const_child_iterator(), const_child_iterator());
0142   }
0143 };
0144 // Represents the 'seq' clause.
0145 class OpenACCSeqClause : public OpenACCClause {
0146 protected:
0147   OpenACCSeqClause(SourceLocation BeginLoc, SourceLocation EndLoc)
0148       : OpenACCClause(OpenACCClauseKind::Seq, BeginLoc, EndLoc) {}
0149 
0150 public:
0151   static bool classof(const OpenACCClause *C) {
0152     return C->getClauseKind() == OpenACCClauseKind::Seq;
0153   }
0154 
0155   static OpenACCSeqClause *
0156   Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
0157 
0158   child_range children() {
0159     return child_range(child_iterator(), child_iterator());
0160   }
0161   const_child_range children() const {
0162     return const_child_range(const_child_iterator(), const_child_iterator());
0163   }
0164 };
0165 
0166 /// Represents a clause that has a list of parameters.
0167 class OpenACCClauseWithParams : public OpenACCClause {
0168   /// Location of the '('.
0169   SourceLocation LParenLoc;
0170 
0171 protected:
0172   OpenACCClauseWithParams(OpenACCClauseKind K, SourceLocation BeginLoc,
0173                           SourceLocation LParenLoc, SourceLocation EndLoc)
0174       : OpenACCClause(K, BeginLoc, EndLoc), LParenLoc(LParenLoc) {}
0175 
0176 public:
0177   static bool classof(const OpenACCClause *C);
0178 
0179   SourceLocation getLParenLoc() const { return LParenLoc; }
0180 
0181   child_range children() {
0182     return child_range(child_iterator(), child_iterator());
0183   }
0184   const_child_range children() const {
0185     return const_child_range(const_child_iterator(), const_child_iterator());
0186   }
0187 };
0188 
0189 using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
0190 /// A 'device_type' or 'dtype' clause, takes a list of either an 'asterisk' or
0191 /// an identifier. The 'asterisk' means 'the rest'.
0192 class OpenACCDeviceTypeClause final
0193     : public OpenACCClauseWithParams,
0194       private llvm::TrailingObjects<OpenACCDeviceTypeClause,
0195                                    DeviceTypeArgument> {
0196   friend TrailingObjects;
0197   // Data stored in trailing objects as IdentifierInfo* /SourceLocation pairs. A
0198   // nullptr IdentifierInfo* represents an asterisk.
0199   unsigned NumArchs;
0200   OpenACCDeviceTypeClause(OpenACCClauseKind K, SourceLocation BeginLoc,
0201                           SourceLocation LParenLoc,
0202                           ArrayRef<DeviceTypeArgument> Archs,
0203                           SourceLocation EndLoc)
0204       : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
0205         NumArchs(Archs.size()) {
0206     assert(
0207         (K == OpenACCClauseKind::DeviceType || K == OpenACCClauseKind::DType) &&
0208         "Invalid clause kind for device-type");
0209 
0210     assert(!llvm::any_of(Archs, [](const DeviceTypeArgument &Arg) {
0211       return Arg.second.isInvalid();
0212     }) && "Invalid SourceLocation for an argument");
0213 
0214     assert(
0215         (Archs.size() == 1 || !llvm::any_of(Archs,
0216                                             [](const DeviceTypeArgument &Arg) {
0217                                               return Arg.first == nullptr;
0218                                             })) &&
0219         "Only a single asterisk version is permitted, and must be the "
0220         "only one");
0221 
0222     std::uninitialized_copy(Archs.begin(), Archs.end(),
0223                             getTrailingObjects<DeviceTypeArgument>());
0224   }
0225 
0226 public:
0227   static bool classof(const OpenACCClause *C) {
0228     return C->getClauseKind() == OpenACCClauseKind::DType ||
0229            C->getClauseKind() == OpenACCClauseKind::DeviceType;
0230   }
0231   bool hasAsterisk() const {
0232     return getArchitectures().size() > 0 &&
0233            getArchitectures()[0].first == nullptr;
0234   }
0235 
0236   ArrayRef<DeviceTypeArgument> getArchitectures() const {
0237     return ArrayRef<DeviceTypeArgument>(
0238         getTrailingObjects<DeviceTypeArgument>(), NumArchs);
0239   }
0240 
0241   static OpenACCDeviceTypeClause *
0242   Create(const ASTContext &C, OpenACCClauseKind K, SourceLocation BeginLoc,
0243          SourceLocation LParenLoc, ArrayRef<DeviceTypeArgument> Archs,
0244          SourceLocation EndLoc);
0245 };
0246 
0247 /// A 'default' clause, has the optional 'none' or 'present' argument.
0248 class OpenACCDefaultClause : public OpenACCClauseWithParams {
0249   friend class ASTReaderStmt;
0250   friend class ASTWriterStmt;
0251 
0252   OpenACCDefaultClauseKind DefaultClauseKind;
0253 
0254 protected:
0255   OpenACCDefaultClause(OpenACCDefaultClauseKind K, SourceLocation BeginLoc,
0256                        SourceLocation LParenLoc, SourceLocation EndLoc)
0257       : OpenACCClauseWithParams(OpenACCClauseKind::Default, BeginLoc, LParenLoc,
0258                                 EndLoc),
0259         DefaultClauseKind(K) {
0260     assert((DefaultClauseKind == OpenACCDefaultClauseKind::None ||
0261             DefaultClauseKind == OpenACCDefaultClauseKind::Present) &&
0262            "Invalid Clause Kind");
0263   }
0264 
0265 public:
0266   static bool classof(const OpenACCClause *C) {
0267     return C->getClauseKind() == OpenACCClauseKind::Default;
0268   }
0269   OpenACCDefaultClauseKind getDefaultClauseKind() const {
0270     return DefaultClauseKind;
0271   }
0272 
0273   static OpenACCDefaultClause *Create(const ASTContext &C,
0274                                       OpenACCDefaultClauseKind K,
0275                                       SourceLocation BeginLoc,
0276                                       SourceLocation LParenLoc,
0277                                       SourceLocation EndLoc);
0278 };
0279 
0280 /// Represents one of the handful of classes that has an optional/required
0281 /// 'condition' expression as an argument.
0282 class OpenACCClauseWithCondition : public OpenACCClauseWithParams {
0283   Expr *ConditionExpr = nullptr;
0284 
0285 protected:
0286   OpenACCClauseWithCondition(OpenACCClauseKind K, SourceLocation BeginLoc,
0287                              SourceLocation LParenLoc, Expr *ConditionExpr,
0288                              SourceLocation EndLoc)
0289       : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
0290         ConditionExpr(ConditionExpr) {}
0291 
0292 public:
0293   static bool classof(const OpenACCClause *C);
0294 
0295   bool hasConditionExpr() const { return ConditionExpr; }
0296   const Expr *getConditionExpr() const { return ConditionExpr; }
0297   Expr *getConditionExpr() { return ConditionExpr; }
0298 
0299   child_range children() {
0300     if (ConditionExpr)
0301       return child_range(reinterpret_cast<Stmt **>(&ConditionExpr),
0302                          reinterpret_cast<Stmt **>(&ConditionExpr + 1));
0303     return child_range(child_iterator(), child_iterator());
0304   }
0305 
0306   const_child_range children() const {
0307     if (ConditionExpr)
0308       return const_child_range(
0309           reinterpret_cast<Stmt *const *>(&ConditionExpr),
0310           reinterpret_cast<Stmt *const *>(&ConditionExpr + 1));
0311     return const_child_range(const_child_iterator(), const_child_iterator());
0312   }
0313 };
0314 
0315 /// An 'if' clause, which has a required condition expression.
0316 class OpenACCIfClause : public OpenACCClauseWithCondition {
0317 protected:
0318   OpenACCIfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0319                   Expr *ConditionExpr, SourceLocation EndLoc);
0320 
0321 public:
0322   static bool classof(const OpenACCClause *C) {
0323     return C->getClauseKind() == OpenACCClauseKind::If;
0324   }
0325   static OpenACCIfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
0326                                  SourceLocation LParenLoc, Expr *ConditionExpr,
0327                                  SourceLocation EndLoc);
0328 };
0329 
0330 /// A 'self' clause, which has an optional condition expression, or, in the
0331 /// event of an 'update' directive, contains a 'VarList'.
0332 class OpenACCSelfClause final
0333     : public OpenACCClauseWithParams,
0334       private llvm::TrailingObjects<OpenACCSelfClause, Expr *> {
0335   friend TrailingObjects;
0336   // Holds whether this HAS a condition expression. Lacks a value if this is NOT
0337   // a condition-expr self clause.
0338   std::optional<bool> HasConditionExpr;
0339   // Holds the number of stored expressions.  In the case of a condition-expr
0340   // self clause, this is expected to be ONE (and there to be 1 trailing
0341   // object), whether or not that is null.
0342   unsigned NumExprs;
0343 
0344   OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0345                     Expr *ConditionExpr, SourceLocation EndLoc);
0346   OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0347                     ArrayRef<Expr *> VarList, SourceLocation EndLoc);
0348 
0349   // Intentionally internal, meant to be an implementation detail of everything
0350   // else. All non-internal uses should go through getConditionExpr/getVarList.
0351   llvm::ArrayRef<Expr *> getExprs() const {
0352     return {getTrailingObjects<Expr *>(), NumExprs};
0353   }
0354 
0355 public:
0356   static bool classof(const OpenACCClause *C) {
0357     return C->getClauseKind() == OpenACCClauseKind::Self;
0358   }
0359 
0360   bool isConditionExprClause() const { return HasConditionExpr.has_value(); }
0361 
0362   bool hasConditionExpr() const {
0363     assert(HasConditionExpr.has_value() &&
0364            "VarList Self Clause asked about condition expression");
0365     return *HasConditionExpr;
0366   }
0367 
0368   const Expr *getConditionExpr() const {
0369     assert(HasConditionExpr.has_value() &&
0370            "VarList Self Clause asked about condition expression");
0371     assert(getExprs().size() == 1 &&
0372            "ConditionExpr Self Clause with too many Exprs");
0373     return getExprs()[0];
0374   }
0375 
0376   Expr *getConditionExpr() {
0377     assert(HasConditionExpr.has_value() &&
0378            "VarList Self Clause asked about condition expression");
0379     assert(getExprs().size() == 1 &&
0380            "ConditionExpr Self Clause with too many Exprs");
0381     return getExprs()[0];
0382   }
0383 
0384   ArrayRef<Expr *> getVarList() {
0385     assert(!HasConditionExpr.has_value() &&
0386            "Condition Expr self clause asked about var list");
0387     return getExprs();
0388   }
0389   ArrayRef<Expr *> getVarList() const {
0390     assert(!HasConditionExpr.has_value() &&
0391            "Condition Expr self clause asked about var list");
0392     return getExprs();
0393   }
0394 
0395   child_range children() {
0396     return child_range(
0397         reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>()),
0398         reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>() + NumExprs));
0399   }
0400 
0401   const_child_range children() const {
0402     child_range Children = const_cast<OpenACCSelfClause *>(this)->children();
0403     return const_child_range(Children.begin(), Children.end());
0404   }
0405 
0406   static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
0407                                    SourceLocation LParenLoc,
0408                                    Expr *ConditionExpr, SourceLocation EndLoc);
0409   static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
0410                                    SourceLocation LParenLoc,
0411                                    ArrayRef<Expr *> ConditionExpr,
0412                                    SourceLocation EndLoc);
0413 };
0414 
0415 /// Represents a clause that has one or more expressions associated with it.
0416 class OpenACCClauseWithExprs : public OpenACCClauseWithParams {
0417   MutableArrayRef<Expr *> Exprs;
0418 
0419 protected:
0420   OpenACCClauseWithExprs(OpenACCClauseKind K, SourceLocation BeginLoc,
0421                          SourceLocation LParenLoc, SourceLocation EndLoc)
0422       : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {}
0423 
0424   /// Used only for initialization, the leaf class can initialize this to
0425   /// trailing storage.
0426   void setExprs(MutableArrayRef<Expr *> NewExprs) {
0427     assert(Exprs.empty() && "Cannot change Exprs list");
0428     Exprs = NewExprs;
0429   }
0430 
0431   /// Gets the entire list of expressions, but leave it to the
0432   /// individual clauses to expose this how they'd like.
0433   llvm::ArrayRef<Expr *> getExprs() const { return Exprs; }
0434 
0435 public:
0436   static bool classof(const OpenACCClause *C);
0437   child_range children() {
0438     return child_range(reinterpret_cast<Stmt **>(Exprs.begin()),
0439                        reinterpret_cast<Stmt **>(Exprs.end()));
0440   }
0441 
0442   const_child_range children() const {
0443     child_range Children =
0444         const_cast<OpenACCClauseWithExprs *>(this)->children();
0445     return const_child_range(Children.begin(), Children.end());
0446   }
0447 };
0448 
0449 // Represents the 'devnum' and expressions lists for the 'wait' clause.
0450 class OpenACCWaitClause final
0451     : public OpenACCClauseWithExprs,
0452       private llvm::TrailingObjects<OpenACCWaitClause, Expr *> {
0453   friend TrailingObjects;
0454   SourceLocation QueuesLoc;
0455   OpenACCWaitClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0456                     Expr *DevNumExpr, SourceLocation QueuesLoc,
0457                     ArrayRef<Expr *> QueueIdExprs, SourceLocation EndLoc)
0458       : OpenACCClauseWithExprs(OpenACCClauseKind::Wait, BeginLoc, LParenLoc,
0459                                EndLoc),
0460         QueuesLoc(QueuesLoc) {
0461     // The first element of the trailing storage is always the devnum expr,
0462     // whether it is used or not.
0463     std::uninitialized_copy(&DevNumExpr, &DevNumExpr + 1,
0464                             getTrailingObjects<Expr *>());
0465     std::uninitialized_copy(QueueIdExprs.begin(), QueueIdExprs.end(),
0466                             getTrailingObjects<Expr *>() + 1);
0467     setExprs(
0468         MutableArrayRef(getTrailingObjects<Expr *>(), QueueIdExprs.size() + 1));
0469   }
0470 
0471 public:
0472   static bool classof(const OpenACCClause *C) {
0473     return C->getClauseKind() == OpenACCClauseKind::Wait;
0474   }
0475   static OpenACCWaitClause *Create(const ASTContext &C, SourceLocation BeginLoc,
0476                                    SourceLocation LParenLoc, Expr *DevNumExpr,
0477                                    SourceLocation QueuesLoc,
0478                                    ArrayRef<Expr *> QueueIdExprs,
0479                                    SourceLocation EndLoc);
0480 
0481   bool hasQueuesTag() const { return !QueuesLoc.isInvalid(); }
0482   SourceLocation getQueuesLoc() const { return QueuesLoc; }
0483   bool hasDevNumExpr() const { return getExprs()[0]; }
0484   Expr *getDevNumExpr() const { return getExprs()[0]; }
0485   llvm::ArrayRef<Expr *> getQueueIdExprs() {
0486     return OpenACCClauseWithExprs::getExprs().drop_front();
0487   }
0488   llvm::ArrayRef<Expr *> getQueueIdExprs() const {
0489     return OpenACCClauseWithExprs::getExprs().drop_front();
0490   }
0491 };
0492 
0493 class OpenACCNumGangsClause final
0494     : public OpenACCClauseWithExprs,
0495       private llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {
0496   friend TrailingObjects;
0497 
0498   OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0499                         ArrayRef<Expr *> IntExprs, SourceLocation EndLoc)
0500       : OpenACCClauseWithExprs(OpenACCClauseKind::NumGangs, BeginLoc, LParenLoc,
0501                                EndLoc) {
0502     std::uninitialized_copy(IntExprs.begin(), IntExprs.end(),
0503                             getTrailingObjects<Expr *>());
0504     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));
0505   }
0506 
0507 public:
0508   static bool classof(const OpenACCClause *C) {
0509     return C->getClauseKind() == OpenACCClauseKind::NumGangs;
0510   }
0511   static OpenACCNumGangsClause *
0512   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0513          ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
0514 
0515   llvm::ArrayRef<Expr *> getIntExprs() {
0516     return OpenACCClauseWithExprs::getExprs();
0517   }
0518 
0519   llvm::ArrayRef<Expr *> getIntExprs() const {
0520     return OpenACCClauseWithExprs::getExprs();
0521   }
0522 };
0523 
0524 class OpenACCTileClause final
0525     : public OpenACCClauseWithExprs,
0526       private llvm::TrailingObjects<OpenACCTileClause, Expr *> {
0527   friend TrailingObjects;
0528   OpenACCTileClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0529                     ArrayRef<Expr *> SizeExprs, SourceLocation EndLoc)
0530       : OpenACCClauseWithExprs(OpenACCClauseKind::Tile, BeginLoc, LParenLoc,
0531                                EndLoc) {
0532     std::uninitialized_copy(SizeExprs.begin(), SizeExprs.end(),
0533                             getTrailingObjects<Expr *>());
0534     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), SizeExprs.size()));
0535   }
0536 
0537 public:
0538   static bool classof(const OpenACCClause *C) {
0539     return C->getClauseKind() == OpenACCClauseKind::Tile;
0540   }
0541   static OpenACCTileClause *Create(const ASTContext &C, SourceLocation BeginLoc,
0542                                    SourceLocation LParenLoc,
0543                                    ArrayRef<Expr *> SizeExprs,
0544                                    SourceLocation EndLoc);
0545   llvm::ArrayRef<Expr *> getSizeExprs() {
0546     return OpenACCClauseWithExprs::getExprs();
0547   }
0548 
0549   llvm::ArrayRef<Expr *> getSizeExprs() const {
0550     return OpenACCClauseWithExprs::getExprs();
0551   }
0552 };
0553 
0554 /// Represents one of a handful of clauses that have a single integer
0555 /// expression.
0556 class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithExprs {
0557   Expr *IntExpr;
0558 
0559 protected:
0560   OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc,
0561                                  SourceLocation LParenLoc, Expr *IntExpr,
0562                                  SourceLocation EndLoc)
0563       : OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc),
0564         IntExpr(IntExpr) {
0565     if (IntExpr)
0566       setExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1});
0567   }
0568 
0569 public:
0570   static bool classof(const OpenACCClause *C);
0571   bool hasIntExpr() const { return !getExprs().empty(); }
0572   const Expr *getIntExpr() const {
0573     return hasIntExpr() ? getExprs()[0] : nullptr;
0574   }
0575 
0576   Expr *getIntExpr() { return hasIntExpr() ? getExprs()[0] : nullptr; };
0577 };
0578 
0579 class OpenACCGangClause final
0580     : public OpenACCClauseWithExprs,
0581       private llvm::TrailingObjects<OpenACCGangClause, Expr *, OpenACCGangKind> {
0582   friend TrailingObjects;
0583 protected:
0584   OpenACCGangClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0585                     ArrayRef<OpenACCGangKind> GangKinds,
0586                     ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
0587 
0588   OpenACCGangKind getGangKind(unsigned I) const {
0589     return getTrailingObjects<OpenACCGangKind>()[I];
0590   }
0591 
0592 public:
0593   static bool classof(const OpenACCClause *C) {
0594     return C->getClauseKind() == OpenACCClauseKind::Gang;
0595   }
0596 
0597   size_t numTrailingObjects(OverloadToken<Expr *>) const {
0598     return getNumExprs();
0599   }
0600 
0601   unsigned getNumExprs() const { return getExprs().size(); }
0602   std::pair<OpenACCGangKind, const Expr *> getExpr(unsigned I) const {
0603     return {getGangKind(I), getExprs()[I]};
0604   }
0605 
0606   bool hasExprOfKind(OpenACCGangKind GK) const {
0607     for (unsigned I = 0; I < getNumExprs(); ++I) {
0608       if (getGangKind(I) == GK)
0609         return true;
0610     }
0611     return false;
0612   }
0613 
0614   static OpenACCGangClause *
0615   Create(const ASTContext &Ctx, SourceLocation BeginLoc,
0616          SourceLocation LParenLoc, ArrayRef<OpenACCGangKind> GangKinds,
0617          ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
0618 };
0619 
0620 class OpenACCWorkerClause : public OpenACCClauseWithSingleIntExpr {
0621 protected:
0622   OpenACCWorkerClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0623                       Expr *IntExpr, SourceLocation EndLoc);
0624 
0625 public:
0626   static bool classof(const OpenACCClause *C) {
0627     return C->getClauseKind() == OpenACCClauseKind::Worker;
0628   }
0629 
0630   static OpenACCWorkerClause *Create(const ASTContext &Ctx,
0631                                      SourceLocation BeginLoc,
0632                                      SourceLocation LParenLoc, Expr *IntExpr,
0633                                      SourceLocation EndLoc);
0634 };
0635 
0636 class OpenACCVectorClause : public OpenACCClauseWithSingleIntExpr {
0637 protected:
0638   OpenACCVectorClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0639                       Expr *IntExpr, SourceLocation EndLoc);
0640 
0641 public:
0642   static bool classof(const OpenACCClause *C) {
0643     return C->getClauseKind() == OpenACCClauseKind::Vector;
0644   }
0645 
0646   static OpenACCVectorClause *Create(const ASTContext &Ctx,
0647                                      SourceLocation BeginLoc,
0648                                      SourceLocation LParenLoc, Expr *IntExpr,
0649                                      SourceLocation EndLoc);
0650 };
0651 
0652 class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
0653   OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0654                           Expr *IntExpr, SourceLocation EndLoc);
0655 
0656 public:
0657   static bool classof(const OpenACCClause *C) {
0658     return C->getClauseKind() == OpenACCClauseKind::NumWorkers;
0659   }
0660   static OpenACCNumWorkersClause *Create(const ASTContext &C,
0661                                          SourceLocation BeginLoc,
0662                                          SourceLocation LParenLoc,
0663                                          Expr *IntExpr, SourceLocation EndLoc);
0664 };
0665 
0666 class OpenACCVectorLengthClause : public OpenACCClauseWithSingleIntExpr {
0667   OpenACCVectorLengthClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0668                             Expr *IntExpr, SourceLocation EndLoc);
0669 
0670 public:
0671   static bool classof(const OpenACCClause *C) {
0672     return C->getClauseKind() == OpenACCClauseKind::VectorLength;
0673   }
0674   static OpenACCVectorLengthClause *
0675   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0676          Expr *IntExpr, SourceLocation EndLoc);
0677 };
0678 
0679 class OpenACCAsyncClause : public OpenACCClauseWithSingleIntExpr {
0680   OpenACCAsyncClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0681                      Expr *IntExpr, SourceLocation EndLoc);
0682 
0683 public:
0684   static bool classof(const OpenACCClause *C) {
0685     return C->getClauseKind() == OpenACCClauseKind::Async;
0686   }
0687   static OpenACCAsyncClause *Create(const ASTContext &C,
0688                                     SourceLocation BeginLoc,
0689                                     SourceLocation LParenLoc, Expr *IntExpr,
0690                                     SourceLocation EndLoc);
0691 };
0692 
0693 class OpenACCDeviceNumClause : public OpenACCClauseWithSingleIntExpr {
0694   OpenACCDeviceNumClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0695                      Expr *IntExpr, SourceLocation EndLoc);
0696 
0697 public:
0698   static bool classof(const OpenACCClause *C) {
0699     return C->getClauseKind() == OpenACCClauseKind::DeviceNum;
0700   }
0701   static OpenACCDeviceNumClause *Create(const ASTContext &C,
0702                                         SourceLocation BeginLoc,
0703                                         SourceLocation LParenLoc, Expr *IntExpr,
0704                                         SourceLocation EndLoc);
0705 };
0706 
0707 class OpenACCDefaultAsyncClause : public OpenACCClauseWithSingleIntExpr {
0708   OpenACCDefaultAsyncClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0709                             Expr *IntExpr, SourceLocation EndLoc);
0710 
0711 public:
0712   static bool classof(const OpenACCClause *C) {
0713     return C->getClauseKind() == OpenACCClauseKind::DefaultAsync;
0714   }
0715   static OpenACCDefaultAsyncClause *
0716   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0717          Expr *IntExpr, SourceLocation EndLoc);
0718 };
0719 
0720 /// Represents a 'collapse' clause on a 'loop' construct. This clause takes an
0721 /// integer constant expression 'N' that represents how deep to collapse the
0722 /// construct. It also takes an optional 'force' tag that permits intervening
0723 /// code in the loops.
0724 class OpenACCCollapseClause : public OpenACCClauseWithSingleIntExpr {
0725   bool HasForce = false;
0726 
0727   OpenACCCollapseClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0728                         bool HasForce, Expr *LoopCount, SourceLocation EndLoc);
0729 
0730 public:
0731   const Expr *getLoopCount() const { return getIntExpr(); }
0732   Expr *getLoopCount() { return getIntExpr(); }
0733 
0734   bool hasForce() const { return HasForce; }
0735 
0736   static bool classof(const OpenACCClause *C) {
0737     return C->getClauseKind() == OpenACCClauseKind::Collapse;
0738   }
0739 
0740   static OpenACCCollapseClause *Create(const ASTContext &C,
0741                                        SourceLocation BeginLoc,
0742                                        SourceLocation LParenLoc, bool HasForce,
0743                                        Expr *LoopCount, SourceLocation EndLoc);
0744 };
0745 
0746 /// Represents a clause with one or more 'var' objects, represented as an expr,
0747 /// as its arguments. Var-list is expected to be stored in trailing storage.
0748 /// For now, we're just storing the original expression in its entirety, unlike
0749 /// OMP which has to do a bunch of work to create a private.
0750 class OpenACCClauseWithVarList : public OpenACCClauseWithExprs {
0751 protected:
0752   OpenACCClauseWithVarList(OpenACCClauseKind K, SourceLocation BeginLoc,
0753                            SourceLocation LParenLoc, SourceLocation EndLoc)
0754       : OpenACCClauseWithExprs(K, BeginLoc, LParenLoc, EndLoc) {}
0755 
0756 public:
0757   static bool classof(const OpenACCClause *C);
0758   ArrayRef<Expr *> getVarList() { return getExprs(); }
0759   ArrayRef<Expr *> getVarList() const { return getExprs(); }
0760 };
0761 
0762 class OpenACCPrivateClause final
0763     : public OpenACCClauseWithVarList,
0764       private llvm::TrailingObjects<OpenACCPrivateClause, Expr *> {
0765   friend TrailingObjects;
0766 
0767   OpenACCPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0768                        ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0769       : OpenACCClauseWithVarList(OpenACCClauseKind::Private, BeginLoc,
0770                                  LParenLoc, EndLoc) {
0771     std::uninitialized_copy(VarList.begin(), VarList.end(),
0772                             getTrailingObjects<Expr *>());
0773     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
0774   }
0775 
0776 public:
0777   static bool classof(const OpenACCClause *C) {
0778     return C->getClauseKind() == OpenACCClauseKind::Private;
0779   }
0780   static OpenACCPrivateClause *
0781   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0782          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
0783 };
0784 
0785 class OpenACCFirstPrivateClause final
0786     : public OpenACCClauseWithVarList,
0787       private llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *> {
0788   friend TrailingObjects;
0789 
0790   OpenACCFirstPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0791                             ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0792       : OpenACCClauseWithVarList(OpenACCClauseKind::FirstPrivate, BeginLoc,
0793                                  LParenLoc, EndLoc) {
0794     std::uninitialized_copy(VarList.begin(), VarList.end(),
0795                             getTrailingObjects<Expr *>());
0796     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
0797   }
0798 
0799 public:
0800   static bool classof(const OpenACCClause *C) {
0801     return C->getClauseKind() == OpenACCClauseKind::FirstPrivate;
0802   }
0803   static OpenACCFirstPrivateClause *
0804   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0805          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
0806 };
0807 
0808 class OpenACCDevicePtrClause final
0809     : public OpenACCClauseWithVarList,
0810       private llvm::TrailingObjects<OpenACCDevicePtrClause, Expr *> {
0811   friend TrailingObjects;
0812 
0813   OpenACCDevicePtrClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0814                          ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0815       : OpenACCClauseWithVarList(OpenACCClauseKind::DevicePtr, BeginLoc,
0816                                  LParenLoc, EndLoc) {
0817     std::uninitialized_copy(VarList.begin(), VarList.end(),
0818                             getTrailingObjects<Expr *>());
0819     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
0820   }
0821 
0822 public:
0823   static bool classof(const OpenACCClause *C) {
0824     return C->getClauseKind() == OpenACCClauseKind::DevicePtr;
0825   }
0826   static OpenACCDevicePtrClause *
0827   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0828          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
0829 };
0830 
0831 class OpenACCAttachClause final
0832     : public OpenACCClauseWithVarList,
0833       private llvm::TrailingObjects<OpenACCAttachClause, Expr *> {
0834   friend TrailingObjects;
0835 
0836   OpenACCAttachClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0837                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0838       : OpenACCClauseWithVarList(OpenACCClauseKind::Attach, BeginLoc, LParenLoc,
0839                                  EndLoc) {
0840     std::uninitialized_copy(VarList.begin(), VarList.end(),
0841                             getTrailingObjects<Expr *>());
0842     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
0843   }
0844 
0845 public:
0846   static bool classof(const OpenACCClause *C) {
0847     return C->getClauseKind() == OpenACCClauseKind::Attach;
0848   }
0849   static OpenACCAttachClause *
0850   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0851          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
0852 };
0853 
0854 class OpenACCDetachClause final
0855     : public OpenACCClauseWithVarList,
0856       private llvm::TrailingObjects<OpenACCDetachClause, Expr *> {
0857   friend TrailingObjects;
0858 
0859   OpenACCDetachClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0860                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0861       : OpenACCClauseWithVarList(OpenACCClauseKind::Detach, BeginLoc, LParenLoc,
0862                                  EndLoc) {
0863     std::uninitialized_copy(VarList.begin(), VarList.end(),
0864                             getTrailingObjects<Expr *>());
0865     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
0866   }
0867 
0868 public:
0869   static bool classof(const OpenACCClause *C) {
0870     return C->getClauseKind() == OpenACCClauseKind::Detach;
0871   }
0872   static OpenACCDetachClause *
0873   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0874          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
0875 };
0876 
0877 class OpenACCDeleteClause final
0878     : public OpenACCClauseWithVarList,
0879       private llvm::TrailingObjects<OpenACCDeleteClause, Expr *> {
0880   friend TrailingObjects;
0881 
0882   OpenACCDeleteClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0883                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0884       : OpenACCClauseWithVarList(OpenACCClauseKind::Delete, BeginLoc, LParenLoc,
0885                                  EndLoc) {
0886     std::uninitialized_copy(VarList.begin(), VarList.end(),
0887                             getTrailingObjects<Expr *>());
0888     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
0889   }
0890 
0891 public:
0892   static bool classof(const OpenACCClause *C) {
0893     return C->getClauseKind() == OpenACCClauseKind::Delete;
0894   }
0895   static OpenACCDeleteClause *
0896   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0897          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
0898 };
0899 
0900 class OpenACCUseDeviceClause final
0901     : public OpenACCClauseWithVarList,
0902       private llvm::TrailingObjects<OpenACCUseDeviceClause, Expr *> {
0903   friend TrailingObjects;
0904 
0905   OpenACCUseDeviceClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0906                          ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0907       : OpenACCClauseWithVarList(OpenACCClauseKind::UseDevice, BeginLoc,
0908                                  LParenLoc, EndLoc) {
0909     std::uninitialized_copy(VarList.begin(), VarList.end(),
0910                             getTrailingObjects<Expr *>());
0911     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
0912   }
0913 
0914 public:
0915   static bool classof(const OpenACCClause *C) {
0916     return C->getClauseKind() == OpenACCClauseKind::UseDevice;
0917   }
0918   static OpenACCUseDeviceClause *
0919   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0920          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
0921 };
0922 
0923 class OpenACCNoCreateClause final
0924     : public OpenACCClauseWithVarList,
0925       private llvm::TrailingObjects<OpenACCNoCreateClause, Expr *> {
0926   friend TrailingObjects;
0927 
0928   OpenACCNoCreateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0929                         ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0930       : OpenACCClauseWithVarList(OpenACCClauseKind::NoCreate, BeginLoc,
0931                                  LParenLoc, EndLoc) {
0932     std::uninitialized_copy(VarList.begin(), VarList.end(),
0933                             getTrailingObjects<Expr *>());
0934     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
0935   }
0936 
0937 public:
0938   static bool classof(const OpenACCClause *C) {
0939     return C->getClauseKind() == OpenACCClauseKind::NoCreate;
0940   }
0941   static OpenACCNoCreateClause *
0942   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0943          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
0944 };
0945 
0946 class OpenACCPresentClause final
0947     : public OpenACCClauseWithVarList,
0948       private llvm::TrailingObjects<OpenACCPresentClause, Expr *> {
0949   friend TrailingObjects;
0950 
0951   OpenACCPresentClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0952                        ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0953       : OpenACCClauseWithVarList(OpenACCClauseKind::Present, BeginLoc,
0954                                  LParenLoc, EndLoc) {
0955     std::uninitialized_copy(VarList.begin(), VarList.end(),
0956                             getTrailingObjects<Expr *>());
0957     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
0958   }
0959 
0960 public:
0961   static bool classof(const OpenACCClause *C) {
0962     return C->getClauseKind() == OpenACCClauseKind::Present;
0963   }
0964   static OpenACCPresentClause *
0965   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
0966          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
0967 };
0968 class OpenACCHostClause final
0969     : public OpenACCClauseWithVarList,
0970       private llvm::TrailingObjects<OpenACCHostClause, Expr *> {
0971   friend TrailingObjects;
0972 
0973   OpenACCHostClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0974                     ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0975       : OpenACCClauseWithVarList(OpenACCClauseKind::Host, BeginLoc, LParenLoc,
0976                                  EndLoc) {
0977     std::uninitialized_copy(VarList.begin(), VarList.end(),
0978                             getTrailingObjects<Expr *>());
0979     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
0980   }
0981 
0982 public:
0983   static bool classof(const OpenACCClause *C) {
0984     return C->getClauseKind() == OpenACCClauseKind::Host;
0985   }
0986   static OpenACCHostClause *Create(const ASTContext &C, SourceLocation BeginLoc,
0987                                    SourceLocation LParenLoc,
0988                                    ArrayRef<Expr *> VarList,
0989                                    SourceLocation EndLoc);
0990 };
0991 
0992 class OpenACCDeviceClause final
0993     : public OpenACCClauseWithVarList,
0994       private llvm::TrailingObjects<OpenACCDeviceClause, Expr *> {
0995   friend TrailingObjects;
0996 
0997   OpenACCDeviceClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
0998                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
0999       : OpenACCClauseWithVarList(OpenACCClauseKind::Device, BeginLoc, LParenLoc,
1000                                  EndLoc) {
1001     std::uninitialized_copy(VarList.begin(), VarList.end(),
1002                             getTrailingObjects<Expr *>());
1003     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1004   }
1005 
1006 public:
1007   static bool classof(const OpenACCClause *C) {
1008     return C->getClauseKind() == OpenACCClauseKind::Device;
1009   }
1010   static OpenACCDeviceClause *
1011   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
1012          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
1013 };
1014 
1015 class OpenACCCopyClause final
1016     : public OpenACCClauseWithVarList,
1017       private llvm::TrailingObjects<OpenACCCopyClause, Expr *> {
1018   friend TrailingObjects;
1019 
1020   OpenACCCopyClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
1021                     SourceLocation LParenLoc, ArrayRef<Expr *> VarList,
1022                     SourceLocation EndLoc)
1023       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc) {
1024     assert((Spelling == OpenACCClauseKind::Copy ||
1025             Spelling == OpenACCClauseKind::PCopy ||
1026             Spelling == OpenACCClauseKind::PresentOrCopy) &&
1027            "Invalid clause kind for copy-clause");
1028     std::uninitialized_copy(VarList.begin(), VarList.end(),
1029                             getTrailingObjects<Expr *>());
1030     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1031   }
1032 
1033 public:
1034   static bool classof(const OpenACCClause *C) {
1035     return C->getClauseKind() == OpenACCClauseKind::Copy ||
1036            C->getClauseKind() == OpenACCClauseKind::PCopy ||
1037            C->getClauseKind() == OpenACCClauseKind::PresentOrCopy;
1038   }
1039   static OpenACCCopyClause *
1040   Create(const ASTContext &C, OpenACCClauseKind Spelling,
1041          SourceLocation BeginLoc, SourceLocation LParenLoc,
1042          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
1043 };
1044 
1045 class OpenACCCopyInClause final
1046     : public OpenACCClauseWithVarList,
1047       private llvm::TrailingObjects<OpenACCCopyInClause, Expr *> {
1048   friend TrailingObjects;
1049   bool IsReadOnly;
1050 
1051   OpenACCCopyInClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
1052                       SourceLocation LParenLoc, bool IsReadOnly,
1053                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
1054       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
1055         IsReadOnly(IsReadOnly) {
1056     assert((Spelling == OpenACCClauseKind::CopyIn ||
1057             Spelling == OpenACCClauseKind::PCopyIn ||
1058             Spelling == OpenACCClauseKind::PresentOrCopyIn) &&
1059            "Invalid clause kind for copyin-clause");
1060     std::uninitialized_copy(VarList.begin(), VarList.end(),
1061                             getTrailingObjects<Expr *>());
1062     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1063   }
1064 
1065 public:
1066   static bool classof(const OpenACCClause *C) {
1067     return C->getClauseKind() == OpenACCClauseKind::CopyIn ||
1068            C->getClauseKind() == OpenACCClauseKind::PCopyIn ||
1069            C->getClauseKind() == OpenACCClauseKind::PresentOrCopyIn;
1070   }
1071   bool isReadOnly() const { return IsReadOnly; }
1072   static OpenACCCopyInClause *
1073   Create(const ASTContext &C, OpenACCClauseKind Spelling,
1074          SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsReadOnly,
1075          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
1076 };
1077 
1078 class OpenACCCopyOutClause final
1079     : public OpenACCClauseWithVarList,
1080       private llvm::TrailingObjects<OpenACCCopyOutClause, Expr *> {
1081   friend TrailingObjects;
1082   bool IsZero;
1083 
1084   OpenACCCopyOutClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
1085                        SourceLocation LParenLoc, bool IsZero,
1086                        ArrayRef<Expr *> VarList, SourceLocation EndLoc)
1087       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
1088         IsZero(IsZero) {
1089     assert((Spelling == OpenACCClauseKind::CopyOut ||
1090             Spelling == OpenACCClauseKind::PCopyOut ||
1091             Spelling == OpenACCClauseKind::PresentOrCopyOut) &&
1092            "Invalid clause kind for copyout-clause");
1093     std::uninitialized_copy(VarList.begin(), VarList.end(),
1094                             getTrailingObjects<Expr *>());
1095     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1096   }
1097 
1098 public:
1099   static bool classof(const OpenACCClause *C) {
1100     return C->getClauseKind() == OpenACCClauseKind::CopyOut ||
1101            C->getClauseKind() == OpenACCClauseKind::PCopyOut ||
1102            C->getClauseKind() == OpenACCClauseKind::PresentOrCopyOut;
1103   }
1104   bool isZero() const { return IsZero; }
1105   static OpenACCCopyOutClause *
1106   Create(const ASTContext &C, OpenACCClauseKind Spelling,
1107          SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsZero,
1108          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
1109 };
1110 
1111 class OpenACCCreateClause final
1112     : public OpenACCClauseWithVarList,
1113       private llvm::TrailingObjects<OpenACCCreateClause, Expr *> {
1114   friend TrailingObjects;
1115   bool IsZero;
1116 
1117   OpenACCCreateClause(OpenACCClauseKind Spelling, SourceLocation BeginLoc,
1118                       SourceLocation LParenLoc, bool IsZero,
1119                       ArrayRef<Expr *> VarList, SourceLocation EndLoc)
1120       : OpenACCClauseWithVarList(Spelling, BeginLoc, LParenLoc, EndLoc),
1121         IsZero(IsZero) {
1122     assert((Spelling == OpenACCClauseKind::Create ||
1123             Spelling == OpenACCClauseKind::PCreate ||
1124             Spelling == OpenACCClauseKind::PresentOrCreate) &&
1125            "Invalid clause kind for create-clause");
1126     std::uninitialized_copy(VarList.begin(), VarList.end(),
1127                             getTrailingObjects<Expr *>());
1128     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1129   }
1130 
1131 public:
1132   static bool classof(const OpenACCClause *C) {
1133     return C->getClauseKind() == OpenACCClauseKind::Create ||
1134            C->getClauseKind() == OpenACCClauseKind::PCreate ||
1135            C->getClauseKind() == OpenACCClauseKind::PresentOrCreate;
1136   }
1137   bool isZero() const { return IsZero; }
1138   static OpenACCCreateClause *
1139   Create(const ASTContext &C, OpenACCClauseKind Spelling,
1140          SourceLocation BeginLoc, SourceLocation LParenLoc, bool IsZero,
1141          ArrayRef<Expr *> VarList, SourceLocation EndLoc);
1142 };
1143 
1144 class OpenACCReductionClause final
1145     : public OpenACCClauseWithVarList,
1146       private llvm::TrailingObjects<OpenACCReductionClause, Expr *> {
1147   friend TrailingObjects;
1148   OpenACCReductionOperator Op;
1149 
1150   OpenACCReductionClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
1151                          OpenACCReductionOperator Operator,
1152                          ArrayRef<Expr *> VarList, SourceLocation EndLoc)
1153       : OpenACCClauseWithVarList(OpenACCClauseKind::Reduction, BeginLoc,
1154                                  LParenLoc, EndLoc),
1155         Op(Operator) {
1156     std::uninitialized_copy(VarList.begin(), VarList.end(),
1157                             getTrailingObjects<Expr *>());
1158     setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
1159   }
1160 
1161 public:
1162   static bool classof(const OpenACCClause *C) {
1163     return C->getClauseKind() == OpenACCClauseKind::Reduction;
1164   }
1165 
1166   static OpenACCReductionClause *
1167   Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
1168          OpenACCReductionOperator Operator, ArrayRef<Expr *> VarList,
1169          SourceLocation EndLoc);
1170 
1171   OpenACCReductionOperator getReductionOp() const { return Op; }
1172 };
1173 
1174 template <class Impl> class OpenACCClauseVisitor {
1175   Impl &getDerived() { return static_cast<Impl &>(*this); }
1176 
1177 public:
1178   void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
1179     for (const OpenACCClause *Clause : List)
1180       Visit(Clause);
1181   }
1182 
1183   void Visit(const OpenACCClause *C) {
1184     if (!C)
1185       return;
1186 
1187     switch (C->getClauseKind()) {
1188 #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
1189   case OpenACCClauseKind::CLAUSE_NAME:                                         \
1190     Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C));        \
1191     return;
1192 #define CLAUSE_ALIAS(ALIAS_NAME, CLAUSE_NAME, DEPRECATED)                      \
1193   case OpenACCClauseKind::ALIAS_NAME:                                          \
1194     Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C));        \
1195     return;
1196 #include "clang/Basic/OpenACCClauses.def"
1197 
1198     default:
1199       llvm_unreachable("Clause visitor not yet implemented");
1200     }
1201     llvm_unreachable("Invalid Clause kind");
1202   }
1203 
1204 #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
1205   void Visit##CLAUSE_NAME##Clause(                                             \
1206       const OpenACC##CLAUSE_NAME##Clause &Clause) {                            \
1207     return getDerived().Visit##CLAUSE_NAME##Clause(Clause);                    \
1208   }
1209 
1210 #include "clang/Basic/OpenACCClauses.def"
1211 };
1212 
1213 class OpenACCClausePrinter final
1214     : public OpenACCClauseVisitor<OpenACCClausePrinter> {
1215   raw_ostream &OS;
1216   const PrintingPolicy &Policy;
1217 
1218   void printExpr(const Expr *E);
1219 
1220 public:
1221   void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
1222     for (const OpenACCClause *Clause : List) {
1223       Visit(Clause);
1224 
1225       if (Clause != List.back())
1226         OS << ' ';
1227     }
1228   }
1229   OpenACCClausePrinter(raw_ostream &OS, const PrintingPolicy &Policy)
1230       : OS(OS), Policy(Policy) {}
1231 
1232 #define VISIT_CLAUSE(CLAUSE_NAME)                                              \
1233   void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause);
1234 #include "clang/Basic/OpenACCClauses.def"
1235 };
1236 
1237 } // namespace clang
1238 
1239 #endif // LLVM_CLANG_AST_OPENACCCLAUSE_H