Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:37:04

0001 //===----- SemaOpenACC.h - Semantic Analysis for OpenACC constructs -------===//
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 declares semantic analysis for OpenACC constructs and
0010 /// clauses.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_SEMA_SEMAOPENACC_H
0015 #define LLVM_CLANG_SEMA_SEMAOPENACC_H
0016 
0017 #include "clang/AST/DeclGroup.h"
0018 #include "clang/AST/StmtOpenACC.h"
0019 #include "clang/Basic/LLVM.h"
0020 #include "clang/Basic/OpenACCKinds.h"
0021 #include "clang/Basic/SourceLocation.h"
0022 #include "clang/Sema/Ownership.h"
0023 #include "clang/Sema/SemaBase.h"
0024 #include "llvm/ADT/SmallVector.h"
0025 #include "llvm/Support/Compiler.h"
0026 #include <cassert>
0027 #include <optional>
0028 #include <utility>
0029 #include <variant>
0030 
0031 namespace clang {
0032 class IdentifierInfo;
0033 class OpenACCClause;
0034 
0035 class SemaOpenACC : public SemaBase {
0036 private:
0037   struct ComputeConstructInfo {
0038     /// Which type of compute construct we are inside of, which we can use to
0039     /// determine whether we should add loops to the above collection.  We can
0040     /// also use it to diagnose loop construct clauses.
0041     OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
0042     // If we have an active compute construct, stores the list of clauses we've
0043     // prepared for it, so that we can diagnose limitations on child constructs.
0044     ArrayRef<OpenACCClause *> Clauses;
0045   } ActiveComputeConstructInfo;
0046 
0047   bool isInComputeConstruct() const {
0048     return ActiveComputeConstructInfo.Kind != OpenACCDirectiveKind::Invalid;
0049   }
0050 
0051   /// Certain clauses care about the same things that aren't specific to the
0052   /// individual clause, but can be shared by a few, so store them here. All
0053   /// require a 'no intervening constructs' rule, so we know they are all from
0054   /// the same 'place'.
0055   struct LoopCheckingInfo {
0056     /// Records whether we've seen the top level 'for'. We already diagnose
0057     /// later that the 'top level' is a for loop, so we use this to suppress the
0058     /// 'collapse inner loop not a 'for' loop' diagnostic.
0059     LLVM_PREFERRED_TYPE(bool)
0060     unsigned TopLevelLoopSeen : 1;
0061 
0062     /// Records whether this 'tier' of the loop has already seen a 'for' loop,
0063     /// used to diagnose if there are multiple 'for' loops at any one level.
0064     LLVM_PREFERRED_TYPE(bool)
0065     unsigned CurLevelHasLoopAlready : 1;
0066 
0067   } LoopInfo{/*TopLevelLoopSeen=*/false, /*CurLevelHasLoopAlready=*/false};
0068 
0069   /// The 'collapse' clause requires quite a bit of checking while
0070   /// parsing/instantiating its body, so this structure/object keeps all of the
0071   /// necessary information as we do checking.  This should rarely be directly
0072   /// modified, and typically should be controlled by the RAII objects.
0073   ///
0074   /// Collapse has an 'N' count that makes it apply to a number of loops 'below'
0075   /// it.
0076   struct CollapseCheckingInfo {
0077     OpenACCCollapseClause *ActiveCollapse = nullptr;
0078 
0079     /// This is a value that maintains the current value of the 'N' on the
0080     /// current collapse, minus the depth that has already been traversed. When
0081     /// there is not an active collapse, or a collapse whose depth we don't know
0082     /// (for example, if it is a dependent value), this should be `nullopt`,
0083     /// else it should be 'N' minus the current depth traversed.
0084     std::optional<llvm::APSInt> CurCollapseCount;
0085 
0086     /// Records whether we've hit a CurCollapseCount of '0' on the way down,
0087     /// which allows us to diagnose if the value of 'N' is too large for the
0088     /// current number of 'for' loops.
0089     bool CollapseDepthSatisfied = true;
0090 
0091     /// Records the kind of the directive that this clause is attached to, which
0092     /// allows us to use it in diagnostics.
0093     OpenACCDirectiveKind DirectiveKind = OpenACCDirectiveKind::Invalid;
0094   } CollapseInfo;
0095 
0096   /// The 'tile' clause requires a bit of additional checking as well, so like
0097   /// the `CollapseCheckingInfo`, ensure we maintain information here too.
0098   struct TileCheckingInfo {
0099     OpenACCTileClause *ActiveTile = nullptr;
0100 
0101     /// This is the number of expressions on a 'tile' clause.  This doesn't have
0102     /// to be an APSInt because it isn't the result of a constexpr, just by our
0103     /// own counting of elements.
0104     std::optional<unsigned> CurTileCount;
0105 
0106     /// Records whether we've hit a 'CurTileCount' of '0' on the wya down,
0107     /// which allows us to diagnose if the number of arguments is too large for
0108     /// the current number of 'for' loops.
0109     bool TileDepthSatisfied = true;
0110 
0111     /// Records the kind of the directive that this clause is attached to, which
0112     /// allows us to use it in diagnostics.
0113     OpenACCDirectiveKind DirectiveKind = OpenACCDirectiveKind::Invalid;
0114   } TileInfo;
0115 
0116   /// A list of the active reduction clauses, which allows us to check that all
0117   /// vars on nested constructs for the same reduction var have the same
0118   /// reduction operator. Currently this is enforced against all constructs
0119   /// despite the rule being in the 'loop' section. By current reading, this
0120   /// should apply to all anyway, but we may need to make this more like the
0121   /// 'loop' clause enforcement, where this is 'blocked' by a compute construct.
0122   llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses;
0123 
0124   // Type to check the info about the 'for stmt'.
0125   struct ForStmtBeginChecker {
0126     SemaOpenACC &SemaRef;
0127     SourceLocation ForLoc;
0128     bool IsRangeFor = false;
0129     std::optional<const CXXForRangeStmt *> RangeFor = nullptr;
0130     const Stmt *Init = nullptr;
0131     bool InitChanged = false;
0132     std::optional<const Stmt *> Cond = nullptr;
0133     std::optional<const Stmt *> Inc = nullptr;
0134     // Prevent us from checking 2x, which can happen with collapse & tile.
0135     bool AlreadyChecked = false;
0136 
0137     ForStmtBeginChecker(SemaOpenACC &SemaRef, SourceLocation ForLoc,
0138                         std::optional<const CXXForRangeStmt *> S)
0139         : SemaRef(SemaRef), ForLoc(ForLoc), IsRangeFor(true), RangeFor(S) {}
0140 
0141     ForStmtBeginChecker(SemaOpenACC &SemaRef, SourceLocation ForLoc,
0142                         const Stmt *I, bool InitChanged,
0143                         std::optional<const Stmt *> C,
0144                         std::optional<const Stmt *> Inc)
0145         : SemaRef(SemaRef), ForLoc(ForLoc), IsRangeFor(false), Init(I),
0146           InitChanged(InitChanged), Cond(C), Inc(Inc) {}
0147     // Do the checking for the For/Range-For. Currently this implements the 'not
0148     // seq' restrictions only, and should be called either if we know we are a
0149     // top-level 'for' (the one associated via associated-stmt), or extended via
0150     // 'collapse'.
0151     void check();
0152 
0153     const ValueDecl *checkInit();
0154     void checkCond();
0155     void checkInc(const ValueDecl *Init);
0156   };
0157 
0158   /// Helper function for checking the 'for' and 'range for' stmts.
0159   void ForStmtBeginHelper(SourceLocation ForLoc, ForStmtBeginChecker &C);
0160 
0161 public:
0162   ComputeConstructInfo &getActiveComputeConstructInfo() {
0163     return ActiveComputeConstructInfo;
0164   }
0165 
0166   /// If there is a current 'active' loop construct with a 'gang' clause on a
0167   /// 'kernel' construct, this will have the source location for it, and the
0168   /// 'kernel kind'. This permits us to implement the restriction of no further
0169   /// 'gang' clauses.
0170   struct LoopGangOnKernelTy {
0171     SourceLocation Loc;
0172     OpenACCDirectiveKind DirKind = OpenACCDirectiveKind::Invalid;
0173   } LoopGangClauseOnKernel;
0174 
0175   /// If there is a current 'active' loop construct with a 'worker' clause on it
0176   /// (on any sort of construct), this has the source location for it.  This
0177   /// permits us to implement the restriction of no further 'gang' or 'worker'
0178   /// clauses.
0179   SourceLocation LoopWorkerClauseLoc;
0180   /// If there is a current 'active' loop construct with a 'vector' clause on it
0181   /// (on any sort of construct), this has the source location for it.  This
0182   /// permits us to implement the restriction of no further 'gang', 'vector', or
0183   /// 'worker' clauses.
0184   SourceLocation LoopVectorClauseLoc;
0185   /// If there is a current 'active' loop construct that does NOT have a 'seq'
0186   /// clause on it, this has that source location and loop Directive 'kind'.
0187   /// This permits us to implement the 'loop' restrictions on the loop variable.
0188   /// This can be extended via 'collapse', so we need to keep this around for a
0189   /// while.
0190   struct LoopWithoutSeqCheckingInfo {
0191     OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
0192     SourceLocation Loc;
0193   } LoopWithoutSeqInfo;
0194 
0195   // Redeclaration of the version in OpenACCClause.h.
0196   using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
0197 
0198   /// A type to represent all the data for an OpenACC Clause that has been
0199   /// parsed, but not yet created/semantically analyzed. This is effectively a
0200   /// discriminated union on the 'Clause Kind', with all of the individual
0201   /// clause details stored in a std::variant.
0202   class OpenACCParsedClause {
0203     OpenACCDirectiveKind DirKind;
0204     OpenACCClauseKind ClauseKind;
0205     SourceRange ClauseRange;
0206     SourceLocation LParenLoc;
0207 
0208     struct DefaultDetails {
0209       OpenACCDefaultClauseKind DefaultClauseKind;
0210     };
0211 
0212     struct ConditionDetails {
0213       Expr *ConditionExpr;
0214     };
0215 
0216     struct IntExprDetails {
0217       SmallVector<Expr *> IntExprs;
0218     };
0219 
0220     struct VarListDetails {
0221       SmallVector<Expr *> VarList;
0222       bool IsReadOnly;
0223       bool IsZero;
0224     };
0225 
0226     struct WaitDetails {
0227       Expr *DevNumExpr;
0228       SourceLocation QueuesLoc;
0229       SmallVector<Expr *> QueueIdExprs;
0230     };
0231 
0232     struct DeviceTypeDetails {
0233       SmallVector<DeviceTypeArgument> Archs;
0234     };
0235     struct ReductionDetails {
0236       OpenACCReductionOperator Op;
0237       SmallVector<Expr *> VarList;
0238     };
0239 
0240     struct CollapseDetails {
0241       bool IsForce;
0242       Expr *LoopCount;
0243     };
0244 
0245     struct GangDetails {
0246       SmallVector<OpenACCGangKind> GangKinds;
0247       SmallVector<Expr *> IntExprs;
0248     };
0249 
0250     std::variant<std::monostate, DefaultDetails, ConditionDetails,
0251                  IntExprDetails, VarListDetails, WaitDetails, DeviceTypeDetails,
0252                  ReductionDetails, CollapseDetails, GangDetails>
0253         Details = std::monostate{};
0254 
0255   public:
0256     OpenACCParsedClause(OpenACCDirectiveKind DirKind,
0257                         OpenACCClauseKind ClauseKind, SourceLocation BeginLoc)
0258         : DirKind(DirKind), ClauseKind(ClauseKind), ClauseRange(BeginLoc, {}) {}
0259 
0260     OpenACCDirectiveKind getDirectiveKind() const { return DirKind; }
0261 
0262     OpenACCClauseKind getClauseKind() const { return ClauseKind; }
0263 
0264     SourceLocation getBeginLoc() const { return ClauseRange.getBegin(); }
0265 
0266     SourceLocation getLParenLoc() const { return LParenLoc; }
0267 
0268     SourceLocation getEndLoc() const { return ClauseRange.getEnd(); }
0269 
0270     OpenACCDefaultClauseKind getDefaultClauseKind() const {
0271       assert(ClauseKind == OpenACCClauseKind::Default &&
0272              "Parsed clause is not a default clause");
0273       return std::get<DefaultDetails>(Details).DefaultClauseKind;
0274     }
0275 
0276     const Expr *getConditionExpr() const {
0277       return const_cast<OpenACCParsedClause *>(this)->getConditionExpr();
0278     }
0279 
0280     Expr *getConditionExpr() {
0281       assert((ClauseKind == OpenACCClauseKind::If ||
0282               (ClauseKind == OpenACCClauseKind::Self &&
0283                DirKind != OpenACCDirectiveKind::Update)) &&
0284              "Parsed clause kind does not have a condition expr");
0285 
0286       // 'self' has an optional ConditionExpr, so be tolerant of that. This will
0287       // assert in variant otherwise.
0288       if (ClauseKind == OpenACCClauseKind::Self &&
0289           std::holds_alternative<std::monostate>(Details))
0290         return nullptr;
0291 
0292       return std::get<ConditionDetails>(Details).ConditionExpr;
0293     }
0294 
0295     unsigned getNumIntExprs() const {
0296       assert((ClauseKind == OpenACCClauseKind::NumGangs ||
0297               ClauseKind == OpenACCClauseKind::NumWorkers ||
0298               ClauseKind == OpenACCClauseKind::Async ||
0299               ClauseKind == OpenACCClauseKind::DeviceNum ||
0300               ClauseKind == OpenACCClauseKind::DefaultAsync ||
0301               ClauseKind == OpenACCClauseKind::Tile ||
0302               ClauseKind == OpenACCClauseKind::Worker ||
0303               ClauseKind == OpenACCClauseKind::Vector ||
0304               ClauseKind == OpenACCClauseKind::VectorLength) &&
0305              "Parsed clause kind does not have a int exprs");
0306 
0307       // 'async', 'worker', 'vector', and 'wait' have an optional IntExpr, so be
0308       // tolerant of that.
0309       if ((ClauseKind == OpenACCClauseKind::Async ||
0310            ClauseKind == OpenACCClauseKind::Worker ||
0311            ClauseKind == OpenACCClauseKind::Vector ||
0312            ClauseKind == OpenACCClauseKind::Wait) &&
0313           std::holds_alternative<std::monostate>(Details))
0314         return 0;
0315       return std::get<IntExprDetails>(Details).IntExprs.size();
0316     }
0317 
0318     SourceLocation getQueuesLoc() const {
0319       assert(ClauseKind == OpenACCClauseKind::Wait &&
0320              "Parsed clause kind does not have a queues location");
0321 
0322       if (std::holds_alternative<std::monostate>(Details))
0323         return SourceLocation{};
0324 
0325       return std::get<WaitDetails>(Details).QueuesLoc;
0326     }
0327 
0328     Expr *getDevNumExpr() const {
0329       assert(ClauseKind == OpenACCClauseKind::Wait &&
0330              "Parsed clause kind does not have a device number expr");
0331 
0332       if (std::holds_alternative<std::monostate>(Details))
0333         return nullptr;
0334 
0335       return std::get<WaitDetails>(Details).DevNumExpr;
0336     }
0337 
0338     ArrayRef<Expr *> getQueueIdExprs() const {
0339       assert(ClauseKind == OpenACCClauseKind::Wait &&
0340              "Parsed clause kind does not have a queue id expr list");
0341 
0342       if (std::holds_alternative<std::monostate>(Details))
0343         return ArrayRef<Expr *>();
0344 
0345       return std::get<WaitDetails>(Details).QueueIdExprs;
0346     }
0347 
0348     ArrayRef<Expr *> getIntExprs() {
0349       assert((ClauseKind == OpenACCClauseKind::NumGangs ||
0350               ClauseKind == OpenACCClauseKind::NumWorkers ||
0351               ClauseKind == OpenACCClauseKind::Async ||
0352               ClauseKind == OpenACCClauseKind::DeviceNum ||
0353               ClauseKind == OpenACCClauseKind::DefaultAsync ||
0354               ClauseKind == OpenACCClauseKind::Tile ||
0355               ClauseKind == OpenACCClauseKind::Gang ||
0356               ClauseKind == OpenACCClauseKind::Worker ||
0357               ClauseKind == OpenACCClauseKind::Vector ||
0358               ClauseKind == OpenACCClauseKind::VectorLength) &&
0359              "Parsed clause kind does not have a int exprs");
0360 
0361       if (ClauseKind == OpenACCClauseKind::Gang) {
0362         // There might not be any gang int exprs, as this is an optional
0363         // argument.
0364         if (std::holds_alternative<std::monostate>(Details))
0365           return {};
0366         return std::get<GangDetails>(Details).IntExprs;
0367       }
0368 
0369       return std::get<IntExprDetails>(Details).IntExprs;
0370     }
0371 
0372     ArrayRef<Expr *> getIntExprs() const {
0373       return const_cast<OpenACCParsedClause *>(this)->getIntExprs();
0374     }
0375 
0376     OpenACCReductionOperator getReductionOp() const {
0377       return std::get<ReductionDetails>(Details).Op;
0378     }
0379 
0380     ArrayRef<OpenACCGangKind> getGangKinds() const {
0381       assert(ClauseKind == OpenACCClauseKind::Gang &&
0382              "Parsed clause kind does not have gang kind");
0383       // The args on gang are optional, so this might not actually hold
0384       // anything.
0385       if (std::holds_alternative<std::monostate>(Details))
0386         return {};
0387       return std::get<GangDetails>(Details).GangKinds;
0388     }
0389 
0390     ArrayRef<Expr *> getVarList() {
0391       assert((ClauseKind == OpenACCClauseKind::Private ||
0392               ClauseKind == OpenACCClauseKind::NoCreate ||
0393               ClauseKind == OpenACCClauseKind::Present ||
0394               ClauseKind == OpenACCClauseKind::Copy ||
0395               ClauseKind == OpenACCClauseKind::PCopy ||
0396               ClauseKind == OpenACCClauseKind::PresentOrCopy ||
0397               ClauseKind == OpenACCClauseKind::CopyIn ||
0398               ClauseKind == OpenACCClauseKind::PCopyIn ||
0399               ClauseKind == OpenACCClauseKind::PresentOrCopyIn ||
0400               ClauseKind == OpenACCClauseKind::CopyOut ||
0401               ClauseKind == OpenACCClauseKind::PCopyOut ||
0402               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
0403               ClauseKind == OpenACCClauseKind::Create ||
0404               ClauseKind == OpenACCClauseKind::PCreate ||
0405               ClauseKind == OpenACCClauseKind::PresentOrCreate ||
0406               ClauseKind == OpenACCClauseKind::Attach ||
0407               ClauseKind == OpenACCClauseKind::Delete ||
0408               ClauseKind == OpenACCClauseKind::UseDevice ||
0409               ClauseKind == OpenACCClauseKind::Detach ||
0410               ClauseKind == OpenACCClauseKind::DevicePtr ||
0411               ClauseKind == OpenACCClauseKind::Reduction ||
0412               ClauseKind == OpenACCClauseKind::Host ||
0413               ClauseKind == OpenACCClauseKind::Device ||
0414               (ClauseKind == OpenACCClauseKind::Self &&
0415                DirKind == OpenACCDirectiveKind::Update) ||
0416               ClauseKind == OpenACCClauseKind::FirstPrivate) &&
0417              "Parsed clause kind does not have a var-list");
0418 
0419       if (ClauseKind == OpenACCClauseKind::Reduction)
0420         return std::get<ReductionDetails>(Details).VarList;
0421 
0422       return std::get<VarListDetails>(Details).VarList;
0423     }
0424 
0425     ArrayRef<Expr *> getVarList() const {
0426       return const_cast<OpenACCParsedClause *>(this)->getVarList();
0427     }
0428 
0429     bool isReadOnly() const {
0430       assert((ClauseKind == OpenACCClauseKind::CopyIn ||
0431               ClauseKind == OpenACCClauseKind::PCopyIn ||
0432               ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
0433              "Only copyin accepts 'readonly:' tag");
0434       return std::get<VarListDetails>(Details).IsReadOnly;
0435     }
0436 
0437     bool isZero() const {
0438       assert((ClauseKind == OpenACCClauseKind::CopyOut ||
0439               ClauseKind == OpenACCClauseKind::PCopyOut ||
0440               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
0441               ClauseKind == OpenACCClauseKind::Create ||
0442               ClauseKind == OpenACCClauseKind::PCreate ||
0443               ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
0444              "Only copyout/create accepts 'zero' tag");
0445       return std::get<VarListDetails>(Details).IsZero;
0446     }
0447 
0448     bool isForce() const {
0449       assert(ClauseKind == OpenACCClauseKind::Collapse &&
0450              "Only 'collapse' has a force tag");
0451       return std::get<CollapseDetails>(Details).IsForce;
0452     }
0453 
0454     Expr *getLoopCount() const {
0455       assert(ClauseKind == OpenACCClauseKind::Collapse &&
0456              "Only 'collapse' has a loop count");
0457       return std::get<CollapseDetails>(Details).LoopCount;
0458     }
0459 
0460     ArrayRef<DeviceTypeArgument> getDeviceTypeArchitectures() const {
0461       assert((ClauseKind == OpenACCClauseKind::DeviceType ||
0462               ClauseKind == OpenACCClauseKind::DType) &&
0463              "Only 'device_type'/'dtype' has a device-type-arg list");
0464       return std::get<DeviceTypeDetails>(Details).Archs;
0465     }
0466 
0467     void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
0468     void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }
0469 
0470     void setDefaultDetails(OpenACCDefaultClauseKind DefKind) {
0471       assert(ClauseKind == OpenACCClauseKind::Default &&
0472              "Parsed clause is not a default clause");
0473       Details = DefaultDetails{DefKind};
0474     }
0475 
0476     void setConditionDetails(Expr *ConditionExpr) {
0477       assert((ClauseKind == OpenACCClauseKind::If ||
0478               (ClauseKind == OpenACCClauseKind::Self &&
0479                DirKind != OpenACCDirectiveKind::Update)) &&
0480              "Parsed clause kind does not have a condition expr");
0481       // In C++ we can count on this being a 'bool', but in C this gets left as
0482       // some sort of scalar that codegen will have to take care of converting.
0483       assert((!ConditionExpr || ConditionExpr->isInstantiationDependent() ||
0484               ConditionExpr->getType()->isScalarType()) &&
0485              "Condition expression type not scalar/dependent");
0486 
0487       Details = ConditionDetails{ConditionExpr};
0488     }
0489 
0490     void setIntExprDetails(ArrayRef<Expr *> IntExprs) {
0491       assert((ClauseKind == OpenACCClauseKind::NumGangs ||
0492               ClauseKind == OpenACCClauseKind::NumWorkers ||
0493               ClauseKind == OpenACCClauseKind::Async ||
0494               ClauseKind == OpenACCClauseKind::DeviceNum ||
0495               ClauseKind == OpenACCClauseKind::DefaultAsync ||
0496               ClauseKind == OpenACCClauseKind::Tile ||
0497               ClauseKind == OpenACCClauseKind::Worker ||
0498               ClauseKind == OpenACCClauseKind::Vector ||
0499               ClauseKind == OpenACCClauseKind::VectorLength) &&
0500              "Parsed clause kind does not have a int exprs");
0501       Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}};
0502     }
0503     void setIntExprDetails(llvm::SmallVector<Expr *> &&IntExprs) {
0504       assert((ClauseKind == OpenACCClauseKind::NumGangs ||
0505               ClauseKind == OpenACCClauseKind::NumWorkers ||
0506               ClauseKind == OpenACCClauseKind::Async ||
0507               ClauseKind == OpenACCClauseKind::DeviceNum ||
0508               ClauseKind == OpenACCClauseKind::DefaultAsync ||
0509               ClauseKind == OpenACCClauseKind::Tile ||
0510               ClauseKind == OpenACCClauseKind::Worker ||
0511               ClauseKind == OpenACCClauseKind::Vector ||
0512               ClauseKind == OpenACCClauseKind::VectorLength) &&
0513              "Parsed clause kind does not have a int exprs");
0514       Details = IntExprDetails{std::move(IntExprs)};
0515     }
0516 
0517     void setGangDetails(ArrayRef<OpenACCGangKind> GKs,
0518                         ArrayRef<Expr *> IntExprs) {
0519       assert(ClauseKind == OpenACCClauseKind::Gang &&
0520              "Parsed Clause kind does not have gang details");
0521       assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");
0522 
0523       Details = GangDetails{{GKs.begin(), GKs.end()},
0524                             {IntExprs.begin(), IntExprs.end()}};
0525     }
0526 
0527     void setGangDetails(llvm::SmallVector<OpenACCGangKind> &&GKs,
0528                         llvm::SmallVector<Expr *> &&IntExprs) {
0529       assert(ClauseKind == OpenACCClauseKind::Gang &&
0530              "Parsed Clause kind does not have gang details");
0531       assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");
0532 
0533       Details = GangDetails{std::move(GKs), std::move(IntExprs)};
0534     }
0535 
0536     void setVarListDetails(ArrayRef<Expr *> VarList, bool IsReadOnly,
0537                            bool IsZero) {
0538       assert((ClauseKind == OpenACCClauseKind::Private ||
0539               ClauseKind == OpenACCClauseKind::NoCreate ||
0540               ClauseKind == OpenACCClauseKind::Present ||
0541               ClauseKind == OpenACCClauseKind::Copy ||
0542               ClauseKind == OpenACCClauseKind::PCopy ||
0543               ClauseKind == OpenACCClauseKind::PresentOrCopy ||
0544               ClauseKind == OpenACCClauseKind::CopyIn ||
0545               ClauseKind == OpenACCClauseKind::PCopyIn ||
0546               ClauseKind == OpenACCClauseKind::PresentOrCopyIn ||
0547               ClauseKind == OpenACCClauseKind::CopyOut ||
0548               ClauseKind == OpenACCClauseKind::PCopyOut ||
0549               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
0550               ClauseKind == OpenACCClauseKind::Create ||
0551               ClauseKind == OpenACCClauseKind::PCreate ||
0552               ClauseKind == OpenACCClauseKind::PresentOrCreate ||
0553               ClauseKind == OpenACCClauseKind::Attach ||
0554               ClauseKind == OpenACCClauseKind::Delete ||
0555               ClauseKind == OpenACCClauseKind::UseDevice ||
0556               ClauseKind == OpenACCClauseKind::Detach ||
0557               ClauseKind == OpenACCClauseKind::DevicePtr ||
0558               ClauseKind == OpenACCClauseKind::Host ||
0559               ClauseKind == OpenACCClauseKind::Device ||
0560               (ClauseKind == OpenACCClauseKind::Self &&
0561                DirKind == OpenACCDirectiveKind::Update) ||
0562               ClauseKind == OpenACCClauseKind::FirstPrivate) &&
0563              "Parsed clause kind does not have a var-list");
0564       assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
0565               ClauseKind == OpenACCClauseKind::PCopyIn ||
0566               ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
0567              "readonly: tag only valid on copyin");
0568       assert((!IsZero || ClauseKind == OpenACCClauseKind::CopyOut ||
0569               ClauseKind == OpenACCClauseKind::PCopyOut ||
0570               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
0571               ClauseKind == OpenACCClauseKind::Create ||
0572               ClauseKind == OpenACCClauseKind::PCreate ||
0573               ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
0574              "zero: tag only valid on copyout/create");
0575       Details =
0576           VarListDetails{{VarList.begin(), VarList.end()}, IsReadOnly, IsZero};
0577     }
0578 
0579     void setVarListDetails(llvm::SmallVector<Expr *> &&VarList, bool IsReadOnly,
0580                            bool IsZero) {
0581       assert((ClauseKind == OpenACCClauseKind::Private ||
0582               ClauseKind == OpenACCClauseKind::NoCreate ||
0583               ClauseKind == OpenACCClauseKind::Present ||
0584               ClauseKind == OpenACCClauseKind::Copy ||
0585               ClauseKind == OpenACCClauseKind::PCopy ||
0586               ClauseKind == OpenACCClauseKind::PresentOrCopy ||
0587               ClauseKind == OpenACCClauseKind::CopyIn ||
0588               ClauseKind == OpenACCClauseKind::PCopyIn ||
0589               ClauseKind == OpenACCClauseKind::PresentOrCopyIn ||
0590               ClauseKind == OpenACCClauseKind::CopyOut ||
0591               ClauseKind == OpenACCClauseKind::PCopyOut ||
0592               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
0593               ClauseKind == OpenACCClauseKind::Create ||
0594               ClauseKind == OpenACCClauseKind::PCreate ||
0595               ClauseKind == OpenACCClauseKind::PresentOrCreate ||
0596               ClauseKind == OpenACCClauseKind::Attach ||
0597               ClauseKind == OpenACCClauseKind::Delete ||
0598               ClauseKind == OpenACCClauseKind::UseDevice ||
0599               ClauseKind == OpenACCClauseKind::Detach ||
0600               ClauseKind == OpenACCClauseKind::DevicePtr ||
0601               ClauseKind == OpenACCClauseKind::Host ||
0602               ClauseKind == OpenACCClauseKind::Device ||
0603               (ClauseKind == OpenACCClauseKind::Self &&
0604                DirKind == OpenACCDirectiveKind::Update) ||
0605               ClauseKind == OpenACCClauseKind::FirstPrivate) &&
0606              "Parsed clause kind does not have a var-list");
0607       assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
0608               ClauseKind == OpenACCClauseKind::PCopyIn ||
0609               ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
0610              "readonly: tag only valid on copyin");
0611       assert((!IsZero || ClauseKind == OpenACCClauseKind::CopyOut ||
0612               ClauseKind == OpenACCClauseKind::PCopyOut ||
0613               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
0614               ClauseKind == OpenACCClauseKind::Create ||
0615               ClauseKind == OpenACCClauseKind::PCreate ||
0616               ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
0617              "zero: tag only valid on copyout/create");
0618       Details = VarListDetails{std::move(VarList), IsReadOnly, IsZero};
0619     }
0620 
0621     void setReductionDetails(OpenACCReductionOperator Op,
0622                              llvm::SmallVector<Expr *> &&VarList) {
0623       assert(ClauseKind == OpenACCClauseKind::Reduction &&
0624              "reduction details only valid on reduction");
0625       Details = ReductionDetails{Op, std::move(VarList)};
0626     }
0627 
0628     void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc,
0629                         llvm::SmallVector<Expr *> &&IntExprs) {
0630       assert(ClauseKind == OpenACCClauseKind::Wait &&
0631              "Parsed clause kind does not have a wait-details");
0632       Details = WaitDetails{DevNum, QueuesLoc, std::move(IntExprs)};
0633     }
0634 
0635     void setDeviceTypeDetails(llvm::SmallVector<DeviceTypeArgument> &&Archs) {
0636       assert((ClauseKind == OpenACCClauseKind::DeviceType ||
0637               ClauseKind == OpenACCClauseKind::DType) &&
0638              "Only 'device_type'/'dtype' has a device-type-arg list");
0639       Details = DeviceTypeDetails{std::move(Archs)};
0640     }
0641 
0642     void setCollapseDetails(bool IsForce, Expr *LoopCount) {
0643       assert(ClauseKind == OpenACCClauseKind::Collapse &&
0644              "Only 'collapse' has collapse details");
0645       Details = CollapseDetails{IsForce, LoopCount};
0646     }
0647   };
0648 
0649   SemaOpenACC(Sema &S);
0650 
0651   // Called when we encounter a 'while' statement, before looking at its 'body'.
0652   void ActOnWhileStmt(SourceLocation WhileLoc);
0653   // Called when we encounter a 'do' statement, before looking at its 'body'.
0654   void ActOnDoStmt(SourceLocation DoLoc);
0655   // Called when we encounter a 'for' statement, before looking at its 'body',
0656   // for the 'range-for'. 'ActOnForStmtEnd' is used after the body.
0657   void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor,
0658                               const Stmt *RangeFor);
0659   void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *RangeFor);
0660   // Called when we encounter a 'for' statement, before looking at its 'body'.
0661   // 'ActOnForStmtEnd' is used after the body.
0662   void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First,
0663                          const Stmt *Second, const Stmt *Third);
0664   void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *OldFirst,
0665                          const Stmt *First, const Stmt *OldSecond,
0666                          const Stmt *Second, const Stmt *OldThird,
0667                          const Stmt *Third);
0668   // Called when we encounter a 'for' statement, after we've consumed/checked
0669   // the body. This is necessary for a number of checks on the contents of the
0670   // 'for' statement.
0671   void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body);
0672 
0673   /// Called after parsing an OpenACC Clause so that it can be checked.
0674   OpenACCClause *ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
0675                              OpenACCParsedClause &Clause);
0676 
0677   /// Called after the construct has been parsed, but clauses haven't been
0678   /// parsed.  This allows us to diagnose not-implemented, as well as set up any
0679   /// state required for parsing the clauses.
0680   void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc);
0681 
0682   /// Called after the directive, including its clauses, have been parsed and
0683   /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
0684   /// happen before any associated declarations or statements have been parsed.
0685   /// This function is only called when we are parsing a 'statement' context.
0686   bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc,
0687                                ArrayRef<const OpenACCClause *> Clauses);
0688 
0689   /// Called after the directive, including its clauses, have been parsed and
0690   /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
0691   /// happen before any associated declarations or statements have been parsed.
0692   /// This function is only called when we are parsing a 'Decl' context.
0693   bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc);
0694   /// Called when we encounter an associated statement for our construct, this
0695   /// should check legality of the statement as it appertains to this Construct.
0696   StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc,
0697                                  OpenACCDirectiveKind K,
0698                                  ArrayRef<const OpenACCClause *> Clauses,
0699                                  StmtResult AssocStmt);
0700 
0701   /// Called after the directive has been completely parsed, including the
0702   /// declaration group or associated statement.
0703   /// LParenLoc: Location of the left paren, if it exists (not on all
0704   /// constructs).
0705   /// MiscLoc: First misc location, if necessary (not all constructs).
0706   /// Exprs: List of expressions on the construct itself, if necessary (not all
0707   /// constructs).
0708   /// RParenLoc: Location of the right paren, if it exists (not on all
0709   /// constructs).
0710   StmtResult ActOnEndStmtDirective(
0711       OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
0712       SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
0713       SourceLocation RParenLoc, SourceLocation EndLoc,
0714       ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt);
0715 
0716   /// Called after the directive has been completely parsed, including the
0717   /// declaration group or associated statement.
0718   DeclGroupRef ActOnEndDeclDirective();
0719 
0720   /// Called when encountering an 'int-expr' for OpenACC, and manages
0721   /// conversions and diagnostics to 'int'.
0722   ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
0723                           SourceLocation Loc, Expr *IntExpr);
0724 
0725   /// Called when encountering a 'var' for OpenACC, ensures it is actually a
0726   /// declaration reference to a variable of the correct type.
0727   ExprResult ActOnVar(OpenACCClauseKind CK, Expr *VarExpr);
0728 
0729   /// Called while semantically analyzing the reduction clause, ensuring the var
0730   /// is the correct kind of reference.
0731   ExprResult CheckReductionVar(OpenACCDirectiveKind DirectiveKind,
0732                                OpenACCReductionOperator ReductionOp,
0733                                Expr *VarExpr);
0734 
0735   /// Called to check the 'var' type is a variable of pointer type, necessary
0736   /// for 'deviceptr' and 'attach' clauses. Returns true on success.
0737   bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr);
0738 
0739   /// Checks and creates an Array Section used in an OpenACC construct/clause.
0740   ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
0741                                    Expr *LowerBound,
0742                                    SourceLocation ColonLocFirst, Expr *Length,
0743                                    SourceLocation RBLoc);
0744   /// Checks the loop depth value for a collapse clause.
0745   ExprResult CheckCollapseLoopCount(Expr *LoopCount);
0746   /// Checks a single size expr for a tile clause.
0747   ExprResult CheckTileSizeExpr(Expr *SizeExpr);
0748 
0749   // Check a single expression on a gang clause.
0750   ExprResult CheckGangExpr(ArrayRef<const OpenACCClause *> ExistingClauses,
0751                            OpenACCDirectiveKind DK, OpenACCGangKind GK,
0752                            Expr *E);
0753 
0754   // Does the checking for a 'gang' clause that needs to be done in dependent
0755   // and not dependent cases.
0756   OpenACCClause *
0757   CheckGangClause(OpenACCDirectiveKind DirKind,
0758                   ArrayRef<const OpenACCClause *> ExistingClauses,
0759                   SourceLocation BeginLoc, SourceLocation LParenLoc,
0760                   ArrayRef<OpenACCGangKind> GangKinds,
0761                   ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
0762   // Does the checking for a 'reduction ' clause that needs to be done in
0763   // dependent and not dependent cases.
0764   OpenACCClause *
0765   CheckReductionClause(ArrayRef<const OpenACCClause *> ExistingClauses,
0766                        OpenACCDirectiveKind DirectiveKind,
0767                        SourceLocation BeginLoc, SourceLocation LParenLoc,
0768                        OpenACCReductionOperator ReductionOp,
0769                        ArrayRef<Expr *> Vars, SourceLocation EndLoc);
0770 
0771   ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);
0772   ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);
0773 
0774   /// Helper type to restore the state of various 'loop' constructs when we run
0775   /// into a loop (for, etc) inside the construct.
0776   class LoopInConstructRAII {
0777     SemaOpenACC &SemaRef;
0778     LoopCheckingInfo OldLoopInfo;
0779     CollapseCheckingInfo OldCollapseInfo;
0780     TileCheckingInfo OldTileInfo;
0781     bool PreserveDepth;
0782 
0783   public:
0784     LoopInConstructRAII(SemaOpenACC &SemaRef, bool PreserveDepth = true)
0785         : SemaRef(SemaRef), OldLoopInfo(SemaRef.LoopInfo),
0786           OldCollapseInfo(SemaRef.CollapseInfo), OldTileInfo(SemaRef.TileInfo),
0787           PreserveDepth(PreserveDepth) {}
0788     ~LoopInConstructRAII() {
0789       // The associated-statement level of this should NOT preserve this, as it
0790       // is a new construct, but other loop uses need to preserve the depth so
0791       // it makes it to the 'top level' for diagnostics.
0792       bool CollapseDepthSatisified =
0793           PreserveDepth ? SemaRef.CollapseInfo.CollapseDepthSatisfied
0794                         : OldCollapseInfo.CollapseDepthSatisfied;
0795       bool TileDepthSatisfied = PreserveDepth
0796                                     ? SemaRef.TileInfo.TileDepthSatisfied
0797                                     : OldTileInfo.TileDepthSatisfied;
0798       bool CurLevelHasLoopAlready =
0799           PreserveDepth ? SemaRef.LoopInfo.CurLevelHasLoopAlready
0800                         : OldLoopInfo.CurLevelHasLoopAlready;
0801 
0802       SemaRef.LoopInfo = OldLoopInfo;
0803       SemaRef.CollapseInfo = OldCollapseInfo;
0804       SemaRef.TileInfo = OldTileInfo;
0805 
0806       SemaRef.CollapseInfo.CollapseDepthSatisfied = CollapseDepthSatisified;
0807       SemaRef.TileInfo.TileDepthSatisfied = TileDepthSatisfied;
0808       SemaRef.LoopInfo.CurLevelHasLoopAlready = CurLevelHasLoopAlready;
0809     }
0810   };
0811 
0812   /// Helper type for the registration/assignment of constructs that need to
0813   /// 'know' about their parent constructs and hold a reference to them, such as
0814   /// Loop needing its parent construct.
0815   class AssociatedStmtRAII {
0816     SemaOpenACC &SemaRef;
0817     ComputeConstructInfo OldActiveComputeConstructInfo;
0818     OpenACCDirectiveKind DirKind;
0819     LoopGangOnKernelTy OldLoopGangClauseOnKernel;
0820     SourceLocation OldLoopWorkerClauseLoc;
0821     SourceLocation OldLoopVectorClauseLoc;
0822     LoopWithoutSeqCheckingInfo OldLoopWithoutSeqInfo;
0823     llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses;
0824     LoopInConstructRAII LoopRAII;
0825 
0826   public:
0827     AssociatedStmtRAII(SemaOpenACC &, OpenACCDirectiveKind, SourceLocation,
0828                        ArrayRef<const OpenACCClause *>,
0829                        ArrayRef<OpenACCClause *>);
0830     void SetCollapseInfoBeforeAssociatedStmt(
0831         ArrayRef<const OpenACCClause *> UnInstClauses,
0832         ArrayRef<OpenACCClause *> Clauses);
0833     void SetTileInfoBeforeAssociatedStmt(
0834         ArrayRef<const OpenACCClause *> UnInstClauses,
0835         ArrayRef<OpenACCClause *> Clauses);
0836     ~AssociatedStmtRAII();
0837   };
0838 };
0839 
0840 } // namespace clang
0841 
0842 #endif // LLVM_CLANG_SEMA_SEMAOPENACC_H