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 26 namespace clang { 27 28 /// This is a basic class for representing single OpenMP declarative directive. 29 /// 30 template <typename U> class OMPDeclarativeDirective : public U { 31 friend class ASTDeclReader; 32 friend class ASTDeclWriter; 33 34 /// Get the clauses storage. getClauses()35 MutableArrayRef<OMPClause *> getClauses() { 36 if (!Data) 37 return std::nullopt; 38 return Data->getClauses(); 39 } 40 41 protected: 42 /// Data, associated with the directive. 43 OMPChildren *Data = nullptr; 44 45 /// Build instance of directive. 46 template <typename... Params> OMPDeclarativeDirective(Params &&...P)47 OMPDeclarativeDirective(Params &&... P) : U(std::forward<Params>(P)...) {} 48 49 template <typename T, typename... Params> createDirective(const ASTContext & C,DeclContext * DC,ArrayRef<OMPClause * > Clauses,unsigned NumChildren,Params &&...P)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> createEmptyDirective(const ASTContext & C,GlobalDeclID ID,unsigned NumClauses,unsigned NumChildren,Params &&...P)62 static T *createEmptyDirective(const ASTContext &C, GlobalDeclID 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 size(unsigned NumClauses,unsigned NumChildren)72 static size_t size(unsigned NumClauses, unsigned NumChildren) { 73 return OMPChildren::size(NumClauses, /*HasAssociatedStmt=*/false, 74 NumChildren); 75 } 76 77 public: 78 /// Get number of clauses. getNumClauses()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 /// getClause(unsigned I)89 OMPClause *getClause(unsigned I) const { return clauses()[I]; } 90 clauses()91 ArrayRef<OMPClause *> clauses() const { 92 if (!Data) 93 return std::nullopt; 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 /// 110 class 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 getVars()119 ArrayRef<const Expr *> getVars() const { 120 auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); 121 return llvm::ArrayRef(Storage, Data->getNumChildren()); 122 } 123 getVars()124 MutableArrayRef<Expr *> getVars() { 125 auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); 126 return llvm::MutableArrayRef(Storage, Data->getNumChildren()); 127 } 128 129 void setVars(ArrayRef<Expr *> VL); 130 131 public: 132 static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC, 133 SourceLocation L, 134 ArrayRef<Expr *> VL); 135 static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, 136 GlobalDeclID 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 varlist_size()143 unsigned varlist_size() const { return Data->getNumChildren(); } varlist_empty()144 bool varlist_empty() const { return Data->getChildren().empty(); } 145 varlists()146 varlist_range varlists() { 147 return varlist_range(varlist_begin(), varlist_end()); 148 } varlists()149 varlist_const_range varlists() const { 150 return varlist_const_range(varlist_begin(), varlist_end()); 151 } varlist_begin()152 varlist_iterator varlist_begin() { return getVars().begin(); } varlist_end()153 varlist_iterator varlist_end() { return getVars().end(); } varlist_begin()154 varlist_const_iterator varlist_begin() const { return getVars().begin(); } varlist_end()155 varlist_const_iterator varlist_end() const { return getVars().end(); } 156 classof(const Decl * D)157 static bool classof(const Decl *D) { return classofKind(D->getKind()); } classofKind(Kind K)158 static bool classofKind(Kind K) { return K == OMPThreadPrivate; } 159 }; 160 161 enum class OMPDeclareReductionInitKind { 162 Call, // Initialized by function call. 163 Direct, // omp_priv(<expr>) 164 Copy // omp_priv = <expr> 165 }; 166 167 /// This represents '#pragma omp declare reduction ...' directive. 168 /// For example, in the following, declared reduction 'foo' for types 'int' and 169 /// 'float': 170 /// 171 /// \code 172 /// #pragma omp declare reduction (foo : int,float : omp_out += omp_in) 173 /// initializer (omp_priv = 0) 174 /// \endcode 175 /// 176 /// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer. 177 class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext { 178 // This class stores some data in DeclContext::OMPDeclareReductionDeclBits 179 // to save some space. Use the provided accessors to access it. 180 181 friend class ASTDeclReader; 182 /// Combiner for declare reduction construct. 183 Expr *Combiner = nullptr; 184 /// Initializer for declare reduction construct. 185 Expr *Initializer = nullptr; 186 /// In parameter of the combiner. 187 Expr *In = nullptr; 188 /// Out parameter of the combiner. 189 Expr *Out = nullptr; 190 /// Priv parameter of the initializer. 191 Expr *Priv = nullptr; 192 /// Orig parameter of the initializer. 193 Expr *Orig = nullptr; 194 195 /// Reference to the previous declare reduction construct in the same 196 /// scope with the same name. Required for proper templates instantiation if 197 /// the declare reduction construct is declared inside compound statement. 198 LazyDeclPtr PrevDeclInScope; 199 200 void anchor() override; 201 202 OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L, 203 DeclarationName Name, QualType Ty, 204 OMPDeclareReductionDecl *PrevDeclInScope); 205 setPrevDeclInScope(OMPDeclareReductionDecl * Prev)206 void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) { 207 PrevDeclInScope = Prev; 208 } 209 210 public: 211 /// Create declare reduction node. 212 static OMPDeclareReductionDecl * 213 Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, 214 QualType T, OMPDeclareReductionDecl *PrevDeclInScope); 215 /// Create deserialized declare reduction node. 216 static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C, 217 GlobalDeclID ID); 218 219 /// Get combiner expression of the declare reduction construct. getCombiner()220 Expr *getCombiner() { return Combiner; } getCombiner()221 const Expr *getCombiner() const { return Combiner; } 222 /// Get In variable of the combiner. getCombinerIn()223 Expr *getCombinerIn() { return In; } getCombinerIn()224 const Expr *getCombinerIn() const { return In; } 225 /// Get Out variable of the combiner. getCombinerOut()226 Expr *getCombinerOut() { return Out; } getCombinerOut()227 const Expr *getCombinerOut() const { return Out; } 228 /// Set combiner expression for the declare reduction construct. setCombiner(Expr * E)229 void setCombiner(Expr *E) { Combiner = E; } 230 /// Set combiner In and Out vars. setCombinerData(Expr * InE,Expr * OutE)231 void setCombinerData(Expr *InE, Expr *OutE) { 232 In = InE; 233 Out = OutE; 234 } 235 236 /// Get initializer expression (if specified) of the declare reduction 237 /// construct. getInitializer()238 Expr *getInitializer() { return Initializer; } getInitializer()239 const Expr *getInitializer() const { return Initializer; } 240 /// Get initializer kind. getInitializerKind()241 OMPDeclareReductionInitKind getInitializerKind() const { 242 return static_cast<OMPDeclareReductionInitKind>( 243 OMPDeclareReductionDeclBits.InitializerKind); 244 } 245 /// Get Orig variable of the initializer. getInitOrig()246 Expr *getInitOrig() { return Orig; } getInitOrig()247 const Expr *getInitOrig() const { return Orig; } 248 /// Get Priv variable of the initializer. getInitPriv()249 Expr *getInitPriv() { return Priv; } getInitPriv()250 const Expr *getInitPriv() const { return Priv; } 251 /// Set initializer expression for the declare reduction construct. setInitializer(Expr * E,OMPDeclareReductionInitKind IK)252 void setInitializer(Expr *E, OMPDeclareReductionInitKind IK) { 253 Initializer = E; 254 OMPDeclareReductionDeclBits.InitializerKind = llvm::to_underlying(IK); 255 } 256 /// Set initializer Orig and Priv vars. setInitializerData(Expr * OrigE,Expr * PrivE)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 classof(const Decl * D)267 static bool classof(const Decl *D) { return classofKind(D->getKind()); } classofKind(Kind K)268 static bool classofKind(Kind K) { return K == OMPDeclareReduction; } castToDeclContext(const OMPDeclareReductionDecl * D)269 static DeclContext *castToDeclContext(const OMPDeclareReductionDecl *D) { 270 return static_cast<DeclContext *>(const_cast<OMPDeclareReductionDecl *>(D)); 271 } castFromDeclContext(const DeclContext * DC)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 286 class 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 OMPDeclareMapperDecl(DeclContext * DC,SourceLocation L,DeclarationName Name,QualType Ty,DeclarationName VarName,OMPDeclareMapperDecl * PrevDeclInScope)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 setPrevDeclInScope(OMPDeclareMapperDecl * Prev)309 void setPrevDeclInScope(OMPDeclareMapperDecl *Prev) { 310 PrevDeclInScope = Prev; 311 } 312 313 public: 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, 322 GlobalDeclID ID, 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 clauselist_size()330 unsigned clauselist_size() const { return Data->getNumClauses(); } clauselist_empty()331 bool clauselist_empty() const { return Data->getClauses().empty(); } 332 clauselists()333 clauselist_range clauselists() { 334 return clauselist_range(clauselist_begin(), clauselist_end()); 335 } clauselists()336 clauselist_const_range clauselists() const { 337 return clauselist_const_range(clauselist_begin(), clauselist_end()); 338 } clauselist_begin()339 clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); } clauselist_end()340 clauselist_iterator clauselist_end() { return Data->getClauses().end(); } clauselist_begin()341 clauselist_const_iterator clauselist_begin() const { 342 return Data->getClauses().begin(); 343 } clauselist_end()344 clauselist_const_iterator clauselist_end() const { 345 return Data->getClauses().end(); 346 } 347 348 /// Get the variable declared in the mapper getMapperVarRef()349 Expr *getMapperVarRef() { return cast_or_null<Expr>(Data->getChildren()[0]); } getMapperVarRef()350 const Expr *getMapperVarRef() const { 351 return cast_or_null<Expr>(Data->getChildren()[0]); 352 } 353 /// Set the variable declared in the mapper setMapperVarRef(Expr * MapperVarRefE)354 void setMapperVarRef(Expr *MapperVarRefE) { 355 Data->getChildren()[0] = MapperVarRefE; 356 } 357 358 /// Get the name of the variable declared in the mapper getVarName()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 classof(const Decl * D)366 static bool classof(const Decl *D) { return classofKind(D->getKind()); } classofKind(Kind K)367 static bool classofKind(Kind K) { return K == OMPDeclareMapper; } castToDeclContext(const OMPDeclareMapperDecl * D)368 static DeclContext *castToDeclContext(const OMPDeclareMapperDecl *D) { 369 return static_cast<DeclContext *>(const_cast<OMPDeclareMapperDecl *>(D)); 370 } castFromDeclContext(const DeclContext * DC)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. 383 class OMPCapturedExprDecl final : public VarDecl { 384 friend class ASTDeclReader; 385 void anchor() override; 386 OMPCapturedExprDecl(ASTContext & C,DeclContext * DC,IdentifierInfo * Id,QualType Type,TypeSourceInfo * TInfo,SourceLocation StartLoc)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 395 public: 396 static OMPCapturedExprDecl *Create(ASTContext &C, DeclContext *DC, 397 IdentifierInfo *Id, QualType T, 398 SourceLocation StartLoc); 399 400 static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, 401 GlobalDeclID ID); 402 403 SourceRange getSourceRange() const override LLVM_READONLY; 404 405 // Implement isa/cast/dyncast/etc. classof(const Decl * D)406 static bool classof(const Decl *D) { return classofKind(D->getKind()); } classofKind(Kind K)407 static bool classofKind(Kind K) { return K == OMPCapturedExpr; } 408 }; 409 410 /// This represents '#pragma omp requires...' directive. 411 /// For example 412 /// 413 /// \code 414 /// #pragma omp requires unified_address 415 /// \endcode 416 /// 417 class OMPRequiresDecl final : public OMPDeclarativeDirective<Decl> { 418 friend class OMPDeclarativeDirective<Decl>; 419 friend class ASTDeclReader; 420 421 virtual void anchor(); 422 OMPRequiresDecl(DeclContext * DC,SourceLocation L)423 OMPRequiresDecl(DeclContext *DC, SourceLocation L) 424 : OMPDeclarativeDirective<Decl>(OMPRequires, DC, L) {} 425 426 public: 427 /// Create requires node. 428 static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC, 429 SourceLocation L, ArrayRef<OMPClause *> CL); 430 /// Create deserialized requires node. 431 static OMPRequiresDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID, 432 unsigned N); 433 434 using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator; 435 using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator; 436 using clauselist_range = llvm::iterator_range<clauselist_iterator>; 437 using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>; 438 clauselist_size()439 unsigned clauselist_size() const { return Data->getNumClauses(); } clauselist_empty()440 bool clauselist_empty() const { return Data->getClauses().empty(); } 441 clauselists()442 clauselist_range clauselists() { 443 return clauselist_range(clauselist_begin(), clauselist_end()); 444 } clauselists()445 clauselist_const_range clauselists() const { 446 return clauselist_const_range(clauselist_begin(), clauselist_end()); 447 } clauselist_begin()448 clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); } clauselist_end()449 clauselist_iterator clauselist_end() { return Data->getClauses().end(); } clauselist_begin()450 clauselist_const_iterator clauselist_begin() const { 451 return Data->getClauses().begin(); 452 } clauselist_end()453 clauselist_const_iterator clauselist_end() const { 454 return Data->getClauses().end(); 455 } 456 classof(const Decl * D)457 static bool classof(const Decl *D) { return classofKind(D->getKind()); } classofKind(Kind K)458 static bool classofKind(Kind K) { return K == OMPRequires; } 459 }; 460 461 /// This represents '#pragma omp allocate ...' directive. 462 /// For example, in the following, the default allocator is used for both 'a' 463 /// and 'A::b': 464 /// 465 /// \code 466 /// int a; 467 /// #pragma omp allocate(a) 468 /// struct A { 469 /// static int b; 470 /// #pragma omp allocate(b) 471 /// }; 472 /// \endcode 473 /// 474 class OMPAllocateDecl final : public OMPDeclarativeDirective<Decl> { 475 friend class OMPDeclarativeDirective<Decl>; 476 friend class ASTDeclReader; 477 478 virtual void anchor(); 479 OMPAllocateDecl(DeclContext * DC,SourceLocation L)480 OMPAllocateDecl(DeclContext *DC, SourceLocation L) 481 : OMPDeclarativeDirective<Decl>(OMPAllocate, DC, L) {} 482 getVars()483 ArrayRef<const Expr *> getVars() const { 484 auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); 485 return llvm::ArrayRef(Storage, Data->getNumChildren()); 486 } 487 getVars()488 MutableArrayRef<Expr *> getVars() { 489 auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); 490 return llvm::MutableArrayRef(Storage, Data->getNumChildren()); 491 } 492 493 void setVars(ArrayRef<Expr *> VL); 494 495 public: 496 static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC, 497 SourceLocation L, ArrayRef<Expr *> VL, 498 ArrayRef<OMPClause *> CL); 499 static OMPAllocateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID, 500 unsigned NVars, unsigned NClauses); 501 502 typedef MutableArrayRef<Expr *>::iterator varlist_iterator; 503 typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; 504 typedef llvm::iterator_range<varlist_iterator> varlist_range; 505 typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; 506 using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator; 507 using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator; 508 using clauselist_range = llvm::iterator_range<clauselist_iterator>; 509 using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>; 510 varlist_size()511 unsigned varlist_size() const { return Data->getNumChildren(); } varlist_empty()512 bool varlist_empty() const { return Data->getChildren().empty(); } clauselist_size()513 unsigned clauselist_size() const { return Data->getNumClauses(); } clauselist_empty()514 bool clauselist_empty() const { return Data->getClauses().empty(); } 515 varlists()516 varlist_range varlists() { 517 return varlist_range(varlist_begin(), varlist_end()); 518 } varlists()519 varlist_const_range varlists() const { 520 return varlist_const_range(varlist_begin(), varlist_end()); 521 } varlist_begin()522 varlist_iterator varlist_begin() { return getVars().begin(); } varlist_end()523 varlist_iterator varlist_end() { return getVars().end(); } varlist_begin()524 varlist_const_iterator varlist_begin() const { return getVars().begin(); } varlist_end()525 varlist_const_iterator varlist_end() const { return getVars().end(); } 526 clauselists()527 clauselist_range clauselists() { 528 return clauselist_range(clauselist_begin(), clauselist_end()); 529 } clauselists()530 clauselist_const_range clauselists() const { 531 return clauselist_const_range(clauselist_begin(), clauselist_end()); 532 } clauselist_begin()533 clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); } clauselist_end()534 clauselist_iterator clauselist_end() { return Data->getClauses().end(); } clauselist_begin()535 clauselist_const_iterator clauselist_begin() const { 536 return Data->getClauses().begin(); 537 } clauselist_end()538 clauselist_const_iterator clauselist_end() const { 539 return Data->getClauses().end(); 540 } 541 classof(const Decl * D)542 static bool classof(const Decl *D) { return classofKind(D->getKind()); } classofKind(Kind K)543 static bool classofKind(Kind K) { return K == OMPAllocate; } 544 }; 545 546 } // end namespace clang 547 548 #endif 549