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