1 //===- StmtOpenACC.h - Classes for OpenACC directives ----------*- 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 /// \file 9 /// This file defines OpenACC AST classes for statement-level contructs. 10 /// 11 //===----------------------------------------------------------------------===// 12 13 #ifndef LLVM_CLANG_AST_STMTOPENACC_H 14 #define LLVM_CLANG_AST_STMTOPENACC_H 15 16 #include "clang/AST/OpenACCClause.h" 17 #include "clang/AST/Stmt.h" 18 #include "clang/Basic/OpenACCKinds.h" 19 #include "clang/Basic/SourceLocation.h" 20 #include <memory> 21 22 namespace clang { 23 /// This is the base class for an OpenACC statement-level construct, other 24 /// construct types are expected to inherit from this. 25 class OpenACCConstructStmt : public Stmt { 26 friend class ASTStmtWriter; 27 friend class ASTStmtReader; 28 /// The directive kind. Each implementation of this interface should handle 29 /// specific kinds. 30 OpenACCDirectiveKind Kind = OpenACCDirectiveKind::Invalid; 31 /// The location of the directive statement, from the '#' to the last token of 32 /// the directive. 33 SourceRange Range; 34 /// The location of the directive name. 35 SourceLocation DirectiveLoc; 36 37 /// The list of clauses. This is stored here as an ArrayRef, as this is the 38 /// most convienient place to access the list, however the list itself should 39 /// be stored in leaf nodes, likely in trailing-storage. 40 MutableArrayRef<const OpenACCClause *> Clauses; 41 42 protected: 43 OpenACCConstructStmt(StmtClass SC, OpenACCDirectiveKind K, 44 SourceLocation Start, SourceLocation DirectiveLoc, 45 SourceLocation End) 46 : Stmt(SC), Kind(K), Range(Start, End), DirectiveLoc(DirectiveLoc) {} 47 48 // Used only for initialization, the leaf class can initialize this to 49 // trailing storage. 50 void setClauseList(MutableArrayRef<const OpenACCClause *> NewClauses) { 51 assert(Clauses.empty() && "Cannot change clause list"); 52 Clauses = NewClauses; 53 } 54 55 public: 56 OpenACCDirectiveKind getDirectiveKind() const { return Kind; } 57 58 static bool classof(const Stmt *S) { 59 return S->getStmtClass() >= firstOpenACCConstructStmtConstant && 60 S->getStmtClass() <= lastOpenACCConstructStmtConstant; 61 } 62 63 SourceLocation getBeginLoc() const { return Range.getBegin(); } 64 SourceLocation getEndLoc() const { return Range.getEnd(); } 65 SourceLocation getDirectiveLoc() const { return DirectiveLoc; } 66 ArrayRef<const OpenACCClause *> clauses() const { return Clauses; } 67 68 child_range children() { 69 return child_range(child_iterator(), child_iterator()); 70 } 71 72 const_child_range children() const { 73 return const_cast<OpenACCConstructStmt *>(this)->children(); 74 } 75 }; 76 77 /// This is a base class for any OpenACC statement-level constructs that have an 78 /// associated statement. This class is not intended to be instantiated, but is 79 /// a convenient place to hold the associated statement. 80 class OpenACCAssociatedStmtConstruct : public OpenACCConstructStmt { 81 friend class ASTStmtWriter; 82 friend class ASTStmtReader; 83 template <typename Derived> friend class RecursiveASTVisitor; 84 Stmt *AssociatedStmt = nullptr; 85 86 protected: 87 OpenACCAssociatedStmtConstruct(StmtClass SC, OpenACCDirectiveKind K, 88 SourceLocation Start, 89 SourceLocation DirectiveLoc, 90 SourceLocation End, Stmt *AssocStmt) 91 : OpenACCConstructStmt(SC, K, Start, DirectiveLoc, End), 92 AssociatedStmt(AssocStmt) {} 93 94 void setAssociatedStmt(Stmt *S) { AssociatedStmt = S; } 95 Stmt *getAssociatedStmt() { return AssociatedStmt; } 96 const Stmt *getAssociatedStmt() const { 97 return const_cast<OpenACCAssociatedStmtConstruct *>(this) 98 ->getAssociatedStmt(); 99 } 100 101 public: 102 static bool classof(const Stmt *T) { 103 return false; 104 } 105 106 child_range children() { 107 if (getAssociatedStmt()) 108 return child_range(&AssociatedStmt, &AssociatedStmt + 1); 109 return child_range(child_iterator(), child_iterator()); 110 } 111 112 const_child_range children() const { 113 return const_cast<OpenACCAssociatedStmtConstruct *>(this)->children(); 114 } 115 }; 116 117 /// This class represents a compute construct, representing a 'Kind' of 118 /// `parallel', 'serial', or 'kernel'. These constructs are associated with a 119 /// 'structured block', defined as: 120 /// 121 /// in C or C++, an executable statement, possibly compound, with a single 122 /// entry at the top and a single exit at the bottom 123 /// 124 /// At the moment there is no real motivation to have a different AST node for 125 /// those three, as they are semantically identical, and have only minor 126 /// differences in the permitted list of clauses, which can be differentiated by 127 /// the 'Kind'. 128 class OpenACCComputeConstruct final 129 : public OpenACCAssociatedStmtConstruct, 130 private llvm::TrailingObjects<OpenACCComputeConstruct, 131 const OpenACCClause *> { 132 friend class ASTStmtWriter; 133 friend class ASTStmtReader; 134 friend class ASTContext; 135 friend TrailingObjects; 136 OpenACCComputeConstruct(unsigned NumClauses) 137 : OpenACCAssociatedStmtConstruct( 138 OpenACCComputeConstructClass, OpenACCDirectiveKind::Invalid, 139 SourceLocation{}, SourceLocation{}, SourceLocation{}, 140 /*AssociatedStmt=*/nullptr) { 141 // We cannot send the TrailingObjects storage to the base class (which holds 142 // a reference to the data) until it is constructed, so we have to set it 143 // separately here. 144 std::uninitialized_value_construct( 145 getTrailingObjects<const OpenACCClause *>(), 146 getTrailingObjects<const OpenACCClause *>() + NumClauses); 147 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 148 NumClauses)); 149 } 150 151 OpenACCComputeConstruct(OpenACCDirectiveKind K, SourceLocation Start, 152 SourceLocation DirectiveLoc, SourceLocation End, 153 ArrayRef<const OpenACCClause *> Clauses, 154 Stmt *StructuredBlock) 155 : OpenACCAssociatedStmtConstruct(OpenACCComputeConstructClass, K, Start, 156 DirectiveLoc, End, StructuredBlock) { 157 assert(isOpenACCComputeDirectiveKind(K) && 158 "Only parallel, serial, and kernels constructs should be " 159 "represented by this type"); 160 161 // Initialize the trailing storage. 162 std::uninitialized_copy(Clauses.begin(), Clauses.end(), 163 getTrailingObjects<const OpenACCClause *>()); 164 165 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 166 Clauses.size())); 167 } 168 169 void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } 170 171 public: 172 static bool classof(const Stmt *T) { 173 return T->getStmtClass() == OpenACCComputeConstructClass; 174 } 175 176 static OpenACCComputeConstruct *CreateEmpty(const ASTContext &C, 177 unsigned NumClauses); 178 static OpenACCComputeConstruct * 179 Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation BeginLoc, 180 SourceLocation DirectiveLoc, SourceLocation EndLoc, 181 ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock); 182 183 Stmt *getStructuredBlock() { return getAssociatedStmt(); } 184 const Stmt *getStructuredBlock() const { 185 return const_cast<OpenACCComputeConstruct *>(this)->getStructuredBlock(); 186 } 187 }; 188 /// This class represents a 'loop' construct. The 'loop' construct applies to a 189 /// 'for' loop (or range-for loop), and is optionally associated with a Compute 190 /// Construct. 191 class OpenACCLoopConstruct final 192 : public OpenACCAssociatedStmtConstruct, 193 private llvm::TrailingObjects<OpenACCLoopConstruct, 194 const OpenACCClause *> { 195 // The compute/combined construct kind this loop is associated with, or 196 // invalid if this is an orphaned loop construct. 197 OpenACCDirectiveKind ParentComputeConstructKind = 198 OpenACCDirectiveKind::Invalid; 199 200 friend class ASTStmtWriter; 201 friend class ASTStmtReader; 202 friend class ASTContext; 203 friend class OpenACCAssociatedStmtConstruct; 204 friend class OpenACCCombinedConstruct; 205 friend class OpenACCComputeConstruct; 206 friend TrailingObjects; 207 208 OpenACCLoopConstruct(unsigned NumClauses); 209 210 OpenACCLoopConstruct(OpenACCDirectiveKind ParentKind, SourceLocation Start, 211 SourceLocation DirLoc, SourceLocation End, 212 ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop); 213 214 public: 215 static bool classof(const Stmt *T) { 216 return T->getStmtClass() == OpenACCLoopConstructClass; 217 } 218 219 static OpenACCLoopConstruct *CreateEmpty(const ASTContext &C, 220 unsigned NumClauses); 221 222 static OpenACCLoopConstruct * 223 Create(const ASTContext &C, OpenACCDirectiveKind ParentKind, 224 SourceLocation BeginLoc, SourceLocation DirLoc, SourceLocation EndLoc, 225 ArrayRef<const OpenACCClause *> Clauses, Stmt *Loop); 226 227 Stmt *getLoop() { return getAssociatedStmt(); } 228 const Stmt *getLoop() const { 229 return const_cast<OpenACCLoopConstruct *>(this)->getLoop(); 230 } 231 232 /// OpenACC 3.3 2.9: 233 /// An orphaned loop construct is a loop construct that is not lexically 234 /// enclosed within a compute construct. The parent compute construct of a 235 /// loop construct is the nearest compute construct that lexically contains 236 /// the loop construct. 237 bool isOrphanedLoopConstruct() const { 238 return ParentComputeConstructKind == OpenACCDirectiveKind::Invalid; 239 } 240 241 OpenACCDirectiveKind getParentComputeConstructKind() const { 242 return ParentComputeConstructKind; 243 } 244 }; 245 246 // This class represents a 'combined' construct, which has a bunch of rules 247 // shared with both loop and compute constructs. 248 class OpenACCCombinedConstruct final 249 : public OpenACCAssociatedStmtConstruct, 250 private llvm::TrailingObjects<OpenACCCombinedConstruct, 251 const OpenACCClause *> { 252 friend TrailingObjects; 253 OpenACCCombinedConstruct(unsigned NumClauses) 254 : OpenACCAssociatedStmtConstruct( 255 OpenACCCombinedConstructClass, OpenACCDirectiveKind::Invalid, 256 SourceLocation{}, SourceLocation{}, SourceLocation{}, 257 /*AssociatedStmt=*/nullptr) { 258 std::uninitialized_value_construct( 259 getTrailingObjects<const OpenACCClause *>(), 260 getTrailingObjects<const OpenACCClause *>() + NumClauses); 261 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 262 NumClauses)); 263 } 264 265 OpenACCCombinedConstruct(OpenACCDirectiveKind K, SourceLocation Start, 266 SourceLocation DirectiveLoc, SourceLocation End, 267 ArrayRef<const OpenACCClause *> Clauses, 268 Stmt *StructuredBlock) 269 : OpenACCAssociatedStmtConstruct(OpenACCCombinedConstructClass, K, Start, 270 DirectiveLoc, End, StructuredBlock) { 271 assert(isOpenACCCombinedDirectiveKind(K) && 272 "Only parallel loop, serial loop, and kernels loop constructs " 273 "should be represented by this type"); 274 275 std::uninitialized_copy(Clauses.begin(), Clauses.end(), 276 getTrailingObjects<const OpenACCClause *>()); 277 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 278 Clauses.size())); 279 } 280 void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } 281 282 public: 283 static bool classof(const Stmt *T) { 284 return T->getStmtClass() == OpenACCCombinedConstructClass; 285 } 286 287 static OpenACCCombinedConstruct *CreateEmpty(const ASTContext &C, 288 unsigned NumClauses); 289 static OpenACCCombinedConstruct * 290 Create(const ASTContext &C, OpenACCDirectiveKind K, SourceLocation Start, 291 SourceLocation DirectiveLoc, SourceLocation End, 292 ArrayRef<const OpenACCClause *> Clauses, Stmt *StructuredBlock); 293 Stmt *getLoop() { return getAssociatedStmt(); } 294 const Stmt *getLoop() const { 295 return const_cast<OpenACCCombinedConstruct *>(this)->getLoop(); 296 } 297 }; 298 299 // This class represents a 'data' construct, which has an associated statement 300 // and clauses, but is otherwise pretty simple. 301 class OpenACCDataConstruct final 302 : public OpenACCAssociatedStmtConstruct, 303 private llvm::TrailingObjects<OpenACCDataConstruct, 304 const OpenACCClause *> { 305 friend TrailingObjects; 306 OpenACCDataConstruct(unsigned NumClauses) 307 : OpenACCAssociatedStmtConstruct( 308 OpenACCDataConstructClass, OpenACCDirectiveKind::Data, 309 SourceLocation{}, SourceLocation{}, SourceLocation{}, 310 /*AssociatedStmt=*/nullptr) { 311 std::uninitialized_value_construct( 312 getTrailingObjects<const OpenACCClause *>(), 313 getTrailingObjects<const OpenACCClause *>() + NumClauses); 314 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 315 NumClauses)); 316 } 317 318 OpenACCDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc, 319 SourceLocation End, 320 ArrayRef<const OpenACCClause *> Clauses, 321 Stmt *StructuredBlock) 322 : OpenACCAssociatedStmtConstruct(OpenACCDataConstructClass, 323 OpenACCDirectiveKind::Data, Start, 324 DirectiveLoc, End, StructuredBlock) { 325 std::uninitialized_copy(Clauses.begin(), Clauses.end(), 326 getTrailingObjects<const OpenACCClause *>()); 327 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 328 Clauses.size())); 329 } 330 void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } 331 332 public: 333 static bool classof(const Stmt *T) { 334 return T->getStmtClass() == OpenACCDataConstructClass; 335 } 336 337 static OpenACCDataConstruct *CreateEmpty(const ASTContext &C, 338 unsigned NumClauses); 339 static OpenACCDataConstruct *Create(const ASTContext &C, SourceLocation Start, 340 SourceLocation DirectiveLoc, 341 SourceLocation End, 342 ArrayRef<const OpenACCClause *> Clauses, 343 Stmt *StructuredBlock); 344 Stmt *getStructuredBlock() { return getAssociatedStmt(); } 345 const Stmt *getStructuredBlock() const { 346 return const_cast<OpenACCDataConstruct *>(this)->getStructuredBlock(); 347 } 348 }; 349 // This class represents a 'enter data' construct, which JUST has clauses. 350 class OpenACCEnterDataConstruct final 351 : public OpenACCConstructStmt, 352 private llvm::TrailingObjects<OpenACCEnterDataConstruct, 353 const OpenACCClause *> { 354 friend TrailingObjects; 355 OpenACCEnterDataConstruct(unsigned NumClauses) 356 : OpenACCConstructStmt(OpenACCEnterDataConstructClass, 357 OpenACCDirectiveKind::EnterData, SourceLocation{}, 358 SourceLocation{}, SourceLocation{}) { 359 std::uninitialized_value_construct( 360 getTrailingObjects<const OpenACCClause *>(), 361 getTrailingObjects<const OpenACCClause *>() + NumClauses); 362 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 363 NumClauses)); 364 } 365 OpenACCEnterDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc, 366 SourceLocation End, 367 ArrayRef<const OpenACCClause *> Clauses) 368 : OpenACCConstructStmt(OpenACCEnterDataConstructClass, 369 OpenACCDirectiveKind::EnterData, Start, 370 DirectiveLoc, End) { 371 std::uninitialized_copy(Clauses.begin(), Clauses.end(), 372 getTrailingObjects<const OpenACCClause *>()); 373 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 374 Clauses.size())); 375 } 376 377 public: 378 static bool classof(const Stmt *T) { 379 return T->getStmtClass() == OpenACCEnterDataConstructClass; 380 } 381 static OpenACCEnterDataConstruct *CreateEmpty(const ASTContext &C, 382 unsigned NumClauses); 383 static OpenACCEnterDataConstruct * 384 Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, 385 SourceLocation End, ArrayRef<const OpenACCClause *> Clauses); 386 }; 387 // This class represents a 'exit data' construct, which JUST has clauses. 388 class OpenACCExitDataConstruct final 389 : public OpenACCConstructStmt, 390 private llvm::TrailingObjects<OpenACCExitDataConstruct, 391 const OpenACCClause *> { 392 friend TrailingObjects; 393 OpenACCExitDataConstruct(unsigned NumClauses) 394 : OpenACCConstructStmt(OpenACCExitDataConstructClass, 395 OpenACCDirectiveKind::ExitData, SourceLocation{}, 396 SourceLocation{}, SourceLocation{}) { 397 std::uninitialized_value_construct( 398 getTrailingObjects<const OpenACCClause *>(), 399 getTrailingObjects<const OpenACCClause *>() + NumClauses); 400 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 401 NumClauses)); 402 } 403 OpenACCExitDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc, 404 SourceLocation End, 405 ArrayRef<const OpenACCClause *> Clauses) 406 : OpenACCConstructStmt(OpenACCExitDataConstructClass, 407 OpenACCDirectiveKind::ExitData, Start, 408 DirectiveLoc, End) { 409 std::uninitialized_copy(Clauses.begin(), Clauses.end(), 410 getTrailingObjects<const OpenACCClause *>()); 411 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 412 Clauses.size())); 413 } 414 415 public: 416 static bool classof(const Stmt *T) { 417 return T->getStmtClass() == OpenACCExitDataConstructClass; 418 } 419 static OpenACCExitDataConstruct *CreateEmpty(const ASTContext &C, 420 unsigned NumClauses); 421 static OpenACCExitDataConstruct * 422 Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, 423 SourceLocation End, ArrayRef<const OpenACCClause *> Clauses); 424 }; 425 // This class represents a 'host_data' construct, which has an associated 426 // statement and clauses, but is otherwise pretty simple. 427 class OpenACCHostDataConstruct final 428 : public OpenACCAssociatedStmtConstruct, 429 private llvm::TrailingObjects<OpenACCHostDataConstruct, 430 const OpenACCClause *> { 431 friend TrailingObjects; 432 OpenACCHostDataConstruct(unsigned NumClauses) 433 : OpenACCAssociatedStmtConstruct( 434 OpenACCHostDataConstructClass, OpenACCDirectiveKind::HostData, 435 SourceLocation{}, SourceLocation{}, SourceLocation{}, 436 /*AssociatedStmt=*/nullptr) { 437 std::uninitialized_value_construct( 438 getTrailingObjects<const OpenACCClause *>(), 439 getTrailingObjects<const OpenACCClause *>() + NumClauses); 440 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 441 NumClauses)); 442 } 443 OpenACCHostDataConstruct(SourceLocation Start, SourceLocation DirectiveLoc, 444 SourceLocation End, 445 ArrayRef<const OpenACCClause *> Clauses, 446 Stmt *StructuredBlock) 447 : OpenACCAssociatedStmtConstruct(OpenACCHostDataConstructClass, 448 OpenACCDirectiveKind::HostData, Start, 449 DirectiveLoc, End, StructuredBlock) { 450 std::uninitialized_copy(Clauses.begin(), Clauses.end(), 451 getTrailingObjects<const OpenACCClause *>()); 452 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 453 Clauses.size())); 454 } 455 void setStructuredBlock(Stmt *S) { setAssociatedStmt(S); } 456 457 public: 458 static bool classof(const Stmt *T) { 459 return T->getStmtClass() == OpenACCHostDataConstructClass; 460 } 461 static OpenACCHostDataConstruct *CreateEmpty(const ASTContext &C, 462 unsigned NumClauses); 463 static OpenACCHostDataConstruct * 464 Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, 465 SourceLocation End, ArrayRef<const OpenACCClause *> Clauses, 466 Stmt *StructuredBlock); 467 Stmt *getStructuredBlock() { return getAssociatedStmt(); } 468 const Stmt *getStructuredBlock() const { 469 return const_cast<OpenACCHostDataConstruct *>(this)->getStructuredBlock(); 470 } 471 }; 472 473 // This class represents a 'wait' construct, which has some expressions plus a 474 // clause list. 475 class OpenACCWaitConstruct final 476 : public OpenACCConstructStmt, 477 private llvm::TrailingObjects<OpenACCWaitConstruct, Expr *, 478 OpenACCClause *> { 479 // FIXME: We should be storing a `const OpenACCClause *` to be consistent with 480 // the rest of the constructs, but TrailingObjects doesn't allow for mixing 481 // constness in its implementation of `getTrailingObjects`. 482 483 friend TrailingObjects; 484 friend class ASTStmtWriter; 485 friend class ASTStmtReader; 486 // Locations of the left and right parens of the 'wait-argument' 487 // expression-list. 488 SourceLocation LParenLoc, RParenLoc; 489 // Location of the 'queues' keyword, if present. 490 SourceLocation QueuesLoc; 491 492 // Number of the expressions being represented. Index '0' is always the 493 // 'devnum' expression, even if it not present. 494 unsigned NumExprs = 0; 495 496 OpenACCWaitConstruct(unsigned NumExprs, unsigned NumClauses) 497 : OpenACCConstructStmt(OpenACCWaitConstructClass, 498 OpenACCDirectiveKind::Wait, SourceLocation{}, 499 SourceLocation{}, SourceLocation{}), 500 NumExprs(NumExprs) { 501 assert(NumExprs >= 1 && 502 "NumExprs should always be >= 1 because the 'devnum' " 503 "expr is represented by a null if necessary"); 504 std::uninitialized_value_construct(getExprPtr(), 505 getExprPtr() + NumExprs); 506 std::uninitialized_value_construct(getTrailingObjects<OpenACCClause *>(), 507 getTrailingObjects<OpenACCClause *>() + 508 NumClauses); 509 setClauseList(MutableArrayRef(const_cast<const OpenACCClause **>( 510 getTrailingObjects<OpenACCClause *>()), 511 NumClauses)); 512 } 513 514 OpenACCWaitConstruct(SourceLocation Start, SourceLocation DirectiveLoc, 515 SourceLocation LParenLoc, Expr *DevNumExpr, 516 SourceLocation QueuesLoc, ArrayRef<Expr *> QueueIdExprs, 517 SourceLocation RParenLoc, SourceLocation End, 518 ArrayRef<const OpenACCClause *> Clauses) 519 : OpenACCConstructStmt(OpenACCWaitConstructClass, 520 OpenACCDirectiveKind::Wait, Start, DirectiveLoc, 521 End), 522 LParenLoc(LParenLoc), RParenLoc(RParenLoc), QueuesLoc(QueuesLoc), 523 NumExprs(QueueIdExprs.size() + 1) { 524 assert(NumExprs >= 1 && 525 "NumExprs should always be >= 1 because the 'devnum' " 526 "expr is represented by a null if necessary"); 527 528 std::uninitialized_copy(&DevNumExpr, &DevNumExpr + 1, 529 getExprPtr()); 530 std::uninitialized_copy(QueueIdExprs.begin(), QueueIdExprs.end(), 531 getExprPtr() + 1); 532 533 std::uninitialized_copy(const_cast<OpenACCClause **>(Clauses.begin()), 534 const_cast<OpenACCClause **>(Clauses.end()), 535 getTrailingObjects<OpenACCClause *>()); 536 setClauseList(MutableArrayRef(const_cast<const OpenACCClause **>( 537 getTrailingObjects<OpenACCClause *>()), 538 Clauses.size())); 539 } 540 541 size_t numTrailingObjects(OverloadToken<Expr *>) const { return NumExprs; } 542 size_t numTrailingObjects(OverloadToken<const OpenACCClause *>) const { 543 return clauses().size(); 544 } 545 546 Expr **getExprPtr() const { 547 return const_cast<Expr**>(getTrailingObjects<Expr *>()); 548 } 549 550 llvm::ArrayRef<Expr *> getExprs() const { 551 return llvm::ArrayRef<Expr *>(getExprPtr(), NumExprs); 552 } 553 554 llvm::ArrayRef<Expr *> getExprs() { 555 return llvm::ArrayRef<Expr *>(getExprPtr(), NumExprs); 556 } 557 558 public: 559 static bool classof(const Stmt *T) { 560 return T->getStmtClass() == OpenACCWaitConstructClass; 561 } 562 563 static OpenACCWaitConstruct * 564 CreateEmpty(const ASTContext &C, unsigned NumExprs, unsigned NumClauses); 565 566 static OpenACCWaitConstruct * 567 Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, 568 SourceLocation LParenLoc, Expr *DevNumExpr, SourceLocation QueuesLoc, 569 ArrayRef<Expr *> QueueIdExprs, SourceLocation RParenLoc, 570 SourceLocation End, ArrayRef<const OpenACCClause *> Clauses); 571 572 SourceLocation getLParenLoc() const { return LParenLoc; } 573 SourceLocation getRParenLoc() const { return RParenLoc; } 574 bool hasQueuesTag() const { return !QueuesLoc.isInvalid(); } 575 SourceLocation getQueuesLoc() const { return QueuesLoc; } 576 577 bool hasDevNumExpr() const { return getExprs()[0]; } 578 Expr *getDevNumExpr() const { return getExprs()[0]; } 579 llvm::ArrayRef<Expr *> getQueueIdExprs() { return getExprs().drop_front(); } 580 llvm::ArrayRef<Expr *> getQueueIdExprs() const { 581 return getExprs().drop_front(); 582 } 583 584 child_range children() { 585 Stmt **Begin = reinterpret_cast<Stmt **>(getExprPtr()); 586 return child_range(Begin, Begin + NumExprs); 587 } 588 589 const_child_range children() const { 590 Stmt *const *Begin = 591 reinterpret_cast<Stmt *const *>(getExprPtr()); 592 return const_child_range(Begin, Begin + NumExprs); 593 } 594 }; 595 596 // This class represents an 'init' construct, which has just a clause list. 597 class OpenACCInitConstruct final 598 : public OpenACCConstructStmt, 599 private llvm::TrailingObjects<OpenACCInitConstruct, 600 const OpenACCClause *> { 601 friend TrailingObjects; 602 OpenACCInitConstruct(unsigned NumClauses) 603 : OpenACCConstructStmt(OpenACCInitConstructClass, 604 OpenACCDirectiveKind::Init, SourceLocation{}, 605 SourceLocation{}, SourceLocation{}) { 606 std::uninitialized_value_construct( 607 getTrailingObjects<const OpenACCClause *>(), 608 getTrailingObjects<const OpenACCClause *>() + NumClauses); 609 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 610 NumClauses)); 611 } 612 OpenACCInitConstruct(SourceLocation Start, SourceLocation DirectiveLoc, 613 SourceLocation End, 614 ArrayRef<const OpenACCClause *> Clauses) 615 : OpenACCConstructStmt(OpenACCInitConstructClass, 616 OpenACCDirectiveKind::Init, Start, DirectiveLoc, 617 End) { 618 std::uninitialized_copy(Clauses.begin(), Clauses.end(), 619 getTrailingObjects<const OpenACCClause *>()); 620 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 621 Clauses.size())); 622 } 623 624 public: 625 static bool classof(const Stmt *T) { 626 return T->getStmtClass() == OpenACCInitConstructClass; 627 } 628 static OpenACCInitConstruct *CreateEmpty(const ASTContext &C, 629 unsigned NumClauses); 630 static OpenACCInitConstruct *Create(const ASTContext &C, SourceLocation Start, 631 SourceLocation DirectiveLoc, 632 SourceLocation End, 633 ArrayRef<const OpenACCClause *> Clauses); 634 }; 635 636 // This class represents a 'shutdown' construct, which has just a clause list. 637 class OpenACCShutdownConstruct final 638 : public OpenACCConstructStmt, 639 private llvm::TrailingObjects<OpenACCShutdownConstruct, 640 const OpenACCClause *> { 641 friend TrailingObjects; 642 OpenACCShutdownConstruct(unsigned NumClauses) 643 : OpenACCConstructStmt(OpenACCShutdownConstructClass, 644 OpenACCDirectiveKind::Shutdown, SourceLocation{}, 645 SourceLocation{}, SourceLocation{}) { 646 std::uninitialized_value_construct( 647 getTrailingObjects<const OpenACCClause *>(), 648 getTrailingObjects<const OpenACCClause *>() + NumClauses); 649 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 650 NumClauses)); 651 } 652 OpenACCShutdownConstruct(SourceLocation Start, SourceLocation DirectiveLoc, 653 SourceLocation End, 654 ArrayRef<const OpenACCClause *> Clauses) 655 : OpenACCConstructStmt(OpenACCShutdownConstructClass, 656 OpenACCDirectiveKind::Shutdown, Start, 657 DirectiveLoc, End) { 658 std::uninitialized_copy(Clauses.begin(), Clauses.end(), 659 getTrailingObjects<const OpenACCClause *>()); 660 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 661 Clauses.size())); 662 } 663 664 public: 665 static bool classof(const Stmt *T) { 666 return T->getStmtClass() == OpenACCShutdownConstructClass; 667 } 668 static OpenACCShutdownConstruct *CreateEmpty(const ASTContext &C, 669 unsigned NumClauses); 670 static OpenACCShutdownConstruct * 671 Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, 672 SourceLocation End, ArrayRef<const OpenACCClause *> Clauses); 673 }; 674 675 // This class represents a 'set' construct, which has just a clause list. 676 class OpenACCSetConstruct final 677 : public OpenACCConstructStmt, 678 private llvm::TrailingObjects<OpenACCSetConstruct, 679 const OpenACCClause *> { 680 friend TrailingObjects; 681 OpenACCSetConstruct(unsigned NumClauses) 682 : OpenACCConstructStmt(OpenACCSetConstructClass, 683 OpenACCDirectiveKind::Set, SourceLocation{}, 684 SourceLocation{}, SourceLocation{}) { 685 std::uninitialized_value_construct( 686 getTrailingObjects<const OpenACCClause *>(), 687 getTrailingObjects<const OpenACCClause *>() + NumClauses); 688 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 689 NumClauses)); 690 } 691 692 OpenACCSetConstruct(SourceLocation Start, SourceLocation DirectiveLoc, 693 SourceLocation End, 694 ArrayRef<const OpenACCClause *> Clauses) 695 : OpenACCConstructStmt(OpenACCSetConstructClass, 696 OpenACCDirectiveKind::Set, Start, DirectiveLoc, 697 End) { 698 std::uninitialized_copy(Clauses.begin(), Clauses.end(), 699 getTrailingObjects<const OpenACCClause *>()); 700 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 701 Clauses.size())); 702 } 703 704 public: 705 static bool classof(const Stmt *T) { 706 return T->getStmtClass() == OpenACCSetConstructClass; 707 } 708 static OpenACCSetConstruct *CreateEmpty(const ASTContext &C, 709 unsigned NumClauses); 710 static OpenACCSetConstruct *Create(const ASTContext &C, SourceLocation Start, 711 SourceLocation DirectiveLoc, 712 SourceLocation End, 713 ArrayRef<const OpenACCClause *> Clauses); 714 }; 715 // This class represents an 'update' construct, which has just a clause list. 716 class OpenACCUpdateConstruct final 717 : public OpenACCConstructStmt, 718 private llvm::TrailingObjects<OpenACCUpdateConstruct, 719 const OpenACCClause *> { 720 friend TrailingObjects; 721 OpenACCUpdateConstruct(unsigned NumClauses) 722 : OpenACCConstructStmt(OpenACCUpdateConstructClass, 723 OpenACCDirectiveKind::Update, SourceLocation{}, 724 SourceLocation{}, SourceLocation{}) { 725 std::uninitialized_value_construct( 726 getTrailingObjects<const OpenACCClause *>(), 727 getTrailingObjects<const OpenACCClause *>() + NumClauses); 728 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 729 NumClauses)); 730 } 731 732 OpenACCUpdateConstruct(SourceLocation Start, SourceLocation DirectiveLoc, 733 SourceLocation End, 734 ArrayRef<const OpenACCClause *> Clauses) 735 : OpenACCConstructStmt(OpenACCUpdateConstructClass, 736 OpenACCDirectiveKind::Update, Start, DirectiveLoc, 737 End) { 738 std::uninitialized_copy(Clauses.begin(), Clauses.end(), 739 getTrailingObjects<const OpenACCClause *>()); 740 setClauseList(MutableArrayRef(getTrailingObjects<const OpenACCClause *>(), 741 Clauses.size())); 742 } 743 744 public: 745 static bool classof(const Stmt *T) { 746 return T->getStmtClass() == OpenACCUpdateConstructClass; 747 } 748 static OpenACCUpdateConstruct *CreateEmpty(const ASTContext &C, 749 unsigned NumClauses); 750 static OpenACCUpdateConstruct * 751 Create(const ASTContext &C, SourceLocation Start, SourceLocation DirectiveLoc, 752 SourceLocation End, ArrayRef<const OpenACCClause *> Clauses); 753 }; 754 } // namespace clang 755 #endif // LLVM_CLANG_AST_STMTOPENACC_H 756