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