Home | History | Annotate | Line # | Download | only in AST
      1 //===--- ExprOpenMP.h - Classes for representing expressions ----*- 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 //  This file defines the Expr interface and subclasses.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #ifndef LLVM_CLANG_AST_EXPROPENMP_H
     14 #define LLVM_CLANG_AST_EXPROPENMP_H
     15 
     16 #include "clang/AST/ComputeDependence.h"
     17 #include "clang/AST/Expr.h"
     18 
     19 namespace clang {
     20 /// OpenMP 5.0 [2.1.5, Array Sections].
     21 /// To specify an array section in an OpenMP construct, array subscript
     22 /// expressions are extended with the following syntax:
     23 /// \code
     24 /// [ lower-bound : length : stride ]
     25 /// [ lower-bound : length : ]
     26 /// [ lower-bound : length ]
     27 /// [ lower-bound : : stride ]
     28 /// [ lower-bound : : ]
     29 /// [ lower-bound : ]
     30 /// [ : length : stride ]
     31 /// [ : length : ]
     32 /// [ : length ]
     33 /// [ : : stride ]
     34 /// [ : : ]
     35 /// [ : ]
     36 /// \endcode
     37 /// The array section must be a subset of the original array.
     38 /// Array sections are allowed on multidimensional arrays. Base language array
     39 /// subscript expressions can be used to specify length-one dimensions of
     40 /// multidimensional array sections.
     41 /// Each of the lower-bound, length, and stride expressions if specified must be
     42 /// an integral type expressions of the base language. When evaluated
     43 /// they represent a set of integer values as follows:
     44 /// \code
     45 /// { lower-bound, lower-bound + stride, lower-bound + 2 * stride,... ,
     46 /// lower-bound + ((length - 1) * stride) }
     47 /// \endcode
     48 /// The lower-bound and length must evaluate to non-negative integers.
     49 /// The stride must evaluate to a positive integer.
     50 /// When the size of the array dimension is not known, the length must be
     51 /// specified explicitly.
     52 /// When the stride is absent it defaults to 1.
     53 /// When the length is absent it defaults to (size  lower-bound)/stride,
     54 /// where size is the size of the array dimension. When the lower-bound is
     55 /// absent it defaults to 0.
     56 class OMPArraySectionExpr : public Expr {
     57   enum { BASE, LOWER_BOUND, LENGTH, STRIDE, END_EXPR };
     58   Stmt *SubExprs[END_EXPR];
     59   SourceLocation ColonLocFirst;
     60   SourceLocation ColonLocSecond;
     61   SourceLocation RBracketLoc;
     62 
     63 public:
     64   OMPArraySectionExpr(Expr *Base, Expr *LowerBound, Expr *Length, Expr *Stride,
     65                       QualType Type, ExprValueKind VK, ExprObjectKind OK,
     66                       SourceLocation ColonLocFirst,
     67                       SourceLocation ColonLocSecond, SourceLocation RBracketLoc)
     68       : Expr(OMPArraySectionExprClass, Type, VK, OK),
     69         ColonLocFirst(ColonLocFirst), ColonLocSecond(ColonLocSecond),
     70         RBracketLoc(RBracketLoc) {
     71     SubExprs[BASE] = Base;
     72     SubExprs[LOWER_BOUND] = LowerBound;
     73     SubExprs[LENGTH] = Length;
     74     SubExprs[STRIDE] = Stride;
     75     setDependence(computeDependence(this));
     76   }
     77 
     78   /// Create an empty array section expression.
     79   explicit OMPArraySectionExpr(EmptyShell Shell)
     80       : Expr(OMPArraySectionExprClass, Shell) {}
     81 
     82   /// An array section can be written only as Base[LowerBound:Length].
     83 
     84   /// Get base of the array section.
     85   Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
     86   const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
     87   /// Set base of the array section.
     88   void setBase(Expr *E) { SubExprs[BASE] = E; }
     89 
     90   /// Return original type of the base expression for array section.
     91   static QualType getBaseOriginalType(const Expr *Base);
     92 
     93   /// Get lower bound of array section.
     94   Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
     95   const Expr *getLowerBound() const {
     96     return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
     97   }
     98   /// Set lower bound of the array section.
     99   void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
    100 
    101   /// Get length of array section.
    102   Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
    103   const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
    104   /// Set length of the array section.
    105   void setLength(Expr *E) { SubExprs[LENGTH] = E; }
    106 
    107   /// Get stride of array section.
    108   Expr *getStride() { return cast_or_null<Expr>(SubExprs[STRIDE]); }
    109   const Expr *getStride() const { return cast_or_null<Expr>(SubExprs[STRIDE]); }
    110   /// Set length of the array section.
    111   void setStride(Expr *E) { SubExprs[STRIDE] = E; }
    112 
    113   SourceLocation getBeginLoc() const LLVM_READONLY {
    114     return getBase()->getBeginLoc();
    115   }
    116   SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }
    117 
    118   SourceLocation getColonLocFirst() const { return ColonLocFirst; }
    119   void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; }
    120 
    121   SourceLocation getColonLocSecond() const { return ColonLocSecond; }
    122   void setColonLocSecond(SourceLocation L) { ColonLocSecond = L; }
    123 
    124   SourceLocation getRBracketLoc() const { return RBracketLoc; }
    125   void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
    126 
    127   SourceLocation getExprLoc() const LLVM_READONLY {
    128     return getBase()->getExprLoc();
    129   }
    130 
    131   static bool classof(const Stmt *T) {
    132     return T->getStmtClass() == OMPArraySectionExprClass;
    133   }
    134 
    135   child_range children() {
    136     return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
    137   }
    138 
    139   const_child_range children() const {
    140     return const_child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
    141   }
    142 };
    143 
    144 /// An explicit cast in C or a C-style cast in C++, which uses the syntax
    145 /// ([s1][s2]...[sn])expr. For example: @c ([3][3])f.
    146 class OMPArrayShapingExpr final
    147     : public Expr,
    148       private llvm::TrailingObjects<OMPArrayShapingExpr, Expr *, SourceRange> {
    149   friend TrailingObjects;
    150   friend class ASTStmtReader;
    151   friend class ASTStmtWriter;
    152   /// Base node.
    153   SourceLocation LPLoc; /// The location of the left paren
    154   SourceLocation RPLoc; /// The location of the right paren
    155   unsigned NumDims = 0; /// Number of dimensions in the shaping expression.
    156 
    157   /// Construct full expression.
    158   OMPArrayShapingExpr(QualType ExprTy, Expr *Op, SourceLocation L,
    159                       SourceLocation R, ArrayRef<Expr *> Dims);
    160 
    161   /// Construct an empty expression.
    162   explicit OMPArrayShapingExpr(EmptyShell Shell, unsigned NumDims)
    163       : Expr(OMPArrayShapingExprClass, Shell), NumDims(NumDims) {}
    164 
    165   /// Sets the dimensions for the array shaping.
    166   void setDimensions(ArrayRef<Expr *> Dims);
    167 
    168   /// Sets the base expression for array shaping operation.
    169   void setBase(Expr *Op) { getTrailingObjects<Expr *>()[NumDims] = Op; }
    170 
    171   /// Sets source ranges for the brackets in the array shaping operation.
    172   void setBracketsRanges(ArrayRef<SourceRange> BR);
    173 
    174   unsigned numTrailingObjects(OverloadToken<Expr *>) const {
    175     // Add an extra one for the base expression.
    176     return NumDims + 1;
    177   }
    178 
    179   unsigned numTrailingObjects(OverloadToken<SourceRange>) const {
    180     return NumDims;
    181   }
    182 
    183 public:
    184   static OMPArrayShapingExpr *Create(const ASTContext &Context, QualType T,
    185                                      Expr *Op, SourceLocation L,
    186                                      SourceLocation R, ArrayRef<Expr *> Dims,
    187                                      ArrayRef<SourceRange> BracketRanges);
    188 
    189   static OMPArrayShapingExpr *CreateEmpty(const ASTContext &Context,
    190                                           unsigned NumDims);
    191 
    192   SourceLocation getLParenLoc() const { return LPLoc; }
    193   void setLParenLoc(SourceLocation L) { LPLoc = L; }
    194 
    195   SourceLocation getRParenLoc() const { return RPLoc; }
    196   void setRParenLoc(SourceLocation L) { RPLoc = L; }
    197 
    198   SourceLocation getBeginLoc() const LLVM_READONLY { return LPLoc; }
    199   SourceLocation getEndLoc() const LLVM_READONLY {
    200     return getBase()->getEndLoc();
    201   }
    202 
    203   /// Fetches the dimensions for array shaping expression.
    204   ArrayRef<Expr *> getDimensions() const {
    205     return llvm::makeArrayRef(getTrailingObjects<Expr *>(), NumDims);
    206   }
    207 
    208   /// Fetches source ranges for the brackets os the array shaping expression.
    209   ArrayRef<SourceRange> getBracketsRanges() const {
    210     return llvm::makeArrayRef(getTrailingObjects<SourceRange>(), NumDims);
    211   }
    212 
    213   /// Fetches base expression of array shaping expression.
    214   Expr *getBase() { return getTrailingObjects<Expr *>()[NumDims]; }
    215   const Expr *getBase() const { return getTrailingObjects<Expr *>()[NumDims]; }
    216 
    217   static bool classof(const Stmt *T) {
    218     return T->getStmtClass() == OMPArrayShapingExprClass;
    219   }
    220 
    221   // Iterators
    222   child_range children() {
    223     Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
    224     return child_range(Begin, Begin + NumDims + 1);
    225   }
    226   const_child_range children() const {
    227     Stmt *const *Begin =
    228         reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
    229     return const_child_range(Begin, Begin + NumDims + 1);
    230   }
    231 };
    232 
    233 /// Helper expressions and declaration for OMPIteratorExpr class for each
    234 /// iteration space.
    235 struct OMPIteratorHelperData {
    236   /// Internal normalized counter.
    237   VarDecl *CounterVD = nullptr;
    238   /// Normalized upper bound. Normalized loop iterates from 0 to Upper with
    239   /// step 1.
    240   Expr *Upper = nullptr;
    241   /// Update expression for the originally specified iteration variable,
    242   /// calculated as VD = Begin + CounterVD * Step;
    243   Expr *Update = nullptr;
    244   /// Updater for the internal counter: ++CounterVD;
    245   Expr *CounterUpdate = nullptr;
    246 };
    247 
    248 /// OpenMP 5.0 [2.1.6 Iterators]
    249 /// Iterators are identifiers that expand to multiple values in the clause on
    250 /// which they appear.
    251 /// The syntax of the iterator modifier is as follows:
    252 /// \code
    253 /// iterator(iterators-definition)
    254 /// \endcode
    255 /// where iterators-definition is one of the following:
    256 /// \code
    257 /// iterator-specifier [, iterators-definition ]
    258 /// \endcode
    259 /// where iterator-specifier is one of the following:
    260 /// \code
    261 /// [ iterator-type ] identifier = range-specification
    262 /// \endcode
    263 /// where identifier is a base language identifier.
    264 /// iterator-type is a type name.
    265 /// range-specification is of the form begin:end[:step], where begin and end are
    266 /// expressions for which their types can be converted to iterator-type and step
    267 /// is an integral expression.
    268 /// In an iterator-specifier, if the iterator-type is not specified then the
    269 /// type of that iterator is of int type.
    270 /// The iterator-type must be an integral or pointer type.
    271 /// The iterator-type must not be const qualified.
    272 class OMPIteratorExpr final
    273     : public Expr,
    274       private llvm::TrailingObjects<OMPIteratorExpr, Decl *, Expr *,
    275                                     SourceLocation, OMPIteratorHelperData> {
    276 public:
    277   /// Iterator range representation begin:end[:step].
    278   struct IteratorRange {
    279     Expr *Begin = nullptr;
    280     Expr *End = nullptr;
    281     Expr *Step = nullptr;
    282   };
    283   /// Iterator definition representation.
    284   struct IteratorDefinition {
    285     Decl *IteratorDecl = nullptr;
    286     IteratorRange Range;
    287     SourceLocation AssignmentLoc;
    288     SourceLocation ColonLoc, SecondColonLoc;
    289   };
    290 
    291 private:
    292   friend TrailingObjects;
    293   friend class ASTStmtReader;
    294   friend class ASTStmtWriter;
    295 
    296   /// Offset in the list of expressions for subelements of the ranges.
    297   enum class RangeExprOffset {
    298     Begin = 0,
    299     End = 1,
    300     Step = 2,
    301     Total = 3,
    302   };
    303   /// Offset in the list of locations for subelements of colon symbols
    304   /// locations.
    305   enum class RangeLocOffset {
    306     AssignLoc = 0,
    307     FirstColonLoc = 1,
    308     SecondColonLoc = 2,
    309     Total = 3,
    310   };
    311   /// Location of 'iterator' keyword.
    312   SourceLocation IteratorKwLoc;
    313   /// Location of '('.
    314   SourceLocation LPLoc;
    315   /// Location of ')'.
    316   SourceLocation RPLoc;
    317   /// Number of iterator definitions.
    318   unsigned NumIterators = 0;
    319 
    320   OMPIteratorExpr(QualType ExprTy, SourceLocation IteratorKwLoc,
    321                   SourceLocation L, SourceLocation R,
    322                   ArrayRef<IteratorDefinition> Data,
    323                   ArrayRef<OMPIteratorHelperData> Helpers);
    324 
    325   /// Construct an empty expression.
    326   explicit OMPIteratorExpr(EmptyShell Shell, unsigned NumIterators)
    327       : Expr(OMPIteratorExprClass, Shell), NumIterators(NumIterators) {}
    328 
    329   /// Sets basic declaration for the specified iterator definition.
    330   void setIteratorDeclaration(unsigned I, Decl *D);
    331 
    332   /// Sets the location of the assignment symbol for the specified iterator
    333   /// definition.
    334   void setAssignmentLoc(unsigned I, SourceLocation Loc);
    335 
    336   /// Sets begin, end and optional step expressions for specified iterator
    337   /// definition.
    338   void setIteratorRange(unsigned I, Expr *Begin, SourceLocation ColonLoc,
    339                         Expr *End, SourceLocation SecondColonLoc, Expr *Step);
    340 
    341   /// Sets helpers for the specified iteration space.
    342   void setHelper(unsigned I, const OMPIteratorHelperData &D);
    343 
    344   unsigned numTrailingObjects(OverloadToken<Decl *>) const {
    345     return NumIterators;
    346   }
    347 
    348   unsigned numTrailingObjects(OverloadToken<Expr *>) const {
    349     return NumIterators * static_cast<int>(RangeExprOffset::Total);
    350   }
    351 
    352   unsigned numTrailingObjects(OverloadToken<SourceLocation>) const {
    353     return NumIterators * static_cast<int>(RangeLocOffset::Total);
    354   }
    355 
    356 public:
    357   static OMPIteratorExpr *Create(const ASTContext &Context, QualType T,
    358                                  SourceLocation IteratorKwLoc, SourceLocation L,
    359                                  SourceLocation R,
    360                                  ArrayRef<IteratorDefinition> Data,
    361                                  ArrayRef<OMPIteratorHelperData> Helpers);
    362 
    363   static OMPIteratorExpr *CreateEmpty(const ASTContext &Context,
    364                                       unsigned NumIterators);
    365 
    366   SourceLocation getLParenLoc() const { return LPLoc; }
    367   void setLParenLoc(SourceLocation L) { LPLoc = L; }
    368 
    369   SourceLocation getRParenLoc() const { return RPLoc; }
    370   void setRParenLoc(SourceLocation L) { RPLoc = L; }
    371 
    372   SourceLocation getIteratorKwLoc() const { return IteratorKwLoc; }
    373   void setIteratorKwLoc(SourceLocation L) { IteratorKwLoc = L; }
    374   SourceLocation getBeginLoc() const LLVM_READONLY { return IteratorKwLoc; }
    375   SourceLocation getEndLoc() const LLVM_READONLY { return RPLoc; }
    376 
    377   /// Gets the iterator declaration for the given iterator.
    378   Decl *getIteratorDecl(unsigned I);
    379   const Decl *getIteratorDecl(unsigned I) const {
    380     return const_cast<OMPIteratorExpr *>(this)->getIteratorDecl(I);
    381   }
    382 
    383   /// Gets the iterator range for the given iterator.
    384   IteratorRange getIteratorRange(unsigned I);
    385   const IteratorRange getIteratorRange(unsigned I) const {
    386     return const_cast<OMPIteratorExpr *>(this)->getIteratorRange(I);
    387   }
    388 
    389   /// Gets the location of '=' for the given iterator definition.
    390   SourceLocation getAssignLoc(unsigned I) const;
    391   /// Gets the location of the first ':' in the range for the given iterator
    392   /// definition.
    393   SourceLocation getColonLoc(unsigned I) const;
    394   /// Gets the location of the second ':' (if any) in the range for the given
    395   /// iteratori definition.
    396   SourceLocation getSecondColonLoc(unsigned I) const;
    397 
    398   /// Returns number of iterator definitions.
    399   unsigned numOfIterators() const { return NumIterators; }
    400 
    401   /// Fetches helper data for the specified iteration space.
    402   OMPIteratorHelperData &getHelper(unsigned I);
    403   const OMPIteratorHelperData &getHelper(unsigned I) const;
    404 
    405   static bool classof(const Stmt *T) {
    406     return T->getStmtClass() == OMPIteratorExprClass;
    407   }
    408 
    409   // Iterators
    410   child_range children() {
    411     Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
    412     return child_range(
    413         Begin, Begin + NumIterators * static_cast<int>(RangeExprOffset::Total));
    414   }
    415   const_child_range children() const {
    416     Stmt *const *Begin =
    417         reinterpret_cast<Stmt *const *>(getTrailingObjects<Expr *>());
    418     return const_child_range(
    419         Begin, Begin + NumIterators * static_cast<int>(RangeExprOffset::Total));
    420   }
    421 };
    422 
    423 } // end namespace clang
    424 
    425 #endif
    426