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 25 namespace 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 /// 39 class 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 62 public: 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. 102 class 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. 105 public: 106 enum InitKind { 107 CallInit, // Initialized by function call. 108 DirectInit, // omp_priv(<expr>) 109 CopyInit // omp_priv = <expr> 110 }; 111 112 private: 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 142 public: 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 217 class 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 247 public: 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. 312 class 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 324 public: 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 /// 345 class 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 374 public: 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 /// 422 class 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 469 public: 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