Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14 | pmbaty | 1 | //===- DeclOpenMP.h - Classes for representing OpenMP 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 | /// |
||
9 | /// \file |
||
10 | /// This file defines OpenMP nodes for declarative directives. |
||
11 | /// |
||
12 | //===----------------------------------------------------------------------===// |
||
13 | |||
14 | #ifndef LLVM_CLANG_AST_DECLOPENMP_H |
||
15 | #define LLVM_CLANG_AST_DECLOPENMP_H |
||
16 | |||
17 | #include "clang/AST/ASTContext.h" |
||
18 | #include "clang/AST/Decl.h" |
||
19 | #include "clang/AST/Expr.h" |
||
20 | #include "clang/AST/ExternalASTSource.h" |
||
21 | #include "clang/AST/OpenMPClause.h" |
||
22 | #include "clang/AST/Type.h" |
||
23 | #include "llvm/ADT/ArrayRef.h" |
||
24 | #include "llvm/Support/TrailingObjects.h" |
||
25 | |||
26 | namespace clang { |
||
27 | |||
28 | /// This is a basic class for representing single OpenMP declarative directive. |
||
29 | /// |
||
30 | template <typename U> class OMPDeclarativeDirective : public U { |
||
31 | friend class ASTDeclReader; |
||
32 | friend class ASTDeclWriter; |
||
33 | |||
34 | /// Get the clauses storage. |
||
35 | MutableArrayRef<OMPClause *> getClauses() { |
||
36 | if (!Data) |
||
37 | return std::nullopt; |
||
38 | return Data->getClauses(); |
||
39 | } |
||
40 | |||
41 | protected: |
||
42 | /// Data, associated with the directive. |
||
43 | OMPChildren *Data = nullptr; |
||
44 | |||
45 | /// Build instance of directive. |
||
46 | template <typename... Params> |
||
47 | OMPDeclarativeDirective(Params &&... P) : U(std::forward<Params>(P)...) {} |
||
48 | |||
49 | template <typename T, typename... Params> |
||
50 | static T *createDirective(const ASTContext &C, DeclContext *DC, |
||
51 | ArrayRef<OMPClause *> Clauses, unsigned NumChildren, |
||
52 | Params &&... P) { |
||
53 | auto *Inst = new (C, DC, size(Clauses.size(), NumChildren)) |
||
54 | T(DC, std::forward<Params>(P)...); |
||
55 | Inst->Data = OMPChildren::Create(Inst + 1, Clauses, |
||
56 | /*AssociatedStmt=*/nullptr, NumChildren); |
||
57 | Inst->Data->setClauses(Clauses); |
||
58 | return Inst; |
||
59 | } |
||
60 | |||
61 | template <typename T, typename... Params> |
||
62 | static T *createEmptyDirective(const ASTContext &C, unsigned ID, |
||
63 | unsigned NumClauses, unsigned NumChildren, |
||
64 | Params &&... P) { |
||
65 | auto *Inst = new (C, ID, size(NumClauses, NumChildren)) |
||
66 | T(nullptr, std::forward<Params>(P)...); |
||
67 | Inst->Data = OMPChildren::CreateEmpty( |
||
68 | Inst + 1, NumClauses, /*HasAssociatedStmt=*/false, NumChildren); |
||
69 | return Inst; |
||
70 | } |
||
71 | |||
72 | static size_t size(unsigned NumClauses, unsigned NumChildren) { |
||
73 | return OMPChildren::size(NumClauses, /*HasAssociatedStmt=*/false, |
||
74 | NumChildren); |
||
75 | } |
||
76 | |||
77 | public: |
||
78 | /// Get number of clauses. |
||
79 | unsigned getNumClauses() const { |
||
80 | if (!Data) |
||
81 | return 0; |
||
82 | return Data->getNumClauses(); |
||
83 | } |
||
84 | |||
85 | /// Returns specified clause. |
||
86 | /// |
||
87 | /// \param I Number of clause. |
||
88 | /// |
||
89 | OMPClause *getClause(unsigned I) const { return clauses()[I]; } |
||
90 | |||
91 | ArrayRef<OMPClause *> clauses() const { |
||
92 | if (!Data) |
||
93 | return std::nullopt; |
||
94 | return Data->getClauses(); |
||
95 | } |
||
96 | }; |
||
97 | |||
98 | /// This represents '#pragma omp threadprivate ...' directive. |
||
99 | /// For example, in the following, both 'a' and 'A::b' are threadprivate: |
||
100 | /// |
||
101 | /// \code |
||
102 | /// int a; |
||
103 | /// #pragma omp threadprivate(a) |
||
104 | /// struct A { |
||
105 | /// static int b; |
||
106 | /// #pragma omp threadprivate(b) |
||
107 | /// }; |
||
108 | /// \endcode |
||
109 | /// |
||
110 | class OMPThreadPrivateDecl final : public OMPDeclarativeDirective<Decl> { |
||
111 | friend class OMPDeclarativeDirective<Decl>; |
||
112 | |||
113 | virtual void anchor(); |
||
114 | |||
115 | OMPThreadPrivateDecl(DeclContext *DC = nullptr, |
||
116 | SourceLocation L = SourceLocation()) |
||
117 | : OMPDeclarativeDirective<Decl>(OMPThreadPrivate, DC, L) {} |
||
118 | |||
119 | ArrayRef<const Expr *> getVars() const { |
||
120 | auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); |
||
121 | return llvm::ArrayRef(Storage, Data->getNumChildren()); |
||
122 | } |
||
123 | |||
124 | MutableArrayRef<Expr *> getVars() { |
||
125 | auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); |
||
126 | return llvm::MutableArrayRef(Storage, Data->getNumChildren()); |
||
127 | } |
||
128 | |||
129 | void setVars(ArrayRef<Expr *> VL); |
||
130 | |||
131 | public: |
||
132 | static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC, |
||
133 | SourceLocation L, |
||
134 | ArrayRef<Expr *> VL); |
||
135 | static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, |
||
136 | unsigned ID, unsigned N); |
||
137 | |||
138 | typedef MutableArrayRef<Expr *>::iterator varlist_iterator; |
||
139 | typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; |
||
140 | typedef llvm::iterator_range<varlist_iterator> varlist_range; |
||
141 | typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; |
||
142 | |||
143 | unsigned varlist_size() const { return Data->getNumChildren(); } |
||
144 | bool varlist_empty() const { return Data->getChildren().empty(); } |
||
145 | |||
146 | varlist_range varlists() { |
||
147 | return varlist_range(varlist_begin(), varlist_end()); |
||
148 | } |
||
149 | varlist_const_range varlists() const { |
||
150 | return varlist_const_range(varlist_begin(), varlist_end()); |
||
151 | } |
||
152 | varlist_iterator varlist_begin() { return getVars().begin(); } |
||
153 | varlist_iterator varlist_end() { return getVars().end(); } |
||
154 | varlist_const_iterator varlist_begin() const { return getVars().begin(); } |
||
155 | varlist_const_iterator varlist_end() const { return getVars().end(); } |
||
156 | |||
157 | static bool classof(const Decl *D) { return classofKind(D->getKind()); } |
||
158 | static bool classofKind(Kind K) { return K == OMPThreadPrivate; } |
||
159 | }; |
||
160 | |||
161 | /// This represents '#pragma omp declare reduction ...' directive. |
||
162 | /// For example, in the following, declared reduction 'foo' for types 'int' and |
||
163 | /// 'float': |
||
164 | /// |
||
165 | /// \code |
||
166 | /// #pragma omp declare reduction (foo : int,float : omp_out += omp_in) |
||
167 | /// initializer (omp_priv = 0) |
||
168 | /// \endcode |
||
169 | /// |
||
170 | /// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer. |
||
171 | class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext { |
||
172 | // This class stores some data in DeclContext::OMPDeclareReductionDeclBits |
||
173 | // to save some space. Use the provided accessors to access it. |
||
174 | public: |
||
175 | enum InitKind { |
||
176 | CallInit, // Initialized by function call. |
||
177 | DirectInit, // omp_priv(<expr>) |
||
178 | CopyInit // omp_priv = <expr> |
||
179 | }; |
||
180 | |||
181 | private: |
||
182 | friend class ASTDeclReader; |
||
183 | /// Combiner for declare reduction construct. |
||
184 | Expr *Combiner = nullptr; |
||
185 | /// Initializer for declare reduction construct. |
||
186 | Expr *Initializer = nullptr; |
||
187 | /// In parameter of the combiner. |
||
188 | Expr *In = nullptr; |
||
189 | /// Out parameter of the combiner. |
||
190 | Expr *Out = nullptr; |
||
191 | /// Priv parameter of the initializer. |
||
192 | Expr *Priv = nullptr; |
||
193 | /// Orig parameter of the initializer. |
||
194 | Expr *Orig = nullptr; |
||
195 | |||
196 | /// Reference to the previous declare reduction construct in the same |
||
197 | /// scope with the same name. Required for proper templates instantiation if |
||
198 | /// the declare reduction construct is declared inside compound statement. |
||
199 | LazyDeclPtr PrevDeclInScope; |
||
200 | |||
201 | void anchor() override; |
||
202 | |||
203 | OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L, |
||
204 | DeclarationName Name, QualType Ty, |
||
205 | OMPDeclareReductionDecl *PrevDeclInScope); |
||
206 | |||
207 | void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) { |
||
208 | PrevDeclInScope = Prev; |
||
209 | } |
||
210 | |||
211 | public: |
||
212 | /// Create declare reduction node. |
||
213 | static OMPDeclareReductionDecl * |
||
214 | Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, |
||
215 | QualType T, OMPDeclareReductionDecl *PrevDeclInScope); |
||
216 | /// Create deserialized declare reduction node. |
||
217 | static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C, |
||
218 | unsigned ID); |
||
219 | |||
220 | /// Get combiner expression of the declare reduction construct. |
||
221 | Expr *getCombiner() { return Combiner; } |
||
222 | const Expr *getCombiner() const { return Combiner; } |
||
223 | /// Get In variable of the combiner. |
||
224 | Expr *getCombinerIn() { return In; } |
||
225 | const Expr *getCombinerIn() const { return In; } |
||
226 | /// Get Out variable of the combiner. |
||
227 | Expr *getCombinerOut() { return Out; } |
||
228 | const Expr *getCombinerOut() const { return Out; } |
||
229 | /// Set combiner expression for the declare reduction construct. |
||
230 | void setCombiner(Expr *E) { Combiner = E; } |
||
231 | /// Set combiner In and Out vars. |
||
232 | void setCombinerData(Expr *InE, Expr *OutE) { |
||
233 | In = InE; |
||
234 | Out = OutE; |
||
235 | } |
||
236 | |||
237 | /// Get initializer expression (if specified) of the declare reduction |
||
238 | /// construct. |
||
239 | Expr *getInitializer() { return Initializer; } |
||
240 | const Expr *getInitializer() const { return Initializer; } |
||
241 | /// Get initializer kind. |
||
242 | InitKind getInitializerKind() const { |
||
243 | return static_cast<InitKind>(OMPDeclareReductionDeclBits.InitializerKind); |
||
244 | } |
||
245 | /// Get Orig variable of the initializer. |
||
246 | Expr *getInitOrig() { return Orig; } |
||
247 | const Expr *getInitOrig() const { return Orig; } |
||
248 | /// Get Priv variable of the initializer. |
||
249 | Expr *getInitPriv() { return Priv; } |
||
250 | const Expr *getInitPriv() const { return Priv; } |
||
251 | /// Set initializer expression for the declare reduction construct. |
||
252 | void setInitializer(Expr *E, InitKind IK) { |
||
253 | Initializer = E; |
||
254 | OMPDeclareReductionDeclBits.InitializerKind = IK; |
||
255 | } |
||
256 | /// Set initializer Orig and Priv vars. |
||
257 | void setInitializerData(Expr *OrigE, Expr *PrivE) { |
||
258 | Orig = OrigE; |
||
259 | Priv = PrivE; |
||
260 | } |
||
261 | |||
262 | /// Get reference to previous declare reduction construct in the same |
||
263 | /// scope with the same name. |
||
264 | OMPDeclareReductionDecl *getPrevDeclInScope(); |
||
265 | const OMPDeclareReductionDecl *getPrevDeclInScope() const; |
||
266 | |||
267 | static bool classof(const Decl *D) { return classofKind(D->getKind()); } |
||
268 | static bool classofKind(Kind K) { return K == OMPDeclareReduction; } |
||
269 | static DeclContext *castToDeclContext(const OMPDeclareReductionDecl *D) { |
||
270 | return static_cast<DeclContext *>(const_cast<OMPDeclareReductionDecl *>(D)); |
||
271 | } |
||
272 | static OMPDeclareReductionDecl *castFromDeclContext(const DeclContext *DC) { |
||
273 | return static_cast<OMPDeclareReductionDecl *>( |
||
274 | const_cast<DeclContext *>(DC)); |
||
275 | } |
||
276 | }; |
||
277 | |||
278 | /// This represents '#pragma omp declare mapper ...' directive. Map clauses are |
||
279 | /// allowed to use with this directive. The following example declares a user |
||
280 | /// defined mapper for the type 'struct vec'. This example instructs the fields |
||
281 | /// 'len' and 'data' should be mapped when mapping instances of 'struct vec'. |
||
282 | /// |
||
283 | /// \code |
||
284 | /// #pragma omp declare mapper(mid: struct vec v) map(v.len, v.data[0:N]) |
||
285 | /// \endcode |
||
286 | class OMPDeclareMapperDecl final : public OMPDeclarativeDirective<ValueDecl>, |
||
287 | public DeclContext { |
||
288 | friend class OMPDeclarativeDirective<ValueDecl>; |
||
289 | friend class ASTDeclReader; |
||
290 | friend class ASTDeclWriter; |
||
291 | |||
292 | /// Mapper variable, which is 'v' in the example above |
||
293 | Expr *MapperVarRef = nullptr; |
||
294 | |||
295 | /// Name of the mapper variable |
||
296 | DeclarationName VarName; |
||
297 | |||
298 | LazyDeclPtr PrevDeclInScope; |
||
299 | |||
300 | void anchor() override; |
||
301 | |||
302 | OMPDeclareMapperDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, |
||
303 | QualType Ty, DeclarationName VarName, |
||
304 | OMPDeclareMapperDecl *PrevDeclInScope) |
||
305 | : OMPDeclarativeDirective<ValueDecl>(OMPDeclareMapper, DC, L, Name, Ty), |
||
306 | DeclContext(OMPDeclareMapper), VarName(VarName), |
||
307 | PrevDeclInScope(PrevDeclInScope) {} |
||
308 | |||
309 | void setPrevDeclInScope(OMPDeclareMapperDecl *Prev) { |
||
310 | PrevDeclInScope = Prev; |
||
311 | } |
||
312 | |||
313 | public: |
||
314 | /// Creates declare mapper node. |
||
315 | static OMPDeclareMapperDecl *Create(ASTContext &C, DeclContext *DC, |
||
316 | SourceLocation L, DeclarationName Name, |
||
317 | QualType T, DeclarationName VarName, |
||
318 | ArrayRef<OMPClause *> Clauses, |
||
319 | OMPDeclareMapperDecl *PrevDeclInScope); |
||
320 | /// Creates deserialized declare mapper node. |
||
321 | static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C, unsigned ID, |
||
322 | unsigned N); |
||
323 | |||
324 | using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator; |
||
325 | using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator; |
||
326 | using clauselist_range = llvm::iterator_range<clauselist_iterator>; |
||
327 | using clauselist_const_range = |
||
328 | llvm::iterator_range<clauselist_const_iterator>; |
||
329 | |||
330 | unsigned clauselist_size() const { return Data->getNumClauses(); } |
||
331 | bool clauselist_empty() const { return Data->getClauses().empty(); } |
||
332 | |||
333 | clauselist_range clauselists() { |
||
334 | return clauselist_range(clauselist_begin(), clauselist_end()); |
||
335 | } |
||
336 | clauselist_const_range clauselists() const { |
||
337 | return clauselist_const_range(clauselist_begin(), clauselist_end()); |
||
338 | } |
||
339 | clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); } |
||
340 | clauselist_iterator clauselist_end() { return Data->getClauses().end(); } |
||
341 | clauselist_const_iterator clauselist_begin() const { |
||
342 | return Data->getClauses().begin(); |
||
343 | } |
||
344 | clauselist_const_iterator clauselist_end() const { |
||
345 | return Data->getClauses().end(); |
||
346 | } |
||
347 | |||
348 | /// Get the variable declared in the mapper |
||
349 | Expr *getMapperVarRef() { return cast_or_null<Expr>(Data->getChildren()[0]); } |
||
350 | const Expr *getMapperVarRef() const { |
||
351 | return cast_or_null<Expr>(Data->getChildren()[0]); |
||
352 | } |
||
353 | /// Set the variable declared in the mapper |
||
354 | void setMapperVarRef(Expr *MapperVarRefE) { |
||
355 | Data->getChildren()[0] = MapperVarRefE; |
||
356 | } |
||
357 | |||
358 | /// Get the name of the variable declared in the mapper |
||
359 | DeclarationName getVarName() { return VarName; } |
||
360 | |||
361 | /// Get reference to previous declare mapper construct in the same |
||
362 | /// scope with the same name. |
||
363 | OMPDeclareMapperDecl *getPrevDeclInScope(); |
||
364 | const OMPDeclareMapperDecl *getPrevDeclInScope() const; |
||
365 | |||
366 | static bool classof(const Decl *D) { return classofKind(D->getKind()); } |
||
367 | static bool classofKind(Kind K) { return K == OMPDeclareMapper; } |
||
368 | static DeclContext *castToDeclContext(const OMPDeclareMapperDecl *D) { |
||
369 | return static_cast<DeclContext *>(const_cast<OMPDeclareMapperDecl *>(D)); |
||
370 | } |
||
371 | static OMPDeclareMapperDecl *castFromDeclContext(const DeclContext *DC) { |
||
372 | return static_cast<OMPDeclareMapperDecl *>(const_cast<DeclContext *>(DC)); |
||
373 | } |
||
374 | }; |
||
375 | |||
376 | /// Pseudo declaration for capturing expressions. Also is used for capturing of |
||
377 | /// non-static data members in non-static member functions. |
||
378 | /// |
||
379 | /// Clang supports capturing of variables only, but OpenMP 4.5 allows to |
||
380 | /// privatize non-static members of current class in non-static member |
||
381 | /// functions. This pseudo-declaration allows properly handle this kind of |
||
382 | /// capture by wrapping captured expression into a variable-like declaration. |
||
383 | class OMPCapturedExprDecl final : public VarDecl { |
||
384 | friend class ASTDeclReader; |
||
385 | void anchor() override; |
||
386 | |||
387 | OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, |
||
388 | QualType Type, TypeSourceInfo *TInfo, |
||
389 | SourceLocation StartLoc) |
||
390 | : VarDecl(OMPCapturedExpr, C, DC, StartLoc, StartLoc, Id, Type, TInfo, |
||
391 | SC_None) { |
||
392 | setImplicit(); |
||
393 | } |
||
394 | |||
395 | public: |
||
396 | static OMPCapturedExprDecl *Create(ASTContext &C, DeclContext *DC, |
||
397 | IdentifierInfo *Id, QualType T, |
||
398 | SourceLocation StartLoc); |
||
399 | |||
400 | static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, unsigned ID); |
||
401 | |||
402 | SourceRange getSourceRange() const override LLVM_READONLY; |
||
403 | |||
404 | // Implement isa/cast/dyncast/etc. |
||
405 | static bool classof(const Decl *D) { return classofKind(D->getKind()); } |
||
406 | static bool classofKind(Kind K) { return K == OMPCapturedExpr; } |
||
407 | }; |
||
408 | |||
409 | /// This represents '#pragma omp requires...' directive. |
||
410 | /// For example |
||
411 | /// |
||
412 | /// \code |
||
413 | /// #pragma omp requires unified_address |
||
414 | /// \endcode |
||
415 | /// |
||
416 | class OMPRequiresDecl final : public OMPDeclarativeDirective<Decl> { |
||
417 | friend class OMPDeclarativeDirective<Decl>; |
||
418 | friend class ASTDeclReader; |
||
419 | |||
420 | virtual void anchor(); |
||
421 | |||
422 | OMPRequiresDecl(DeclContext *DC, SourceLocation L) |
||
423 | : OMPDeclarativeDirective<Decl>(OMPRequires, DC, L) {} |
||
424 | |||
425 | public: |
||
426 | /// Create requires node. |
||
427 | static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC, |
||
428 | SourceLocation L, ArrayRef<OMPClause *> CL); |
||
429 | /// Create deserialized requires node. |
||
430 | static OMPRequiresDecl *CreateDeserialized(ASTContext &C, unsigned ID, |
||
431 | unsigned N); |
||
432 | |||
433 | using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator; |
||
434 | using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator; |
||
435 | using clauselist_range = llvm::iterator_range<clauselist_iterator>; |
||
436 | using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>; |
||
437 | |||
438 | unsigned clauselist_size() const { return Data->getNumClauses(); } |
||
439 | bool clauselist_empty() const { return Data->getClauses().empty(); } |
||
440 | |||
441 | clauselist_range clauselists() { |
||
442 | return clauselist_range(clauselist_begin(), clauselist_end()); |
||
443 | } |
||
444 | clauselist_const_range clauselists() const { |
||
445 | return clauselist_const_range(clauselist_begin(), clauselist_end()); |
||
446 | } |
||
447 | clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); } |
||
448 | clauselist_iterator clauselist_end() { return Data->getClauses().end(); } |
||
449 | clauselist_const_iterator clauselist_begin() const { |
||
450 | return Data->getClauses().begin(); |
||
451 | } |
||
452 | clauselist_const_iterator clauselist_end() const { |
||
453 | return Data->getClauses().end(); |
||
454 | } |
||
455 | |||
456 | static bool classof(const Decl *D) { return classofKind(D->getKind()); } |
||
457 | static bool classofKind(Kind K) { return K == OMPRequires; } |
||
458 | }; |
||
459 | |||
460 | /// This represents '#pragma omp allocate ...' directive. |
||
461 | /// For example, in the following, the default allocator is used for both 'a' |
||
462 | /// and 'A::b': |
||
463 | /// |
||
464 | /// \code |
||
465 | /// int a; |
||
466 | /// #pragma omp allocate(a) |
||
467 | /// struct A { |
||
468 | /// static int b; |
||
469 | /// #pragma omp allocate(b) |
||
470 | /// }; |
||
471 | /// \endcode |
||
472 | /// |
||
473 | class OMPAllocateDecl final : public OMPDeclarativeDirective<Decl> { |
||
474 | friend class OMPDeclarativeDirective<Decl>; |
||
475 | friend class ASTDeclReader; |
||
476 | |||
477 | virtual void anchor(); |
||
478 | |||
479 | OMPAllocateDecl(DeclContext *DC, SourceLocation L) |
||
480 | : OMPDeclarativeDirective<Decl>(OMPAllocate, DC, L) {} |
||
481 | |||
482 | ArrayRef<const Expr *> getVars() const { |
||
483 | auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); |
||
484 | return llvm::ArrayRef(Storage, Data->getNumChildren()); |
||
485 | } |
||
486 | |||
487 | MutableArrayRef<Expr *> getVars() { |
||
488 | auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); |
||
489 | return llvm::MutableArrayRef(Storage, Data->getNumChildren()); |
||
490 | } |
||
491 | |||
492 | void setVars(ArrayRef<Expr *> VL); |
||
493 | |||
494 | public: |
||
495 | static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC, |
||
496 | SourceLocation L, ArrayRef<Expr *> VL, |
||
497 | ArrayRef<OMPClause *> CL); |
||
498 | static OMPAllocateDecl *CreateDeserialized(ASTContext &C, unsigned ID, |
||
499 | unsigned NVars, unsigned NClauses); |
||
500 | |||
501 | typedef MutableArrayRef<Expr *>::iterator varlist_iterator; |
||
502 | typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; |
||
503 | typedef llvm::iterator_range<varlist_iterator> varlist_range; |
||
504 | typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; |
||
505 | using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator; |
||
506 | using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator; |
||
507 | using clauselist_range = llvm::iterator_range<clauselist_iterator>; |
||
508 | using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>; |
||
509 | |||
510 | unsigned varlist_size() const { return Data->getNumChildren(); } |
||
511 | bool varlist_empty() const { return Data->getChildren().empty(); } |
||
512 | unsigned clauselist_size() const { return Data->getNumClauses(); } |
||
513 | bool clauselist_empty() const { return Data->getClauses().empty(); } |
||
514 | |||
515 | varlist_range varlists() { |
||
516 | return varlist_range(varlist_begin(), varlist_end()); |
||
517 | } |
||
518 | varlist_const_range varlists() const { |
||
519 | return varlist_const_range(varlist_begin(), varlist_end()); |
||
520 | } |
||
521 | varlist_iterator varlist_begin() { return getVars().begin(); } |
||
522 | varlist_iterator varlist_end() { return getVars().end(); } |
||
523 | varlist_const_iterator varlist_begin() const { return getVars().begin(); } |
||
524 | varlist_const_iterator varlist_end() const { return getVars().end(); } |
||
525 | |||
526 | clauselist_range clauselists() { |
||
527 | return clauselist_range(clauselist_begin(), clauselist_end()); |
||
528 | } |
||
529 | clauselist_const_range clauselists() const { |
||
530 | return clauselist_const_range(clauselist_begin(), clauselist_end()); |
||
531 | } |
||
532 | clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); } |
||
533 | clauselist_iterator clauselist_end() { return Data->getClauses().end(); } |
||
534 | clauselist_const_iterator clauselist_begin() const { |
||
535 | return Data->getClauses().begin(); |
||
536 | } |
||
537 | clauselist_const_iterator clauselist_end() const { |
||
538 | return Data->getClauses().end(); |
||
539 | } |
||
540 | |||
541 | static bool classof(const Decl *D) { return classofKind(D->getKind()); } |
||
542 | static bool classofKind(Kind K) { return K == OMPAllocate; } |
||
543 | }; |
||
544 | |||
545 | } // end namespace clang |
||
546 | |||
547 | #endif |