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