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/Stmt.h" 18 #include "llvm/Support/Compiler.h" 19 20 namespace clang { 21 22 class VarDecl; 23 24 /// CXXCatchStmt - This represents a C++ catch block. 25 /// 26 class CXXCatchStmt : public Stmt { 27 SourceLocation CatchLoc; 28 /// The exception-declaration of the type. 29 VarDecl *ExceptionDecl; 30 /// The handler block. 31 Stmt *HandlerBlock; 32 33 public: CXXCatchStmt(SourceLocation catchLoc,VarDecl * exDecl,Stmt * handlerBlock)34 CXXCatchStmt(SourceLocation catchLoc, VarDecl *exDecl, Stmt *handlerBlock) 35 : Stmt(CXXCatchStmtClass), CatchLoc(catchLoc), ExceptionDecl(exDecl), 36 HandlerBlock(handlerBlock) {} 37 CXXCatchStmt(EmptyShell Empty)38 CXXCatchStmt(EmptyShell Empty) 39 : Stmt(CXXCatchStmtClass), ExceptionDecl(0), HandlerBlock(0) {} 40 getSourceRange()41 SourceRange getSourceRange() const LLVM_READONLY { 42 return SourceRange(CatchLoc, HandlerBlock->getLocEnd()); 43 } 44 getCatchLoc()45 SourceLocation getCatchLoc() const { return CatchLoc; } getExceptionDecl()46 VarDecl *getExceptionDecl() const { return ExceptionDecl; } 47 QualType getCaughtType() const; getHandlerBlock()48 Stmt *getHandlerBlock() const { return HandlerBlock; } 49 classof(const Stmt * T)50 static bool classof(const Stmt *T) { 51 return T->getStmtClass() == CXXCatchStmtClass; 52 } classof(const CXXCatchStmt *)53 static bool classof(const CXXCatchStmt *) { return true; } 54 children()55 child_range children() { return child_range(&HandlerBlock, &HandlerBlock+1); } 56 57 friend class ASTStmtReader; 58 }; 59 60 /// CXXTryStmt - A C++ try block, including all handlers. 61 /// 62 class CXXTryStmt : public Stmt { 63 SourceLocation TryLoc; 64 unsigned NumHandlers; 65 66 CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, Stmt **handlers, 67 unsigned numHandlers); 68 CXXTryStmt(EmptyShell Empty,unsigned numHandlers)69 CXXTryStmt(EmptyShell Empty, unsigned numHandlers) 70 : Stmt(CXXTryStmtClass), NumHandlers(numHandlers) { } 71 getStmts()72 Stmt const * const *getStmts() const { 73 return reinterpret_cast<Stmt const * const*>(this + 1); 74 } getStmts()75 Stmt **getStmts() { 76 return reinterpret_cast<Stmt **>(this + 1); 77 } 78 79 public: 80 static CXXTryStmt *Create(ASTContext &C, SourceLocation tryLoc, 81 Stmt *tryBlock, Stmt **handlers, 82 unsigned numHandlers); 83 84 static CXXTryStmt *Create(ASTContext &C, EmptyShell Empty, 85 unsigned numHandlers); 86 getSourceRange()87 SourceRange getSourceRange() const LLVM_READONLY { 88 return SourceRange(getTryLoc(), getEndLoc()); 89 } 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 llvm::cast<CompoundStmt>(getStmts()[0]); 98 } getTryBlock()99 const CompoundStmt *getTryBlock() const { 100 return llvm::cast<CompoundStmt>(getStmts()[0]); 101 } 102 getNumHandlers()103 unsigned getNumHandlers() const { return NumHandlers; } getHandler(unsigned i)104 CXXCatchStmt *getHandler(unsigned i) { 105 return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]); 106 } getHandler(unsigned i)107 const CXXCatchStmt *getHandler(unsigned i) const { 108 return llvm::cast<CXXCatchStmt>(getStmts()[i + 1]); 109 } 110 classof(const Stmt * T)111 static bool classof(const Stmt *T) { 112 return T->getStmtClass() == CXXTryStmtClass; 113 } classof(const CXXTryStmt *)114 static bool classof(const CXXTryStmt *) { return true; } 115 children()116 child_range children() { 117 return child_range(getStmts(), getStmts() + getNumHandlers() + 1); 118 } 119 120 friend class ASTStmtReader; 121 }; 122 123 /// CXXForRangeStmt - This represents C++0x [stmt.ranged]'s ranged for 124 /// statement, represented as 'for (range-declarator : range-expression)'. 125 /// 126 /// This is stored in a partially-desugared form to allow full semantic 127 /// analysis of the constituent components. The original syntactic components 128 /// can be extracted using getLoopVariable and getRangeInit. 129 class CXXForRangeStmt : public Stmt { 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 ForLoc; 135 SourceLocation ColonLoc; 136 SourceLocation RParenLoc; 137 public: 138 CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEnd, 139 Expr *Cond, Expr *Inc, DeclStmt *LoopVar, Stmt *Body, 140 SourceLocation FL, SourceLocation CL, SourceLocation RPL); CXXForRangeStmt(EmptyShell Empty)141 CXXForRangeStmt(EmptyShell Empty) : Stmt(CXXForRangeStmtClass, Empty) { } 142 143 144 VarDecl *getLoopVariable(); 145 Expr *getRangeInit(); 146 147 const VarDecl *getLoopVariable() const; 148 const Expr *getRangeInit() const; 149 150 getRangeStmt()151 DeclStmt *getRangeStmt() { return cast<DeclStmt>(SubExprs[RANGE]); } getBeginEndStmt()152 DeclStmt *getBeginEndStmt() { 153 return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); 154 } getCond()155 Expr *getCond() { return cast_or_null<Expr>(SubExprs[COND]); } getInc()156 Expr *getInc() { return cast_or_null<Expr>(SubExprs[INC]); } getLoopVarStmt()157 DeclStmt *getLoopVarStmt() { return cast<DeclStmt>(SubExprs[LOOPVAR]); } getBody()158 Stmt *getBody() { return SubExprs[BODY]; } 159 getRangeStmt()160 const DeclStmt *getRangeStmt() const { 161 return cast<DeclStmt>(SubExprs[RANGE]); 162 } getBeginEndStmt()163 const DeclStmt *getBeginEndStmt() const { 164 return cast_or_null<DeclStmt>(SubExprs[BEGINEND]); 165 } getCond()166 const Expr *getCond() const { 167 return cast_or_null<Expr>(SubExprs[COND]); 168 } getInc()169 const Expr *getInc() const { 170 return cast_or_null<Expr>(SubExprs[INC]); 171 } getLoopVarStmt()172 const DeclStmt *getLoopVarStmt() const { 173 return cast<DeclStmt>(SubExprs[LOOPVAR]); 174 } getBody()175 const Stmt *getBody() const { return SubExprs[BODY]; } 176 setRangeInit(Expr * E)177 void setRangeInit(Expr *E) { SubExprs[RANGE] = reinterpret_cast<Stmt*>(E); } setRangeStmt(Stmt * S)178 void setRangeStmt(Stmt *S) { SubExprs[RANGE] = S; } setBeginEndStmt(Stmt * S)179 void setBeginEndStmt(Stmt *S) { SubExprs[BEGINEND] = S; } setCond(Expr * E)180 void setCond(Expr *E) { SubExprs[COND] = reinterpret_cast<Stmt*>(E); } setInc(Expr * E)181 void setInc(Expr *E) { SubExprs[INC] = reinterpret_cast<Stmt*>(E); } setLoopVarStmt(Stmt * S)182 void setLoopVarStmt(Stmt *S) { SubExprs[LOOPVAR] = S; } setBody(Stmt * S)183 void setBody(Stmt *S) { SubExprs[BODY] = S; } 184 185 getForLoc()186 SourceLocation getForLoc() const { return ForLoc; } setForLoc(SourceLocation Loc)187 void setForLoc(SourceLocation Loc) { ForLoc = Loc; } getColonLoc()188 SourceLocation getColonLoc() const { return ColonLoc; } setColonLoc(SourceLocation Loc)189 void setColonLoc(SourceLocation Loc) { ColonLoc = Loc; } getRParenLoc()190 SourceLocation getRParenLoc() const { return RParenLoc; } setRParenLoc(SourceLocation Loc)191 void setRParenLoc(SourceLocation Loc) { RParenLoc = Loc; } 192 getSourceRange()193 SourceRange getSourceRange() const LLVM_READONLY { 194 return SourceRange(ForLoc, SubExprs[BODY]->getLocEnd()); 195 } classof(const Stmt * T)196 static bool classof(const Stmt *T) { 197 return T->getStmtClass() == CXXForRangeStmtClass; 198 } classof(const CXXForRangeStmt *)199 static bool classof(const CXXForRangeStmt *) { return true; } 200 201 // Iterators children()202 child_range children() { 203 return child_range(&SubExprs[0], &SubExprs[END]); 204 } 205 }; 206 207 /// \brief Representation of a Microsoft __if_exists or __if_not_exists 208 /// statement with a dependent name. 209 /// 210 /// The __if_exists statement can be used to include a sequence of statements 211 /// in the program only when a particular dependent name does not exist. For 212 /// example: 213 /// 214 /// \code 215 /// template<typename T> 216 /// void call_foo(T &t) { 217 /// __if_exists (T::foo) { 218 /// t.foo(); // okay: only called when T::foo exists. 219 /// } 220 /// } 221 /// \endcode 222 /// 223 /// Similarly, the __if_not_exists statement can be used to include the 224 /// statements when a particular name does not exist. 225 /// 226 /// Note that this statement only captures __if_exists and __if_not_exists 227 /// statements whose name is dependent. All non-dependent cases are handled 228 /// directly in the parser, so that they don't introduce a new scope. Clang 229 /// introduces scopes in the dependent case to keep names inside the compound 230 /// statement from leaking out into the surround statements, which would 231 /// compromise the template instantiation model. This behavior differs from 232 /// Visual C++ (which never introduces a scope), but is a fairly reasonable 233 /// approximation of the VC++ behavior. 234 class MSDependentExistsStmt : public Stmt { 235 SourceLocation KeywordLoc; 236 bool IsIfExists; 237 NestedNameSpecifierLoc QualifierLoc; 238 DeclarationNameInfo NameInfo; 239 Stmt *SubStmt; 240 241 friend class ASTReader; 242 friend class ASTStmtReader; 243 244 public: MSDependentExistsStmt(SourceLocation KeywordLoc,bool IsIfExists,NestedNameSpecifierLoc QualifierLoc,DeclarationNameInfo NameInfo,CompoundStmt * SubStmt)245 MSDependentExistsStmt(SourceLocation KeywordLoc, bool IsIfExists, 246 NestedNameSpecifierLoc QualifierLoc, 247 DeclarationNameInfo NameInfo, 248 CompoundStmt *SubStmt) 249 : Stmt(MSDependentExistsStmtClass), 250 KeywordLoc(KeywordLoc), IsIfExists(IsIfExists), 251 QualifierLoc(QualifierLoc), NameInfo(NameInfo), 252 SubStmt(reinterpret_cast<Stmt *>(SubStmt)) { } 253 254 /// \brief Retrieve the location of the __if_exists or __if_not_exists 255 /// keyword. getKeywordLoc()256 SourceLocation getKeywordLoc() const { return KeywordLoc; } 257 258 /// \brief Determine whether this is an __if_exists statement. isIfExists()259 bool isIfExists() const { return IsIfExists; } 260 261 /// \brief Determine whether this is an __if_exists statement. isIfNotExists()262 bool isIfNotExists() const { return !IsIfExists; } 263 264 /// \brief Retrieve the nested-name-specifier that qualifies this name, if 265 /// any. getQualifierLoc()266 NestedNameSpecifierLoc getQualifierLoc() const { return QualifierLoc; } 267 268 /// \brief Retrieve the name of the entity we're testing for, along with 269 /// location information getNameInfo()270 DeclarationNameInfo getNameInfo() const { return NameInfo; } 271 272 /// \brief Retrieve the compound statement that will be included in the 273 /// program only if the existence of the symbol matches the initial keyword. getSubStmt()274 CompoundStmt *getSubStmt() const { 275 return reinterpret_cast<CompoundStmt *>(SubStmt); 276 } 277 getSourceRange()278 SourceRange getSourceRange() const LLVM_READONLY { 279 return SourceRange(KeywordLoc, SubStmt->getLocEnd()); 280 } 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 classof(MSDependentExistsStmt *)290 static bool classof(MSDependentExistsStmt *) { return true; } 291 }; 292 293 } // end namespace clang 294 295 #endif 296