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