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, BEGINEND, 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 *BeginEnd, 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]); } getBeginEndStmt()155 DeclStmt *getBeginEndStmt() { 156 return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); 157 } getCond()158 Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); } getInc()159 Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); } getLoopVarStmt()160 DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); } getBody()161 Stmt *getBody() { return SubExprs[BODY]; } 162 getRangeStmt()163 const DeclStmt *getRangeStmt() const { 164 return cast<DeclStmt>(SubExprs[RANGE]); 165 } getBeginEndStmt()166 const DeclStmt *getBeginEndStmt() const { 167 return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); 168 } getCond()169 const Expr *getCond() const { 170 return cast_or_null<Expr>(SubExprs[COND]); 171 } getInc()172 const Expr *getInc() const { 173 return cast_or_null<Expr>(SubExprs[INC]); 174 } getLoopVarStmt()175 const DeclStmt *getLoopVarStmt() const { 176 return cast<DeclStmt>(SubExprs[LOOPVAR]); 177 } getBody()178 const Stmt *getBody() const { return SubExprs[BODY]; } 179 setRangeInit(Expr * E)180 void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); } setRangeStmt(Stmt * S)181 void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } setBeginEndStmt(Stmt * S)182 void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; } setCond(Expr * E)183 void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } setInc(Expr * E)184 void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } setLoopVarStmt(Stmt * S)185 void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } setBody(Stmt * S)186 void setBody(Stmt *S) { SubExprs[BODY] = S; } 187 getForLoc()188 SourceLocation getForLoc() const { return ForLoc; } getCoawaitLoc()189 SourceLocation getCoawaitLoc() const { return CoawaitLoc; } getColonLoc()190 SourceLocation getColonLoc() const { return ColonLoc; } getRParenLoc()191 SourceLocation getRParenLoc() const { return RParenLoc; } 192 getLocStart()193 SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } getLocEnd()194 SourceLocation getLocEnd() const LLVM_READONLY { 195 return SubExprs[BODY]->getLocEnd(); 196 } 197 classof(const Stmt * T)198 static bool classof(const Stmt *T) { 199 return T->getStmtClass() == CXXForRangeStmtClass; 200 } 201 202 // Iterators children()203 child_range children() { 204 return child_range(&SubExprs[0], &SubExprs[END]); 205 } 206 }; 207 208 /// \brief Representation of a Microsoft __if_exists or __if_not_exists 209 /// statement with a dependent name. 210 /// 211 /// The __if_exists statement can be used to include a sequence of statements 212 /// in the program only when a particular dependent name does not exist. For 213 /// example: 214 /// 215 /// \code 216 /// template<typename T> 217 /// void call_foo(T &t) { 218 /// __if_exists (T::foo) { 219 /// t.foo(); // okay: only called when T::foo exists. 220 /// } 221 /// } 222 /// \endcode 223 /// 224 /// Similarly, the __if_not_exists statement can be used to include the 225 /// statements when a particular name does not exist. 226 /// 227 /// Note that this statement only captures __if_exists and __if_not_exists 228 /// statements whose name is dependent. All non-dependent cases are handled 229 /// directly in the parser, so that they don't introduce a new scope. Clang 230 /// introduces scopes in the dependent case to keep names inside the compound 231 /// statement from leaking out into the surround statements, which would 232 /// compromise the template instantiation model. This behavior differs from 233 /// Visual C++ (which never introduces a scope), but is a fairly reasonable 234 /// approximation of the VC++ behavior. 235 class MSDependentExistsStmt : public Stmt { 236 SourceLocation KeywordLoc; 237 bool IsIfExists; 238 NestedNameSpecifierLoc QualifierLoc; 239 DeclarationNameInfo NameInfo; 240 Stmt *SubStmt; 241 242 friend class ASTReader; 243 friend class ASTStmtReader; 244 245 public: MSDependentExistsStmt(SourceLocation KeywordLoc,bool IsIfExists,NestedNameSpecifierLoc QualifierLoc,DeclarationNameInfo NameInfo,CompoundStmt * SubStmt)246 MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, 247 NestedNameSpecifierLoc QualifierLoc, 248 DeclarationNameInfo NameInfo, 249 CompoundStmt *SubStmt) 250 : Stmt(MSDependentExistsStmtClass), 251 KeywordLoc(KeywordLoc), IsIfExists(IsIfExists), 252 QualifierLoc(QualifierLoc), NameInfo(NameInfo), 253 SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { } 254 255 /// \brief Retrieve the location of the __if_exists or __if_not_exists 256 /// keyword. getKeywordLoc()257 SourceLocation getKeywordLoc() const { return KeywordLoc; } 258 259 /// \brief Determine whether this is an __if_exists statement. isIfExists()260 bool isIfExists() const { return IsIfExists; } 261 262 /// \brief Determine whether this is an __if_exists statement. isIfNotExists()263 bool isIfNotExists() const { return !IsIfExists; } 264 265 /// \brief Retrieve the nested-name-specifier that qualifies this name, if 266 /// any. getQualifierLoc()267 NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } 268 269 /// \brief Retrieve the name of the entity we're testing for, along with 270 /// location information getNameInfo()271 DeclarationNameInfo getNameInfo() const { return NameInfo; } 272 273 /// \brief Retrieve the compound statement that will be included in the 274 /// program only if the existence of the symbol matches the initial keyword. getSubStmt()275 CompoundStmt *getSubStmt() const { 276 return reinterpret_cast<CompoundStmt *>(SubStmt); 277 } 278 getLocStart()279 SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } getLocEnd()280 SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} 281 children()282 child_range children() { 283 return child_range(&SubStmt, &SubStmt+1); 284 } 285 classof(const Stmt * T)286 static bool classof(const Stmt *T) { 287 return T->getStmtClass() == MSDependentExistsStmtClass; 288 } 289 }; 290 291 /// \brief Represents the body of a coroutine. This wraps the normal function 292 /// body and holds the additional semantic context required to set up and tear 293 /// down the coroutine frame. 294 class CoroutineBodyStmt : public Stmt { 295 enum SubStmt { 296 Body, ///< The body of the coroutine. 297 Promise, ///< The promise statement. 298 InitSuspend, ///< The initial suspend statement, run before the body. 299 FinalSuspend, ///< The final suspend statement, run after the body. 300 OnException, ///< Handler for exceptions thrown in the body. 301 OnFallthrough, ///< Handler for control flow falling off the body. 302 ReturnValue, ///< Return value for thunk function. 303 FirstParamMove ///< First offset for move construction of parameter copies. 304 }; 305 Stmt *SubStmts[SubStmt::FirstParamMove]; 306 307 friend class ASTStmtReader; 308 public: CoroutineBodyStmt(Stmt * Body,Stmt * Promise,Stmt * InitSuspend,Stmt * FinalSuspend,Stmt * OnException,Stmt * OnFallthrough,Expr * ReturnValue,ArrayRef<Expr * > ParamMoves)309 CoroutineBodyStmt(Stmt *Body, Stmt *Promise, Stmt *InitSuspend, 310 Stmt *FinalSuspend, Stmt *OnException, Stmt *OnFallthrough, 311 Expr *ReturnValue, ArrayRef<Expr *> ParamMoves) 312 : Stmt(CoroutineBodyStmtClass) { 313 SubStmts[CoroutineBodyStmt::Body] = Body; 314 SubStmts[CoroutineBodyStmt::Promise] = Promise; 315 SubStmts[CoroutineBodyStmt::InitSuspend] = InitSuspend; 316 SubStmts[CoroutineBodyStmt::FinalSuspend] = FinalSuspend; 317 SubStmts[CoroutineBodyStmt::OnException] = OnException; 318 SubStmts[CoroutineBodyStmt::OnFallthrough] = OnFallthrough; 319 SubStmts[CoroutineBodyStmt::ReturnValue] = ReturnValue; 320 // FIXME: Tail-allocate space for parameter move expressions and store them. 321 assert(ParamMoves.empty() && "not implemented yet"); 322 } 323 324 /// \brief Retrieve the body of the coroutine as written. This will be either 325 /// a CompoundStmt or a TryStmt. getBody()326 Stmt *getBody() const { 327 return SubStmts[SubStmt::Body]; 328 } 329 getPromiseDeclStmt()330 Stmt *getPromiseDeclStmt() const { return SubStmts[SubStmt::Promise]; } getPromiseDecl()331 VarDecl *getPromiseDecl() const { 332 return cast<VarDecl>(cast<DeclStmt>(getPromiseDeclStmt())->getSingleDecl()); 333 } 334 getInitSuspendStmt()335 Stmt *getInitSuspendStmt() const { return SubStmts[SubStmt::InitSuspend]; } getFinalSuspendStmt()336 Stmt *getFinalSuspendStmt() const { return SubStmts[SubStmt::FinalSuspend]; } 337 getExceptionHandler()338 Stmt *getExceptionHandler() const { return SubStmts[SubStmt::OnException]; } getFallthroughHandler()339 Stmt *getFallthroughHandler() const { 340 return SubStmts[SubStmt::OnFallthrough]; 341 } 342 getReturnValueInit()343 Expr *getReturnValueInit() const { 344 return cast<Expr>(SubStmts[SubStmt::ReturnValue]); 345 } 346 getLocStart()347 SourceLocation getLocStart() const LLVM_READONLY { 348 return getBody()->getLocStart(); 349 } getLocEnd()350 SourceLocation getLocEnd() const LLVM_READONLY { 351 return getBody()->getLocEnd(); 352 } 353 children()354 child_range children() { 355 return child_range(SubStmts, SubStmts + SubStmt::FirstParamMove); 356 } 357 classof(const Stmt * T)358 static bool classof(const Stmt *T) { 359 return T->getStmtClass() == CoroutineBodyStmtClass; 360 } 361 }; 362 363 /// \brief Represents a 'co_return' statement in the C++ Coroutines TS. 364 /// 365 /// This statament models the initialization of the coroutine promise 366 /// (encapsulating the eventual notional return value) from an expression 367 /// (or braced-init-list), followed by termination of the coroutine. 368 /// 369 /// This initialization is modeled by the evaluation of the operand 370 /// followed by a call to one of: 371 /// <promise>.return_value(<operand>) 372 /// <promise>.return_void() 373 /// which we name the "promise call". 374 class CoreturnStmt : public Stmt { 375 SourceLocation CoreturnLoc; 376 377 enum SubStmt { Operand, PromiseCall, Count }; 378 Stmt *SubStmts[SubStmt::Count]; 379 380 friend class ASTStmtReader; 381 public: CoreturnStmt(SourceLocation CoreturnLoc,Stmt * Operand,Stmt * PromiseCall)382 CoreturnStmt(SourceLocation CoreturnLoc, Stmt *Operand, Stmt *PromiseCall) 383 : Stmt(CoreturnStmtClass), CoreturnLoc(CoreturnLoc) { 384 SubStmts[SubStmt::Operand] = Operand; 385 SubStmts[SubStmt::PromiseCall] = PromiseCall; 386 } 387 getKeywordLoc()388 SourceLocation getKeywordLoc() const { return CoreturnLoc; } 389 390 /// \brief Retrieve the operand of the 'co_return' statement. Will be nullptr 391 /// if none was specified. getOperand()392 Expr *getOperand() const { return static_cast<Expr*>(SubStmts[Operand]); } 393 394 /// \brief Retrieve the promise call that results from this 'co_return' 395 /// statement. Will be nullptr if either the coroutine has not yet been 396 /// finalized or the coroutine has no eventual return type. getPromiseCall()397 Expr *getPromiseCall() const { 398 return static_cast<Expr*>(SubStmts[PromiseCall]); 399 } 400 getLocStart()401 SourceLocation getLocStart() const LLVM_READONLY { return CoreturnLoc; } getLocEnd()402 SourceLocation getLocEnd() const LLVM_READONLY { 403 return getOperand()->getLocEnd(); 404 } 405 children()406 child_range children() { 407 return child_range(SubStmts, SubStmts + SubStmt::Count); 408 } 409 classof(const Stmt * T)410 static bool classof(const Stmt *T) { 411 return T->getStmtClass() == CoreturnStmtClass; 412 } 413 }; 414 415 } // end namespace clang 416 417 #endif 418