1//===- StmtOpenACC.h - Classes for OpenACC directives ----------*- 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/// \file
9/// This file defines OpenACC AST classes for statement-level contructs.
10///
11//===----------------------------------------------------------------------===//
12
13#ifndef LLVM_CLANG_AST_STMTOPENACC_H
14#define LLVM_CLANG_AST_STMTOPENACC_H
15
16#include "clang/AST/OpenACCClause.h"
17#include "clang/AST/Stmt.h"
18#include "clang/Basic/OpenACCKinds.h"
19#include "clang/Basic/SourceLocation.h"
20#include <memory>
21
22namespace clang {
23/// This is the base class for an OpenACC statement-level construct, other
24/// construct types are expected to inherit from this.
25class OpenACCConstructStmt : public Stmt {
26 friend class ASTStmtWriter;
27 friend class ASTStmtReader;
28 /// The directive kind. Each implementation of this interface should handle
29 /// specific kinds.
30 OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid;
31 /// The location of the directive statement, from the '#' to the last token of
32 /// the directive.
33 SourceRange Range;
34
35 /// The list of clauses. This is stored here as an ArrayRef, as this is the
36 /// most convienient place to access the list, however the list itself should
37 /// be stored in leaf nodes, likely in trailing-storage.
38 MutableArrayRef<const OpenACCClause *> Clauses;
39
40protected:
41 OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K,
42 SourceLocation Start, SourceLocation End)
43 : Stmt(SC), Kind(K), Range(Start, End) {}
44
45 // Used only for initialization, the leaf class can initialize this to
46 // trailing storage.
47 void setClauseList(MutableArrayRef<const OpenACCClause *> NewClauses) {
48 assert(Clauses.empty() && "Cannot change clause list");
49 Clauses = NewClauses;
50 }
51
52public:
53 OpenACCDirectiveKind getDirectiveKind() const { return Kind; }
54
55 static bool classof(const Stmt *S) {
56 return S->getStmtClass() >= firstOpenACCConstructStmtConstant &&
57 S->getStmtClass() <= lastOpenACCConstructStmtConstant;
58 }
59
60 SourceLocation getBeginLoc() const { return Range.getBegin(); }
61 SourceLocation getEndLoc() const { return Range.getEnd(); }
62 ArrayRef<const OpenACCClause *> clauses() const { return Clauses; }
63
64 child_range children() {
65 return child_range(child_iterator(), child_iterator());
66 }
67
68 const_child_range children() const {
69 return const_cast<OpenACCConstructStmt *>(this)->children();
70 }
71};
72
73/// This is a base class for any OpenACC statement-level constructs that have an
74/// associated statement. This class is not intended to be instantiated, but is
75/// a convenient place to hold the associated statement.
76class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt {
77 friend class ASTStmtWriter;
78 friend class ASTStmtReader;
79 template <typename Derived> friend class RecursiveASTVisitor;
80 Stmt *AssociatedStmt = nullptr;
81
82protected:
83 OpenACCAssociatedStmtConstruct(StmtClass SC, OpenACCDirectiveKind K,
84 SourceLocation Start, SourceLocation End,
85 Stmt *AssocStmt)
86 : OpenACCConstructStmt(SC, K, Start, End), AssociatedStmt(AssocStmt) {}
87
88 void setAssociatedStmt(Stmt *S) { AssociatedStmt = S; }
89 Stmt *getAssociatedStmt() { return AssociatedStmt; }
90 const Stmt *getAssociatedStmt() const {
91 return const_cast<OpenACCAssociatedStmtConstruct *>(this)
92 ->getAssociatedStmt();
93 }
94
95public:
96 child_range children() {
97 if (getAssociatedStmt())
98 return child_range(&AssociatedStmt, &AssociatedStmt + 1);
99 return child_range(child_iterator(), child_iterator());
100 }
101
102 const_child_range children() const {
103 return const_cast<OpenACCAssociatedStmtConstruct *>(this)->children();
104 }
105};
106/// This class represents a compute construct, representing a 'Kind' of
107/// `parallel', 'serial', or 'kernel'. These constructs are associated with a
108/// 'structured block', defined as:
109///
110/// in C or C++, an executable statement, possibly compound, with a single
111/// entry at the top and a single exit at the bottom
112///
113/// At the moment there is no real motivation to have a different AST node for
114/// those three, as they are semantically identical, and have only minor
115/// differences in the permitted list of clauses, which can be differentiated by
116/// the 'Kind'.
117class OpenACCComputeConstruct final
118 : public OpenACCAssociatedStmtConstruct,
119 public llvm::TrailingObjects<OpenACCComputeConstruct,
120 const OpenACCClause *> {
121 friend class ASTStmtWriter;
122 friend class ASTStmtReader;
123 friend class ASTContext;
124 OpenACCComputeConstruct(unsigned NumClauses)
125 : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass,
126 OpenACCDirectiveKind::Invalid,
127 SourceLocation{}, SourceLocation{},
128 /*AssociatedStmt=*/nullptr) {
129 // We cannot send the TrailingObjects storage to the base class (which holds
130 // a reference to the data) until it is constructed, so we have to set it
131 // separately here.
132 std::uninitialized_value_construct(
133 first: getTrailingObjects<const OpenACCClause *>(),
134 last: getTrailingObjects<const OpenACCClause *>() + NumClauses);
135 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
136 NumClauses));
137 }
138
139 OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start,
140 SourceLocation End,
141 ArrayRef<const OpenACCClause *> Clauses,
142 Stmt *StructuredBlock)
143 : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start,
144 End, StructuredBlock) {
145 assert(isOpenACCComputeDirectiveKind(K) &&
146 "Only parallel, serial, and kernels constructs should be "
147 "represented by this type");
148
149 // Initialize the trailing storage.
150 std::uninitialized_copy(first: Clauses.begin(), last: Clauses.end(),
151 result: getTrailingObjects<const OpenACCClause *>());
152
153 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(),
154 Clauses.size()));
155 }
156
157 void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); }
158
159public:
160 static bool classof(const Stmt *T) {
161 return T->getStmtClass() == OpenACCComputeConstructClass;
162 }
163
164 static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C,
165 unsigned NumClauses);
166 static OpenACCComputeConstruct *
167 Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc,
168 SourceLocation EndLoc, ArrayRef<const OpenACCClause *> Clauses,
169 Stmt *StructuredBlock);
170
171 Stmt *getStructuredBlock() { return getAssociatedStmt(); }
172 const Stmt *getStructuredBlock() const {
173 return const_cast<OpenACCComputeConstruct *>(this)->getStructuredBlock();
174 }
175};
176} // namespace clang
177#endif // LLVM_CLANG_AST_STMTOPENACC_H
178

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