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:
OMPArraySectionExpr(Expr * Base,Expr * LowerBound,Expr * Length,Expr * Stride,QualType Type,ExprValueKind VK,ExprObjectKind OK,SourceLocation ColonLocFirst,SourceLocation ColonLocSecond,SourceLocation RBracketLoc)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.
OMPArraySectionExpr(EmptyShell Shell)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.
getBase()85   Expr *getBase() { return cast<Expr>(SubExprs[BASE]); }
getBase()86   const Expr *getBase() const { return cast<Expr>(SubExprs[BASE]); }
87   /// Set base of the array section.
setBase(Expr * E)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.
getLowerBound()94   Expr *getLowerBound() { return cast_or_null<Expr>(SubExprs[LOWER_BOUND]); }
getLowerBound()95   const Expr *getLowerBound() const {
96     return cast_or_null<Expr>(SubExprs[LOWER_BOUND]);
97   }
98   /// Set lower bound of the array section.
setLowerBound(Expr * E)99   void setLowerBound(Expr *E) { SubExprs[LOWER_BOUND] = E; }
100 
101   /// Get length of array section.
getLength()102   Expr *getLength() { return cast_or_null<Expr>(SubExprs[LENGTH]); }
getLength()103   const Expr *getLength() const { return cast_or_null<Expr>(SubExprs[LENGTH]); }
104   /// Set length of the array section.
setLength(Expr * E)105   void setLength(Expr *E) { SubExprs[LENGTH] = E; }
106 
107   /// Get stride of array section.
getStride()108   Expr *getStride() { return cast_or_null<Expr>(SubExprs[STRIDE]); }
getStride()109   const Expr *getStride() const { return cast_or_null<Expr>(SubExprs[STRIDE]); }
110   /// Set length of the array section.
setStride(Expr * E)111   void setStride(Expr *E) { SubExprs[STRIDE] = E; }
112 
getBeginLoc()113   SourceLocation getBeginLoc() const LLVM_READONLY {
114     return getBase()->getBeginLoc();
115   }
getEndLoc()116   SourceLocation getEndLoc() const LLVM_READONLY { return RBracketLoc; }
117 
getColonLocFirst()118   SourceLocation getColonLocFirst() const { return ColonLocFirst; }
setColonLocFirst(SourceLocation L)119   void setColonLocFirst(SourceLocation L) { ColonLocFirst = L; }
120 
getColonLocSecond()121   SourceLocation getColonLocSecond() const { return ColonLocSecond; }
setColonLocSecond(SourceLocation L)122   void setColonLocSecond(SourceLocation L) { ColonLocSecond = L; }
123 
getRBracketLoc()124   SourceLocation getRBracketLoc() const { return RBracketLoc; }
setRBracketLoc(SourceLocation L)125   void setRBracketLoc(SourceLocation L) { RBracketLoc = L; }
126 
getExprLoc()127   SourceLocation getExprLoc() const LLVM_READONLY {
128     return getBase()->getExprLoc();
129   }
130 
classof(const Stmt * T)131   static bool classof(const Stmt *T) {
132     return T->getStmtClass() == OMPArraySectionExprClass;
133   }
134 
children()135   child_range children() {
136     return child_range(&SubExprs[BASE], &SubExprs[END_EXPR]);
137   }
138 
children()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.
OMPArrayShapingExpr(EmptyShell Shell,unsigned NumDims)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.
setBase(Expr * Op)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 
numTrailingObjects(OverloadToken<Expr * >)174   unsigned numTrailingObjects(OverloadToken<Expr *>) const {
175     // Add an extra one for the base expression.
176     return NumDims + 1;
177   }
178 
numTrailingObjects(OverloadToken<SourceRange>)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 
getLParenLoc()192   SourceLocation getLParenLoc() const { return LPLoc; }
setLParenLoc(SourceLocation L)193   void setLParenLoc(SourceLocation L) { LPLoc = L; }
194 
getRParenLoc()195   SourceLocation getRParenLoc() const { return RPLoc; }
setRParenLoc(SourceLocation L)196   void setRParenLoc(SourceLocation L) { RPLoc = L; }
197 
getBeginLoc()198   SourceLocation getBeginLoc() const LLVM_READONLY { return LPLoc; }
getEndLoc()199   SourceLocation getEndLoc() const LLVM_READONLY {
200     return getBase()->getEndLoc();
201   }
202 
203   /// Fetches the dimensions for array shaping expression.
getDimensions()204   ArrayRef<Expr *> getDimensions() const {
205     return llvm::ArrayRef(getTrailingObjects<Expr *>(), NumDims);
206   }
207 
208   /// Fetches source ranges for the brackets os the array shaping expression.
getBracketsRanges()209   ArrayRef<SourceRange> getBracketsRanges() const {
210     return llvm::ArrayRef(getTrailingObjects<SourceRange>(), NumDims);
211   }
212 
213   /// Fetches base expression of array shaping expression.
getBase()214   Expr *getBase() { return getTrailingObjects<Expr *>()[NumDims]; }
getBase()215   const Expr *getBase() const { return getTrailingObjects<Expr *>()[NumDims]; }
216 
classof(const Stmt * T)217   static bool classof(const Stmt *T) {
218     return T->getStmtClass() == OMPArrayShapingExprClass;
219   }
220 
221   // Iterators
children()222   child_range children() {
223     Stmt **Begin = reinterpret_cast<Stmt **>(getTrailingObjects<Expr *>());
224     return child_range(Begin, Begin + NumDims + 1);
225   }
children()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.
OMPIteratorExpr(EmptyShell Shell,unsigned NumIterators)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 
numTrailingObjects(OverloadToken<Decl * >)344   unsigned numTrailingObjects(OverloadToken<Decl *>) const {
345     return NumIterators;
346   }
347 
numTrailingObjects(OverloadToken<Expr * >)348   unsigned numTrailingObjects(OverloadToken<Expr *>) const {
349     return NumIterators * static_cast<int>(RangeExprOffset::Total);
350   }
351 
numTrailingObjects(OverloadToken<SourceLocation>)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 
getLParenLoc()366   SourceLocation getLParenLoc() const { return LPLoc; }
setLParenLoc(SourceLocation L)367   void setLParenLoc(SourceLocation L) { LPLoc = L; }
368 
getRParenLoc()369   SourceLocation getRParenLoc() const { return RPLoc; }
setRParenLoc(SourceLocation L)370   void setRParenLoc(SourceLocation L) { RPLoc = L; }
371 
getIteratorKwLoc()372   SourceLocation getIteratorKwLoc() const { return IteratorKwLoc; }
setIteratorKwLoc(SourceLocation L)373   void setIteratorKwLoc(SourceLocation L) { IteratorKwLoc = L; }
getBeginLoc()374   SourceLocation getBeginLoc() const LLVM_READONLY { return IteratorKwLoc; }
getEndLoc()375   SourceLocation getEndLoc() const LLVM_READONLY { return RPLoc; }
376 
377   /// Gets the iterator declaration for the given iterator.
378   Decl *getIteratorDecl(unsigned I);
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);
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.
numOfIterators()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 
classof(const Stmt * T)405   static bool classof(const Stmt *T) {
406     return T->getStmtClass() == OMPIteratorExprClass;
407   }
408 
409   // Iterators
children()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   }
children()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