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