xref: /llvm-project/clang/include/clang/Sema/SemaOpenACC.h (revision be32621ce8cbffe674c62e87c0c51c9fc4a21e5f)
1 //===----- SemaOpenACC.h - Semantic Analysis for OpenACC constructs -------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 /// \file
9 /// This file declares semantic analysis for OpenACC constructs and
10 /// clauses.
11 ///
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef LLVM_CLANG_SEMA_SEMAOPENACC_H
15 #define LLVM_CLANG_SEMA_SEMAOPENACC_H
16 
17 #include "clang/AST/DeclGroup.h"
18 #include "clang/AST/StmtOpenACC.h"
19 #include "clang/Basic/LLVM.h"
20 #include "clang/Basic/OpenACCKinds.h"
21 #include "clang/Basic/SourceLocation.h"
22 #include "clang/Sema/Ownership.h"
23 #include "clang/Sema/SemaBase.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/Support/Compiler.h"
26 #include <cassert>
27 #include <optional>
28 #include <utility>
29 #include <variant>
30 
31 namespace clang {
32 class IdentifierInfo;
33 class OpenACCClause;
34 
35 class SemaOpenACC : public SemaBase {
36 private:
37   struct ComputeConstructInfo {
38     /// Which type of compute construct we are inside of, which we can use to
39     /// determine whether we should add loops to the above collection.  We can
40     /// also use it to diagnose loop construct clauses.
41     OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
42     // If we have an active compute construct, stores the list of clauses we've
43     // prepared for it, so that we can diagnose limitations on child constructs.
44     ArrayRef<OpenACCClause *> Clauses;
45   } ActiveComputeConstructInfo;
46 
47   bool isInComputeConstruct() const {
48     return ActiveComputeConstructInfo.Kind != OpenACCDirectiveKind::Invalid;
49   }
50 
51   /// Certain clauses care about the same things that aren't specific to the
52   /// individual clause, but can be shared by a few, so store them here. All
53   /// require a 'no intervening constructs' rule, so we know they are all from
54   /// the same 'place'.
55   struct LoopCheckingInfo {
56     /// Records whether we've seen the top level 'for'. We already diagnose
57     /// later that the 'top level' is a for loop, so we use this to suppress the
58     /// 'collapse inner loop not a 'for' loop' diagnostic.
59     LLVM_PREFERRED_TYPE(bool)
60     unsigned TopLevelLoopSeen : 1;
61 
62     /// Records whether this 'tier' of the loop has already seen a 'for' loop,
63     /// used to diagnose if there are multiple 'for' loops at any one level.
64     LLVM_PREFERRED_TYPE(bool)
65     unsigned CurLevelHasLoopAlready : 1;
66 
67   } LoopInfo{/*TopLevelLoopSeen=*/false, /*CurLevelHasLoopAlready=*/false};
68 
69   /// The 'collapse' clause requires quite a bit of checking while
70   /// parsing/instantiating its body, so this structure/object keeps all of the
71   /// necessary information as we do checking.  This should rarely be directly
72   /// modified, and typically should be controlled by the RAII objects.
73   ///
74   /// Collapse has an 'N' count that makes it apply to a number of loops 'below'
75   /// it.
76   struct CollapseCheckingInfo {
77     OpenACCCollapseClause *ActiveCollapse = nullptr;
78 
79     /// This is a value that maintains the current value of the 'N' on the
80     /// current collapse, minus the depth that has already been traversed. When
81     /// there is not an active collapse, or a collapse whose depth we don't know
82     /// (for example, if it is a dependent value), this should be `nullopt`,
83     /// else it should be 'N' minus the current depth traversed.
84     std::optional<llvm::APSInt> CurCollapseCount;
85 
86     /// Records whether we've hit a CurCollapseCount of '0' on the way down,
87     /// which allows us to diagnose if the value of 'N' is too large for the
88     /// current number of 'for' loops.
89     bool CollapseDepthSatisfied = true;
90 
91     /// Records the kind of the directive that this clause is attached to, which
92     /// allows us to use it in diagnostics.
93     OpenACCDirectiveKind DirectiveKind = OpenACCDirectiveKind::Invalid;
94   } CollapseInfo;
95 
96   /// The 'tile' clause requires a bit of additional checking as well, so like
97   /// the `CollapseCheckingInfo`, ensure we maintain information here too.
98   struct TileCheckingInfo {
99     OpenACCTileClause *ActiveTile = nullptr;
100 
101     /// This is the number of expressions on a 'tile' clause.  This doesn't have
102     /// to be an APSInt because it isn't the result of a constexpr, just by our
103     /// own counting of elements.
104     std::optional<unsigned> CurTileCount;
105 
106     /// Records whether we've hit a 'CurTileCount' of '0' on the wya down,
107     /// which allows us to diagnose if the number of arguments is too large for
108     /// the current number of 'for' loops.
109     bool TileDepthSatisfied = true;
110 
111     /// Records the kind of the directive that this clause is attached to, which
112     /// allows us to use it in diagnostics.
113     OpenACCDirectiveKind DirectiveKind = OpenACCDirectiveKind::Invalid;
114   } TileInfo;
115 
116   /// A list of the active reduction clauses, which allows us to check that all
117   /// vars on nested constructs for the same reduction var have the same
118   /// reduction operator. Currently this is enforced against all constructs
119   /// despite the rule being in the 'loop' section. By current reading, this
120   /// should apply to all anyway, but we may need to make this more like the
121   /// 'loop' clause enforcement, where this is 'blocked' by a compute construct.
122   llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses;
123 
124   // Type to check the info about the 'for stmt'.
125   struct ForStmtBeginChecker {
126     SemaOpenACC &SemaRef;
127     SourceLocation ForLoc;
128     bool IsRangeFor = false;
129     std::optional<const CXXForRangeStmt *> RangeFor = nullptr;
130     const Stmt *Init = nullptr;
131     bool InitChanged = false;
132     std::optional<const Stmt *> Cond = nullptr;
133     std::optional<const Stmt *> Inc = nullptr;
134     // Prevent us from checking 2x, which can happen with collapse & tile.
135     bool AlreadyChecked = false;
136 
137     ForStmtBeginChecker(SemaOpenACC &SemaRef, SourceLocation ForLoc,
138                         std::optional<const CXXForRangeStmt *> S)
139         : SemaRef(SemaRef), ForLoc(ForLoc), IsRangeFor(true), RangeFor(S) {}
140 
141     ForStmtBeginChecker(SemaOpenACC &SemaRef, SourceLocation ForLoc,
142                         const Stmt *I, bool InitChanged,
143                         std::optional<const Stmt *> C,
144                         std::optional<const Stmt *> Inc)
145         : SemaRef(SemaRef), ForLoc(ForLoc), IsRangeFor(false), Init(I),
146           InitChanged(InitChanged), Cond(C), Inc(Inc) {}
147     // Do the checking for the For/Range-For. Currently this implements the 'not
148     // seq' restrictions only, and should be called either if we know we are a
149     // top-level 'for' (the one associated via associated-stmt), or extended via
150     // 'collapse'.
151     void check();
152 
153     const ValueDecl *checkInit();
154     void checkCond();
155     void checkInc(const ValueDecl *Init);
156   };
157 
158   /// Helper function for checking the 'for' and 'range for' stmts.
159   void ForStmtBeginHelper(SourceLocation ForLoc, ForStmtBeginChecker &C);
160 
161 public:
162   ComputeConstructInfo &getActiveComputeConstructInfo() {
163     return ActiveComputeConstructInfo;
164   }
165 
166   /// If there is a current 'active' loop construct with a 'gang' clause on a
167   /// 'kernel' construct, this will have the source location for it, and the
168   /// 'kernel kind'. This permits us to implement the restriction of no further
169   /// 'gang' clauses.
170   struct LoopGangOnKernelTy {
171     SourceLocation Loc;
172     OpenACCDirectiveKind DirKind = OpenACCDirectiveKind::Invalid;
173   } LoopGangClauseOnKernel;
174 
175   /// If there is a current 'active' loop construct with a 'worker' clause on it
176   /// (on any sort of construct), this has the source location for it.  This
177   /// permits us to implement the restriction of no further 'gang' or 'worker'
178   /// clauses.
179   SourceLocation LoopWorkerClauseLoc;
180   /// If there is a current 'active' loop construct with a 'vector' clause on it
181   /// (on any sort of construct), this has the source location for it.  This
182   /// permits us to implement the restriction of no further 'gang', 'vector', or
183   /// 'worker' clauses.
184   SourceLocation LoopVectorClauseLoc;
185   /// If there is a current 'active' loop construct that does NOT have a 'seq'
186   /// clause on it, this has that source location and loop Directive 'kind'.
187   /// This permits us to implement the 'loop' restrictions on the loop variable.
188   /// This can be extended via 'collapse', so we need to keep this around for a
189   /// while.
190   struct LoopWithoutSeqCheckingInfo {
191     OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
192     SourceLocation Loc;
193   } LoopWithoutSeqInfo;
194 
195   // Redeclaration of the version in OpenACCClause.h.
196   using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
197 
198   /// A type to represent all the data for an OpenACC Clause that has been
199   /// parsed, but not yet created/semantically analyzed. This is effectively a
200   /// discriminated union on the 'Clause Kind', with all of the individual
201   /// clause details stored in a std::variant.
202   class OpenACCParsedClause {
203     OpenACCDirectiveKind DirKind;
204     OpenACCClauseKind ClauseKind;
205     SourceRange ClauseRange;
206     SourceLocation LParenLoc;
207 
208     struct DefaultDetails {
209       OpenACCDefaultClauseKind DefaultClauseKind;
210     };
211 
212     struct ConditionDetails {
213       Expr *ConditionExpr;
214     };
215 
216     struct IntExprDetails {
217       SmallVector<Expr *> IntExprs;
218     };
219 
220     struct VarListDetails {
221       SmallVector<Expr *> VarList;
222       bool IsReadOnly;
223       bool IsZero;
224     };
225 
226     struct WaitDetails {
227       Expr *DevNumExpr;
228       SourceLocation QueuesLoc;
229       SmallVector<Expr *> QueueIdExprs;
230     };
231 
232     struct DeviceTypeDetails {
233       SmallVector<DeviceTypeArgument> Archs;
234     };
235     struct ReductionDetails {
236       OpenACCReductionOperator Op;
237       SmallVector<Expr *> VarList;
238     };
239 
240     struct CollapseDetails {
241       bool IsForce;
242       Expr *LoopCount;
243     };
244 
245     struct GangDetails {
246       SmallVector<OpenACCGangKind> GangKinds;
247       SmallVector<Expr *> IntExprs;
248     };
249 
250     std::variant<std::monostate, DefaultDetails, ConditionDetails,
251                  IntExprDetails, VarListDetails, WaitDetails, DeviceTypeDetails,
252                  ReductionDetails, CollapseDetails, GangDetails>
253         Details = std::monostate{};
254 
255   public:
256     OpenACCParsedClause(OpenACCDirectiveKind DirKind,
257                         OpenACCClauseKind ClauseKind, SourceLocation BeginLoc)
258         : DirKind(DirKind), ClauseKind(ClauseKind), ClauseRange(BeginLoc, {}) {}
259 
260     OpenACCDirectiveKind getDirectiveKind() const { return DirKind; }
261 
262     OpenACCClauseKind getClauseKind() const { return ClauseKind; }
263 
264     SourceLocation getBeginLoc() const { return ClauseRange.getBegin(); }
265 
266     SourceLocation getLParenLoc() const { return LParenLoc; }
267 
268     SourceLocation getEndLoc() const { return ClauseRange.getEnd(); }
269 
270     OpenACCDefaultClauseKind getDefaultClauseKind() const {
271       assert(ClauseKind == OpenACCClauseKind::Default &&
272              "Parsed clause is not a default clause");
273       return std::get<DefaultDetails>(Details).DefaultClauseKind;
274     }
275 
276     const Expr *getConditionExpr() const {
277       return const_cast<OpenACCParsedClause *>(this)->getConditionExpr();
278     }
279 
280     Expr *getConditionExpr() {
281       assert((ClauseKind == OpenACCClauseKind::If ||
282               (ClauseKind == OpenACCClauseKind::Self &&
283                DirKind != OpenACCDirectiveKind::Update)) &&
284              "Parsed clause kind does not have a condition expr");
285 
286       // 'self' has an optional ConditionExpr, so be tolerant of that. This will
287       // assert in variant otherwise.
288       if (ClauseKind == OpenACCClauseKind::Self &&
289           std::holds_alternative<std::monostate>(Details))
290         return nullptr;
291 
292       return std::get<ConditionDetails>(Details).ConditionExpr;
293     }
294 
295     unsigned getNumIntExprs() const {
296       assert((ClauseKind == OpenACCClauseKind::NumGangs ||
297               ClauseKind == OpenACCClauseKind::NumWorkers ||
298               ClauseKind == OpenACCClauseKind::Async ||
299               ClauseKind == OpenACCClauseKind::DeviceNum ||
300               ClauseKind == OpenACCClauseKind::DefaultAsync ||
301               ClauseKind == OpenACCClauseKind::Tile ||
302               ClauseKind == OpenACCClauseKind::Worker ||
303               ClauseKind == OpenACCClauseKind::Vector ||
304               ClauseKind == OpenACCClauseKind::VectorLength) &&
305              "Parsed clause kind does not have a int exprs");
306 
307       // 'async', 'worker', 'vector', and 'wait' have an optional IntExpr, so be
308       // tolerant of that.
309       if ((ClauseKind == OpenACCClauseKind::Async ||
310            ClauseKind == OpenACCClauseKind::Worker ||
311            ClauseKind == OpenACCClauseKind::Vector ||
312            ClauseKind == OpenACCClauseKind::Wait) &&
313           std::holds_alternative<std::monostate>(Details))
314         return 0;
315       return std::get<IntExprDetails>(Details).IntExprs.size();
316     }
317 
318     SourceLocation getQueuesLoc() const {
319       assert(ClauseKind == OpenACCClauseKind::Wait &&
320              "Parsed clause kind does not have a queues location");
321 
322       if (std::holds_alternative<std::monostate>(Details))
323         return SourceLocation{};
324 
325       return std::get<WaitDetails>(Details).QueuesLoc;
326     }
327 
328     Expr *getDevNumExpr() const {
329       assert(ClauseKind == OpenACCClauseKind::Wait &&
330              "Parsed clause kind does not have a device number expr");
331 
332       if (std::holds_alternative<std::monostate>(Details))
333         return nullptr;
334 
335       return std::get<WaitDetails>(Details).DevNumExpr;
336     }
337 
338     ArrayRef<Expr *> getQueueIdExprs() const {
339       assert(ClauseKind == OpenACCClauseKind::Wait &&
340              "Parsed clause kind does not have a queue id expr list");
341 
342       if (std::holds_alternative<std::monostate>(Details))
343         return ArrayRef<Expr *>();
344 
345       return std::get<WaitDetails>(Details).QueueIdExprs;
346     }
347 
348     ArrayRef<Expr *> getIntExprs() {
349       assert((ClauseKind == OpenACCClauseKind::NumGangs ||
350               ClauseKind == OpenACCClauseKind::NumWorkers ||
351               ClauseKind == OpenACCClauseKind::Async ||
352               ClauseKind == OpenACCClauseKind::DeviceNum ||
353               ClauseKind == OpenACCClauseKind::DefaultAsync ||
354               ClauseKind == OpenACCClauseKind::Tile ||
355               ClauseKind == OpenACCClauseKind::Gang ||
356               ClauseKind == OpenACCClauseKind::Worker ||
357               ClauseKind == OpenACCClauseKind::Vector ||
358               ClauseKind == OpenACCClauseKind::VectorLength) &&
359              "Parsed clause kind does not have a int exprs");
360 
361       if (ClauseKind == OpenACCClauseKind::Gang) {
362         // There might not be any gang int exprs, as this is an optional
363         // argument.
364         if (std::holds_alternative<std::monostate>(Details))
365           return {};
366         return std::get<GangDetails>(Details).IntExprs;
367       }
368 
369       return std::get<IntExprDetails>(Details).IntExprs;
370     }
371 
372     ArrayRef<Expr *> getIntExprs() const {
373       return const_cast<OpenACCParsedClause *>(this)->getIntExprs();
374     }
375 
376     OpenACCReductionOperator getReductionOp() const {
377       return std::get<ReductionDetails>(Details).Op;
378     }
379 
380     ArrayRef<OpenACCGangKind> getGangKinds() const {
381       assert(ClauseKind == OpenACCClauseKind::Gang &&
382              "Parsed clause kind does not have gang kind");
383       // The args on gang are optional, so this might not actually hold
384       // anything.
385       if (std::holds_alternative<std::monostate>(Details))
386         return {};
387       return std::get<GangDetails>(Details).GangKinds;
388     }
389 
390     ArrayRef<Expr *> getVarList() {
391       assert((ClauseKind == OpenACCClauseKind::Private ||
392               ClauseKind == OpenACCClauseKind::NoCreate ||
393               ClauseKind == OpenACCClauseKind::Present ||
394               ClauseKind == OpenACCClauseKind::Copy ||
395               ClauseKind == OpenACCClauseKind::PCopy ||
396               ClauseKind == OpenACCClauseKind::PresentOrCopy ||
397               ClauseKind == OpenACCClauseKind::CopyIn ||
398               ClauseKind == OpenACCClauseKind::PCopyIn ||
399               ClauseKind == OpenACCClauseKind::PresentOrCopyIn ||
400               ClauseKind == OpenACCClauseKind::CopyOut ||
401               ClauseKind == OpenACCClauseKind::PCopyOut ||
402               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
403               ClauseKind == OpenACCClauseKind::Create ||
404               ClauseKind == OpenACCClauseKind::PCreate ||
405               ClauseKind == OpenACCClauseKind::PresentOrCreate ||
406               ClauseKind == OpenACCClauseKind::Attach ||
407               ClauseKind == OpenACCClauseKind::Delete ||
408               ClauseKind == OpenACCClauseKind::UseDevice ||
409               ClauseKind == OpenACCClauseKind::Detach ||
410               ClauseKind == OpenACCClauseKind::DevicePtr ||
411               ClauseKind == OpenACCClauseKind::Reduction ||
412               ClauseKind == OpenACCClauseKind::Host ||
413               ClauseKind == OpenACCClauseKind::Device ||
414               (ClauseKind == OpenACCClauseKind::Self &&
415                DirKind == OpenACCDirectiveKind::Update) ||
416               ClauseKind == OpenACCClauseKind::FirstPrivate) &&
417              "Parsed clause kind does not have a var-list");
418 
419       if (ClauseKind == OpenACCClauseKind::Reduction)
420         return std::get<ReductionDetails>(Details).VarList;
421 
422       return std::get<VarListDetails>(Details).VarList;
423     }
424 
425     ArrayRef<Expr *> getVarList() const {
426       return const_cast<OpenACCParsedClause *>(this)->getVarList();
427     }
428 
429     bool isReadOnly() const {
430       assert((ClauseKind == OpenACCClauseKind::CopyIn ||
431               ClauseKind == OpenACCClauseKind::PCopyIn ||
432               ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
433              "Only copyin accepts 'readonly:' tag");
434       return std::get<VarListDetails>(Details).IsReadOnly;
435     }
436 
437     bool isZero() const {
438       assert((ClauseKind == OpenACCClauseKind::CopyOut ||
439               ClauseKind == OpenACCClauseKind::PCopyOut ||
440               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
441               ClauseKind == OpenACCClauseKind::Create ||
442               ClauseKind == OpenACCClauseKind::PCreate ||
443               ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
444              "Only copyout/create accepts 'zero' tag");
445       return std::get<VarListDetails>(Details).IsZero;
446     }
447 
448     bool isForce() const {
449       assert(ClauseKind == OpenACCClauseKind::Collapse &&
450              "Only 'collapse' has a force tag");
451       return std::get<CollapseDetails>(Details).IsForce;
452     }
453 
454     Expr *getLoopCount() const {
455       assert(ClauseKind == OpenACCClauseKind::Collapse &&
456              "Only 'collapse' has a loop count");
457       return std::get<CollapseDetails>(Details).LoopCount;
458     }
459 
460     ArrayRef<DeviceTypeArgument> getDeviceTypeArchitectures() const {
461       assert((ClauseKind == OpenACCClauseKind::DeviceType ||
462               ClauseKind == OpenACCClauseKind::DType) &&
463              "Only 'device_type'/'dtype' has a device-type-arg list");
464       return std::get<DeviceTypeDetails>(Details).Archs;
465     }
466 
467     void setLParenLoc(SourceLocation EndLoc) { LParenLoc = EndLoc; }
468     void setEndLoc(SourceLocation EndLoc) { ClauseRange.setEnd(EndLoc); }
469 
470     void setDefaultDetails(OpenACCDefaultClauseKind DefKind) {
471       assert(ClauseKind == OpenACCClauseKind::Default &&
472              "Parsed clause is not a default clause");
473       Details = DefaultDetails{DefKind};
474     }
475 
476     void setConditionDetails(Expr *ConditionExpr) {
477       assert((ClauseKind == OpenACCClauseKind::If ||
478               (ClauseKind == OpenACCClauseKind::Self &&
479                DirKind != OpenACCDirectiveKind::Update)) &&
480              "Parsed clause kind does not have a condition expr");
481       // In C++ we can count on this being a 'bool', but in C this gets left as
482       // some sort of scalar that codegen will have to take care of converting.
483       assert((!ConditionExpr || ConditionExpr->isInstantiationDependent() ||
484               ConditionExpr->getType()->isScalarType()) &&
485              "Condition expression type not scalar/dependent");
486 
487       Details = ConditionDetails{ConditionExpr};
488     }
489 
490     void setIntExprDetails(ArrayRef<Expr *> IntExprs) {
491       assert((ClauseKind == OpenACCClauseKind::NumGangs ||
492               ClauseKind == OpenACCClauseKind::NumWorkers ||
493               ClauseKind == OpenACCClauseKind::Async ||
494               ClauseKind == OpenACCClauseKind::DeviceNum ||
495               ClauseKind == OpenACCClauseKind::DefaultAsync ||
496               ClauseKind == OpenACCClauseKind::Tile ||
497               ClauseKind == OpenACCClauseKind::Worker ||
498               ClauseKind == OpenACCClauseKind::Vector ||
499               ClauseKind == OpenACCClauseKind::VectorLength) &&
500              "Parsed clause kind does not have a int exprs");
501       Details = IntExprDetails{{IntExprs.begin(), IntExprs.end()}};
502     }
503     void setIntExprDetails(llvm::SmallVector<Expr *> &&IntExprs) {
504       assert((ClauseKind == OpenACCClauseKind::NumGangs ||
505               ClauseKind == OpenACCClauseKind::NumWorkers ||
506               ClauseKind == OpenACCClauseKind::Async ||
507               ClauseKind == OpenACCClauseKind::DeviceNum ||
508               ClauseKind == OpenACCClauseKind::DefaultAsync ||
509               ClauseKind == OpenACCClauseKind::Tile ||
510               ClauseKind == OpenACCClauseKind::Worker ||
511               ClauseKind == OpenACCClauseKind::Vector ||
512               ClauseKind == OpenACCClauseKind::VectorLength) &&
513              "Parsed clause kind does not have a int exprs");
514       Details = IntExprDetails{std::move(IntExprs)};
515     }
516 
517     void setGangDetails(ArrayRef<OpenACCGangKind> GKs,
518                         ArrayRef<Expr *> IntExprs) {
519       assert(ClauseKind == OpenACCClauseKind::Gang &&
520              "Parsed Clause kind does not have gang details");
521       assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");
522 
523       Details = GangDetails{{GKs.begin(), GKs.end()},
524                             {IntExprs.begin(), IntExprs.end()}};
525     }
526 
527     void setGangDetails(llvm::SmallVector<OpenACCGangKind> &&GKs,
528                         llvm::SmallVector<Expr *> &&IntExprs) {
529       assert(ClauseKind == OpenACCClauseKind::Gang &&
530              "Parsed Clause kind does not have gang details");
531       assert(GKs.size() == IntExprs.size() && "Mismatched kind/size?");
532 
533       Details = GangDetails{std::move(GKs), std::move(IntExprs)};
534     }
535 
536     void setVarListDetails(ArrayRef<Expr *> VarList, bool IsReadOnly,
537                            bool IsZero) {
538       assert((ClauseKind == OpenACCClauseKind::Private ||
539               ClauseKind == OpenACCClauseKind::NoCreate ||
540               ClauseKind == OpenACCClauseKind::Present ||
541               ClauseKind == OpenACCClauseKind::Copy ||
542               ClauseKind == OpenACCClauseKind::PCopy ||
543               ClauseKind == OpenACCClauseKind::PresentOrCopy ||
544               ClauseKind == OpenACCClauseKind::CopyIn ||
545               ClauseKind == OpenACCClauseKind::PCopyIn ||
546               ClauseKind == OpenACCClauseKind::PresentOrCopyIn ||
547               ClauseKind == OpenACCClauseKind::CopyOut ||
548               ClauseKind == OpenACCClauseKind::PCopyOut ||
549               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
550               ClauseKind == OpenACCClauseKind::Create ||
551               ClauseKind == OpenACCClauseKind::PCreate ||
552               ClauseKind == OpenACCClauseKind::PresentOrCreate ||
553               ClauseKind == OpenACCClauseKind::Attach ||
554               ClauseKind == OpenACCClauseKind::Delete ||
555               ClauseKind == OpenACCClauseKind::UseDevice ||
556               ClauseKind == OpenACCClauseKind::Detach ||
557               ClauseKind == OpenACCClauseKind::DevicePtr ||
558               ClauseKind == OpenACCClauseKind::Host ||
559               ClauseKind == OpenACCClauseKind::Device ||
560               (ClauseKind == OpenACCClauseKind::Self &&
561                DirKind == OpenACCDirectiveKind::Update) ||
562               ClauseKind == OpenACCClauseKind::FirstPrivate) &&
563              "Parsed clause kind does not have a var-list");
564       assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
565               ClauseKind == OpenACCClauseKind::PCopyIn ||
566               ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
567              "readonly: tag only valid on copyin");
568       assert((!IsZero || ClauseKind == OpenACCClauseKind::CopyOut ||
569               ClauseKind == OpenACCClauseKind::PCopyOut ||
570               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
571               ClauseKind == OpenACCClauseKind::Create ||
572               ClauseKind == OpenACCClauseKind::PCreate ||
573               ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
574              "zero: tag only valid on copyout/create");
575       Details =
576           VarListDetails{{VarList.begin(), VarList.end()}, IsReadOnly, IsZero};
577     }
578 
579     void setVarListDetails(llvm::SmallVector<Expr *> &&VarList, bool IsReadOnly,
580                            bool IsZero) {
581       assert((ClauseKind == OpenACCClauseKind::Private ||
582               ClauseKind == OpenACCClauseKind::NoCreate ||
583               ClauseKind == OpenACCClauseKind::Present ||
584               ClauseKind == OpenACCClauseKind::Copy ||
585               ClauseKind == OpenACCClauseKind::PCopy ||
586               ClauseKind == OpenACCClauseKind::PresentOrCopy ||
587               ClauseKind == OpenACCClauseKind::CopyIn ||
588               ClauseKind == OpenACCClauseKind::PCopyIn ||
589               ClauseKind == OpenACCClauseKind::PresentOrCopyIn ||
590               ClauseKind == OpenACCClauseKind::CopyOut ||
591               ClauseKind == OpenACCClauseKind::PCopyOut ||
592               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
593               ClauseKind == OpenACCClauseKind::Create ||
594               ClauseKind == OpenACCClauseKind::PCreate ||
595               ClauseKind == OpenACCClauseKind::PresentOrCreate ||
596               ClauseKind == OpenACCClauseKind::Attach ||
597               ClauseKind == OpenACCClauseKind::Delete ||
598               ClauseKind == OpenACCClauseKind::UseDevice ||
599               ClauseKind == OpenACCClauseKind::Detach ||
600               ClauseKind == OpenACCClauseKind::DevicePtr ||
601               ClauseKind == OpenACCClauseKind::Host ||
602               ClauseKind == OpenACCClauseKind::Device ||
603               (ClauseKind == OpenACCClauseKind::Self &&
604                DirKind == OpenACCDirectiveKind::Update) ||
605               ClauseKind == OpenACCClauseKind::FirstPrivate) &&
606              "Parsed clause kind does not have a var-list");
607       assert((!IsReadOnly || ClauseKind == OpenACCClauseKind::CopyIn ||
608               ClauseKind == OpenACCClauseKind::PCopyIn ||
609               ClauseKind == OpenACCClauseKind::PresentOrCopyIn) &&
610              "readonly: tag only valid on copyin");
611       assert((!IsZero || ClauseKind == OpenACCClauseKind::CopyOut ||
612               ClauseKind == OpenACCClauseKind::PCopyOut ||
613               ClauseKind == OpenACCClauseKind::PresentOrCopyOut ||
614               ClauseKind == OpenACCClauseKind::Create ||
615               ClauseKind == OpenACCClauseKind::PCreate ||
616               ClauseKind == OpenACCClauseKind::PresentOrCreate) &&
617              "zero: tag only valid on copyout/create");
618       Details = VarListDetails{std::move(VarList), IsReadOnly, IsZero};
619     }
620 
621     void setReductionDetails(OpenACCReductionOperator Op,
622                              llvm::SmallVector<Expr *> &&VarList) {
623       assert(ClauseKind == OpenACCClauseKind::Reduction &&
624              "reduction details only valid on reduction");
625       Details = ReductionDetails{Op, std::move(VarList)};
626     }
627 
628     void setWaitDetails(Expr *DevNum, SourceLocation QueuesLoc,
629                         llvm::SmallVector<Expr *> &&IntExprs) {
630       assert(ClauseKind == OpenACCClauseKind::Wait &&
631              "Parsed clause kind does not have a wait-details");
632       Details = WaitDetails{DevNum, QueuesLoc, std::move(IntExprs)};
633     }
634 
635     void setDeviceTypeDetails(llvm::SmallVector<DeviceTypeArgument> &&Archs) {
636       assert((ClauseKind == OpenACCClauseKind::DeviceType ||
637               ClauseKind == OpenACCClauseKind::DType) &&
638              "Only 'device_type'/'dtype' has a device-type-arg list");
639       Details = DeviceTypeDetails{std::move(Archs)};
640     }
641 
642     void setCollapseDetails(bool IsForce, Expr *LoopCount) {
643       assert(ClauseKind == OpenACCClauseKind::Collapse &&
644              "Only 'collapse' has collapse details");
645       Details = CollapseDetails{IsForce, LoopCount};
646     }
647   };
648 
649   SemaOpenACC(Sema &S);
650 
651   // Called when we encounter a 'while' statement, before looking at its 'body'.
652   void ActOnWhileStmt(SourceLocation WhileLoc);
653   // Called when we encounter a 'do' statement, before looking at its 'body'.
654   void ActOnDoStmt(SourceLocation DoLoc);
655   // Called when we encounter a 'for' statement, before looking at its 'body',
656   // for the 'range-for'. 'ActOnForStmtEnd' is used after the body.
657   void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *OldRangeFor,
658                               const Stmt *RangeFor);
659   void ActOnRangeForStmtBegin(SourceLocation ForLoc, const Stmt *RangeFor);
660   // Called when we encounter a 'for' statement, before looking at its 'body'.
661   // 'ActOnForStmtEnd' is used after the body.
662   void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *First,
663                          const Stmt *Second, const Stmt *Third);
664   void ActOnForStmtBegin(SourceLocation ForLoc, const Stmt *OldFirst,
665                          const Stmt *First, const Stmt *OldSecond,
666                          const Stmt *Second, const Stmt *OldThird,
667                          const Stmt *Third);
668   // Called when we encounter a 'for' statement, after we've consumed/checked
669   // the body. This is necessary for a number of checks on the contents of the
670   // 'for' statement.
671   void ActOnForStmtEnd(SourceLocation ForLoc, StmtResult Body);
672 
673   /// Called after parsing an OpenACC Clause so that it can be checked.
674   OpenACCClause *ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
675                              OpenACCParsedClause &Clause);
676 
677   /// Called after the construct has been parsed, but clauses haven't been
678   /// parsed.  This allows us to diagnose not-implemented, as well as set up any
679   /// state required for parsing the clauses.
680   void ActOnConstruct(OpenACCDirectiveKind K, SourceLocation DirLoc);
681 
682   /// Called after the directive, including its clauses, have been parsed and
683   /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
684   /// happen before any associated declarations or statements have been parsed.
685   /// This function is only called when we are parsing a 'statement' context.
686   bool ActOnStartStmtDirective(OpenACCDirectiveKind K, SourceLocation StartLoc,
687                                ArrayRef<const OpenACCClause *> Clauses);
688 
689   /// Called after the directive, including its clauses, have been parsed and
690   /// parsing has consumed the 'annot_pragma_openacc_end' token. This DOES
691   /// happen before any associated declarations or statements have been parsed.
692   /// This function is only called when we are parsing a 'Decl' context.
693   bool ActOnStartDeclDirective(OpenACCDirectiveKind K, SourceLocation StartLoc);
694   /// Called when we encounter an associated statement for our construct, this
695   /// should check legality of the statement as it appertains to this Construct.
696   StmtResult ActOnAssociatedStmt(SourceLocation DirectiveLoc,
697                                  OpenACCDirectiveKind K,
698                                  ArrayRef<const OpenACCClause *> Clauses,
699                                  StmtResult AssocStmt);
700 
701   /// Called after the directive has been completely parsed, including the
702   /// declaration group or associated statement.
703   /// LParenLoc: Location of the left paren, if it exists (not on all
704   /// constructs).
705   /// MiscLoc: First misc location, if necessary (not all constructs).
706   /// Exprs: List of expressions on the construct itself, if necessary (not all
707   /// constructs).
708   /// RParenLoc: Location of the right paren, if it exists (not on all
709   /// constructs).
710   StmtResult ActOnEndStmtDirective(
711       OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc,
712       SourceLocation LParenLoc, SourceLocation MiscLoc, ArrayRef<Expr *> Exprs,
713       SourceLocation RParenLoc, SourceLocation EndLoc,
714       ArrayRef<OpenACCClause *> Clauses, StmtResult AssocStmt);
715 
716   /// Called after the directive has been completely parsed, including the
717   /// declaration group or associated statement.
718   DeclGroupRef ActOnEndDeclDirective();
719 
720   /// Called when encountering an 'int-expr' for OpenACC, and manages
721   /// conversions and diagnostics to 'int'.
722   ExprResult ActOnIntExpr(OpenACCDirectiveKind DK, OpenACCClauseKind CK,
723                           SourceLocation Loc, Expr *IntExpr);
724 
725   /// Called when encountering a 'var' for OpenACC, ensures it is actually a
726   /// declaration reference to a variable of the correct type.
727   ExprResult ActOnVar(OpenACCClauseKind CK, Expr *VarExpr);
728 
729   /// Called while semantically analyzing the reduction clause, ensuring the var
730   /// is the correct kind of reference.
731   ExprResult CheckReductionVar(OpenACCDirectiveKind DirectiveKind,
732                                OpenACCReductionOperator ReductionOp,
733                                Expr *VarExpr);
734 
735   /// Called to check the 'var' type is a variable of pointer type, necessary
736   /// for 'deviceptr' and 'attach' clauses. Returns true on success.
737   bool CheckVarIsPointerType(OpenACCClauseKind ClauseKind, Expr *VarExpr);
738 
739   /// Checks and creates an Array Section used in an OpenACC construct/clause.
740   ExprResult ActOnArraySectionExpr(Expr *Base, SourceLocation LBLoc,
741                                    Expr *LowerBound,
742                                    SourceLocation ColonLocFirst, Expr *Length,
743                                    SourceLocation RBLoc);
744   /// Checks the loop depth value for a collapse clause.
745   ExprResult CheckCollapseLoopCount(Expr *LoopCount);
746   /// Checks a single size expr for a tile clause.
747   ExprResult CheckTileSizeExpr(Expr *SizeExpr);
748 
749   // Check a single expression on a gang clause.
750   ExprResult CheckGangExpr(ArrayRef<const OpenACCClause *> ExistingClauses,
751                            OpenACCDirectiveKind DK, OpenACCGangKind GK,
752                            Expr *E);
753 
754   // Does the checking for a 'gang' clause that needs to be done in dependent
755   // and not dependent cases.
756   OpenACCClause *
757   CheckGangClause(OpenACCDirectiveKind DirKind,
758                   ArrayRef<const OpenACCClause *> ExistingClauses,
759                   SourceLocation BeginLoc, SourceLocation LParenLoc,
760                   ArrayRef<OpenACCGangKind> GangKinds,
761                   ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
762   // Does the checking for a 'reduction ' clause that needs to be done in
763   // dependent and not dependent cases.
764   OpenACCClause *
765   CheckReductionClause(ArrayRef<const OpenACCClause *> ExistingClauses,
766                        OpenACCDirectiveKind DirectiveKind,
767                        SourceLocation BeginLoc, SourceLocation LParenLoc,
768                        OpenACCReductionOperator ReductionOp,
769                        ArrayRef<Expr *> Vars, SourceLocation EndLoc);
770 
771   ExprResult BuildOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);
772   ExprResult ActOnOpenACCAsteriskSizeExpr(SourceLocation AsteriskLoc);
773 
774   /// Helper type to restore the state of various 'loop' constructs when we run
775   /// into a loop (for, etc) inside the construct.
776   class LoopInConstructRAII {
777     SemaOpenACC &SemaRef;
778     LoopCheckingInfo OldLoopInfo;
779     CollapseCheckingInfo OldCollapseInfo;
780     TileCheckingInfo OldTileInfo;
781     bool PreserveDepth;
782 
783   public:
784     LoopInConstructRAII(SemaOpenACC &SemaRef, bool PreserveDepth = true)
785         : SemaRef(SemaRef), OldLoopInfo(SemaRef.LoopInfo),
786           OldCollapseInfo(SemaRef.CollapseInfo), OldTileInfo(SemaRef.TileInfo),
787           PreserveDepth(PreserveDepth) {}
788     ~LoopInConstructRAII() {
789       // The associated-statement level of this should NOT preserve this, as it
790       // is a new construct, but other loop uses need to preserve the depth so
791       // it makes it to the 'top level' for diagnostics.
792       bool CollapseDepthSatisified =
793           PreserveDepth ? SemaRef.CollapseInfo.CollapseDepthSatisfied
794                         : OldCollapseInfo.CollapseDepthSatisfied;
795       bool TileDepthSatisfied = PreserveDepth
796                                     ? SemaRef.TileInfo.TileDepthSatisfied
797                                     : OldTileInfo.TileDepthSatisfied;
798       bool CurLevelHasLoopAlready =
799           PreserveDepth ? SemaRef.LoopInfo.CurLevelHasLoopAlready
800                         : OldLoopInfo.CurLevelHasLoopAlready;
801 
802       SemaRef.LoopInfo = OldLoopInfo;
803       SemaRef.CollapseInfo = OldCollapseInfo;
804       SemaRef.TileInfo = OldTileInfo;
805 
806       SemaRef.CollapseInfo.CollapseDepthSatisfied = CollapseDepthSatisified;
807       SemaRef.TileInfo.TileDepthSatisfied = TileDepthSatisfied;
808       SemaRef.LoopInfo.CurLevelHasLoopAlready = CurLevelHasLoopAlready;
809     }
810   };
811 
812   /// Helper type for the registration/assignment of constructs that need to
813   /// 'know' about their parent constructs and hold a reference to them, such as
814   /// Loop needing its parent construct.
815   class AssociatedStmtRAII {
816     SemaOpenACC &SemaRef;
817     ComputeConstructInfo OldActiveComputeConstructInfo;
818     OpenACCDirectiveKind DirKind;
819     LoopGangOnKernelTy OldLoopGangClauseOnKernel;
820     SourceLocation OldLoopWorkerClauseLoc;
821     SourceLocation OldLoopVectorClauseLoc;
822     LoopWithoutSeqCheckingInfo OldLoopWithoutSeqInfo;
823     llvm::SmallVector<OpenACCReductionClause *> ActiveReductionClauses;
824     LoopInConstructRAII LoopRAII;
825 
826   public:
827     AssociatedStmtRAII(SemaOpenACC &, OpenACCDirectiveKind, SourceLocation,
828                        ArrayRef<const OpenACCClause *>,
829                        ArrayRef<OpenACCClause *>);
830     void SetCollapseInfoBeforeAssociatedStmt(
831         ArrayRef<const OpenACCClause *> UnInstClauses,
832         ArrayRef<OpenACCClause *> Clauses);
833     void SetTileInfoBeforeAssociatedStmt(
834         ArrayRef<const OpenACCClause *> UnInstClauses,
835         ArrayRef<OpenACCClause *> Clauses);
836     ~AssociatedStmtRAII();
837   };
838 };
839 
840 } // namespace clang
841 
842 #endif // LLVM_CLANG_SEMA_SEMAOPENACC_H
843