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 getLocStart()44 SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; } getLocEnd()45 SourceLocation getLocEnd() const LLVM_READONLY { 46 return HandlerBlock->getLocEnd(); 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 : public Stmt { 66 SourceLocation TryLoc; 67 unsigned NumHandlers; 68 69 CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers); 70 CXXTryStmt(EmptyShell Empty,unsigned numHandlers)71 CXXTryStmt(EmptyShell Empty, unsigned numHandlers) 72 : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } 73 getStmts()74 Stmt const * const *getStmts() const { 75 return reinterpret_cast<Stmt const * const*>(this + 1); 76 } getStmts()77 Stmt **getStmts() { 78 return reinterpret_cast<Stmt **>(this + 1); 79 } 80 81 public: 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 getLocStart()88 SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } getLocEnd()89 SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } 90 getTryLoc()91 SourceLocation getTryLoc() const { return TryLoc; } getEndLoc()92 SourceLocation getEndLoc() const { 93 return getStmts()[NumHandlers]->getLocEnd(); 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 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. 128 class 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; 139 public: 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); CXXForRangeStmt(EmptyShell Empty)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 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 setRangeInit(Expr * E)184 void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); } setRangeStmt(Stmt * S)185 void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } setBeginStmt(Stmt * S)186 void setBeginStmt(Stmt *S) { SubExprs[BEGINSTMT] = S; } setEndStmt(Stmt * S)187 void setEndStmt(Stmt *S) { SubExprs[ENDSTMT] = S; } setCond(Expr * E)188 void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } setInc(Expr * E)189 void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } setLoopVarStmt(Stmt * S)190 void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } setBody(Stmt * S)191 void setBody(Stmt *S) { SubExprs[BODY] = S; } 192 getForLoc()193 SourceLocation getForLoc() const { return ForLoc; } getCoawaitLoc()194 SourceLocation getCoawaitLoc() const { return CoawaitLoc; } getColonLoc()195 SourceLocation getColonLoc() const { return ColonLoc; } getRParenLoc()196 SourceLocation getRParenLoc() const { return RParenLoc; } 197 getLocStart()198 SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } getLocEnd()199 SourceLocation getLocEnd() const LLVM_READONLY { 200 return SubExprs[BODY]->getLocEnd(); 201 } 202 classof(const Stmt * T)203 static bool classof(const Stmt *T) { 204 return T->getStmtClass() == CXXForRangeStmtClass; 205 } 206 207 // Iterators children()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. 240 class 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 250 public: MSDependentExistsStmt(SourceLocation KeywordLoc,bool IsIfExists,NestedNameSpecifierLoc QualifierLoc,DeclarationNameInfo NameInfo,CompoundStmt * SubStmt)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. getKeywordLoc()262 SourceLocation getKeywordLoc() const { return KeywordLoc; } 263 264 /// \brief Determine whether this is an __if_exists statement. isIfExists()265 bool isIfExists() const { return IsIfExists; } 266 267 /// \brief Determine whether this is an __if_exists statement. isIfNotExists()268 bool isIfNotExists() const { return !IsIfExists; } 269 270 /// \brief Retrieve the nested-name-specifier that qualifies this name, if 271 /// any. getQualifierLoc()272 NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } 273 274 /// \brief Retrieve the name of the entity we're testing for, along with 275 /// location information getNameInfo()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. getSubStmt()280 CompoundStmt *getSubStmt() const { 281 return reinterpret_cast<CompoundStmt *>(SubStmt); 282 } 283 getLocStart()284 SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } getLocEnd()285 SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} 286 children()287 child_range children() { 288 return child_range(&SubStmt, &SubStmt+1); 289 } 290 classof(const Stmt * T)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. 299 class CoroutineBodyStmt : public Stmt { 300 enum SubStmt { 301 Body, ///< The body of the coroutine. 302 Promise, ///< The promise statement. 303 InitSuspend, ///< The initial suspend statement, run before the body. 304 FinalSuspend, ///< The final suspend statement, run after the body. 305 OnException, ///< Handler for exceptions thrown in the body. 306 OnFallthrough, ///< Handler for control flow falling off the body. 307 ReturnValue, ///< Return value for thunk function. 308 FirstParamMove ///< First offset for move construction of parameter copies. 309 }; 310 Stmt *SubStmts[SubStmt::FirstParamMove]; 311 312 friend class ASTStmtReader; 313 public: CoroutineBodyStmt(Stmt * Body,Stmt * Promise,Stmt * InitSuspend,Stmt * FinalSuspend,Stmt * OnException,Stmt * OnFallthrough,Expr * ReturnValue,ArrayRef<Expr * > ParamMoves)314 CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend, 315 Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough, 316 Expr *ReturnValue, ArrayRef<Expr *> ParamMoves) 317 : Stmt(CoroutineBodyStmtClass) { 318 SubStmts[CoroutineBodyStmt::Body] = Body; 319 SubStmts[CoroutineBodyStmt::Promise] = Promise; 320 SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend; 321 SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend; 322 SubStmts[CoroutineBodyStmt::OnException] = OnException; 323 SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough; 324 SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue; 325 // FIXME: Tail-allocate space for parameter move expressions and store them. 326 assert(ParamMoves.empty() && "not implemented yet"); 327 } 328 329 /// \brief Retrieve the body of the coroutine as written. This will be either 330 /// a CompoundStmt or a TryStmt. getBody()331 Stmt *getBody() const { 332 return SubStmts[SubStmt::Body]; 333 } 334 getPromiseDeclStmt()335 Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; } getPromiseDecl()336 VarDecl *getPromiseDecl() const { 337 return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl()); 338 } 339 getInitSuspendStmt()340 Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; } getFinalSuspendStmt()341 Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; } 342 getExceptionHandler()343 Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; } getFallthroughHandler()344 Stmt *getFallthroughHandler() const { 345 return SubStmts[SubStmt::OnFallthrough]; 346 } 347 getReturnValueInit()348 Expr *getReturnValueInit() const { 349 return cast<Expr>(SubStmts[SubStmt::ReturnValue]); 350 } 351 getLocStart()352 SourceLocation getLocStart() const LLVM_READONLY { 353 return getBody()->getLocStart(); 354 } getLocEnd()355 SourceLocation getLocEnd() const LLVM_READONLY { 356 return getBody()->getLocEnd(); 357 } 358 children()359 child_range children() { 360 return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove); 361 } 362 classof(const Stmt * T)363 static bool classof(const Stmt *T) { 364 return T->getStmtClass() == CoroutineBodyStmtClass; 365 } 366 }; 367 368 /// \brief Represents a 'co_return' statement in the C++ Coroutines TS. 369 /// 370 /// This statament models the initialization of the coroutine promise 371 /// (encapsulating the eventual notional return value) from an expression 372 /// (or braced-init-list), followed by termination of the coroutine. 373 /// 374 /// This initialization is modeled by the evaluation of the operand 375 /// followed by a call to one of: 376 /// <promise>.return_value(<operand>) 377 /// <promise>.return_void() 378 /// which we name the "promise call". 379 class CoreturnStmt : public Stmt { 380 SourceLocation CoreturnLoc; 381 382 enum SubStmt { Operand, PromiseCall, Count }; 383 Stmt *SubStmts[SubStmt::Count]; 384 385 friend class ASTStmtReader; 386 public: CoreturnStmt(SourceLocation CoreturnLoc,Stmt * Operand,Stmt * PromiseCall)387 CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall) 388 : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) { 389 SubStmts[SubStmt::Operand] = Operand; 390 SubStmts[SubStmt::PromiseCall] = PromiseCall; 391 } 392 getKeywordLoc()393 SourceLocation getKeywordLoc() const { return CoreturnLoc; } 394 395 /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr 396 /// if none was specified. getOperand()397 Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); } 398 399 /// \brief Retrieve the promise call that results from this 'co_return' 400 /// statement. Will be nullptr if either the coroutine has not yet been 401 /// finalized or the coroutine has no eventual return type. getPromiseCall()402 Expr *getPromiseCall() const { 403 return static_cast<Expr*>(SubStmts[PromiseCall]); 404 } 405 getLocStart()406 SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; } getLocEnd()407 SourceLocation getLocEnd() const LLVM_READONLY { 408 return getOperand()->getLocEnd(); 409 } 410 children()411 child_range children() { 412 return child_range(SubStmts, SubStmts + SubStmt::Count); 413 } 414 classof(const Stmt * T)415 static bool classof(const Stmt *T) { 416 return T->getStmtClass() == CoreturnStmtClass; 417 } 418 }; 419 420 } // end namespace clang 421 422 #endif 423