//=- DeclOpenACC.h - Classes for representing OpenACC 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 OpenACC nodes for declarative directives. /// //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_DECLOPENACC_H #define LLVM_CLANG_AST_DECLOPENACC_H #include "clang/AST/ASTContext.h" #include "clang/AST/Decl.h" #include "clang/AST/OpenACCClause.h" #include "clang/Basic/OpenACCKinds.h" #include "llvm/ADT/STLExtras.h" namespace clang { // A base class for the declaration constructs, which manages the clauses and // basic source location information. Currently not part of the Decl inheritence // tree, as we should never have a reason to store one of these. class OpenACCConstructDecl : public Decl { friend class ASTDeclReader; friend class ASTDeclWriter; // The directive kind, each implementation of this interface is expected to // handle a specific kind. OpenACCDirectiveKind DirKind = OpenACCDirectiveKind::Invalid; SourceLocation DirectiveLoc; SourceLocation EndLoc; /// The list of clauses. This is stored here as an ArrayRef, as this is the /// most convienient place to access the list, however the list itself should /// be stored in leaf nodes, likely in trailing-storage. MutableArrayRef Clauses; protected: OpenACCConstructDecl(Kind DeclKind, DeclContext *DC, OpenACCDirectiveKind K, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation EndLoc) : Decl(DeclKind, DC, StartLoc), DirKind(K), DirectiveLoc(DirLoc), EndLoc(EndLoc) {} OpenACCConstructDecl(Kind DeclKind) : Decl(DeclKind, EmptyShell{}) {} void setClauseList(MutableArrayRef NewClauses) { assert(Clauses.empty() && "Cannot change clause list"); Clauses = NewClauses; } public: OpenACCDirectiveKind getDirectiveKind() const { return DirKind; } SourceLocation getDirectiveLoc() const { return DirectiveLoc; } virtual SourceRange getSourceRange() const override LLVM_READONLY { return SourceRange(getLocation(), EndLoc); } ArrayRef clauses() const { return Clauses; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K); }; class OpenACCDeclareDecl final : public OpenACCConstructDecl, private llvm::TrailingObjects { friend TrailingObjects; friend class ASTDeclReader; friend class ASTDeclWriter; OpenACCDeclareDecl(unsigned NumClauses) : OpenACCConstructDecl(OpenACCDeclare) { std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses); setClauseList(getTrailingObjects(NumClauses)); } OpenACCDeclareDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef Clauses) : OpenACCConstructDecl(OpenACCDeclare, DC, OpenACCDirectiveKind::Declare, StartLoc, DirLoc, EndLoc) { // Initialize the trailing storage. llvm::uninitialized_copy(Clauses, getTrailingObjects()); setClauseList(getTrailingObjects(Clauses.size())); } public: static OpenACCDeclareDecl *Create(ASTContext &Ctx, DeclContext *DC, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation EndLoc, ArrayRef Clauses); static OpenACCDeclareDecl * CreateDeserialized(ASTContext &Ctx, GlobalDeclID ID, unsigned NumClauses); static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == OpenACCDeclare; } }; // Reprents a 'routine' directive with a name. When this has no name, it is // represented as an attribute. class OpenACCRoutineDecl final : public OpenACCConstructDecl, private llvm::TrailingObjects { friend TrailingObjects; friend class ASTDeclReader; friend class ASTDeclWriter; Expr *FuncRef = nullptr; SourceRange ParensLoc; OpenACCRoutineDecl(unsigned NumClauses) : OpenACCConstructDecl(OpenACCRoutine) { std::uninitialized_value_construct_n(getTrailingObjects(), NumClauses); setClauseList(getTrailingObjects(NumClauses)); } OpenACCRoutineDecl(DeclContext *DC, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *FuncRef, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef Clauses) : OpenACCConstructDecl(OpenACCRoutine, DC, OpenACCDirectiveKind::Routine, StartLoc, DirLoc, EndLoc), FuncRef(FuncRef), ParensLoc(LParenLoc, RParenLoc) { assert(LParenLoc.isValid() && "Cannot represent implicit name with this declaration"); // Initialize the trailing storage. llvm::uninitialized_copy(Clauses, getTrailingObjects()); setClauseList(getTrailingObjects(Clauses.size())); } public: static OpenACCRoutineDecl * Create(ASTContext &Ctx, DeclContext *DC, SourceLocation StartLoc, SourceLocation DirLoc, SourceLocation LParenLoc, Expr *FuncRef, SourceLocation RParenLoc, SourceLocation EndLoc, ArrayRef Clauses); static OpenACCRoutineDecl * CreateDeserialized(ASTContext &Ctx, GlobalDeclID ID, unsigned NumClauses); static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == OpenACCRoutine; } const Expr *getFunctionReference() const { return FuncRef; } Expr *getFunctionReference() { return FuncRef; } SourceLocation getLParenLoc() const { return ParensLoc.getBegin(); } SourceLocation getRParenLoc() const { return ParensLoc.getEnd(); } }; } // namespace clang #endif