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