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
26namespace clang {
27
28/// This is a basic class for representing single OpenMP declarative directive.
29///
30template <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 llvm::None;
38 return Data->getClauses();
39 }
40
41protected:
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
77public:
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 llvm::None;
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///
110class 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::makeArrayRef(Storage, Data->getNumChildren());
122 }
123
124 MutableArrayRef<Expr *> getVars() {
125 auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
126 return llvm::makeMutableArrayRef(Storage, Data->getNumChildren());
127 }
128
129 void setVars(ArrayRef<Expr *> VL);
130
131public:
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.
171class 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.
174public:
175 enum InitKind {
176 CallInit, // Initialized by function call.
177 DirectInit, // omp_priv(<expr>)
178 CopyInit // omp_priv = <expr>
179 };
180
181private:
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
211public:
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
286class 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
313public:
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.
383class 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
395public:
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///
416class 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
425public:
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///
473class 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::makeArrayRef(Storage, Data->getNumChildren());
485 }
486
487 MutableArrayRef<Expr *> getVars() {
488 auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
489 return llvm::makeMutableArrayRef(Storage, Data->getNumChildren());
490 }
491
492 void setVars(ArrayRef<Expr *> VL);
493
494public:
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
548