1 //===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 ///
10 /// \file
11 /// This file defines OpenMP nodes for declarative directives.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLVM_CLANG_AST_DECLOPENMP_H
16 #define LLVM_CLANG_AST_DECLOPENMP_H
17 
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 represents '#pragma omp threadprivate ...' directive.
29 /// For example, in the following, both 'a' and 'A::b' are threadprivate:
30 ///
31 /// \code
32 /// int a;
33 /// #pragma omp threadprivate(a)
34 /// struct A {
35 ///   static int b;
36 /// #pragma omp threadprivate(b)
37 /// };
38 /// \endcode
39 ///
40 class OMPThreadPrivateDecl final
41     : public Decl,
42       private llvm::TrailingObjects<OMPThreadPrivateDecl, Expr *> {
43   friend class ASTDeclReader;
44   friend TrailingObjects;
45 
46   unsigned NumVars;
47 
48   virtual void anchor();
49 
OMPThreadPrivateDecl(Kind DK,DeclContext * DC,SourceLocation L)50   OMPThreadPrivateDecl(Kind DK, DeclContext *DC, SourceLocation L) :
51     Decl(DK, DC, L), NumVars(0) { }
52 
getVars()53   ArrayRef<const Expr *> getVars() const {
54     return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumVars);
55   }
56 
getVars()57   MutableArrayRef<Expr *> getVars() {
58     return MutableArrayRef<Expr *>(getTrailingObjects<Expr *>(), NumVars);
59   }
60 
61   void setVars(ArrayRef<Expr *> VL);
62 
63 public:
64   static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
65                                       SourceLocation L,
66                                       ArrayRef<Expr *> VL);
67   static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
68                                                   unsigned ID, unsigned N);
69 
70   typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
71   typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
72   typedef llvm::iterator_range<varlist_iterator> varlist_range;
73   typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
74 
varlist_size()75   unsigned varlist_size() const { return NumVars; }
varlist_empty()76   bool varlist_empty() const { return NumVars == 0; }
77 
varlists()78   varlist_range varlists() {
79     return varlist_range(varlist_begin(), varlist_end());
80   }
varlists()81   varlist_const_range varlists() const {
82     return varlist_const_range(varlist_begin(), varlist_end());
83   }
varlist_begin()84   varlist_iterator varlist_begin() { return getVars().begin(); }
varlist_end()85   varlist_iterator varlist_end() { return getVars().end(); }
varlist_begin()86   varlist_const_iterator varlist_begin() const { return getVars().begin(); }
varlist_end()87   varlist_const_iterator varlist_end() const { return getVars().end(); }
88 
classof(const Decl * D)89   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)90   static bool classofKind(Kind K) { return K == OMPThreadPrivate; }
91 };
92 
93 /// This represents '#pragma omp declare reduction ...' directive.
94 /// For example, in the following, declared reduction 'foo' for types 'int' and
95 /// 'float':
96 ///
97 /// \code
98 /// #pragma omp declare reduction (foo : int,float : omp_out += omp_in) \
99 ///                     initializer (omp_priv = 0)
100 /// \endcode
101 ///
102 /// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer.
103 class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext {
104   // This class stores some data in DeclContext::OMPDeclareReductionDeclBits
105   // to save some space. Use the provided accessors to access it.
106 public:
107   enum InitKind {
108     CallInit,   // Initialized by function call.
109     DirectInit, // omp_priv(<expr>)
110     CopyInit    // omp_priv = <expr>
111   };
112 
113 private:
114   friend class ASTDeclReader;
115   /// Combiner for declare reduction construct.
116   Expr *Combiner = nullptr;
117   /// Initializer for declare reduction construct.
118   Expr *Initializer = nullptr;
119   /// In parameter of the combiner.
120   Expr *In = nullptr;
121   /// Out parameter of the combiner.
122   Expr *Out = nullptr;
123   /// Priv parameter of the initializer.
124   Expr *Priv = nullptr;
125   /// Orig parameter of the initializer.
126   Expr *Orig = nullptr;
127 
128   /// Reference to the previous declare reduction construct in the same
129   /// scope with the same name. Required for proper templates instantiation if
130   /// the declare reduction construct is declared inside compound statement.
131   LazyDeclPtr PrevDeclInScope;
132 
133   virtual void anchor();
134 
135   OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L,
136                           DeclarationName Name, QualType Ty,
137                           OMPDeclareReductionDecl *PrevDeclInScope);
138 
setPrevDeclInScope(OMPDeclareReductionDecl * Prev)139   void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) {
140     PrevDeclInScope = Prev;
141   }
142 
143 public:
144   /// Create declare reduction node.
145   static OMPDeclareReductionDecl *
146   Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name,
147          QualType T, OMPDeclareReductionDecl *PrevDeclInScope);
148   /// Create deserialized declare reduction node.
149   static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C,
150                                                      unsigned ID);
151 
152   /// Get combiner expression of the declare reduction construct.
getCombiner()153   Expr *getCombiner() { return Combiner; }
getCombiner()154   const Expr *getCombiner() const { return Combiner; }
155   /// Get In variable of the combiner.
getCombinerIn()156   Expr *getCombinerIn() { return In; }
getCombinerIn()157   const Expr *getCombinerIn() const { return In; }
158   /// Get Out variable of the combiner.
getCombinerOut()159   Expr *getCombinerOut() { return Out; }
getCombinerOut()160   const Expr *getCombinerOut() const { return Out; }
161   /// Set combiner expression for the declare reduction construct.
setCombiner(Expr * E)162   void setCombiner(Expr *E) { Combiner = E; }
163   /// Set combiner In and Out vars.
setCombinerData(Expr * InE,Expr * OutE)164   void setCombinerData(Expr *InE, Expr *OutE) {
165     In = InE;
166     Out = OutE;
167   }
168 
169   /// Get initializer expression (if specified) of the declare reduction
170   /// construct.
getInitializer()171   Expr *getInitializer() { return Initializer; }
getInitializer()172   const Expr *getInitializer() const { return Initializer; }
173   /// Get initializer kind.
getInitializerKind()174   InitKind getInitializerKind() const {
175     return static_cast<InitKind>(OMPDeclareReductionDeclBits.InitializerKind);
176   }
177   /// Get Orig variable of the initializer.
getInitOrig()178   Expr *getInitOrig() { return Orig; }
getInitOrig()179   const Expr *getInitOrig() const { return Orig; }
180   /// Get Priv variable of the initializer.
getInitPriv()181   Expr *getInitPriv() { return Priv; }
getInitPriv()182   const Expr *getInitPriv() const { return Priv; }
183   /// Set initializer expression for the declare reduction construct.
setInitializer(Expr * E,InitKind IK)184   void setInitializer(Expr *E, InitKind IK) {
185     Initializer = E;
186     OMPDeclareReductionDeclBits.InitializerKind = IK;
187   }
188   /// Set initializer Orig and Priv vars.
setInitializerData(Expr * OrigE,Expr * PrivE)189   void setInitializerData(Expr *OrigE, Expr *PrivE) {
190     Orig = OrigE;
191     Priv = PrivE;
192   }
193 
194   /// Get reference to previous declare reduction construct in the same
195   /// scope with the same name.
196   OMPDeclareReductionDecl *getPrevDeclInScope();
197   const OMPDeclareReductionDecl *getPrevDeclInScope() const;
198 
classof(const Decl * D)199   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)200   static bool classofKind(Kind K) { return K == OMPDeclareReduction; }
castToDeclContext(const OMPDeclareReductionDecl * D)201   static DeclContext *castToDeclContext(const OMPDeclareReductionDecl *D) {
202     return static_cast<DeclContext *>(const_cast<OMPDeclareReductionDecl *>(D));
203   }
castFromDeclContext(const DeclContext * DC)204   static OMPDeclareReductionDecl *castFromDeclContext(const DeclContext *DC) {
205     return static_cast<OMPDeclareReductionDecl *>(
206         const_cast<DeclContext *>(DC));
207   }
208 };
209 
210 /// Pseudo declaration for capturing expressions. Also is used for capturing of
211 /// non-static data members in non-static member functions.
212 ///
213 /// Clang supports capturing of variables only, but OpenMP 4.5 allows to
214 /// privatize non-static members of current class in non-static member
215 /// functions. This pseudo-declaration allows properly handle this kind of
216 /// capture by wrapping captured expression into a variable-like declaration.
217 class OMPCapturedExprDecl final : public VarDecl {
218   friend class ASTDeclReader;
219   void anchor() override;
220 
OMPCapturedExprDecl(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,QualType Type,TypeSourceInfo * TInfo,SourceLocation StartLoc)221   OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
222                       QualType Type, TypeSourceInfo *TInfo,
223                       SourceLocation StartLoc)
224       : VarDecl(OMPCapturedExpr, C, DC, StartLoc, StartLoc, Id, Type, TInfo,
225                 SC_None) {
226     setImplicit();
227   }
228 
229 public:
230   static OMPCapturedExprDecl *Create(ASTContext &C, DeclContext *DC,
231                                      IdentifierInfo *Id, QualType T,
232                                      SourceLocation StartLoc);
233 
234   static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, unsigned ID);
235 
236   SourceRange getSourceRange() const override LLVM_READONLY;
237 
238   // Implement isa/cast/dyncast/etc.
classof(const Decl * D)239   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)240   static bool classofKind(Kind K) { return K == OMPCapturedExpr; }
241 };
242 
243 /// This represents '#pragma omp requires...' directive.
244 /// For example
245 ///
246 /// \code
247 /// #pragma omp requires unified_address
248 /// \endcode
249 ///
250 class OMPRequiresDecl final
251     : public Decl,
252       private llvm::TrailingObjects<OMPRequiresDecl, OMPClause *> {
253   friend class ASTDeclReader;
254   friend TrailingObjects;
255 
256   // Number of clauses associated with this requires declaration
257   unsigned NumClauses = 0;
258 
259   virtual void anchor();
260 
OMPRequiresDecl(Kind DK,DeclContext * DC,SourceLocation L)261   OMPRequiresDecl(Kind DK, DeclContext *DC, SourceLocation L)
262       : Decl(DK, DC, L), NumClauses(0) {}
263 
264   /// Returns an array of immutable clauses associated with this requires
265   /// declaration
getClauses()266   ArrayRef<const OMPClause *> getClauses() const {
267     return llvm::makeArrayRef(getTrailingObjects<OMPClause *>(), NumClauses);
268   }
269 
270   /// Returns an array of clauses associated with this requires declaration
getClauses()271   MutableArrayRef<OMPClause *> getClauses() {
272     return MutableArrayRef<OMPClause *>(getTrailingObjects<OMPClause *>(),
273                                         NumClauses);
274   }
275 
276   /// Sets an array of clauses to this requires declaration
277   void setClauses(ArrayRef<OMPClause *> CL);
278 
279 public:
280   /// Create requires node.
281   static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC,
282                                  SourceLocation L, ArrayRef<OMPClause *> CL);
283   /// Create deserialized requires node.
284   static OMPRequiresDecl *CreateDeserialized(ASTContext &C, unsigned ID,
285                                              unsigned N);
286 
287   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
288   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
289   using clauselist_range = llvm::iterator_range<clauselist_iterator>;
290   using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
291 
clauselist_size()292   unsigned clauselist_size() const { return NumClauses; }
clauselist_empty()293   bool clauselist_empty() const { return NumClauses == 0; }
294 
clauselists()295   clauselist_range clauselists() {
296     return clauselist_range(clauselist_begin(), clauselist_end());
297   }
clauselists()298   clauselist_const_range clauselists() const {
299     return clauselist_const_range(clauselist_begin(), clauselist_end());
300   }
clauselist_begin()301   clauselist_iterator clauselist_begin() { return getClauses().begin(); }
clauselist_end()302   clauselist_iterator clauselist_end() { return getClauses().end(); }
clauselist_begin()303   clauselist_const_iterator clauselist_begin() const {
304     return getClauses().begin();
305   }
clauselist_end()306   clauselist_const_iterator clauselist_end() const {
307     return getClauses().end();
308   }
309 
classof(const Decl * D)310   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
classofKind(Kind K)311   static bool classofKind(Kind K) { return K == OMPRequires; }
312 };
313 } // end namespace clang
314 
315 #endif
316