| //===- 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 llvm::None; |
| 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 llvm::None; |
| 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::makeArrayRef(Storage, Data->getNumChildren()); |
| } |
| |
| MutableArrayRef<Expr *> getVars() { |
| auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); |
| return llvm::makeMutableArrayRef(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::makeArrayRef(Storage, Data->getNumChildren()); |
| } |
| |
| MutableArrayRef<Expr *> getVars() { |
| auto **Storage = reinterpret_cast<Expr **>(Data->getChildren().data()); |
| return llvm::makeMutableArrayRef(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 |