Stmt.cpp revision 201361
1106266Sjulian//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===// 2106266Sjulian// 3106266Sjulian// The LLVM Compiler Infrastructure 4106266Sjulian// 5106266Sjulian// This file is distributed under the University of Illinois Open Source 6106266Sjulian// License. See LICENSE.TXT for details. 7106266Sjulian// 8106266Sjulian//===----------------------------------------------------------------------===// 9106319Sjulian// 10106266Sjulian// This file implements the Stmt class and statement subclasses. 11106319Sjulian// 12106319Sjulian//===----------------------------------------------------------------------===// 13106266Sjulian 14106319Sjulian#include "clang/AST/Stmt.h" 15106319Sjulian#include "clang/AST/ExprCXX.h" 16106266Sjulian#include "clang/AST/ExprObjC.h" 17106266Sjulian#include "clang/AST/StmtCXX.h" 18106266Sjulian#include "clang/AST/StmtObjC.h" 19106319Sjulian#include "clang/AST/Type.h" 20106319Sjulian#include "clang/AST/ASTContext.h" 21106319Sjulian#include "clang/AST/ASTDiagnostic.h" 22106266Sjulian#include <cstdio> 23106266Sjulianusing namespace clang; 24106266Sjulian 25106266Sjulianstatic struct StmtClassNameTable { 26106266Sjulian const char *Name; 27106319Sjulian unsigned Counter; 28106266Sjulian unsigned Size; 29106266Sjulian} StmtClassInfo[Stmt::lastExprConstant+1]; 30106266Sjulian 31106266Sjulianstatic StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) { 32106266Sjulian static bool Initialized = false; 33106266Sjulian if (Initialized) 34106266Sjulian return StmtClassInfo[E]; 35106266Sjulian 36106266Sjulian // Intialize the table on the first use. 37106266Sjulian Initialized = true; 38106266Sjulian#define STMT(CLASS, PARENT) \ 39106266Sjulian StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \ 40106266Sjulian StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS); 41106266Sjulian#include "clang/AST/StmtNodes.def" 42106266Sjulian 43106266Sjulian return StmtClassInfo[E]; 44106266Sjulian} 45106266Sjulian 46106266Sjulianconst char *Stmt::getStmtClassName() const { 47106266Sjulian return getStmtInfoTableEntry((StmtClass)sClass).Name; 48106266Sjulian} 49106266Sjulian 50106266Sjulianvoid Stmt::PrintStats() { 51106266Sjulian // Ensure the table is primed. 52106266Sjulian getStmtInfoTableEntry(Stmt::NullStmtClass); 53106266Sjulian 54106266Sjulian unsigned sum = 0; 55106266Sjulian fprintf(stderr, "*** Stmt/Expr Stats:\n"); 56106266Sjulian for (int i = 0; i != Stmt::lastExprConstant+1; i++) { 57106266Sjulian if (StmtClassInfo[i].Name == 0) continue; 58106266Sjulian sum += StmtClassInfo[i].Counter; 59106266Sjulian } 60106266Sjulian fprintf(stderr, " %d stmts/exprs total.\n", sum); 61106266Sjulian sum = 0; 62106266Sjulian for (int i = 0; i != Stmt::lastExprConstant+1; i++) { 63106266Sjulian if (StmtClassInfo[i].Name == 0) continue; 64106266Sjulian if (StmtClassInfo[i].Counter == 0) continue; 65106266Sjulian fprintf(stderr, " %d %s, %d each (%d bytes)\n", 66106266Sjulian StmtClassInfo[i].Counter, StmtClassInfo[i].Name, 67106266Sjulian StmtClassInfo[i].Size, 68106266Sjulian StmtClassInfo[i].Counter*StmtClassInfo[i].Size); 69106266Sjulian sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size; 70106266Sjulian } 71106266Sjulian fprintf(stderr, "Total bytes = %d\n", sum); 72106266Sjulian} 73106266Sjulian 74106266Sjulianvoid Stmt::addStmtClass(StmtClass s) { 75106266Sjulian ++getStmtInfoTableEntry(s).Counter; 76106266Sjulian} 77106266Sjulian 78106266Sjulianstatic bool StatSwitch = false; 79106266Sjulian 80106266Sjulianbool Stmt::CollectingStats(bool Enable) { 81106266Sjulian if (Enable) StatSwitch = true; 82106266Sjulian return StatSwitch; 83106266Sjulian} 84106266Sjulian 85106266Sjulianvoid CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) { 86106266Sjulian if (this->Body) 87106319Sjulian C.Deallocate(Body); 88106266Sjulian this->NumStmts = NumStmts; 89106266Sjulian 90106319Sjulian Body = new (C) Stmt*[NumStmts]; 91106266Sjulian memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts); 92106266Sjulian} 93106266Sjulian 94106266Sjulianconst char *LabelStmt::getName() const { 95106266Sjulian return getID()->getNameStart(); 96106266Sjulian} 97106266Sjulian 98106266Sjulian// This is defined here to avoid polluting Stmt.h with importing Expr.h 99106266SjulianSourceRange ReturnStmt::getSourceRange() const { 100106266Sjulian if (RetExpr) 101106266Sjulian return SourceRange(RetLoc, RetExpr->getLocEnd()); 102106266Sjulian else 103106266Sjulian return SourceRange(RetLoc); 104106266Sjulian} 105106266Sjulian 106106266Sjulianbool Stmt::hasImplicitControlFlow() const { 107106266Sjulian switch (sClass) { 108106266Sjulian default: 109106266Sjulian return false; 110106266Sjulian 111106266Sjulian case CallExprClass: 112106266Sjulian case ConditionalOperatorClass: 113106266Sjulian case ChooseExprClass: 114106266Sjulian case StmtExprClass: 115106266Sjulian case DeclStmtClass: 116106266Sjulian return true; 117106266Sjulian 118106266Sjulian case Stmt::BinaryOperatorClass: { 119106266Sjulian const BinaryOperator* B = cast<BinaryOperator>(this); 120106266Sjulian if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma) 121106266Sjulian return true; 122106266Sjulian else 123106266Sjulian return false; 124106266Sjulian } 125106266Sjulian } 126106266Sjulian} 127106266Sjulian 128106266SjulianExpr *AsmStmt::getOutputExpr(unsigned i) { 129106266Sjulian return cast<Expr>(Exprs[i]); 130106266Sjulian} 131106266Sjulian 132106266Sjulian/// getOutputConstraint - Return the constraint string for the specified 133106266Sjulian/// output operand. All output constraints are known to be non-empty (either 134106266Sjulian/// '=' or '+'). 135106266Sjulianstd::string AsmStmt::getOutputConstraint(unsigned i) const { 136106266Sjulian return std::string(Constraints[i]->getStrData(), 137106266Sjulian Constraints[i]->getByteLength()); 138106266Sjulian} 139106266Sjulian 140106266Sjulian/// getNumPlusOperands - Return the number of output operands that have a "+" 141106266Sjulian/// constraint. 142106266Sjulianunsigned AsmStmt::getNumPlusOperands() const { 143106266Sjulian unsigned Res = 0; 144106266Sjulian for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) 145106266Sjulian if (isOutputPlusConstraint(i)) 146106266Sjulian ++Res; 147106266Sjulian return Res; 148106266Sjulian} 149106266Sjulian 150106266Sjulian 151106266Sjulian 152106266SjulianExpr *AsmStmt::getInputExpr(unsigned i) { 153106266Sjulian return cast<Expr>(Exprs[i + NumOutputs]); 154106266Sjulian} 155106266Sjulian 156106266Sjulian/// getInputConstraint - Return the specified input constraint. Unlike output 157106266Sjulian/// constraints, these can be empty. 158106266Sjulianstd::string AsmStmt::getInputConstraint(unsigned i) const { 159106266Sjulian return std::string(Constraints[i + NumOutputs]->getStrData(), 160106266Sjulian Constraints[i + NumOutputs]->getByteLength()); 161106266Sjulian} 162106266Sjulian 163106266Sjulian 164106266Sjulianvoid AsmStmt::setOutputsAndInputs(unsigned NumOutputs, 165106266Sjulian unsigned NumInputs, 166106266Sjulian const std::string *Names, 167106266Sjulian StringLiteral **Constraints, 168106266Sjulian Stmt **Exprs) { 169106266Sjulian this->NumOutputs = NumOutputs; 170106266Sjulian this->NumInputs = NumInputs; 171106266Sjulian this->Names.clear(); 172106266Sjulian this->Names.insert(this->Names.end(), Names, Names + NumOutputs + NumInputs); 173106266Sjulian this->Constraints.clear(); 174106266Sjulian this->Constraints.insert(this->Constraints.end(), 175106266Sjulian Constraints, Constraints + NumOutputs + NumInputs); 176106266Sjulian this->Exprs.clear(); 177106266Sjulian this->Exprs.insert(this->Exprs.end(), Exprs, Exprs + NumOutputs + NumInputs); 178106266Sjulian} 179106266Sjulian 180106266Sjulian/// getNamedOperand - Given a symbolic operand reference like %[foo], 181106266Sjulian/// translate this into a numeric value needed to reference the same operand. 182106266Sjulian/// This returns -1 if the operand name is invalid. 183106266Sjulianint AsmStmt::getNamedOperand(const std::string &SymbolicName) const { 184106266Sjulian unsigned NumPlusOperands = 0; 185106266Sjulian 186106266Sjulian // Check if this is an output operand. 187106266Sjulian for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) { 188106266Sjulian if (getOutputName(i) == SymbolicName) 189106266Sjulian return i; 190106266Sjulian } 191106266Sjulian 192106266Sjulian for (unsigned i = 0, e = getNumInputs(); i != e; ++i) 193106266Sjulian if (getInputName(i) == SymbolicName) 194106266Sjulian return getNumOutputs() + NumPlusOperands + i; 195106266Sjulian 196106266Sjulian // Not found. 197106266Sjulian return -1; 198106266Sjulian} 199106266Sjulian 200106266Sjulianvoid AsmStmt::setClobbers(StringLiteral **Clobbers, unsigned NumClobbers) { 201106266Sjulian this->Clobbers.clear(); 202106266Sjulian this->Clobbers.insert(this->Clobbers.end(), Clobbers, Clobbers + NumClobbers); 203106266Sjulian} 204106266Sjulian 205106266Sjulian/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing 206106266Sjulian/// it into pieces. If the asm string is erroneous, emit errors and return 207106266Sjulian/// true, otherwise return false. 208106266Sjulianunsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces, 209106266Sjulian ASTContext &C, unsigned &DiagOffs) const { 210106266Sjulian const char *StrStart = getAsmString()->getStrData(); 211106266Sjulian const char *StrEnd = StrStart + getAsmString()->getByteLength(); 212106266Sjulian const char *CurPtr = StrStart; 213106266Sjulian 214106266Sjulian // "Simple" inline asms have no constraints or operands, just convert the asm 215106266Sjulian // string to escape $'s. 216106266Sjulian if (isSimple()) { 217106266Sjulian std::string Result; 218106266Sjulian for (; CurPtr != StrEnd; ++CurPtr) { 219106266Sjulian switch (*CurPtr) { 220106266Sjulian case '$': 221106266Sjulian Result += "$$"; 222106266Sjulian break; 223106266Sjulian default: 224106266Sjulian Result += *CurPtr; 225106266Sjulian break; 226106266Sjulian } 227106266Sjulian } 228106266Sjulian Pieces.push_back(AsmStringPiece(Result)); 229106266Sjulian return 0; 230106266Sjulian } 231106266Sjulian 232106266Sjulian // CurStringPiece - The current string that we are building up as we scan the 233106266Sjulian // asm string. 234106266Sjulian std::string CurStringPiece; 235106266Sjulian 236106266Sjulian while (1) { 237106266Sjulian // Done with the string? 238106266Sjulian if (CurPtr == StrEnd) { 239106266Sjulian if (!CurStringPiece.empty()) 240106266Sjulian Pieces.push_back(AsmStringPiece(CurStringPiece)); 241106266Sjulian return 0; 242106266Sjulian } 243106266Sjulian 244106266Sjulian char CurChar = *CurPtr++; 245106266Sjulian if (CurChar == '$') { 246106266Sjulian CurStringPiece += "$$"; 247106266Sjulian continue; 248106266Sjulian } else if (CurChar != '%') { 249106266Sjulian CurStringPiece += CurChar; 250106266Sjulian continue; 251106266Sjulian } 252106266Sjulian 253106266Sjulian // Escaped "%" character in asm string. 254106266Sjulian if (CurPtr == StrEnd) { 255106266Sjulian // % at end of string is invalid (no escape). 256106266Sjulian DiagOffs = CurPtr-StrStart-1; 257106266Sjulian return diag::err_asm_invalid_escape; 258106266Sjulian } 259106266Sjulian 260106266Sjulian char EscapedChar = *CurPtr++; 261106266Sjulian if (EscapedChar == '%') { // %% -> % 262106266Sjulian // Escaped percentage sign. 263106266Sjulian CurStringPiece += '%'; 264106266Sjulian continue; 265106266Sjulian } 266106266Sjulian 267106266Sjulian if (EscapedChar == '=') { // %= -> Generate an unique ID. 268106266Sjulian CurStringPiece += "${:uid}"; 269106266Sjulian continue; 270106266Sjulian } 271106266Sjulian 272106266Sjulian // Otherwise, we have an operand. If we have accumulated a string so far, 273106266Sjulian // add it to the Pieces list. 274106266Sjulian if (!CurStringPiece.empty()) { 275106266Sjulian Pieces.push_back(AsmStringPiece(CurStringPiece)); 276106266Sjulian CurStringPiece.clear(); 277106266Sjulian } 278106266Sjulian 279106266Sjulian // Handle %x4 and %x[foo] by capturing x as the modifier character. 280106266Sjulian char Modifier = '\0'; 281106266Sjulian if (isalpha(EscapedChar)) { 282106266Sjulian Modifier = EscapedChar; 283106266Sjulian EscapedChar = *CurPtr++; 284106266Sjulian } 285106266Sjulian 286106266Sjulian if (isdigit(EscapedChar)) { 287106319Sjulian // %n - Assembler operand n 288106266Sjulian unsigned N = 0; 289106266Sjulian 290106319Sjulian --CurPtr; 291106266Sjulian while (CurPtr != StrEnd && isdigit(*CurPtr)) 292106319Sjulian N = N*10 + ((*CurPtr++)-'0'); 293106266Sjulian 294106319Sjulian unsigned NumOperands = 295106266Sjulian getNumOutputs() + getNumPlusOperands() + getNumInputs(); 296106266Sjulian if (N >= NumOperands) { 297106266Sjulian DiagOffs = CurPtr-StrStart-1; 298106266Sjulian return diag::err_asm_invalid_operand_number; 299106266Sjulian } 300106266Sjulian 301106266Sjulian Pieces.push_back(AsmStringPiece(N, Modifier)); 302106266Sjulian continue; 303106266Sjulian } 304106266Sjulian 305106319Sjulian // Handle %[foo], a symbolic operand reference. 306106319Sjulian if (EscapedChar == '[') { 307106266Sjulian DiagOffs = CurPtr-StrStart-1; 308106266Sjulian 309106266Sjulian // Find the ']'. 310106266Sjulian const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr); 311106266Sjulian if (NameEnd == 0) 312106266Sjulian return diag::err_asm_unterminated_symbolic_operand_name; 313106266Sjulian if (NameEnd == CurPtr) 314106266Sjulian return diag::err_asm_empty_symbolic_operand_name; 315106266Sjulian 316106266Sjulian std::string SymbolicName(CurPtr, NameEnd); 317106266Sjulian 318106266Sjulian int N = getNamedOperand(SymbolicName); 319106266Sjulian if (N == -1) { 320106266Sjulian // Verify that an operand with that name exists. 321106266Sjulian DiagOffs = CurPtr-StrStart; 322106266Sjulian return diag::err_asm_unknown_symbolic_operand_name; 323106266Sjulian } 324106266Sjulian Pieces.push_back(AsmStringPiece(N, Modifier)); 325106266Sjulian 326106266Sjulian CurPtr = NameEnd+1; 327106266Sjulian continue; 328106266Sjulian } 329106266Sjulian 330106266Sjulian DiagOffs = CurPtr-StrStart-1; 331106266Sjulian return diag::err_asm_invalid_escape; 332106266Sjulian } 333106266Sjulian} 334106266Sjulian 335106266Sjulian//===----------------------------------------------------------------------===// 336106266Sjulian// Constructors 337106266Sjulian//===----------------------------------------------------------------------===// 338106266Sjulian 339106266SjulianAsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile, 340106266Sjulian unsigned numoutputs, unsigned numinputs, 341106266Sjulian std::string *names, StringLiteral **constraints, 342106266Sjulian Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, 343106266Sjulian StringLiteral **clobbers, SourceLocation rparenloc) 344106266Sjulian : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr) 345106266Sjulian , IsSimple(issimple), IsVolatile(isvolatile) 346106266Sjulian , NumOutputs(numoutputs), NumInputs(numinputs) { 347106266Sjulian for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) { 348106266Sjulian Names.push_back(names[i]); 349106266Sjulian Exprs.push_back(exprs[i]); 350106319Sjulian Constraints.push_back(constraints[i]); 351106266Sjulian } 352106266Sjulian 353106319Sjulian for (unsigned i = 0; i != numclobbers; i++) 354106266Sjulian Clobbers.push_back(clobbers[i]); 355106266Sjulian} 356106266Sjulian 357106266SjulianObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, 358106266Sjulian Stmt *Body, SourceLocation FCL, 359106266Sjulian SourceLocation RPL) 360106266Sjulian: Stmt(ObjCForCollectionStmtClass) { 361106266Sjulian SubExprs[ELEM] = Elem; 362106266Sjulian SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect); 363106266Sjulian SubExprs[BODY] = Body; 364106266Sjulian ForLoc = FCL; 365106266Sjulian RParenLoc = RPL; 366106266Sjulian} 367106266Sjulian 368106266Sjulian 369106266SjulianObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc, 370106266Sjulian SourceLocation rparenloc, 371106266Sjulian ParmVarDecl *catchVarDecl, Stmt *atCatchStmt, 372106266Sjulian Stmt *atCatchList) 373106266Sjulian: Stmt(ObjCAtCatchStmtClass) { 374106266Sjulian ExceptionDecl = catchVarDecl; 375106266Sjulian SubExprs[BODY] = atCatchStmt; 376106266Sjulian SubExprs[NEXT_CATCH] = NULL; 377106266Sjulian // FIXME: O(N^2) in number of catch blocks. 378106266Sjulian if (atCatchList) { 379106266Sjulian ObjCAtCatchStmt *AtCatchList = static_cast<ObjCAtCatchStmt*>(atCatchList); 380106266Sjulian 381106266Sjulian while (ObjCAtCatchStmt* NextCatch = AtCatchList->getNextCatchStmt()) 382106266Sjulian AtCatchList = NextCatch; 383106266Sjulian 384106266Sjulian AtCatchList->SubExprs[NEXT_CATCH] = this; 385106266Sjulian } 386106266Sjulian AtCatchLoc = atCatchLoc; 387106266Sjulian RParenLoc = rparenloc; 388106266Sjulian} 389106266Sjulian 390106266Sjulian//===----------------------------------------------------------------------===// 391106266Sjulian// AST Destruction. 392106266Sjulian//===----------------------------------------------------------------------===// 393106266Sjulian 394106266Sjulianvoid Stmt::DestroyChildren(ASTContext &C) { 395106266Sjulian for (child_iterator I = child_begin(), E = child_end(); I !=E; ) 396106266Sjulian if (Stmt* Child = *I++) Child->Destroy(C); 397106266Sjulian} 398106266Sjulian 399106266Sjulianstatic void BranchDestroy(ASTContext &C, Stmt *S, Stmt **SubExprs, 400106266Sjulian unsigned NumExprs) { 401106266Sjulian // We do not use child_iterator here because that will include 402106266Sjulian // the expressions referenced by the condition variable. 403106266Sjulian for (Stmt **I = SubExprs, **E = SubExprs + NumExprs; I != E; ++I) 404106266Sjulian if (Stmt *Child = *I) Child->Destroy(C); 405106266Sjulian 406106266Sjulian S->~Stmt(); 407106266Sjulian C.Deallocate((void *) S); 408106319Sjulian} 409106319Sjulian 410106266Sjulianvoid Stmt::DoDestroy(ASTContext &C) { 411106319Sjulian DestroyChildren(C); 412106319Sjulian this->~Stmt(); 413106266Sjulian C.Deallocate((void *)this); 414106266Sjulian} 415106266Sjulian 416106266Sjulianvoid CXXCatchStmt::DoDestroy(ASTContext& C) { 417106266Sjulian if (ExceptionDecl) 418106266Sjulian ExceptionDecl->Destroy(C); 419106266Sjulian Stmt::DoDestroy(C); 420106266Sjulian} 421106266Sjulian 422106266Sjulianvoid DeclStmt::DoDestroy(ASTContext &C) { 423106266Sjulian // Don't use StmtIterator to iterate over the Decls, as that can recurse 424106266Sjulian // into VLA size expressions (which are owned by the VLA). Further, Decls 425106266Sjulian // are owned by the DeclContext, and will be destroyed with them. 426106266Sjulian if (DG.isDeclGroup()) 427106266Sjulian DG.getDeclGroup().Destroy(C); 428106266Sjulian} 429106266Sjulian 430106266Sjulianvoid IfStmt::DoDestroy(ASTContext &C) { 431106266Sjulian BranchDestroy(C, this, SubExprs, END_EXPR); 432106266Sjulian} 433106266Sjulian 434106266Sjulianvoid ForStmt::DoDestroy(ASTContext &C) { 435106266Sjulian BranchDestroy(C, this, SubExprs, END_EXPR); 436106319Sjulian} 437106266Sjulian 438106266Sjulianvoid SwitchStmt::DoDestroy(ASTContext &C) { 439106266Sjulian // Destroy the SwitchCase statements in this switch. In the normal 440106266Sjulian // case, this loop will merely decrement the reference counts from 441106266Sjulian // the Retain() calls in addSwitchCase(); 442106266Sjulian SwitchCase *SC = FirstCase; 443106266Sjulian while (SC) { 444106266Sjulian SwitchCase *Next = SC->getNextSwitchCase(); 445106266Sjulian SC->Destroy(C); 446106266Sjulian SC = Next; 447106266Sjulian } 448106266Sjulian 449106266Sjulian BranchDestroy(C, this, SubExprs, END_EXPR); 450106266Sjulian} 451106266Sjulian 452106266Sjulianvoid WhileStmt::DoDestroy(ASTContext &C) { 453106266Sjulian BranchDestroy(C, this, SubExprs, END_EXPR); 454106266Sjulian} 455106266Sjulian 456106266Sjulian//===----------------------------------------------------------------------===// 457106266Sjulian// Child Iterators for iterating over subexpressions/substatements 458106266Sjulian//===----------------------------------------------------------------------===// 459106266Sjulian 460106266Sjulian// DeclStmt 461106319SjulianStmt::child_iterator DeclStmt::child_begin() { 462106266Sjulian return StmtIterator(DG.begin(), DG.end()); 463106266Sjulian} 464106266Sjulian 465106266SjulianStmt::child_iterator DeclStmt::child_end() { 466106266Sjulian return StmtIterator(DG.end(), DG.end()); 467106266Sjulian} 468106266Sjulian 469106266Sjulian// NullStmt 470106266SjulianStmt::child_iterator NullStmt::child_begin() { return child_iterator(); } 471106266SjulianStmt::child_iterator NullStmt::child_end() { return child_iterator(); } 472106266Sjulian 473106266Sjulian// CompoundStmt 474106266SjulianStmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; } 475106266SjulianStmt::child_iterator CompoundStmt::child_end() { return &Body[0]+NumStmts; } 476106319Sjulian 477106266Sjulian// CaseStmt 478106266SjulianStmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; } 479106266SjulianStmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; } 480106266Sjulian 481106266Sjulian// DefaultStmt 482106266SjulianStmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; } 483106266SjulianStmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; } 484106266Sjulian 485106266Sjulian// LabelStmt 486106266SjulianStmt::child_iterator LabelStmt::child_begin() { return &SubStmt; } 487106266SjulianStmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; } 488106266Sjulian 489106266Sjulian// IfStmt 490106266SjulianStmt::child_iterator IfStmt::child_begin() { 491106266Sjulian return child_iterator(Var, &SubExprs[0]); 492106266Sjulian} 493106266SjulianStmt::child_iterator IfStmt::child_end() { 494106266Sjulian return child_iterator(0, &SubExprs[0]+END_EXPR); 495106266Sjulian} 496106266Sjulian 497106266Sjulian// SwitchStmt 498106266SjulianStmt::child_iterator SwitchStmt::child_begin() { 499106266Sjulian return child_iterator(Var, &SubExprs[0]); 500106266Sjulian} 501106266SjulianStmt::child_iterator SwitchStmt::child_end() { 502106266Sjulian return child_iterator(0, &SubExprs[0]+END_EXPR); 503106266Sjulian} 504106266Sjulian 505106266Sjulian// WhileStmt 506106266SjulianStmt::child_iterator WhileStmt::child_begin() { 507106266Sjulian return child_iterator(Var, &SubExprs[0]); 508106266Sjulian} 509106266SjulianStmt::child_iterator WhileStmt::child_end() { 510106266Sjulian return child_iterator(0, &SubExprs[0]+END_EXPR); 511106266Sjulian} 512106266Sjulian 513106266Sjulian// DoStmt 514106266SjulianStmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; } 515106266SjulianStmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; } 516106266Sjulian 517106266Sjulian// ForStmt 518106266SjulianStmt::child_iterator ForStmt::child_begin() { 519106266Sjulian return child_iterator(CondVar, &SubExprs[0]); 520106266Sjulian} 521106266SjulianStmt::child_iterator ForStmt::child_end() { 522106266Sjulian return child_iterator(0, &SubExprs[0]+END_EXPR); 523106266Sjulian} 524106266Sjulian 525106266Sjulian// ObjCForCollectionStmt 526106266SjulianStmt::child_iterator ObjCForCollectionStmt::child_begin() { 527106266Sjulian return &SubExprs[0]; 528106266Sjulian} 529106266SjulianStmt::child_iterator ObjCForCollectionStmt::child_end() { 530106266Sjulian return &SubExprs[0]+END_EXPR; 531106319Sjulian} 532106266Sjulian 533106266Sjulian// GotoStmt 534106266SjulianStmt::child_iterator GotoStmt::child_begin() { return child_iterator(); } 535106266SjulianStmt::child_iterator GotoStmt::child_end() { return child_iterator(); } 536106266Sjulian 537106266Sjulian// IndirectGotoStmt 538106266SjulianExpr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); } 539106266Sjulianconst Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); } 540106266Sjulian 541106266SjulianStmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; } 542106266SjulianStmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; } 543106266Sjulian 544106266Sjulian// ContinueStmt 545106266SjulianStmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); } 546106266SjulianStmt::child_iterator ContinueStmt::child_end() { return child_iterator(); } 547106266Sjulian 548106266Sjulian// BreakStmt 549106266SjulianStmt::child_iterator BreakStmt::child_begin() { return child_iterator(); } 550106266SjulianStmt::child_iterator BreakStmt::child_end() { return child_iterator(); } 551106266Sjulian 552106266Sjulian// ReturnStmt 553106266Sjulianconst Expr* ReturnStmt::getRetValue() const { 554106266Sjulian return cast_or_null<Expr>(RetExpr); 555106266Sjulian} 556106266SjulianExpr* ReturnStmt::getRetValue() { 557106266Sjulian return cast_or_null<Expr>(RetExpr); 558106266Sjulian} 559106266Sjulian 560106266SjulianStmt::child_iterator ReturnStmt::child_begin() { 561106266Sjulian return &RetExpr; 562106266Sjulian} 563106266SjulianStmt::child_iterator ReturnStmt::child_end() { 564106266Sjulian return RetExpr ? &RetExpr+1 : &RetExpr; 565106266Sjulian} 566106266Sjulian 567106266Sjulian// AsmStmt 568106266SjulianStmt::child_iterator AsmStmt::child_begin() { 569106266Sjulian return Exprs.empty() ? 0 : &Exprs[0]; 570106266Sjulian} 571106266SjulianStmt::child_iterator AsmStmt::child_end() { 572106266Sjulian return Exprs.empty() ? 0 : &Exprs[0] + Exprs.size(); 573106266Sjulian} 574106266Sjulian 575106266Sjulian// ObjCAtCatchStmt 576106266SjulianStmt::child_iterator ObjCAtCatchStmt::child_begin() { return &SubExprs[0]; } 577106266SjulianStmt::child_iterator ObjCAtCatchStmt::child_end() { 578106266Sjulian return &SubExprs[0]+END_EXPR; 579106266Sjulian} 580106266Sjulian 581106266Sjulian// ObjCAtFinallyStmt 582106266SjulianStmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; } 583106266SjulianStmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; } 584106266Sjulian 585106266Sjulian// ObjCAtTryStmt 586106266SjulianStmt::child_iterator ObjCAtTryStmt::child_begin() { return &SubStmts[0]; } 587106266SjulianStmt::child_iterator ObjCAtTryStmt::child_end() { 588106266Sjulian return &SubStmts[0]+END_EXPR; 589106319Sjulian} 590106266Sjulian 591106266Sjulian// ObjCAtThrowStmt 592106266SjulianStmt::child_iterator ObjCAtThrowStmt::child_begin() { 593106266Sjulian return &Throw; 594106266Sjulian} 595106266Sjulian 596106266SjulianStmt::child_iterator ObjCAtThrowStmt::child_end() { 597106266Sjulian return &Throw+1; 598106266Sjulian} 599106266Sjulian 600106266Sjulian// ObjCAtSynchronizedStmt 601106266SjulianStmt::child_iterator ObjCAtSynchronizedStmt::child_begin() { 602106266Sjulian return &SubStmts[0]; 603106266Sjulian} 604106266Sjulian 605106266SjulianStmt::child_iterator ObjCAtSynchronizedStmt::child_end() { 606106266Sjulian return &SubStmts[0]+END_EXPR; 607106266Sjulian} 608106266Sjulian 609106266Sjulian// CXXCatchStmt 610106266SjulianStmt::child_iterator CXXCatchStmt::child_begin() { 611106266Sjulian return &HandlerBlock; 612106266Sjulian} 613106266Sjulian 614106266SjulianStmt::child_iterator CXXCatchStmt::child_end() { 615106266Sjulian return &HandlerBlock + 1; 616106266Sjulian} 617106266Sjulian 618106266SjulianQualType CXXCatchStmt::getCaughtType() const { 619106266Sjulian if (ExceptionDecl) 620106266Sjulian return ExceptionDecl->getType(); 621106266Sjulian return QualType(); 622106266Sjulian} 623106266Sjulian 624106266Sjulian// CXXTryStmt 625106266SjulianStmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; } 626106266SjulianStmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); } 627106266Sjulian 628106266SjulianCXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, 629106266Sjulian Stmt **handlers, unsigned numHandlers) 630106266Sjulian : Stmt(CXXTryStmtClass), TryLoc(tryLoc) { 631106266Sjulian Stmts.push_back(tryBlock); 632106266Sjulian Stmts.insert(Stmts.end(), handlers, handlers + numHandlers); 633106266Sjulian} 634106266Sjulian