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
19namespace 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.
56class 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
63public:
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.
146class 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
183public:
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::ArrayRef(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::ArrayRef(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.
235struct 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.
272class OMPIteratorExpr final
273    : public Expr,
274      private llvm::TrailingObjects<OMPIteratorExpr, Decl *, Expr *,
275                                    SourceLocation, OMPIteratorHelperData> {
276public:
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
291private:
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
356public:
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