1//===- OpenACCClause.h - Classes for OpenACC clauses ------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// \file
10// This file defines OpenACC AST classes for clauses.
11//
12//===----------------------------------------------------------------------===//
13
14#ifndef LLVM_CLANG_AST_OPENACCCLAUSE_H
15#define LLVM_CLANG_AST_OPENACCCLAUSE_H
16#include "clang/AST/ASTContext.h"
17#include "clang/AST/StmtIterator.h"
18#include "clang/Basic/OpenACCKinds.h"
19
20namespace clang {
21/// This is the base type for all OpenACC Clauses.
22class OpenACCClause {
23 OpenACCClauseKind Kind;
24 SourceRange Location;
25
26protected:
27 OpenACCClause(OpenACCClauseKind K, SourceLocation BeginLoc,
28 SourceLocation EndLoc)
29 : Kind(K), Location(BeginLoc, EndLoc) {}
30
31public:
32 OpenACCClauseKind getClauseKind() const { return Kind; }
33 SourceLocation getBeginLoc() const { return Location.getBegin(); }
34 SourceLocation getEndLoc() const { return Location.getEnd(); }
35
36 static bool classof(const OpenACCClause *) { return true; }
37
38 using child_iterator = StmtIterator;
39 using const_child_iterator = ConstStmtIterator;
40 using child_range = llvm::iterator_range<child_iterator>;
41 using const_child_range = llvm::iterator_range<const_child_iterator>;
42
43 child_range children();
44 const_child_range children() const {
45 auto Children = const_cast<OpenACCClause *>(this)->children();
46 return const_child_range(Children.begin(), Children.end());
47 }
48
49 virtual ~OpenACCClause() = default;
50};
51
52/// Represents a clause that has a list of parameters.
53class OpenACCClauseWithParams : public OpenACCClause {
54 /// Location of the '('.
55 SourceLocation LParenLoc;
56
57protected:
58 OpenACCClauseWithParams(OpenACCClauseKind K, SourceLocation BeginLoc,
59 SourceLocation LParenLoc, SourceLocation EndLoc)
60 : OpenACCClause(K, BeginLoc, EndLoc), LParenLoc(LParenLoc) {}
61
62public:
63 SourceLocation getLParenLoc() const { return LParenLoc; }
64
65 child_range children() {
66 return child_range(child_iterator(), child_iterator());
67 }
68 const_child_range children() const {
69 return const_child_range(const_child_iterator(), const_child_iterator());
70 }
71};
72
73/// A 'default' clause, has the optional 'none' or 'present' argument.
74class OpenACCDefaultClause : public OpenACCClauseWithParams {
75 friend class ASTReaderStmt;
76 friend class ASTWriterStmt;
77
78 OpenACCDefaultClauseKind DefaultClauseKind;
79
80protected:
81 OpenACCDefaultClause(OpenACCDefaultClauseKind K, SourceLocation BeginLoc,
82 SourceLocation LParenLoc, SourceLocation EndLoc)
83 : OpenACCClauseWithParams(OpenACCClauseKind::Default, BeginLoc, LParenLoc,
84 EndLoc),
85 DefaultClauseKind(K) {
86 assert((DefaultClauseKind == OpenACCDefaultClauseKind::None ||
87 DefaultClauseKind == OpenACCDefaultClauseKind::Present) &&
88 "Invalid Clause Kind");
89 }
90
91public:
92 OpenACCDefaultClauseKind getDefaultClauseKind() const {
93 return DefaultClauseKind;
94 }
95
96 static OpenACCDefaultClause *Create(const ASTContext &C,
97 OpenACCDefaultClauseKind K,
98 SourceLocation BeginLoc,
99 SourceLocation LParenLoc,
100 SourceLocation EndLoc);
101};
102
103/// Represents one of the handful of classes that has an optional/required
104/// 'condition' expression as an argument.
105class OpenACCClauseWithCondition : public OpenACCClauseWithParams {
106 Expr *ConditionExpr = nullptr;
107
108protected:
109 OpenACCClauseWithCondition(OpenACCClauseKind K, SourceLocation BeginLoc,
110 SourceLocation LParenLoc, Expr *ConditionExpr,
111 SourceLocation EndLoc)
112 : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc),
113 ConditionExpr(ConditionExpr) {}
114
115public:
116 bool hasConditionExpr() const { return ConditionExpr; }
117 const Expr *getConditionExpr() const { return ConditionExpr; }
118 Expr *getConditionExpr() { return ConditionExpr; }
119
120 child_range children() {
121 if (ConditionExpr)
122 return child_range(reinterpret_cast<Stmt **>(&ConditionExpr),
123 reinterpret_cast<Stmt **>(&ConditionExpr + 1));
124 return child_range(child_iterator(), child_iterator());
125 }
126
127 const_child_range children() const {
128 if (ConditionExpr)
129 return const_child_range(
130 reinterpret_cast<Stmt *const *>(&ConditionExpr),
131 reinterpret_cast<Stmt *const *>(&ConditionExpr + 1));
132 return const_child_range(const_child_iterator(), const_child_iterator());
133 }
134};
135
136/// An 'if' clause, which has a required condition expression.
137class OpenACCIfClause : public OpenACCClauseWithCondition {
138protected:
139 OpenACCIfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
140 Expr *ConditionExpr, SourceLocation EndLoc);
141
142public:
143 static OpenACCIfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
144 SourceLocation LParenLoc, Expr *ConditionExpr,
145 SourceLocation EndLoc);
146};
147
148/// A 'self' clause, which has an optional condition expression.
149class OpenACCSelfClause : public OpenACCClauseWithCondition {
150 OpenACCSelfClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
151 Expr *ConditionExpr, SourceLocation EndLoc);
152
153public:
154 static OpenACCSelfClause *Create(const ASTContext &C, SourceLocation BeginLoc,
155 SourceLocation LParenLoc,
156 Expr *ConditionExpr, SourceLocation EndLoc);
157};
158
159/// Represents a clause that has one or more IntExprs. It does not own the
160/// IntExprs, but provides 'children' and other accessors.
161class OpenACCClauseWithIntExprs : public OpenACCClauseWithParams {
162 MutableArrayRef<Expr *> IntExprs;
163
164protected:
165 OpenACCClauseWithIntExprs(OpenACCClauseKind K, SourceLocation BeginLoc,
166 SourceLocation LParenLoc, SourceLocation EndLoc)
167 : OpenACCClauseWithParams(K, BeginLoc, LParenLoc, EndLoc) {}
168
169 /// Used only for initialization, the leaf class can initialize this to
170 /// trailing storage.
171 void setIntExprs(MutableArrayRef<Expr *> NewIntExprs) {
172 assert(IntExprs.empty() && "Cannot change IntExprs list");
173 IntExprs = NewIntExprs;
174 }
175
176 /// Gets the entire list of integer expressions, but leave it to the
177 /// individual clauses to expose this how they'd like.
178 llvm::ArrayRef<Expr *> getIntExprs() const { return IntExprs; }
179
180public:
181 child_range children() {
182 return child_range(reinterpret_cast<Stmt **>(IntExprs.begin()),
183 reinterpret_cast<Stmt **>(IntExprs.end()));
184 }
185
186 const_child_range children() const {
187 child_range Children =
188 const_cast<OpenACCClauseWithIntExprs *>(this)->children();
189 return const_child_range(Children.begin(), Children.end());
190 }
191};
192
193class OpenACCNumGangsClause final
194 : public OpenACCClauseWithIntExprs,
195 public llvm::TrailingObjects<OpenACCNumGangsClause, Expr *> {
196
197 OpenACCNumGangsClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
198 ArrayRef<Expr *> IntExprs, SourceLocation EndLoc)
199 : OpenACCClauseWithIntExprs(OpenACCClauseKind::NumGangs, BeginLoc,
200 LParenLoc, EndLoc) {
201 std::uninitialized_copy(first: IntExprs.begin(), last: IntExprs.end(),
202 result: getTrailingObjects<Expr *>());
203 setIntExprs(MutableArrayRef(getTrailingObjects<Expr *>(), IntExprs.size()));
204 }
205
206public:
207 static OpenACCNumGangsClause *
208 Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
209 ArrayRef<Expr *> IntExprs, SourceLocation EndLoc);
210
211 llvm::ArrayRef<Expr *> getIntExprs() {
212 return OpenACCClauseWithIntExprs::getIntExprs();
213 }
214
215 llvm::ArrayRef<Expr *> getIntExprs() const {
216 return OpenACCClauseWithIntExprs::getIntExprs();
217 }
218};
219
220/// Represents one of a handful of clauses that have a single integer
221/// expression.
222class OpenACCClauseWithSingleIntExpr : public OpenACCClauseWithIntExprs {
223 Expr *IntExpr;
224
225protected:
226 OpenACCClauseWithSingleIntExpr(OpenACCClauseKind K, SourceLocation BeginLoc,
227 SourceLocation LParenLoc, Expr *IntExpr,
228 SourceLocation EndLoc)
229 : OpenACCClauseWithIntExprs(K, BeginLoc, LParenLoc, EndLoc),
230 IntExpr(IntExpr) {
231 setIntExprs(MutableArrayRef<Expr *>{&this->IntExpr, 1});
232 }
233
234public:
235 bool hasIntExpr() const { return !getIntExprs().empty(); }
236 const Expr *getIntExpr() const {
237 return hasIntExpr() ? getIntExprs()[0] : nullptr;
238 }
239
240 Expr *getIntExpr() { return hasIntExpr() ? getIntExprs()[0] : nullptr; };
241};
242
243class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
244 OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
245 Expr *IntExpr, SourceLocation EndLoc);
246
247public:
248 static OpenACCNumWorkersClause *Create(const ASTContext &C,
249 SourceLocation BeginLoc,
250 SourceLocation LParenLoc,
251 Expr *IntExpr, SourceLocation EndLoc);
252};
253
254class OpenACCVectorLengthClause : public OpenACCClauseWithSingleIntExpr {
255 OpenACCVectorLengthClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
256 Expr *IntExpr, SourceLocation EndLoc);
257
258public:
259 static OpenACCVectorLengthClause *
260 Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
261 Expr *IntExpr, SourceLocation EndLoc);
262};
263
264template <class Impl> class OpenACCClauseVisitor {
265 Impl &getDerived() { return static_cast<Impl &>(*this); }
266
267public:
268 void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
269 for (const OpenACCClause *Clause : List)
270 Visit(C: Clause);
271 }
272
273 void Visit(const OpenACCClause *C) {
274 if (!C)
275 return;
276
277 switch (C->getClauseKind()) {
278#define VISIT_CLAUSE(CLAUSE_NAME) \
279 case OpenACCClauseKind::CLAUSE_NAME: \
280 Visit##CLAUSE_NAME##Clause(*cast<OpenACC##CLAUSE_NAME##Clause>(C)); \
281 return;
282#include "clang/Basic/OpenACCClauses.def"
283
284 default:
285 llvm_unreachable("Clause visitor not yet implemented");
286 }
287 llvm_unreachable("Invalid Clause kind");
288 }
289
290#define VISIT_CLAUSE(CLAUSE_NAME) \
291 void Visit##CLAUSE_NAME##Clause( \
292 const OpenACC##CLAUSE_NAME##Clause &Clause) { \
293 return getDerived().Visit##CLAUSE_NAME##Clause(Clause); \
294 }
295
296#include "clang/Basic/OpenACCClauses.def"
297};
298
299class OpenACCClausePrinter final
300 : public OpenACCClauseVisitor<OpenACCClausePrinter> {
301 raw_ostream &OS;
302
303public:
304 void VisitClauseList(ArrayRef<const OpenACCClause *> List) {
305 for (const OpenACCClause *Clause : List) {
306 Visit(C: Clause);
307
308 if (Clause != List.back())
309 OS << ' ';
310 }
311 }
312 OpenACCClausePrinter(raw_ostream &OS) : OS(OS) {}
313
314#define VISIT_CLAUSE(CLAUSE_NAME) \
315 void Visit##CLAUSE_NAME##Clause(const OpenACC##CLAUSE_NAME##Clause &Clause);
316#include "clang/Basic/OpenACCClauses.def"
317};
318
319} // namespace clang
320
321#endif // LLVM_CLANG_AST_OPENACCCLAUSE_H
322

source code of clang/include/clang/AST/OpenACCClause.h