1 //===--- StmtCXX.h - Classes for representing C++ statements ----*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file defines the C++ statement AST node classes. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #ifndef LLVM_CLANG_AST_STMTCXX_H 15 #define LLVM_CLANG_AST_STMTCXX_H 16 17 #include "clang/AST/DeclarationName.h" 18 #include "clang/AST/Expr.h" 19 #include "clang/AST/NestedNameSpecifier.h" 20 #include "clang/AST/Stmt.h" 21 #include "llvm/Support/Compiler.h" 22 23 namespace clang { 24 25 class VarDecl; 26 27 /// CXXCatchStmt - This represents a C++ catch block. 28 /// 29 class CXXCatchStmt : public Stmt { 30 SourceLocation CatchLoc; 31 /// The exception-declaration of the type. 32 VarDecl *ExceptionDecl; 33 /// The handler block. 34 Stmt *HandlerBlock; 35 36 public: CXXCatchStmt(SourceLocation catchLoc,VarDecl * exDecl,Stmt * handlerBlock)37 CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock) 38 : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), 39 HandlerBlock(handlerBlock) {} 40 CXXCatchStmt(EmptyShell Empty)41 CXXCatchStmt(EmptyShell Empty) 42 : Stmt(CXXCatchStmtClass), ExceptionDecl(nullptr), HandlerBlock(nullptr) {} 43 getBeginLoc()44 SourceLocation getBeginLoc() const LLVM_READONLY { return CatchLoc; } getEndLoc()45 SourceLocation getEndLoc() const LLVM_READONLY { 46 return HandlerBlock->getEndLoc(); 47 } 48 getCatchLoc()49 SourceLocation getCatchLoc() const { return CatchLoc; } getExceptionDecl()50 VarDecl *getExceptionDecl() const { return ExceptionDecl; } 51 QualType getCaughtType() const; getHandlerBlock()52 Stmt *getHandlerBlock() const { return HandlerBlock; } 53 classof(const Stmt * T)54 static bool classof(const Stmt *T) { 55 return T->getStmtClass() == CXXCatchStmtClass; 56 } 57 children()58 child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); } 59 60 friend class ASTStmtReader; 61 }; 62 63 /// CXXTryStmt - A C++ try block, including all handlers. 64 /// 65 class CXXTryStmt final : public Stmt, 66 private llvm::TrailingObjects<CXXTryStmt, Stmt *> { 67 68 friend TrailingObjects; 69 friend class ASTStmtReader; 70 71 SourceLocation TryLoc; 72 unsigned NumHandlers; numTrailingObjects(OverloadToken<Stmt * >)73 size_t numTrailingObjects(OverloadToken<Stmt *>) const { return NumHandlers; } 74 75 CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers); CXXTryStmt(EmptyShell Empty,unsigned numHandlers)76 CXXTryStmt(EmptyShell Empty, unsigned numHandlers) 77 : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } 78 getStmts()79 Stmt *const *getStmts() const { return getTrailingObjects<Stmt *>(); } getStmts()80 Stmt **getStmts() { return getTrailingObjects<Stmt *>(); } 81 82 public: 83 static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc, 84 Stmt *tryBlock, ArrayRef<Stmt*> handlers); 85 86 static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty, 87 unsigned numHandlers); 88 getBeginLoc()89 SourceLocation getBeginLoc() const LLVM_READONLY { return getTryLoc(); } 90 getTryLoc()91 SourceLocation getTryLoc() const { return TryLoc; } getEndLoc()92 SourceLocation getEndLoc() const { 93 return getStmts()[NumHandlers]->getEndLoc(); 94 } 95 getTryBlock()96 CompoundStmt *getTryBlock() { 97 return cast<CompoundStmt>(getStmts()[0]); 98 } getTryBlock()99 const CompoundStmt *getTryBlock() const { 100 return cast<CompoundStmt>(getStmts()[0]); 101 } 102 getNumHandlers()103 unsigned getNumHandlers() const { return NumHandlers; } getHandler(unsigned i)104 CXXCatchStmt *getHandler(unsigned i) { 105 return cast<CXXCatchStmt>(getStmts()[i + 1]); 106 } getHandler(unsigned i)107 const CXXCatchStmt *getHandler(unsigned i) const { 108 return cast<CXXCatchStmt>(getStmts()[i + 1]); 109 } 110 classof(const Stmt * T)111 static bool classof(const Stmt *T) { 112 return T->getStmtClass() == CXXTryStmtClass; 113 } 114 children()115 child_range children() { 116 return child_range(getStmts(), getStmts() + getNumHandlers() + 1); 117 } 118 }; 119 120 /// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for 121 /// statement, represented as 'for (range-declarator : range-expression)' 122 /// or 'for (init-statement range-declarator : range-expression)'. 123 /// 124 /// This is stored in a partially-desugared form to allow full semantic 125 /// analysis of the constituent components. The original syntactic components 126 /// can be extracted using getLoopVariable and getRangeInit. 127 class CXXForRangeStmt : public Stmt { 128 SourceLocation ForLoc; 129 enum { INIT, RANGE, BEGINSTMT, ENDSTMT, COND, INC, LOOPVAR, BODY, END }; 130 // SubExprs[RANGE] is an expression or declstmt. 131 // SubExprs[COND] and SubExprs[INC] are expressions. 132 Stmt *SubExprs[END]; 133 SourceLocation CoawaitLoc; 134 SourceLocation ColonLoc; 135 SourceLocation RParenLoc; 136 137 friend class ASTStmtReader; 138 public: 139 CXXForRangeStmt(Stmt *InitStmt, DeclStmt *Range, DeclStmt *Begin, 140 DeclStmt *End, Expr *Cond, Expr *Inc, DeclStmt *LoopVar, 141 Stmt *Body, SourceLocation FL, SourceLocation CAL, 142 SourceLocation CL, SourceLocation RPL); CXXForRangeStmt(EmptyShell Empty)143 CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { } 144 getInit()145 Stmt *getInit() { return SubExprs[INIT]; } 146 VarDecl *getLoopVariable(); 147 Expr *getRangeInit(); 148 getInit()149 const Stmt *getInit() const { return SubExprs[INIT]; } 150 const VarDecl *getLoopVariable() const; 151 const Expr *getRangeInit() const; 152 153 getRangeStmt()154 DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); } getBeginStmt()155 DeclStmt *getBeginStmt() { 156 return cast_or_null<DeclStmt>(SubExprs[BEGINSTMT]); 157 } getEndStmt()158 DeclStmt *getEndStmt() { return cast_or_null<DeclStmt>(SubExprs[ENDSTMT]); } getCond()159 Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); } getInc()160 Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); } getLoopVarStmt()161 DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); } getBody()162 Stmt *getBody() { return SubExprs[BODY]; } 163 getRangeStmt()164 const DeclStmt *getRangeStmt() const { 165 return cast<DeclStmt>(SubExprs[RANGE]); 166 } getBeginStmt()167 const DeclStmt *getBeginStmt() const { 168 return cast_or_null<DeclStmt>(SubExprs[BEGINSTMT]); 169 } getEndStmt()170 const DeclStmt *getEndStmt() const { 171 return cast_or_null<DeclStmt>(SubExprs[ENDSTMT]); 172 } getCond()173 const Expr *getCond() const { 174 return cast_or_null<Expr>(SubExprs[COND]); 175 } getInc()176 const Expr *getInc() const { 177 return cast_or_null<Expr>(SubExprs[INC]); 178 } getLoopVarStmt()179 const DeclStmt *getLoopVarStmt() const { 180 return cast<DeclStmt>(SubExprs[LOOPVAR]); 181 } getBody()182 const Stmt *getBody() const { return SubExprs[BODY]; } 183 setInit(Stmt * S)184 void setInit(Stmt *S) { SubExprs[INIT] = S; } setRangeInit(Expr * E)185 void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); } setRangeStmt(Stmt * S)186 void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } setBeginStmt(Stmt * S)187 void setBeginStmt(Stmt *S) { SubExprs[BEGINSTMT] = S; } setEndStmt(Stmt * S)188 void setEndStmt(Stmt *S) { SubExprs[ENDSTMT] = S; } setCond(Expr * E)189 void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } setInc(Expr * E)190 void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } setLoopVarStmt(Stmt * S)191 void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } setBody(Stmt * S)192 void setBody(Stmt *S) { SubExprs[BODY] = S; } 193 getForLoc()194 SourceLocation getForLoc() const { return ForLoc; } getCoawaitLoc()195 SourceLocation getCoawaitLoc() const { return CoawaitLoc; } getColonLoc()196 SourceLocation getColonLoc() const { return ColonLoc; } getRParenLoc()197 SourceLocation getRParenLoc() const { return RParenLoc; } 198 getBeginLoc()199 SourceLocation getBeginLoc() const LLVM_READONLY { return ForLoc; } getEndLoc()200 SourceLocation getEndLoc() const LLVM_READONLY { 201 return SubExprs[BODY]->getEndLoc(); 202 } 203 classof(const Stmt * T)204 static bool classof(const Stmt *T) { 205 return T->getStmtClass() == CXXForRangeStmtClass; 206 } 207 208 // Iterators children()209 child_range children() { 210 return child_range(&SubExprs[0], &SubExprs[END]); 211 } 212 }; 213 214 /// Representation of a Microsoft __if_exists or __if_not_exists 215 /// statement with a dependent name. 216 /// 217 /// The __if_exists statement can be used to include a sequence of statements 218 /// in the program only when a particular dependent name does not exist. For 219 /// example: 220 /// 221 /// \code 222 /// template<typename T> 223 /// void call_foo(T &t) { 224 /// __if_exists (T::foo) { 225 /// t.foo(); // okay: only called when T::foo exists. 226 /// } 227 /// } 228 /// \endcode 229 /// 230 /// Similarly, the __if_not_exists statement can be used to include the 231 /// statements when a particular name does not exist. 232 /// 233 /// Note that this statement only captures __if_exists and __if_not_exists 234 /// statements whose name is dependent. All non-dependent cases are handled 235 /// directly in the parser, so that they don't introduce a new scope. Clang 236 /// introduces scopes in the dependent case to keep names inside the compound 237 /// statement from leaking out into the surround statements, which would 238 /// compromise the template instantiation model. This behavior differs from 239 /// Visual C++ (which never introduces a scope), but is a fairly reasonable 240 /// approximation of the VC++ behavior. 241 class MSDependentExistsStmt : public Stmt { 242 SourceLocation KeywordLoc; 243 bool IsIfExists; 244 NestedNameSpecifierLoc QualifierLoc; 245 DeclarationNameInfo NameInfo; 246 Stmt *SubStmt; 247 248 friend class ASTReader; 249 friend class ASTStmtReader; 250 251 public: MSDependentExistsStmt(SourceLocation KeywordLoc,bool IsIfExists,NestedNameSpecifierLoc QualifierLoc,DeclarationNameInfo NameInfo,CompoundStmt * SubStmt)252 MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, 253 NestedNameSpecifierLoc QualifierLoc, 254 DeclarationNameInfo NameInfo, 255 CompoundStmt *SubStmt) 256 : Stmt(MSDependentExistsStmtClass), 257 KeywordLoc(KeywordLoc), IsIfExists(IsIfExists), 258 QualifierLoc(QualifierLoc), NameInfo(NameInfo), 259 SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { } 260 261 /// Retrieve the location of the __if_exists or __if_not_exists 262 /// keyword. getKeywordLoc()263 SourceLocation getKeywordLoc() const { return KeywordLoc; } 264 265 /// Determine whether this is an __if_exists statement. isIfExists()266 bool isIfExists() const { return IsIfExists; } 267 268 /// Determine whether this is an __if_exists statement. isIfNotExists()269 bool isIfNotExists() const { return !IsIfExists; } 270 271 /// Retrieve the nested-name-specifier that qualifies this name, if 272 /// any. getQualifierLoc()273 NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } 274 275 /// Retrieve the name of the entity we're testing for, along with 276 /// location information getNameInfo()277 DeclarationNameInfo getNameInfo() const { return NameInfo; } 278 279 /// Retrieve the compound statement that will be included in the 280 /// program only if the existence of the symbol matches the initial keyword. getSubStmt()281 CompoundStmt *getSubStmt() const { 282 return reinterpret_cast<CompoundStmt *>(SubStmt); 283 } 284 getBeginLoc()285 SourceLocation getBeginLoc() const LLVM_READONLY { return KeywordLoc; } getEndLoc()286 SourceLocation getEndLoc() const LLVM_READONLY { 287 return SubStmt->getEndLoc(); 288 } 289 children()290 child_range children() { 291 return child_range(&SubStmt, &SubStmt+1); 292 } 293 classof(const Stmt * T)294 static bool classof(const Stmt *T) { 295 return T->getStmtClass() == MSDependentExistsStmtClass; 296 } 297 }; 298 299 /// Represents the body of a coroutine. This wraps the normal function 300 /// body and holds the additional semantic context required to set up and tear 301 /// down the coroutine frame. 302 class CoroutineBodyStmt final 303 : public Stmt, 304 private llvm::TrailingObjects<CoroutineBodyStmt, Stmt *> { 305 enum SubStmt { 306 Body, ///< The body of the coroutine. 307 Promise, ///< The promise statement. 308 InitSuspend, ///< The initial suspend statement, run before the body. 309 FinalSuspend, ///< The final suspend statement, run after the body. 310 OnException, ///< Handler for exceptions thrown in the body. 311 OnFallthrough, ///< Handler for control flow falling off the body. 312 Allocate, ///< Coroutine frame memory allocation. 313 Deallocate, ///< Coroutine frame memory deallocation. 314 ReturnValue, ///< Return value for thunk function: p.get_return_object(). 315 ResultDecl, ///< Declaration holding the result of get_return_object. 316 ReturnStmt, ///< Return statement for the thunk function. 317 ReturnStmtOnAllocFailure, ///< Return statement if allocation failed. 318 FirstParamMove ///< First offset for move construction of parameter copies. 319 }; 320 unsigned NumParams; 321 322 friend class ASTStmtReader; 323 friend class ASTReader; 324 friend TrailingObjects; 325 getStoredStmts()326 Stmt **getStoredStmts() { return getTrailingObjects<Stmt *>(); } 327 getStoredStmts()328 Stmt *const *getStoredStmts() const { return getTrailingObjects<Stmt *>(); } 329 330 public: 331 332 struct CtorArgs { 333 Stmt *Body = nullptr; 334 Stmt *Promise = nullptr; 335 Expr *InitialSuspend = nullptr; 336 Expr *FinalSuspend = nullptr; 337 Stmt *OnException = nullptr; 338 Stmt *OnFallthrough = nullptr; 339 Expr *Allocate = nullptr; 340 Expr *Deallocate = nullptr; 341 Expr *ReturnValue = nullptr; 342 Stmt *ResultDecl = nullptr; 343 Stmt *ReturnStmt = nullptr; 344 Stmt *ReturnStmtOnAllocFailure = nullptr; 345 ArrayRef<Stmt *> ParamMoves; 346 }; 347 348 private: 349 350 CoroutineBodyStmt(CtorArgs const& Args); 351 352 public: 353 static CoroutineBodyStmt *Create(const ASTContext &C, CtorArgs const &Args); 354 static CoroutineBodyStmt *Create(const ASTContext &C, EmptyShell, 355 unsigned NumParams); 356 hasDependentPromiseType()357 bool hasDependentPromiseType() const { 358 return getPromiseDecl()->getType()->isDependentType(); 359 } 360 361 /// Retrieve the body of the coroutine as written. This will be either 362 /// a CompoundStmt or a TryStmt. getBody()363 Stmt *getBody() const { 364 return getStoredStmts()[SubStmt::Body]; 365 } 366 getPromiseDeclStmt()367 Stmt *getPromiseDeclStmt() const { 368 return getStoredStmts()[SubStmt::Promise]; 369 } getPromiseDecl()370 VarDecl *getPromiseDecl() const { 371 return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl()); 372 } 373 getInitSuspendStmt()374 Stmt *getInitSuspendStmt() const { 375 return getStoredStmts()[SubStmt::InitSuspend]; 376 } getFinalSuspendStmt()377 Stmt *getFinalSuspendStmt() const { 378 return getStoredStmts()[SubStmt::FinalSuspend]; 379 } 380 getExceptionHandler()381 Stmt *getExceptionHandler() const { 382 return getStoredStmts()[SubStmt::OnException]; 383 } getFallthroughHandler()384 Stmt *getFallthroughHandler() const { 385 return getStoredStmts()[SubStmt::OnFallthrough]; 386 } 387 getAllocate()388 Expr *getAllocate() const { 389 return cast_or_null<Expr>(getStoredStmts()[SubStmt::Allocate]); 390 } getDeallocate()391 Expr *getDeallocate() const { 392 return cast_or_null<Expr>(getStoredStmts()[SubStmt::Deallocate]); 393 } getReturnValueInit()394 Expr *getReturnValueInit() const { 395 return cast<Expr>(getStoredStmts()[SubStmt::ReturnValue]); 396 } getResultDecl()397 Stmt *getResultDecl() const { return getStoredStmts()[SubStmt::ResultDecl]; } getReturnStmt()398 Stmt *getReturnStmt() const { return getStoredStmts()[SubStmt::ReturnStmt]; } getReturnStmtOnAllocFailure()399 Stmt *getReturnStmtOnAllocFailure() const { 400 return getStoredStmts()[SubStmt::ReturnStmtOnAllocFailure]; 401 } getParamMoves()402 ArrayRef<Stmt const *> getParamMoves() const { 403 return {getStoredStmts() + SubStmt::FirstParamMove, NumParams}; 404 } 405 getBeginLoc()406 SourceLocation getBeginLoc() const LLVM_READONLY { 407 return getBody() ? getBody()->getBeginLoc() 408 : getPromiseDecl()->getBeginLoc(); 409 } getEndLoc()410 SourceLocation getEndLoc() const LLVM_READONLY { 411 return getBody() ? getBody()->getEndLoc() : getPromiseDecl()->getEndLoc(); 412 } 413 children()414 child_range children() { 415 return child_range(getStoredStmts(), 416 getStoredStmts() + SubStmt::FirstParamMove + NumParams); 417 } 418 classof(const Stmt * T)419 static bool classof(const Stmt *T) { 420 return T->getStmtClass() == CoroutineBodyStmtClass; 421 } 422 }; 423 424 /// Represents a 'co_return' statement in the C++ Coroutines TS. 425 /// 426 /// This statament models the initialization of the coroutine promise 427 /// (encapsulating the eventual notional return value) from an expression 428 /// (or braced-init-list), followed by termination of the coroutine. 429 /// 430 /// This initialization is modeled by the evaluation of the operand 431 /// followed by a call to one of: 432 /// <promise>.return_value(<operand>) 433 /// <promise>.return_void() 434 /// which we name the "promise call". 435 class CoreturnStmt : public Stmt { 436 SourceLocation CoreturnLoc; 437 438 enum SubStmt { Operand, PromiseCall, Count }; 439 Stmt *SubStmts[SubStmt::Count]; 440 441 bool IsImplicit : 1; 442 443 friend class ASTStmtReader; 444 public: 445 CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall, 446 bool IsImplicit = false) Stmt(CoreturnStmtClass)447 : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc), 448 IsImplicit(IsImplicit) { 449 SubStmts[SubStmt::Operand] = Operand; 450 SubStmts[SubStmt::PromiseCall] = PromiseCall; 451 } 452 CoreturnStmt(EmptyShell)453 CoreturnStmt(EmptyShell) : CoreturnStmt({}, {}, {}) {} 454 getKeywordLoc()455 SourceLocation getKeywordLoc() const { return CoreturnLoc; } 456 457 /// Retrieve the operand of the 'co_return' statement. Will be nullptr 458 /// if none was specified. getOperand()459 Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); } 460 461 /// Retrieve the promise call that results from this 'co_return' 462 /// statement. Will be nullptr if either the coroutine has not yet been 463 /// finalized or the coroutine has no eventual return type. getPromiseCall()464 Expr *getPromiseCall() const { 465 return static_cast<Expr*>(SubStmts[PromiseCall]); 466 } 467 isImplicit()468 bool isImplicit() const { return IsImplicit; } 469 void setIsImplicit(bool value = true) { IsImplicit = value; } 470 getBeginLoc()471 SourceLocation getBeginLoc() const LLVM_READONLY { return CoreturnLoc; } getEndLoc()472 SourceLocation getEndLoc() const LLVM_READONLY { 473 return getOperand() ? getOperand()->getEndLoc() : getBeginLoc(); 474 } 475 children()476 child_range children() { 477 if (!getOperand()) 478 return child_range(SubStmts + SubStmt::PromiseCall, 479 SubStmts + SubStmt::Count); 480 return child_range(SubStmts, SubStmts + SubStmt::Count); 481 } 482 classof(const Stmt * T)483 static bool classof(const Stmt *T) { 484 return T->getStmtClass() == CoreturnStmtClass; 485 } 486 }; 487 488 } // end namespace clang 489 490 #endif 491