Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-10 08:36:33

0001 //===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-==//
0002 //
0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
0004 // See https://llvm.org/LICENSE.txt for license information.
0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
0006 //
0007 //===----------------------------------------------------------------------===//
0008 ///
0009 /// \file
0010 /// This file defines OpenMP nodes for declarative directives.
0011 ///
0012 //===----------------------------------------------------------------------===//
0013 
0014 #ifndef LLVM_CLANG_AST_DECLOPENMP_H
0015 #define LLVM_CLANG_AST_DECLOPENMP_H
0016 
0017 #include "clang/AST/ASTContext.h"
0018 #include "clang/AST/Decl.h"
0019 #include "clang/AST/Expr.h"
0020 #include "clang/AST/ExternalASTSource.h"
0021 #include "clang/AST/OpenMPClause.h"
0022 #include "clang/AST/Type.h"
0023 #include "llvm/ADT/ArrayRef.h"
0024 #include "llvm/Support/TrailingObjects.h"
0025 
0026 namespace clang {
0027 
0028 /// This is a basic class for representing single OpenMP declarative directive.
0029 ///
0030 template <typename U> class OMPDeclarativeDirective : public U {
0031   friend class ASTDeclReader;
0032   friend class ASTDeclWriter;
0033 
0034   /// Get the clauses storage.
0035   MutableArrayRef<OMPClause *> getClauses() {
0036     if (!Data)
0037       return {};
0038     return Data->getClauses();
0039   }
0040 
0041 protected:
0042   /// Data, associated with the directive.
0043   OMPChildren *Data = nullptr;
0044 
0045   /// Build instance of directive.
0046   template <typename... Params>
0047   OMPDeclarativeDirective(Params &&... P) : U(std::forward<Params>(P)...) {}
0048 
0049   template <typename T, typename... Params>
0050   static T *createDirective(const ASTContext &C, DeclContext *DC,
0051                             ArrayRef<OMPClause *> Clauses, unsigned NumChildren,
0052                             Params &&... P) {
0053     auto *Inst = new (C, DC, size(Clauses.size(), NumChildren))
0054         T(DC, std::forward<Params>(P)...);
0055     Inst->Data = OMPChildren::Create(Inst + 1, Clauses,
0056                                      /*AssociatedStmt=*/nullptr, NumChildren);
0057     Inst->Data->setClauses(Clauses);
0058     return Inst;
0059   }
0060 
0061   template <typename T, typename... Params>
0062   static T *createEmptyDirective(const ASTContext &C, GlobalDeclID ID,
0063                                  unsigned NumClauses, unsigned NumChildren,
0064                                  Params &&... P) {
0065     auto *Inst = new (C, ID, size(NumClauses, NumChildren))
0066         T(nullptr, std::forward<Params>(P)...);
0067     Inst->Data = OMPChildren::CreateEmpty(
0068         Inst + 1, NumClauses, /*HasAssociatedStmt=*/false, NumChildren);
0069     return Inst;
0070   }
0071 
0072   static size_t size(unsigned NumClauses, unsigned NumChildren) {
0073     return OMPChildren::size(NumClauses, /*HasAssociatedStmt=*/false,
0074                              NumChildren);
0075   }
0076 
0077 public:
0078   /// Get number of clauses.
0079   unsigned getNumClauses() const {
0080     if (!Data)
0081       return 0;
0082     return Data->getNumClauses();
0083   }
0084 
0085   /// Returns specified clause.
0086   ///
0087   /// \param I Number of clause.
0088   ///
0089   OMPClause *getClause(unsigned I) const { return clauses()[I]; }
0090 
0091   ArrayRef<OMPClause *> clauses() const {
0092     if (!Data)
0093       return {};
0094     return Data->getClauses();
0095   }
0096 };
0097 
0098 /// This represents '#pragma omp threadprivate ...' directive.
0099 /// For example, in the following, both 'a' and 'A::b' are threadprivate:
0100 ///
0101 /// \code
0102 /// int a;
0103 /// #pragma omp threadprivate(a)
0104 /// struct A {
0105 ///   static int b;
0106 /// #pragma omp threadprivate(b)
0107 /// };
0108 /// \endcode
0109 ///
0110 class OMPThreadPrivateDecl final : public OMPDeclarativeDirective<Decl> {
0111   friend class OMPDeclarativeDirective<Decl>;
0112 
0113   virtual void anchor();
0114 
0115   OMPThreadPrivateDecl(DeclContext *DC = nullptr,
0116                        SourceLocation L = SourceLocation())
0117       : OMPDeclarativeDirective<Decl>(OMPThreadPrivate, DC, L) {}
0118 
0119   ArrayRef<const Expr *> getVars() const {
0120     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
0121     return llvm::ArrayRef(Storage, Data->getNumChildren());
0122   }
0123 
0124   MutableArrayRef<Expr *> getVars() {
0125     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
0126     return llvm::MutableArrayRef(Storage, Data->getNumChildren());
0127   }
0128 
0129   void setVars(ArrayRef<Expr *> VL);
0130 
0131 public:
0132   static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC,
0133                                       SourceLocation L,
0134                                       ArrayRef<Expr *> VL);
0135   static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C,
0136                                                   GlobalDeclID ID, unsigned N);
0137 
0138   typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
0139   typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
0140   typedef llvm::iterator_range<varlist_iterator> varlist_range;
0141   typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
0142 
0143   unsigned varlist_size() const { return Data->getNumChildren(); }
0144   bool varlist_empty() const { return Data->getChildren().empty(); }
0145 
0146   varlist_range varlist() {
0147     return varlist_range(varlist_begin(), varlist_end());
0148   }
0149   varlist_const_range varlist() const {
0150     return varlist_const_range(varlist_begin(), varlist_end());
0151   }
0152   varlist_iterator varlist_begin() { return getVars().begin(); }
0153   varlist_iterator varlist_end() { return getVars().end(); }
0154   varlist_const_iterator varlist_begin() const { return getVars().begin(); }
0155   varlist_const_iterator varlist_end() const { return getVars().end(); }
0156 
0157   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
0158   static bool classofKind(Kind K) { return K == OMPThreadPrivate; }
0159 };
0160 
0161 enum class OMPDeclareReductionInitKind {
0162   Call,   // Initialized by function call.
0163   Direct, // omp_priv(<expr>)
0164   Copy    // omp_priv = <expr>
0165 };
0166 
0167 /// This represents '#pragma omp declare reduction ...' directive.
0168 /// For example, in the following, declared reduction 'foo' for types 'int' and
0169 /// 'float':
0170 ///
0171 /// \code
0172 /// #pragma omp declare reduction (foo : int,float : omp_out += omp_in)
0173 ///                     initializer (omp_priv = 0)
0174 /// \endcode
0175 ///
0176 /// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer.
0177 class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext {
0178   // This class stores some data in DeclContext::OMPDeclareReductionDeclBits
0179   // to save some space. Use the provided accessors to access it.
0180 
0181   friend class ASTDeclReader;
0182   /// Combiner for declare reduction construct.
0183   Expr *Combiner = nullptr;
0184   /// Initializer for declare reduction construct.
0185   Expr *Initializer = nullptr;
0186   /// In parameter of the combiner.
0187   Expr *In = nullptr;
0188   /// Out parameter of the combiner.
0189   Expr *Out = nullptr;
0190   /// Priv parameter of the initializer.
0191   Expr *Priv = nullptr;
0192   /// Orig parameter of the initializer.
0193   Expr *Orig = nullptr;
0194 
0195   /// Reference to the previous declare reduction construct in the same
0196   /// scope with the same name. Required for proper templates instantiation if
0197   /// the declare reduction construct is declared inside compound statement.
0198   LazyDeclPtr PrevDeclInScope;
0199 
0200   void anchor() override;
0201 
0202   OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L,
0203                           DeclarationName Name, QualType Ty,
0204                           OMPDeclareReductionDecl *PrevDeclInScope);
0205 
0206   void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) {
0207     PrevDeclInScope = Prev;
0208   }
0209 
0210 public:
0211   /// Create declare reduction node.
0212   static OMPDeclareReductionDecl *
0213   Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name,
0214          QualType T, OMPDeclareReductionDecl *PrevDeclInScope);
0215   /// Create deserialized declare reduction node.
0216   static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C,
0217                                                      GlobalDeclID ID);
0218 
0219   /// Get combiner expression of the declare reduction construct.
0220   Expr *getCombiner() { return Combiner; }
0221   const Expr *getCombiner() const { return Combiner; }
0222   /// Get In variable of the combiner.
0223   Expr *getCombinerIn() { return In; }
0224   const Expr *getCombinerIn() const { return In; }
0225   /// Get Out variable of the combiner.
0226   Expr *getCombinerOut() { return Out; }
0227   const Expr *getCombinerOut() const { return Out; }
0228   /// Set combiner expression for the declare reduction construct.
0229   void setCombiner(Expr *E) { Combiner = E; }
0230   /// Set combiner In and Out vars.
0231   void setCombinerData(Expr *InE, Expr *OutE) {
0232     In = InE;
0233     Out = OutE;
0234   }
0235 
0236   /// Get initializer expression (if specified) of the declare reduction
0237   /// construct.
0238   Expr *getInitializer() { return Initializer; }
0239   const Expr *getInitializer() const { return Initializer; }
0240   /// Get initializer kind.
0241   OMPDeclareReductionInitKind getInitializerKind() const {
0242     return static_cast<OMPDeclareReductionInitKind>(
0243         OMPDeclareReductionDeclBits.InitializerKind);
0244   }
0245   /// Get Orig variable of the initializer.
0246   Expr *getInitOrig() { return Orig; }
0247   const Expr *getInitOrig() const { return Orig; }
0248   /// Get Priv variable of the initializer.
0249   Expr *getInitPriv() { return Priv; }
0250   const Expr *getInitPriv() const { return Priv; }
0251   /// Set initializer expression for the declare reduction construct.
0252   void setInitializer(Expr *E, OMPDeclareReductionInitKind IK) {
0253     Initializer = E;
0254     OMPDeclareReductionDeclBits.InitializerKind = llvm::to_underlying(IK);
0255   }
0256   /// Set initializer Orig and Priv vars.
0257   void setInitializerData(Expr *OrigE, Expr *PrivE) {
0258     Orig = OrigE;
0259     Priv = PrivE;
0260   }
0261 
0262   /// Get reference to previous declare reduction construct in the same
0263   /// scope with the same name.
0264   OMPDeclareReductionDecl *getPrevDeclInScope();
0265   const OMPDeclareReductionDecl *getPrevDeclInScope() const;
0266 
0267   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
0268   static bool classofKind(Kind K) { return K == OMPDeclareReduction; }
0269   static DeclContext *castToDeclContext(const OMPDeclareReductionDecl *D) {
0270     return static_cast<DeclContext *>(const_cast<OMPDeclareReductionDecl *>(D));
0271   }
0272   static OMPDeclareReductionDecl *castFromDeclContext(const DeclContext *DC) {
0273     return static_cast<OMPDeclareReductionDecl *>(
0274         const_cast<DeclContext *>(DC));
0275   }
0276 };
0277 
0278 /// This represents '#pragma omp declare mapper ...' directive. Map clauses are
0279 /// allowed to use with this directive. The following example declares a user
0280 /// defined mapper for the type 'struct vec'. This example instructs the fields
0281 /// 'len' and 'data' should be mapped when mapping instances of 'struct vec'.
0282 ///
0283 /// \code
0284 /// #pragma omp declare mapper(mid: struct vec v) map(v.len, v.data[0:N])
0285 /// \endcode
0286 class OMPDeclareMapperDecl final : public OMPDeclarativeDirective<ValueDecl>,
0287                                    public DeclContext {
0288   friend class OMPDeclarativeDirective<ValueDecl>;
0289   friend class ASTDeclReader;
0290   friend class ASTDeclWriter;
0291 
0292   /// Mapper variable, which is 'v' in the example above
0293   Expr *MapperVarRef = nullptr;
0294 
0295   /// Name of the mapper variable
0296   DeclarationName VarName;
0297 
0298   LazyDeclPtr PrevDeclInScope;
0299 
0300   void anchor() override;
0301 
0302   OMPDeclareMapperDecl(DeclContext *DC, SourceLocation L, DeclarationName Name,
0303                        QualType Ty, DeclarationName VarName,
0304                        OMPDeclareMapperDecl *PrevDeclInScope)
0305       : OMPDeclarativeDirective<ValueDecl>(OMPDeclareMapper, DC, L, Name, Ty),
0306         DeclContext(OMPDeclareMapper), VarName(VarName),
0307         PrevDeclInScope(PrevDeclInScope) {}
0308 
0309   void setPrevDeclInScope(OMPDeclareMapperDecl *Prev) {
0310     PrevDeclInScope = Prev;
0311   }
0312 
0313 public:
0314   /// Creates declare mapper node.
0315   static OMPDeclareMapperDecl *Create(ASTContext &C, DeclContext *DC,
0316                                       SourceLocation L, DeclarationName Name,
0317                                       QualType T, DeclarationName VarName,
0318                                       ArrayRef<OMPClause *> Clauses,
0319                                       OMPDeclareMapperDecl *PrevDeclInScope);
0320   /// Creates deserialized declare mapper node.
0321   static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C,
0322                                                   GlobalDeclID ID, unsigned N);
0323 
0324   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
0325   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
0326   using clauselist_range = llvm::iterator_range<clauselist_iterator>;
0327   using clauselist_const_range =
0328       llvm::iterator_range<clauselist_const_iterator>;
0329 
0330   unsigned clauselist_size() const { return Data->getNumClauses(); }
0331   bool clauselist_empty() const { return Data->getClauses().empty(); }
0332 
0333   clauselist_range clauselists() {
0334     return clauselist_range(clauselist_begin(), clauselist_end());
0335   }
0336   clauselist_const_range clauselists() const {
0337     return clauselist_const_range(clauselist_begin(), clauselist_end());
0338   }
0339   clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
0340   clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
0341   clauselist_const_iterator clauselist_begin() const {
0342     return Data->getClauses().begin();
0343   }
0344   clauselist_const_iterator clauselist_end() const {
0345     return Data->getClauses().end();
0346   }
0347 
0348   /// Get the variable declared in the mapper
0349   Expr *getMapperVarRef() { return cast_or_null<Expr>(Data->getChildren()[0]); }
0350   const Expr *getMapperVarRef() const {
0351     return cast_or_null<Expr>(Data->getChildren()[0]);
0352   }
0353   /// Set the variable declared in the mapper
0354   void setMapperVarRef(Expr *MapperVarRefE) {
0355     Data->getChildren()[0] = MapperVarRefE;
0356   }
0357 
0358   /// Get the name of the variable declared in the mapper
0359   DeclarationName getVarName() { return VarName; }
0360 
0361   /// Get reference to previous declare mapper construct in the same
0362   /// scope with the same name.
0363   OMPDeclareMapperDecl *getPrevDeclInScope();
0364   const OMPDeclareMapperDecl *getPrevDeclInScope() const;
0365 
0366   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
0367   static bool classofKind(Kind K) { return K == OMPDeclareMapper; }
0368   static DeclContext *castToDeclContext(const OMPDeclareMapperDecl *D) {
0369     return static_cast<DeclContext *>(const_cast<OMPDeclareMapperDecl *>(D));
0370   }
0371   static OMPDeclareMapperDecl *castFromDeclContext(const DeclContext *DC) {
0372     return static_cast<OMPDeclareMapperDecl *>(const_cast<DeclContext *>(DC));
0373   }
0374 };
0375 
0376 /// Pseudo declaration for capturing expressions. Also is used for capturing of
0377 /// non-static data members in non-static member functions.
0378 ///
0379 /// Clang supports capturing of variables only, but OpenMP 4.5 allows to
0380 /// privatize non-static members of current class in non-static member
0381 /// functions. This pseudo-declaration allows properly handle this kind of
0382 /// capture by wrapping captured expression into a variable-like declaration.
0383 class OMPCapturedExprDecl final : public VarDecl {
0384   friend class ASTDeclReader;
0385   void anchor() override;
0386 
0387   OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id,
0388                       QualType Type, TypeSourceInfo *TInfo,
0389                       SourceLocation StartLoc)
0390       : VarDecl(OMPCapturedExpr, C, DC, StartLoc, StartLoc, Id, Type, TInfo,
0391                 SC_None) {
0392     setImplicit();
0393   }
0394 
0395 public:
0396   static OMPCapturedExprDecl *Create(ASTContext &C, DeclContext *DC,
0397                                      IdentifierInfo *Id, QualType T,
0398                                      SourceLocation StartLoc);
0399 
0400   static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C,
0401                                                  GlobalDeclID ID);
0402 
0403   SourceRange getSourceRange() const override LLVM_READONLY;
0404 
0405   // Implement isa/cast/dyncast/etc.
0406   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
0407   static bool classofKind(Kind K) { return K == OMPCapturedExpr; }
0408 };
0409 
0410 /// This represents '#pragma omp requires...' directive.
0411 /// For example
0412 ///
0413 /// \code
0414 /// #pragma omp requires unified_address
0415 /// \endcode
0416 ///
0417 class OMPRequiresDecl final : public OMPDeclarativeDirective<Decl> {
0418   friend class OMPDeclarativeDirective<Decl>;
0419   friend class ASTDeclReader;
0420 
0421   virtual void anchor();
0422 
0423   OMPRequiresDecl(DeclContext *DC, SourceLocation L)
0424       : OMPDeclarativeDirective<Decl>(OMPRequires, DC, L) {}
0425 
0426 public:
0427   /// Create requires node.
0428   static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC,
0429                                  SourceLocation L, ArrayRef<OMPClause *> CL);
0430   /// Create deserialized requires node.
0431   static OMPRequiresDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
0432                                              unsigned N);
0433 
0434   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
0435   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
0436   using clauselist_range = llvm::iterator_range<clauselist_iterator>;
0437   using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
0438 
0439   unsigned clauselist_size() const { return Data->getNumClauses(); }
0440   bool clauselist_empty() const { return Data->getClauses().empty(); }
0441 
0442   clauselist_range clauselists() {
0443     return clauselist_range(clauselist_begin(), clauselist_end());
0444   }
0445   clauselist_const_range clauselists() const {
0446     return clauselist_const_range(clauselist_begin(), clauselist_end());
0447   }
0448   clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
0449   clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
0450   clauselist_const_iterator clauselist_begin() const {
0451     return Data->getClauses().begin();
0452   }
0453   clauselist_const_iterator clauselist_end() const {
0454     return Data->getClauses().end();
0455   }
0456 
0457   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
0458   static bool classofKind(Kind K) { return K == OMPRequires; }
0459 };
0460 
0461 /// This represents '#pragma omp allocate ...' directive.
0462 /// For example, in the following, the default allocator is used for both 'a'
0463 /// and 'A::b':
0464 ///
0465 /// \code
0466 /// int a;
0467 /// #pragma omp allocate(a)
0468 /// struct A {
0469 ///   static int b;
0470 /// #pragma omp allocate(b)
0471 /// };
0472 /// \endcode
0473 ///
0474 class OMPAllocateDecl final : public OMPDeclarativeDirective<Decl> {
0475   friend class OMPDeclarativeDirective<Decl>;
0476   friend class ASTDeclReader;
0477 
0478   virtual void anchor();
0479 
0480   OMPAllocateDecl(DeclContext *DC, SourceLocation L)
0481       : OMPDeclarativeDirective<Decl>(OMPAllocate, DC, L) {}
0482 
0483   ArrayRef<const Expr *> getVars() const {
0484     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
0485     return llvm::ArrayRef(Storage, Data->getNumChildren());
0486   }
0487 
0488   MutableArrayRef<Expr *> getVars() {
0489     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data());
0490     return llvm::MutableArrayRef(Storage, Data->getNumChildren());
0491   }
0492 
0493   void setVars(ArrayRef<Expr *> VL);
0494 
0495 public:
0496   static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC,
0497                                  SourceLocation L, ArrayRef<Expr *> VL,
0498                                  ArrayRef<OMPClause *> CL);
0499   static OMPAllocateDecl *CreateDeserialized(ASTContext &C, GlobalDeclID ID,
0500                                              unsigned NVars, unsigned NClauses);
0501 
0502   typedef MutableArrayRef<Expr *>::iterator varlist_iterator;
0503   typedef ArrayRef<const Expr *>::iterator varlist_const_iterator;
0504   typedef llvm::iterator_range<varlist_iterator> varlist_range;
0505   typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range;
0506   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator;
0507   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator;
0508   using clauselist_range = llvm::iterator_range<clauselist_iterator>;
0509   using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>;
0510 
0511   unsigned varlist_size() const { return Data->getNumChildren(); }
0512   bool varlist_empty() const { return Data->getChildren().empty(); }
0513   unsigned clauselist_size() const { return Data->getNumClauses(); }
0514   bool clauselist_empty() const { return Data->getClauses().empty(); }
0515 
0516   varlist_range varlist() {
0517     return varlist_range(varlist_begin(), varlist_end());
0518   }
0519   varlist_const_range varlist() const {
0520     return varlist_const_range(varlist_begin(), varlist_end());
0521   }
0522   varlist_iterator varlist_begin() { return getVars().begin(); }
0523   varlist_iterator varlist_end() { return getVars().end(); }
0524   varlist_const_iterator varlist_begin() const { return getVars().begin(); }
0525   varlist_const_iterator varlist_end() const { return getVars().end(); }
0526 
0527   clauselist_range clauselists() {
0528     return clauselist_range(clauselist_begin(), clauselist_end());
0529   }
0530   clauselist_const_range clauselists() const {
0531     return clauselist_const_range(clauselist_begin(), clauselist_end());
0532   }
0533   clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); }
0534   clauselist_iterator clauselist_end() { return Data->getClauses().end(); }
0535   clauselist_const_iterator clauselist_begin() const {
0536     return Data->getClauses().begin();
0537   }
0538   clauselist_const_iterator clauselist_end() const {
0539     return Data->getClauses().end();
0540   }
0541 
0542   static bool classof(const Decl *D) { return classofKind(D->getKind()); }
0543   static bool classofKind(Kind K) { return K == OMPAllocate; }
0544 };
0545 
0546 } // end namespace clang
0547 
0548 #endif