- //===- DeclOpenMP.h - Classes for representing OpenMP directives -*- C++ -*-===// 
- // 
- // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 
- // See https://llvm.org/LICENSE.txt for license information. 
- // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 
- // 
- //===----------------------------------------------------------------------===// 
- /// 
- /// \file 
- /// This file defines OpenMP nodes for declarative directives. 
- /// 
- //===----------------------------------------------------------------------===// 
-   
- #ifndef LLVM_CLANG_AST_DECLOPENMP_H 
- #define LLVM_CLANG_AST_DECLOPENMP_H 
-   
- #include "clang/AST/ASTContext.h" 
- #include "clang/AST/Decl.h" 
- #include "clang/AST/Expr.h" 
- #include "clang/AST/ExternalASTSource.h" 
- #include "clang/AST/OpenMPClause.h" 
- #include "clang/AST/Type.h" 
- #include "llvm/ADT/ArrayRef.h" 
- #include "llvm/Support/TrailingObjects.h" 
-   
- namespace clang { 
-   
- /// This is a basic class for representing single OpenMP declarative directive. 
- /// 
- template <typename U> class OMPDeclarativeDirective : public U { 
-   friend class ASTDeclReader; 
-   friend class ASTDeclWriter; 
-   
-   /// Get the clauses storage. 
-   MutableArrayRef<OMPClause *> getClauses() { 
-     if (!Data) 
-       return std::nullopt; 
-     return Data->getClauses(); 
-   } 
-   
- protected: 
-   /// Data, associated with the directive. 
-   OMPChildren *Data = nullptr; 
-   
-   /// Build instance of directive. 
-   template <typename... Params> 
-   OMPDeclarativeDirective(Params &&... P) : U(std::forward<Params>(P)...) {} 
-   
-   template <typename T, typename... Params> 
-   static T *createDirective(const ASTContext &C, DeclContext *DC, 
-                             ArrayRef<OMPClause *> Clauses, unsigned NumChildren, 
-                             Params &&... P) { 
-     auto *Inst = new (C, DC, size(Clauses.size(), NumChildren)) 
-         T(DC, std::forward<Params>(P)...); 
-     Inst->Data = OMPChildren::Create(Inst + 1, Clauses, 
-                                      /*AssociatedStmt=*/nullptr, NumChildren); 
-     Inst->Data->setClauses(Clauses); 
-     return Inst; 
-   } 
-   
-   template <typename T, typename... Params> 
-   static T *createEmptyDirective(const ASTContext &C, unsigned ID, 
-                                  unsigned NumClauses, unsigned NumChildren, 
-                                  Params &&... P) { 
-     auto *Inst = new (C, ID, size(NumClauses, NumChildren)) 
-         T(nullptr, std::forward<Params>(P)...); 
-     Inst->Data = OMPChildren::CreateEmpty( 
-         Inst + 1, NumClauses, /*HasAssociatedStmt=*/false, NumChildren); 
-     return Inst; 
-   } 
-   
-   static size_t size(unsigned NumClauses, unsigned NumChildren) { 
-     return OMPChildren::size(NumClauses, /*HasAssociatedStmt=*/false, 
-                              NumChildren); 
-   } 
-   
- public: 
-   /// Get number of clauses. 
-   unsigned getNumClauses() const { 
-     if (!Data) 
-       return 0; 
-     return Data->getNumClauses(); 
-   } 
-   
-   /// Returns specified clause. 
-   /// 
-   /// \param I Number of clause. 
-   /// 
-   OMPClause *getClause(unsigned I) const { return clauses()[I]; } 
-   
-   ArrayRef<OMPClause *> clauses() const { 
-     if (!Data) 
-       return std::nullopt; 
-     return Data->getClauses(); 
-   } 
- }; 
-   
- /// This represents '#pragma omp threadprivate ...' directive. 
- /// For example, in the following, both 'a' and 'A::b' are threadprivate: 
- /// 
- /// \code 
- /// int a; 
- /// #pragma omp threadprivate(a) 
- /// struct A { 
- ///   static int b; 
- /// #pragma omp threadprivate(b) 
- /// }; 
- /// \endcode 
- /// 
- class OMPThreadPrivateDecl final : public OMPDeclarativeDirective<Decl> { 
-   friend class OMPDeclarativeDirective<Decl>; 
-   
-   virtual void anchor(); 
-   
-   OMPThreadPrivateDecl(DeclContext *DC = nullptr, 
-                        SourceLocation L = SourceLocation()) 
-       : OMPDeclarativeDirective<Decl>(OMPThreadPrivate, DC, L) {} 
-   
-   ArrayRef<const Expr *> getVars() const { 
-     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); 
-     return llvm::ArrayRef(Storage, Data->getNumChildren()); 
-   } 
-   
-   MutableArrayRef<Expr *> getVars() { 
-     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); 
-     return llvm::MutableArrayRef(Storage, Data->getNumChildren()); 
-   } 
-   
-   void setVars(ArrayRef<Expr *> VL); 
-   
- public: 
-   static OMPThreadPrivateDecl *Create(ASTContext &C, DeclContext *DC, 
-                                       SourceLocation L, 
-                                       ArrayRef<Expr *> VL); 
-   static OMPThreadPrivateDecl *CreateDeserialized(ASTContext &C, 
-                                                   unsigned ID, unsigned N); 
-   
-   typedef MutableArrayRef<Expr *>::iterator varlist_iterator; 
-   typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; 
-   typedef llvm::iterator_range<varlist_iterator> varlist_range; 
-   typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; 
-   
-   unsigned varlist_size() const { return Data->getNumChildren(); } 
-   bool varlist_empty() const { return Data->getChildren().empty(); } 
-   
-   varlist_range varlists() { 
-     return varlist_range(varlist_begin(), varlist_end()); 
-   } 
-   varlist_const_range varlists() const { 
-     return varlist_const_range(varlist_begin(), varlist_end()); 
-   } 
-   varlist_iterator varlist_begin() { return getVars().begin(); } 
-   varlist_iterator varlist_end() { return getVars().end(); } 
-   varlist_const_iterator varlist_begin() const { return getVars().begin(); } 
-   varlist_const_iterator varlist_end() const { return getVars().end(); } 
-   
-   static bool classof(const Decl *D) { return classofKind(D->getKind()); } 
-   static bool classofKind(Kind K) { return K == OMPThreadPrivate; } 
- }; 
-   
- /// This represents '#pragma omp declare reduction ...' directive. 
- /// For example, in the following, declared reduction 'foo' for types 'int' and 
- /// 'float': 
- /// 
- /// \code 
- /// #pragma omp declare reduction (foo : int,float : omp_out += omp_in) 
- ///                     initializer (omp_priv = 0) 
- /// \endcode 
- /// 
- /// Here 'omp_out += omp_in' is a combiner and 'omp_priv = 0' is an initializer. 
- class OMPDeclareReductionDecl final : public ValueDecl, public DeclContext { 
-   // This class stores some data in DeclContext::OMPDeclareReductionDeclBits 
-   // to save some space. Use the provided accessors to access it. 
- public: 
-   enum InitKind { 
-     CallInit,   // Initialized by function call. 
-     DirectInit, // omp_priv(<expr>) 
-     CopyInit    // omp_priv = <expr> 
-   }; 
-   
- private: 
-   friend class ASTDeclReader; 
-   /// Combiner for declare reduction construct. 
-   Expr *Combiner = nullptr; 
-   /// Initializer for declare reduction construct. 
-   Expr *Initializer = nullptr; 
-   /// In parameter of the combiner. 
-   Expr *In = nullptr; 
-   /// Out parameter of the combiner. 
-   Expr *Out = nullptr; 
-   /// Priv parameter of the initializer. 
-   Expr *Priv = nullptr; 
-   /// Orig parameter of the initializer. 
-   Expr *Orig = nullptr; 
-   
-   /// Reference to the previous declare reduction construct in the same 
-   /// scope with the same name. Required for proper templates instantiation if 
-   /// the declare reduction construct is declared inside compound statement. 
-   LazyDeclPtr PrevDeclInScope; 
-   
-   void anchor() override; 
-   
-   OMPDeclareReductionDecl(Kind DK, DeclContext *DC, SourceLocation L, 
-                           DeclarationName Name, QualType Ty, 
-                           OMPDeclareReductionDecl *PrevDeclInScope); 
-   
-   void setPrevDeclInScope(OMPDeclareReductionDecl *Prev) { 
-     PrevDeclInScope = Prev; 
-   } 
-   
- public: 
-   /// Create declare reduction node. 
-   static OMPDeclareReductionDecl * 
-   Create(ASTContext &C, DeclContext *DC, SourceLocation L, DeclarationName Name, 
-          QualType T, OMPDeclareReductionDecl *PrevDeclInScope); 
-   /// Create deserialized declare reduction node. 
-   static OMPDeclareReductionDecl *CreateDeserialized(ASTContext &C, 
-                                                      unsigned ID); 
-   
-   /// Get combiner expression of the declare reduction construct. 
-   Expr *getCombiner() { return Combiner; } 
-   const Expr *getCombiner() const { return Combiner; } 
-   /// Get In variable of the combiner. 
-   Expr *getCombinerIn() { return In; } 
-   const Expr *getCombinerIn() const { return In; } 
-   /// Get Out variable of the combiner. 
-   Expr *getCombinerOut() { return Out; } 
-   const Expr *getCombinerOut() const { return Out; } 
-   /// Set combiner expression for the declare reduction construct. 
-   void setCombiner(Expr *E) { Combiner = E; } 
-   /// Set combiner In and Out vars. 
-   void setCombinerData(Expr *InE, Expr *OutE) { 
-     In = InE; 
-     Out = OutE; 
-   } 
-   
-   /// Get initializer expression (if specified) of the declare reduction 
-   /// construct. 
-   Expr *getInitializer() { return Initializer; } 
-   const Expr *getInitializer() const { return Initializer; } 
-   /// Get initializer kind. 
-   InitKind getInitializerKind() const { 
-     return static_cast<InitKind>(OMPDeclareReductionDeclBits.InitializerKind); 
-   } 
-   /// Get Orig variable of the initializer. 
-   Expr *getInitOrig() { return Orig; } 
-   const Expr *getInitOrig() const { return Orig; } 
-   /// Get Priv variable of the initializer. 
-   Expr *getInitPriv() { return Priv; } 
-   const Expr *getInitPriv() const { return Priv; } 
-   /// Set initializer expression for the declare reduction construct. 
-   void setInitializer(Expr *E, InitKind IK) { 
-     Initializer = E; 
-     OMPDeclareReductionDeclBits.InitializerKind = IK; 
-   } 
-   /// Set initializer Orig and Priv vars. 
-   void setInitializerData(Expr *OrigE, Expr *PrivE) { 
-     Orig = OrigE; 
-     Priv = PrivE; 
-   } 
-   
-   /// Get reference to previous declare reduction construct in the same 
-   /// scope with the same name. 
-   OMPDeclareReductionDecl *getPrevDeclInScope(); 
-   const OMPDeclareReductionDecl *getPrevDeclInScope() const; 
-   
-   static bool classof(const Decl *D) { return classofKind(D->getKind()); } 
-   static bool classofKind(Kind K) { return K == OMPDeclareReduction; } 
-   static DeclContext *castToDeclContext(const OMPDeclareReductionDecl *D) { 
-     return static_cast<DeclContext *>(const_cast<OMPDeclareReductionDecl *>(D)); 
-   } 
-   static OMPDeclareReductionDecl *castFromDeclContext(const DeclContext *DC) { 
-     return static_cast<OMPDeclareReductionDecl *>( 
-         const_cast<DeclContext *>(DC)); 
-   } 
- }; 
-   
- /// This represents '#pragma omp declare mapper ...' directive. Map clauses are 
- /// allowed to use with this directive. The following example declares a user 
- /// defined mapper for the type 'struct vec'. This example instructs the fields 
- /// 'len' and 'data' should be mapped when mapping instances of 'struct vec'. 
- /// 
- /// \code 
- /// #pragma omp declare mapper(mid: struct vec v) map(v.len, v.data[0:N]) 
- /// \endcode 
- class OMPDeclareMapperDecl final : public OMPDeclarativeDirective<ValueDecl>, 
-                                    public DeclContext { 
-   friend class OMPDeclarativeDirective<ValueDecl>; 
-   friend class ASTDeclReader; 
-   friend class ASTDeclWriter; 
-   
-   /// Mapper variable, which is 'v' in the example above 
-   Expr *MapperVarRef = nullptr; 
-   
-   /// Name of the mapper variable 
-   DeclarationName VarName; 
-   
-   LazyDeclPtr PrevDeclInScope; 
-   
-   void anchor() override; 
-   
-   OMPDeclareMapperDecl(DeclContext *DC, SourceLocation L, DeclarationName Name, 
-                        QualType Ty, DeclarationName VarName, 
-                        OMPDeclareMapperDecl *PrevDeclInScope) 
-       : OMPDeclarativeDirective<ValueDecl>(OMPDeclareMapper, DC, L, Name, Ty), 
-         DeclContext(OMPDeclareMapper), VarName(VarName), 
-         PrevDeclInScope(PrevDeclInScope) {} 
-   
-   void setPrevDeclInScope(OMPDeclareMapperDecl *Prev) { 
-     PrevDeclInScope = Prev; 
-   } 
-   
- public: 
-   /// Creates declare mapper node. 
-   static OMPDeclareMapperDecl *Create(ASTContext &C, DeclContext *DC, 
-                                       SourceLocation L, DeclarationName Name, 
-                                       QualType T, DeclarationName VarName, 
-                                       ArrayRef<OMPClause *> Clauses, 
-                                       OMPDeclareMapperDecl *PrevDeclInScope); 
-   /// Creates deserialized declare mapper node. 
-   static OMPDeclareMapperDecl *CreateDeserialized(ASTContext &C, unsigned ID, 
-                                                   unsigned N); 
-   
-   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator; 
-   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator; 
-   using clauselist_range = llvm::iterator_range<clauselist_iterator>; 
-   using clauselist_const_range = 
-       llvm::iterator_range<clauselist_const_iterator>; 
-   
-   unsigned clauselist_size() const { return Data->getNumClauses(); } 
-   bool clauselist_empty() const { return Data->getClauses().empty(); } 
-   
-   clauselist_range clauselists() { 
-     return clauselist_range(clauselist_begin(), clauselist_end()); 
-   } 
-   clauselist_const_range clauselists() const { 
-     return clauselist_const_range(clauselist_begin(), clauselist_end()); 
-   } 
-   clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); } 
-   clauselist_iterator clauselist_end() { return Data->getClauses().end(); } 
-   clauselist_const_iterator clauselist_begin() const { 
-     return Data->getClauses().begin(); 
-   } 
-   clauselist_const_iterator clauselist_end() const { 
-     return Data->getClauses().end(); 
-   } 
-   
-   /// Get the variable declared in the mapper 
-   Expr *getMapperVarRef() { return cast_or_null<Expr>(Data->getChildren()[0]); } 
-   const Expr *getMapperVarRef() const { 
-     return cast_or_null<Expr>(Data->getChildren()[0]); 
-   } 
-   /// Set the variable declared in the mapper 
-   void setMapperVarRef(Expr *MapperVarRefE) { 
-     Data->getChildren()[0] = MapperVarRefE; 
-   } 
-   
-   /// Get the name of the variable declared in the mapper 
-   DeclarationName getVarName() { return VarName; } 
-   
-   /// Get reference to previous declare mapper construct in the same 
-   /// scope with the same name. 
-   OMPDeclareMapperDecl *getPrevDeclInScope(); 
-   const OMPDeclareMapperDecl *getPrevDeclInScope() const; 
-   
-   static bool classof(const Decl *D) { return classofKind(D->getKind()); } 
-   static bool classofKind(Kind K) { return K == OMPDeclareMapper; } 
-   static DeclContext *castToDeclContext(const OMPDeclareMapperDecl *D) { 
-     return static_cast<DeclContext *>(const_cast<OMPDeclareMapperDecl *>(D)); 
-   } 
-   static OMPDeclareMapperDecl *castFromDeclContext(const DeclContext *DC) { 
-     return static_cast<OMPDeclareMapperDecl *>(const_cast<DeclContext *>(DC)); 
-   } 
- }; 
-   
- /// Pseudo declaration for capturing expressions. Also is used for capturing of 
- /// non-static data members in non-static member functions. 
- /// 
- /// Clang supports capturing of variables only, but OpenMP 4.5 allows to 
- /// privatize non-static members of current class in non-static member 
- /// functions. This pseudo-declaration allows properly handle this kind of 
- /// capture by wrapping captured expression into a variable-like declaration. 
- class OMPCapturedExprDecl final : public VarDecl { 
-   friend class ASTDeclReader; 
-   void anchor() override; 
-   
-   OMPCapturedExprDecl(ASTContext &C, DeclContext *DC, IdentifierInfo *Id, 
-                       QualType Type, TypeSourceInfo *TInfo, 
-                       SourceLocation StartLoc) 
-       : VarDecl(OMPCapturedExpr, C, DC, StartLoc, StartLoc, Id, Type, TInfo, 
-                 SC_None) { 
-     setImplicit(); 
-   } 
-   
- public: 
-   static OMPCapturedExprDecl *Create(ASTContext &C, DeclContext *DC, 
-                                      IdentifierInfo *Id, QualType T, 
-                                      SourceLocation StartLoc); 
-   
-   static OMPCapturedExprDecl *CreateDeserialized(ASTContext &C, unsigned ID); 
-   
-   SourceRange getSourceRange() const override LLVM_READONLY; 
-   
-   // Implement isa/cast/dyncast/etc. 
-   static bool classof(const Decl *D) { return classofKind(D->getKind()); } 
-   static bool classofKind(Kind K) { return K == OMPCapturedExpr; } 
- }; 
-   
- /// This represents '#pragma omp requires...' directive. 
- /// For example 
- /// 
- /// \code 
- /// #pragma omp requires unified_address 
- /// \endcode 
- /// 
- class OMPRequiresDecl final : public OMPDeclarativeDirective<Decl> { 
-   friend class OMPDeclarativeDirective<Decl>; 
-   friend class ASTDeclReader; 
-   
-   virtual void anchor(); 
-   
-   OMPRequiresDecl(DeclContext *DC, SourceLocation L) 
-       : OMPDeclarativeDirective<Decl>(OMPRequires, DC, L) {} 
-   
- public: 
-   /// Create requires node. 
-   static OMPRequiresDecl *Create(ASTContext &C, DeclContext *DC, 
-                                  SourceLocation L, ArrayRef<OMPClause *> CL); 
-   /// Create deserialized requires node. 
-   static OMPRequiresDecl *CreateDeserialized(ASTContext &C, unsigned ID, 
-                                              unsigned N); 
-   
-   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator; 
-   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator; 
-   using clauselist_range = llvm::iterator_range<clauselist_iterator>; 
-   using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>; 
-   
-   unsigned clauselist_size() const { return Data->getNumClauses(); } 
-   bool clauselist_empty() const { return Data->getClauses().empty(); } 
-   
-   clauselist_range clauselists() { 
-     return clauselist_range(clauselist_begin(), clauselist_end()); 
-   } 
-   clauselist_const_range clauselists() const { 
-     return clauselist_const_range(clauselist_begin(), clauselist_end()); 
-   } 
-   clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); } 
-   clauselist_iterator clauselist_end() { return Data->getClauses().end(); } 
-   clauselist_const_iterator clauselist_begin() const { 
-     return Data->getClauses().begin(); 
-   } 
-   clauselist_const_iterator clauselist_end() const { 
-     return Data->getClauses().end(); 
-   } 
-   
-   static bool classof(const Decl *D) { return classofKind(D->getKind()); } 
-   static bool classofKind(Kind K) { return K == OMPRequires; } 
- }; 
-   
- /// This represents '#pragma omp allocate ...' directive. 
- /// For example, in the following, the default allocator is used for both 'a' 
- /// and 'A::b': 
- /// 
- /// \code 
- /// int a; 
- /// #pragma omp allocate(a) 
- /// struct A { 
- ///   static int b; 
- /// #pragma omp allocate(b) 
- /// }; 
- /// \endcode 
- /// 
- class OMPAllocateDecl final : public OMPDeclarativeDirective<Decl> { 
-   friend class OMPDeclarativeDirective<Decl>; 
-   friend class ASTDeclReader; 
-   
-   virtual void anchor(); 
-   
-   OMPAllocateDecl(DeclContext *DC, SourceLocation L) 
-       : OMPDeclarativeDirective<Decl>(OMPAllocate, DC, L) {} 
-   
-   ArrayRef<const Expr *> getVars() const { 
-     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); 
-     return llvm::ArrayRef(Storage, Data->getNumChildren()); 
-   } 
-   
-   MutableArrayRef<Expr *> getVars() { 
-     auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); 
-     return llvm::MutableArrayRef(Storage, Data->getNumChildren()); 
-   } 
-   
-   void setVars(ArrayRef<Expr *> VL); 
-   
- public: 
-   static OMPAllocateDecl *Create(ASTContext &C, DeclContext *DC, 
-                                  SourceLocation L, ArrayRef<Expr *> VL, 
-                                  ArrayRef<OMPClause *> CL); 
-   static OMPAllocateDecl *CreateDeserialized(ASTContext &C, unsigned ID, 
-                                              unsigned NVars, unsigned NClauses); 
-   
-   typedef MutableArrayRef<Expr *>::iterator varlist_iterator; 
-   typedef ArrayRef<const Expr *>::iterator varlist_const_iterator; 
-   typedef llvm::iterator_range<varlist_iterator> varlist_range; 
-   typedef llvm::iterator_range<varlist_const_iterator> varlist_const_range; 
-   using clauselist_iterator = MutableArrayRef<OMPClause *>::iterator; 
-   using clauselist_const_iterator = ArrayRef<const OMPClause *>::iterator; 
-   using clauselist_range = llvm::iterator_range<clauselist_iterator>; 
-   using clauselist_const_range = llvm::iterator_range<clauselist_const_iterator>; 
-   
-   unsigned varlist_size() const { return Data->getNumChildren(); } 
-   bool varlist_empty() const { return Data->getChildren().empty(); } 
-   unsigned clauselist_size() const { return Data->getNumClauses(); } 
-   bool clauselist_empty() const { return Data->getClauses().empty(); } 
-   
-   varlist_range varlists() { 
-     return varlist_range(varlist_begin(), varlist_end()); 
-   } 
-   varlist_const_range varlists() const { 
-     return varlist_const_range(varlist_begin(), varlist_end()); 
-   } 
-   varlist_iterator varlist_begin() { return getVars().begin(); } 
-   varlist_iterator varlist_end() { return getVars().end(); } 
-   varlist_const_iterator varlist_begin() const { return getVars().begin(); } 
-   varlist_const_iterator varlist_end() const { return getVars().end(); } 
-   
-   clauselist_range clauselists() { 
-     return clauselist_range(clauselist_begin(), clauselist_end()); 
-   } 
-   clauselist_const_range clauselists() const { 
-     return clauselist_const_range(clauselist_begin(), clauselist_end()); 
-   } 
-   clauselist_iterator clauselist_begin() { return Data->getClauses().begin(); } 
-   clauselist_iterator clauselist_end() { return Data->getClauses().end(); } 
-   clauselist_const_iterator clauselist_begin() const { 
-     return Data->getClauses().begin(); 
-   } 
-   clauselist_const_iterator clauselist_end() const { 
-     return Data->getClauses().end(); 
-   } 
-   
-   static bool classof(const Decl *D) { return classofKind(D->getKind()); } 
-   static bool classofKind(Kind K) { return K == OMPAllocate; } 
- }; 
-   
- } // end namespace clang 
-   
- #endif 
-