//===--- ExprOpenMP.h - Classes for representing expressions ----*- 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 // //===----------------------------------------------------------------------===// // // This file defines the Expr interface and subclasses. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_AST_EXPROPENMP_H #define LLVM_CLANG_AST_EXPROPENMP_H #include "clang/AST/ComputeDependence.h" #include "clang/AST/Expr.h" namespace clang { /// OpenMP 5.0 [2.1.5, Array Sections]. /// To specify an array section in an OpenMP construct, array subscript /// expressions are extended with the following syntax: /// \code /// [ lower-bound : length : stride ] /// [ lower-bound : length : ] /// [ lower-bound : length ] /// [ lower-bound : : stride ] /// [ lower-bound : : ] /// [ lower-bound : ] /// [ : length : stride ] /// [ : length : ] /// [ : length ] /// [ : : stride ] /// [ : : ] /// [ : ] /// \endcode /// The array section must be a subset of the original array. /// Array sections are allowed on multidimensional arrays. Base language array /// subscript expressions can be used to specify length-one dimensions of /// multidimensional array sections. /// Each of the lower-bound, length, and stride expressions if specified must be /// an integral type expressions of the base language. When evaluated /// they represent a set of integer values as follows: /// \code /// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... , /// lower-bound + ((length - 1) * stride) } /// \endcode /// The lower-bound and length must evaluate to non-negative integers. /// The stride must evaluate to a positive integer. /// When the size of the array dimension is not known, the length must be /// specified explicitly. /// When the stride is absent it defaults to 1. /// When the length is absent it defaults to ⌈(size − lower-bound)/stride⌉, /// where size is the size of the array dimension. When the lower-bound is /// absent it defaults to 0. class OMPArraySectionExpr : public Expr { enum { BASE, LOWER_BOUND, LENGTH, STRIDE, END_EXPR }; Stmt *SubExprs[END_EXPR]; SourceLocation ColonLocFirst; SourceLocation ColonLocSecond; SourceLocation RBracketLoc; public: OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride, QualType Type, ExprValueKind VK, ExprObjectKind OK, SourceLocation ColonLocFirst, SourceLocation ColonLocSecond, SourceLocation RBracketLoc) : Expr(OMPArraySectionExprClass, Type, VK, OK), ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond), RBracketLoc(RBracketLoc) { SubExprs[BASE] = Base; SubExprs[LOWER_BOUND] = LowerBound; SubExprs[LENGTH] = Length; SubExprs[STRIDE] = Stride; setDependence(computeDependence(this)); } /// Create an empty array section expression. explicit OMPArraySectionExpr(EmptyShell Shell) : Expr(OMPArraySectionExprClass, Shell) {} /// An array section can be written only as Base[LowerBound:Length]. /// Get base of the array section. Expr *getBase() { return cast(SubExprs[BASE]); } const Expr *getBase() const { return cast(SubExprs[BASE]); } /// Set base of the array section. void setBase(Expr *E) { SubExprs[BASE] = E; } /// Return original type of the base expression for array section. static QualType getBaseOriginalType(const Expr *Base); /// Get lower bound of array section. Expr *getLowerBound() { return cast_or_null(SubExprs[LOWER_BOUND]); } const Expr *getLowerBound() const { return cast_or_null(SubExprs[LOWER_BOUND]); } /// Set lower bound of the array section. void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; } /// Get length of array section. Expr *getLength() { return cast_or_null(SubExprs[LENGTH]); } const Expr *getLength() const { return cast_or_null(SubExprs[LENGTH]); } /// Set length of the array section. void setLength(Expr *E) { SubExprs[LENGTH] = E; } /// Get stride of array section. Expr *getStride() { return cast_or_null(SubExprs[STRIDE]); } const Expr *getStride() const { return cast_or_null(SubExprs[STRIDE]); } /// Set length of the array section. void setStride(Expr *E) { SubExprs[STRIDE] = E; } SourceLocation getBeginLoc() const LLVM_READONLY { return getBase()->getBeginLoc(); } SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; } SourceLocation getColonLocFirst() const { return ColonLocFirst; } void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; } SourceLocation getColonLocSecond() const { return ColonLocSecond; } void setColonLocSecond(SourceLocation L) { ColonLocSecond = L; } SourceLocation getRBracketLoc() const { return RBracketLoc; } void setRBracketLoc(SourceLocation L) { RBracketLoc = L; } SourceLocation getExprLoc() const LLVM_READONLY { return getBase()->getExprLoc(); } static bool classof(const Stmt *T) { return T->getStmtClass() == OMPArraySectionExprClass; } child_range children() { return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]); } const_child_range children() const { return const_child_range(&SubExprs[BASE], &SubExprs[END_EXPR]); } }; /// An explicit cast in C or a C-style cast in C++, which uses the syntax /// ([s1][s2]...[sn])expr. For example: @c ([3][3])f. class OMPArrayShapingExpr final : public Expr, private llvm::TrailingObjects { friend TrailingObjects; friend class ASTStmtReader; friend class ASTStmtWriter; /// Base node. SourceLocation LPLoc; /// The location of the left paren SourceLocation RPLoc; /// The location of the right paren unsigned NumDims = 0; /// Number of dimensions in the shaping expression. /// Construct full expression. OMPArrayShapingExpr(QualType ExprTy, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef Dims); /// Construct an empty expression. explicit OMPArrayShapingExpr(EmptyShell Shell, unsigned NumDims) : Expr(OMPArrayShapingExprClass, Shell), NumDims(NumDims) {} /// Sets the dimensions for the array shaping. void setDimensions(ArrayRef Dims); /// Sets the base expression for array shaping operation. void setBase(Expr *Op) { getTrailingObjects()[NumDims] = Op; } /// Sets source ranges for the brackets in the array shaping operation. void setBracketsRanges(ArrayRef BR); unsigned numTrailingObjects(OverloadToken) const { // Add an extra one for the base expression. return NumDims + 1; } unsigned numTrailingObjects(OverloadToken) const { return NumDims; } public: static OMPArrayShapingExpr *Create(const ASTContext &Context, QualType T, Expr *Op, SourceLocation L, SourceLocation R, ArrayRef Dims, ArrayRef BracketRanges); static OMPArrayShapingExpr *CreateEmpty(const ASTContext &Context, unsigned NumDims); SourceLocation getLParenLoc() const { return LPLoc; } void setLParenLoc(SourceLocation L) { LPLoc = L; } SourceLocation getRParenLoc() const { return RPLoc; } void setRParenLoc(SourceLocation L) { RPLoc = L; } SourceLocation getBeginLoc() const LLVM_READONLY { return LPLoc; } SourceLocation getEndLoc() const LLVM_READONLY { return getBase()->getEndLoc(); } /// Fetches the dimensions for array shaping expression. ArrayRef getDimensions() const { return llvm::makeArrayRef(getTrailingObjects(), NumDims); } /// Fetches source ranges for the brackets os the array shaping expression. ArrayRef getBracketsRanges() const { return llvm::makeArrayRef(getTrailingObjects(), NumDims); } /// Fetches base expression of array shaping expression. Expr *getBase() { return getTrailingObjects()[NumDims]; } const Expr *getBase() const { return getTrailingObjects()[NumDims]; } static bool classof(const Stmt *T) { return T->getStmtClass() == OMPArrayShapingExprClass; } // Iterators child_range children() { Stmt **Begin = reinterpret_cast(getTrailingObjects()); return child_range(Begin, Begin + NumDims + 1); } const_child_range children() const { Stmt *const *Begin = reinterpret_cast(getTrailingObjects()); return const_child_range(Begin, Begin + NumDims + 1); } }; /// Helper expressions and declaration for OMPIteratorExpr class for each /// iteration space. struct OMPIteratorHelperData { /// Internal normalized counter. VarDecl *CounterVD = nullptr; /// Normalized upper bound. Normalized loop iterates from 0 to Upper with /// step 1. Expr *Upper = nullptr; /// Update expression for the originally specified iteration variable, /// calculated as VD = Begin + CounterVD * Step; Expr *Update = nullptr; /// Updater for the internal counter: ++CounterVD; Expr *CounterUpdate = nullptr; }; /// OpenMP 5.0 [2.1.6 Iterators] /// Iterators are identifiers that expand to multiple values in the clause on /// which they appear. /// The syntax of the iterator modifier is as follows: /// \code /// iterator(iterators-definition) /// \endcode /// where iterators-definition is one of the following: /// \code /// iterator-specifier [, iterators-definition ] /// \endcode /// where iterator-specifier is one of the following: /// \code /// [ iterator-type ] identifier = range-specification /// \endcode /// where identifier is a base language identifier. /// iterator-type is a type name. /// range-specification is of the form begin:end[:step], where begin and end are /// expressions for which their types can be converted to iterator-type and step /// is an integral expression. /// In an iterator-specifier, if the iterator-type is not specified then the /// type of that iterator is of int type. /// The iterator-type must be an integral or pointer type. /// The iterator-type must not be const qualified. class OMPIteratorExpr final : public Expr, private llvm::TrailingObjects { public: /// Iterator range representation begin:end[:step]. struct IteratorRange { Expr *Begin = nullptr; Expr *End = nullptr; Expr *Step = nullptr; }; /// Iterator definition representation. struct IteratorDefinition { Decl *IteratorDecl = nullptr; IteratorRange Range; SourceLocation AssignmentLoc; SourceLocation ColonLoc, SecondColonLoc; }; private: friend TrailingObjects; friend class ASTStmtReader; friend class ASTStmtWriter; /// Offset in the list of expressions for subelements of the ranges. enum class RangeExprOffset { Begin = 0, End = 1, Step = 2, Total = 3, }; /// Offset in the list of locations for subelements of colon symbols /// locations. enum class RangeLocOffset { AssignLoc = 0, FirstColonLoc = 1, SecondColonLoc = 2, Total = 3, }; /// Location of 'iterator' keyword. SourceLocation IteratorKwLoc; /// Location of '('. SourceLocation LPLoc; /// Location of ')'. SourceLocation RPLoc; /// Number of iterator definitions. unsigned NumIterators = 0; OMPIteratorExpr(QualType ExprTy, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef Data, ArrayRef Helpers); /// Construct an empty expression. explicit OMPIteratorExpr(EmptyShell Shell, unsigned NumIterators) : Expr(OMPIteratorExprClass, Shell), NumIterators(NumIterators) {} /// Sets basic declaration for the specified iterator definition. void setIteratorDeclaration(unsigned I, Decl *D); /// Sets the location of the assignment symbol for the specified iterator /// definition. void setAssignmentLoc(unsigned I, SourceLocation Loc); /// Sets begin, end and optional step expressions for specified iterator /// definition. void setIteratorRange(unsigned I, Expr *Begin, SourceLocation ColonLoc, Expr *End, SourceLocation SecondColonLoc, Expr *Step); /// Sets helpers for the specified iteration space. void setHelper(unsigned I, const OMPIteratorHelperData &D); unsigned numTrailingObjects(OverloadToken) const { return NumIterators; } unsigned numTrailingObjects(OverloadToken) const { return NumIterators * static_cast(RangeExprOffset::Total); } unsigned numTrailingObjects(OverloadToken) const { return NumIterators * static_cast(RangeLocOffset::Total); } public: static OMPIteratorExpr *Create(const ASTContext &Context, QualType T, SourceLocation IteratorKwLoc, SourceLocation L, SourceLocation R, ArrayRef Data, ArrayRef Helpers); static OMPIteratorExpr *CreateEmpty(const ASTContext &Context, unsigned NumIterators); SourceLocation getLParenLoc() const { return LPLoc; } void setLParenLoc(SourceLocation L) { LPLoc = L; } SourceLocation getRParenLoc() const { return RPLoc; } void setRParenLoc(SourceLocation L) { RPLoc = L; } SourceLocation getIteratorKwLoc() const { return IteratorKwLoc; } void setIteratorKwLoc(SourceLocation L) { IteratorKwLoc = L; } SourceLocation getBeginLoc() const LLVM_READONLY { return IteratorKwLoc; } SourceLocation getEndLoc() const LLVM_READONLY { return RPLoc; } /// Gets the iterator declaration for the given iterator. Decl *getIteratorDecl(unsigned I); const Decl *getIteratorDecl(unsigned I) const { return const_cast(this)->getIteratorDecl(I); } /// Gets the iterator range for the given iterator. IteratorRange getIteratorRange(unsigned I); const IteratorRange getIteratorRange(unsigned I) const { return const_cast(this)->getIteratorRange(I); } /// Gets the location of '=' for the given iterator definition. SourceLocation getAssignLoc(unsigned I) const; /// Gets the location of the first ':' in the range for the given iterator /// definition. SourceLocation getColonLoc(unsigned I) const; /// Gets the location of the second ':' (if any) in the range for the given /// iteratori definition. SourceLocation getSecondColonLoc(unsigned I) const; /// Returns number of iterator definitions. unsigned numOfIterators() const { return NumIterators; } /// Fetches helper data for the specified iteration space. OMPIteratorHelperData &getHelper(unsigned I); const OMPIteratorHelperData &getHelper(unsigned I) const; static bool classof(const Stmt *T) { return T->getStmtClass() == OMPIteratorExprClass; } // Iterators child_range children() { Stmt **Begin = reinterpret_cast(getTrailingObjects()); return child_range( Begin, Begin + NumIterators * static_cast(RangeExprOffset::Total)); } const_child_range children() const { Stmt *const *Begin = reinterpret_cast(getTrailingObjects()); return const_child_range( Begin, Begin + NumIterators * static_cast(RangeExprOffset::Total)); } }; } // end namespace clang #endif