1193326Sed//===--- StmtCXX.h - Classes for representing C++ statements ----*- C++ -*-===// 2193326Sed// 3193326Sed// The LLVM Compiler Infrastructure 4193326Sed// 5193326Sed// This file is distributed under the University of Illinois Open Source 6193326Sed// License. See LICENSE.TXT for details. 7193326Sed// 8193326Sed//===----------------------------------------------------------------------===// 9193326Sed// 10193326Sed// This file defines the C++ statement AST node classes. 11193326Sed// 12193326Sed//===----------------------------------------------------------------------===// 13193326Sed 14193326Sed#ifndef LLVM_CLANG_AST_STMTCXX_H 15193326Sed#define LLVM_CLANG_AST_STMTCXX_H 16193326Sed 17252723Sdim#include "clang/AST/DeclarationName.h" 18252723Sdim#include "clang/AST/Expr.h" 19252723Sdim#include "clang/AST/NestedNameSpecifier.h" 20193326Sed#include "clang/AST/Stmt.h" 21235633Sdim#include "llvm/Support/Compiler.h" 22193326Sed 23193326Sednamespace clang { 24193326Sed 25193326Sedclass VarDecl; 26193326Sed 27193326Sed/// CXXCatchStmt - This represents a C++ catch block. 28193326Sed/// 29193326Sedclass CXXCatchStmt : public Stmt { 30193326Sed SourceLocation CatchLoc; 31193326Sed /// The exception-declaration of the type. 32193326Sed VarDecl *ExceptionDecl; 33193326Sed /// The handler block. 34193326Sed Stmt *HandlerBlock; 35193326Sed 36193326Sedpublic: 37193326Sed CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock) 38193326Sed : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), 39193326Sed HandlerBlock(handlerBlock) {} 40193326Sed 41212904Sdim CXXCatchStmt(EmptyShell Empty) 42212904Sdim : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {} 43212904Sdim 44252723Sdim SourceLocation getLocStart() const LLVM_READONLY { return CatchLoc; } 45252723Sdim SourceLocation getLocEnd() const LLVM_READONLY { 46252723Sdim return HandlerBlock->getLocEnd(); 47193326Sed } 48193326Sed 49193326Sed SourceLocation getCatchLoc() const { return CatchLoc; } 50199990Srdivacky VarDecl *getExceptionDecl() const { return ExceptionDecl; } 51199990Srdivacky QualType getCaughtType() const; 52199990Srdivacky Stmt *getHandlerBlock() const { return HandlerBlock; } 53193326Sed 54193326Sed static bool classof(const Stmt *T) { 55193326Sed return T->getStmtClass() == CXXCatchStmtClass; 56193326Sed } 57193326Sed 58218893Sdim child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); } 59212904Sdim 60212904Sdim friend class ASTStmtReader; 61193326Sed}; 62193326Sed 63193326Sed/// CXXTryStmt - A C++ try block, including all handlers. 64193326Sed/// 65193326Sedclass CXXTryStmt : public Stmt { 66193326Sed SourceLocation TryLoc; 67203955Srdivacky unsigned NumHandlers; 68193326Sed 69252723Sdim CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, ArrayRef<Stmt*> handlers); 70203955Srdivacky 71212904Sdim CXXTryStmt(EmptyShell Empty, unsigned numHandlers) 72212904Sdim : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } 73212904Sdim 74212904Sdim Stmt const * const *getStmts() const { 75212904Sdim return reinterpret_cast<Stmt const * const*>(this + 1); 76212904Sdim } 77212904Sdim Stmt **getStmts() { 78212904Sdim return reinterpret_cast<Stmt **>(this + 1); 79212904Sdim } 80212904Sdim 81193326Sedpublic: 82263509Sdim static CXXTryStmt *Create(const ASTContext &C, SourceLocation tryLoc, 83252723Sdim Stmt *tryBlock, ArrayRef<Stmt*> handlers); 84193326Sed 85263509Sdim static CXXTryStmt *Create(const ASTContext &C, EmptyShell Empty, 86212904Sdim unsigned numHandlers); 87212904Sdim 88252723Sdim SourceLocation getLocStart() const LLVM_READONLY { return getTryLoc(); } 89252723Sdim SourceLocation getLocEnd() const LLVM_READONLY { return getEndLoc(); } 90193326Sed 91193326Sed SourceLocation getTryLoc() const { return TryLoc; } 92203955Srdivacky SourceLocation getEndLoc() const { 93212904Sdim return getStmts()[NumHandlers]->getLocEnd(); 94203955Srdivacky } 95193326Sed 96203955Srdivacky CompoundStmt *getTryBlock() { 97252723Sdim return cast<CompoundStmt>(getStmts()[0]); 98203955Srdivacky } 99193326Sed const CompoundStmt *getTryBlock() const { 100252723Sdim return cast<CompoundStmt>(getStmts()[0]); 101193326Sed } 102193326Sed 103203955Srdivacky unsigned getNumHandlers() const { return NumHandlers; } 104193326Sed CXXCatchStmt *getHandler(unsigned i) { 105252723Sdim return cast<CXXCatchStmt>(getStmts()[i + 1]); 106193326Sed } 107193326Sed const CXXCatchStmt *getHandler(unsigned i) const { 108252723Sdim return cast<CXXCatchStmt>(getStmts()[i + 1]); 109193326Sed } 110193326Sed 111193326Sed static bool classof(const Stmt *T) { 112193326Sed return T->getStmtClass() == CXXTryStmtClass; 113193326Sed } 114193326Sed 115218893Sdim child_range children() { 116218893Sdim return child_range(getStmts(), getStmts() + getNumHandlers() + 1); 117218893Sdim } 118212904Sdim 119212904Sdim friend class ASTStmtReader; 120193326Sed}; 121193326Sed 122221345Sdim/// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for 123221345Sdim/// statement, represented as 'for (range-declarator : range-expression)'. 124221345Sdim/// 125221345Sdim/// This is stored in a partially-desugared form to allow full semantic 126221345Sdim/// analysis of the constituent components. The original syntactic components 127221345Sdim/// can be extracted using getLoopVariable and getRangeInit. 128221345Sdimclass CXXForRangeStmt : public Stmt { 129221345Sdim enum { RANGE, BEGINEND, COND, INC, LOOPVAR, BODY, END }; 130221345Sdim // SubExprs[RANGE] is an expression or declstmt. 131221345Sdim // SubExprs[COND] and SubExprs[INC] are expressions. 132221345Sdim Stmt *SubExprs[END]; 133221345Sdim SourceLocation ForLoc; 134221345Sdim SourceLocation ColonLoc; 135221345Sdim SourceLocation RParenLoc; 136221345Sdimpublic: 137221345Sdim CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd, 138221345Sdim Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body, 139221345Sdim SourceLocation FL, SourceLocation CL, SourceLocation RPL); 140221345Sdim CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { } 141193326Sed 142221345Sdim 143221345Sdim VarDecl *getLoopVariable(); 144221345Sdim Expr *getRangeInit(); 145221345Sdim 146221345Sdim const VarDecl *getLoopVariable() const; 147221345Sdim const Expr *getRangeInit() const; 148221345Sdim 149221345Sdim 150221345Sdim DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); } 151235633Sdim DeclStmt *getBeginEndStmt() { 152235633Sdim return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); 153235633Sdim } 154221345Sdim Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); } 155221345Sdim Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); } 156221345Sdim DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); } 157221345Sdim Stmt *getBody() { return SubExprs[BODY]; } 158221345Sdim 159221345Sdim const DeclStmt *getRangeStmt() const { 160221345Sdim return cast<DeclStmt>(SubExprs[RANGE]); 161221345Sdim } 162221345Sdim const DeclStmt *getBeginEndStmt() const { 163221345Sdim return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); 164221345Sdim } 165221345Sdim const Expr *getCond() const { 166221345Sdim return cast_or_null<Expr>(SubExprs[COND]); 167221345Sdim } 168221345Sdim const Expr *getInc() const { 169221345Sdim return cast_or_null<Expr>(SubExprs[INC]); 170221345Sdim } 171221345Sdim const DeclStmt *getLoopVarStmt() const { 172221345Sdim return cast<DeclStmt>(SubExprs[LOOPVAR]); 173221345Sdim } 174221345Sdim const Stmt *getBody() const { return SubExprs[BODY]; } 175221345Sdim 176221345Sdim void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); } 177221345Sdim void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } 178221345Sdim void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; } 179221345Sdim void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } 180221345Sdim void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } 181221345Sdim void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } 182221345Sdim void setBody(Stmt *S) { SubExprs[BODY] = S; } 183221345Sdim 184221345Sdim 185221345Sdim SourceLocation getForLoc() const { return ForLoc; } 186221345Sdim void setForLoc(SourceLocation Loc) { ForLoc = Loc; } 187221345Sdim SourceLocation getColonLoc() const { return ColonLoc; } 188221345Sdim void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } 189221345Sdim SourceLocation getRParenLoc() const { return RParenLoc; } 190221345Sdim void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } 191221345Sdim 192252723Sdim SourceLocation getLocStart() const LLVM_READONLY { return ForLoc; } 193252723Sdim SourceLocation getLocEnd() const LLVM_READONLY { 194252723Sdim return SubExprs[BODY]->getLocEnd(); 195221345Sdim } 196252723Sdim 197221345Sdim static bool classof(const Stmt *T) { 198221345Sdim return T->getStmtClass() == CXXForRangeStmtClass; 199221345Sdim } 200221345Sdim 201221345Sdim // Iterators 202221345Sdim child_range children() { 203221345Sdim return child_range(&SubExprs[0], &SubExprs[END]); 204221345Sdim } 205221345Sdim}; 206221345Sdim 207235633Sdim/// \brief Representation of a Microsoft __if_exists or __if_not_exists 208235633Sdim/// statement with a dependent name. 209235633Sdim/// 210235633Sdim/// The __if_exists statement can be used to include a sequence of statements 211235633Sdim/// in the program only when a particular dependent name does not exist. For 212235633Sdim/// example: 213235633Sdim/// 214235633Sdim/// \code 215235633Sdim/// template<typename T> 216235633Sdim/// void call_foo(T &t) { 217235633Sdim/// __if_exists (T::foo) { 218235633Sdim/// t.foo(); // okay: only called when T::foo exists. 219235633Sdim/// } 220235633Sdim/// } 221235633Sdim/// \endcode 222235633Sdim/// 223235633Sdim/// Similarly, the __if_not_exists statement can be used to include the 224235633Sdim/// statements when a particular name does not exist. 225235633Sdim/// 226235633Sdim/// Note that this statement only captures __if_exists and __if_not_exists 227235633Sdim/// statements whose name is dependent. All non-dependent cases are handled 228235633Sdim/// directly in the parser, so that they don't introduce a new scope. Clang 229235633Sdim/// introduces scopes in the dependent case to keep names inside the compound 230235633Sdim/// statement from leaking out into the surround statements, which would 231235633Sdim/// compromise the template instantiation model. This behavior differs from 232235633Sdim/// Visual C++ (which never introduces a scope), but is a fairly reasonable 233235633Sdim/// approximation of the VC++ behavior. 234235633Sdimclass MSDependentExistsStmt : public Stmt { 235235633Sdim SourceLocation KeywordLoc; 236235633Sdim bool IsIfExists; 237235633Sdim NestedNameSpecifierLoc QualifierLoc; 238235633Sdim DeclarationNameInfo NameInfo; 239235633Sdim Stmt *SubStmt; 240221345Sdim 241235633Sdim friend class ASTReader; 242235633Sdim friend class ASTStmtReader; 243235633Sdim 244235633Sdimpublic: 245235633Sdim MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, 246235633Sdim NestedNameSpecifierLoc QualifierLoc, 247235633Sdim DeclarationNameInfo NameInfo, 248235633Sdim CompoundStmt *SubStmt) 249235633Sdim : Stmt(MSDependentExistsStmtClass), 250235633Sdim KeywordLoc(KeywordLoc), IsIfExists(IsIfExists), 251235633Sdim QualifierLoc(QualifierLoc), NameInfo(NameInfo), 252235633Sdim SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { } 253235633Sdim 254235633Sdim /// \brief Retrieve the location of the __if_exists or __if_not_exists 255235633Sdim /// keyword. 256235633Sdim SourceLocation getKeywordLoc() const { return KeywordLoc; } 257235633Sdim 258235633Sdim /// \brief Determine whether this is an __if_exists statement. 259235633Sdim bool isIfExists() const { return IsIfExists; } 260235633Sdim 261235633Sdim /// \brief Determine whether this is an __if_exists statement. 262235633Sdim bool isIfNotExists() const { return !IsIfExists; } 263235633Sdim 264235633Sdim /// \brief Retrieve the nested-name-specifier that qualifies this name, if 265235633Sdim /// any. 266235633Sdim NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } 267235633Sdim 268235633Sdim /// \brief Retrieve the name of the entity we're testing for, along with 269235633Sdim /// location information 270235633Sdim DeclarationNameInfo getNameInfo() const { return NameInfo; } 271235633Sdim 272235633Sdim /// \brief Retrieve the compound statement that will be included in the 273235633Sdim /// program only if the existence of the symbol matches the initial keyword. 274235633Sdim CompoundStmt *getSubStmt() const { 275235633Sdim return reinterpret_cast<CompoundStmt *>(SubStmt); 276235633Sdim } 277235633Sdim 278252723Sdim SourceLocation getLocStart() const LLVM_READONLY { return KeywordLoc; } 279252723Sdim SourceLocation getLocEnd() const LLVM_READONLY { return SubStmt->getLocEnd();} 280235633Sdim 281235633Sdim child_range children() { 282235633Sdim return child_range(&SubStmt, &SubStmt+1); 283235633Sdim } 284235633Sdim 285235633Sdim static bool classof(const Stmt *T) { 286235633Sdim return T->getStmtClass() == MSDependentExistsStmtClass; 287235633Sdim } 288235633Sdim}; 289235633Sdim 290193326Sed} // end namespace clang 291193326Sed 292193326Sed#endif 293