Stmt.cpp revision 3182db1c8e456c4cd2180fac9d77d331b2c0621f
145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===// 245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// 345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// The LLVM Compiler Infrastructure 445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// 545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// This file is distributed under the University of Illinois Open Source 645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// License. See LICENSE.TXT for details. 745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// 845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//===----------------------------------------------------------------------===// 945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// 1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// This file implements the Stmt class and statement subclasses. 1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// 1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//===----------------------------------------------------------------------===// 1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/Stmt.h" 1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/ExprCXX.h" 1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/ExprObjC.h" 1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/Type.h" 1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/ASTContext.h" 1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/ASTDiagnostic.h" 2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgusing namespace clang; 2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic struct StmtClassNameTable { 2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org const char *Name; 2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned Counter; 2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org unsigned Size; 2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} StmtClassInfo[Stmt::lastExprConstant+1]; 2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) { 2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org static bool Initialized = false; 3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org if (Initialized) 3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return StmtClassInfo[E]; 3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org // Intialize the table on the first use. 3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org Initialized = true; 3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define STMT(CLASS, PARENT) \ 3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \ 3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS); 3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/StmtNodes.def" 3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return StmtClassInfo[E]; 4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} 4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org 4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconst char *Stmt::getStmtClassName() const { 4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org return getStmtInfoTableEntry(sClass).Name; 45} 46 47void Stmt::DestroyChildren(ASTContext &C) { 48 for (child_iterator I = child_begin(), E = child_end(); I !=E; ) 49 if (Stmt* Child = *I++) Child->Destroy(C); 50} 51 52void Stmt::Destroy(ASTContext &C) { 53 DestroyChildren(C); 54 // FIXME: Eventually all Stmts should be allocated with the allocator 55 // in ASTContext, just like with Decls. 56 this->~Stmt(); 57 C.Deallocate((void *)this); 58} 59 60void DeclStmt::Destroy(ASTContext &C) { 61 this->~DeclStmt(); 62 C.Deallocate((void *)this); 63} 64 65void Stmt::PrintStats() { 66 // Ensure the table is primed. 67 getStmtInfoTableEntry(Stmt::NullStmtClass); 68 69 unsigned sum = 0; 70 fprintf(stderr, "*** Stmt/Expr Stats:\n"); 71 for (int i = 0; i != Stmt::lastExprConstant+1; i++) { 72 if (StmtClassInfo[i].Name == 0) continue; 73 sum += StmtClassInfo[i].Counter; 74 } 75 fprintf(stderr, " %d stmts/exprs total.\n", sum); 76 sum = 0; 77 for (int i = 0; i != Stmt::lastExprConstant+1; i++) { 78 if (StmtClassInfo[i].Name == 0) continue; 79 fprintf(stderr, " %d %s, %d each (%d bytes)\n", 80 StmtClassInfo[i].Counter, StmtClassInfo[i].Name, 81 StmtClassInfo[i].Size, 82 StmtClassInfo[i].Counter*StmtClassInfo[i].Size); 83 sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size; 84 } 85 fprintf(stderr, "Total bytes = %d\n", sum); 86} 87 88void Stmt::addStmtClass(StmtClass s) { 89 ++getStmtInfoTableEntry(s).Counter; 90} 91 92static bool StatSwitch = false; 93 94bool Stmt::CollectingStats(bool enable) { 95 if (enable) StatSwitch = true; 96 return StatSwitch; 97} 98 99 100const char *LabelStmt::getName() const { 101 return getID()->getName(); 102} 103 104// This is defined here to avoid polluting Stmt.h with importing Expr.h 105SourceRange ReturnStmt::getSourceRange() const { 106 if (RetExpr) 107 return SourceRange(RetLoc, RetExpr->getLocEnd()); 108 else 109 return SourceRange(RetLoc); 110} 111 112bool Stmt::hasImplicitControlFlow() const { 113 switch (sClass) { 114 default: 115 return false; 116 117 case CallExprClass: 118 case ConditionalOperatorClass: 119 case ChooseExprClass: 120 case StmtExprClass: 121 case DeclStmtClass: 122 return true; 123 124 case Stmt::BinaryOperatorClass: { 125 const BinaryOperator* B = cast<BinaryOperator>(this); 126 if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma) 127 return true; 128 else 129 return false; 130 } 131 } 132} 133 134Expr *AsmStmt::getOutputExpr(unsigned i) { 135 return cast<Expr>(Exprs[i]); 136} 137 138/// getOutputConstraint - Return the constraint string for the specified 139/// output operand. All output constraints are known to be non-empty (either 140/// '=' or '+'). 141std::string AsmStmt::getOutputConstraint(unsigned i) const { 142 return std::string(Constraints[i]->getStrData(), 143 Constraints[i]->getByteLength()); 144} 145 146 147Expr *AsmStmt::getInputExpr(unsigned i) { 148 return cast<Expr>(Exprs[i + NumOutputs]); 149} 150 151/// getInputConstraint - Return the specified input constraint. Unlike output 152/// constraints, these can be empty. 153std::string AsmStmt::getInputConstraint(unsigned i) const { 154 return std::string(Constraints[i + NumOutputs]->getStrData(), 155 Constraints[i + NumOutputs]->getByteLength()); 156} 157 158 159/// getNamedOperand - Given a symbolic operand reference like %[foo], 160/// translate this into a numeric value needed to reference the same operand. 161/// This returns -1 if the operand name is invalid. 162int AsmStmt::getNamedOperand(const std::string &SymbolicName) const { 163 unsigned NumPlusOperands = 0; 164 165 // Check if this is an output operand. 166 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) { 167 if (getOutputName(i) == SymbolicName) 168 return i; 169 170 // Keep track of the number of '+' operands. 171 if (isOutputPlusConstraint(i)) ++NumPlusOperands; 172 } 173 174 for (unsigned i = 0, e = getNumInputs(); i != e; ++i) 175 if (getInputName(i) == SymbolicName) 176 return getNumOutputs() + NumPlusOperands + i; 177 178 // Not found. 179 return -1; 180} 181 182 183/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing 184/// it into pieces. If the asm string is erroneous, emit errors and return 185/// true, otherwise return false. 186unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces, 187 ASTContext &C, unsigned &DiagOffs) const { 188 const char *StrStart = getAsmString()->getStrData(); 189 const char *StrEnd = StrStart + getAsmString()->getByteLength(); 190 const char *CurPtr = StrStart; 191 192 // "Simple" inline asms have no constraints or operands, just convert the asm 193 // string to escape $'s. 194 if (isSimple()) { 195 std::string Result; 196 for (; CurPtr != StrEnd; ++CurPtr) { 197 switch (*CurPtr) { 198 case '$': 199 Result += "$$"; 200 break; 201 default: 202 Result += *CurPtr; 203 break; 204 } 205 } 206 Pieces.push_back(AsmStringPiece(Result)); 207 return 0; 208 } 209 210 // CurStringPiece - The current string that we are building up as we scan the 211 // asm string. 212 std::string CurStringPiece; 213 214 while (1) { 215 // Done with the string? 216 if (CurPtr == StrEnd) { 217 if (!CurStringPiece.empty()) 218 Pieces.push_back(AsmStringPiece(CurStringPiece)); 219 return 0; 220 } 221 222 char CurChar = *CurPtr++; 223 if (CurChar == '$') { 224 CurStringPiece += "$$"; 225 continue; 226 } else if (CurChar != '%') { 227 CurStringPiece += CurChar; 228 continue; 229 } 230 231 // Escaped "%" character in asm string. 232 // FIXME: This should be caught during Sema. 233 assert(CurPtr != StrEnd && "Trailing '%' in asm string."); 234 235 char EscapedChar = *CurPtr++; 236 if (EscapedChar == '%') { // %% -> % 237 // Escaped percentage sign. 238 CurStringPiece += '%'; 239 continue; 240 } 241 242 if (EscapedChar == '=') { // %= -> Generate an unique ID. 243 CurStringPiece += "${:uid}"; 244 continue; 245 } 246 247 // Otherwise, we have an operand. If we have accumulated a string so far, 248 // add it to the Pieces list. 249 if (!CurStringPiece.empty()) { 250 Pieces.push_back(AsmStringPiece(CurStringPiece)); 251 CurStringPiece.clear(); 252 } 253 254 // Handle %x4 and %x[foo] by capturing x as the modifier character. 255 char Modifier = '\0'; 256 if (isalpha(EscapedChar)) { 257 Modifier = EscapedChar; 258 EscapedChar = *CurPtr++; 259 } 260 261 if (isdigit(EscapedChar)) { 262 // %n - Assembler operand n 263 char *End; 264 unsigned long N = strtoul(CurPtr-1, &End, 10); 265 assert(End != CurPtr-1 && "We know that EscapedChar is a digit!"); 266 CurPtr = End; 267 268 // FIXME: This should be caught during Sema. 269 //unsigned NumOperands = S.getNumOutputs() + S.getNumInputs(); 270 //assert(N < NumOperands && "Operand number out of range!"); 271 272 Pieces.push_back(AsmStringPiece(N, Modifier)); 273 continue; 274 } 275 276 // Handle %[foo], a symbolic operand reference. 277 if (EscapedChar == '[') { 278 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr); 279 // FIXME: Should be caught by sema. 280 // FIXME: Does sema catch multiple operands with the same name? 281 assert(NameEnd != 0 && "Could not parse symbolic name"); 282 std::string SymbolicName(CurPtr, NameEnd); 283 CurPtr = NameEnd+1; 284 285 int N = getNamedOperand(SymbolicName); 286 assert(N != -1 && "FIXME: Catch in Sema."); 287 Pieces.push_back(AsmStringPiece(N, Modifier)); 288 continue; 289 } 290 291 DiagOffs = CurPtr-StrStart; 292 return diag::err_asm_invalid_escape; 293 } 294} 295 296//===----------------------------------------------------------------------===// 297// Constructors 298//===----------------------------------------------------------------------===// 299 300AsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile, 301 unsigned numoutputs, unsigned numinputs, 302 std::string *names, StringLiteral **constraints, 303 Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, 304 StringLiteral **clobbers, SourceLocation rparenloc) 305 : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr) 306 , IsSimple(issimple), IsVolatile(isvolatile) 307 , NumOutputs(numoutputs), NumInputs(numinputs) { 308 for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) { 309 Names.push_back(names[i]); 310 Exprs.push_back(exprs[i]); 311 Constraints.push_back(constraints[i]); 312 } 313 314 for (unsigned i = 0; i != numclobbers; i++) 315 Clobbers.push_back(clobbers[i]); 316} 317 318ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, 319 Stmt *Body, SourceLocation FCL, 320 SourceLocation RPL) 321: Stmt(ObjCForCollectionStmtClass) { 322 SubExprs[ELEM] = Elem; 323 SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect); 324 SubExprs[BODY] = Body; 325 ForLoc = FCL; 326 RParenLoc = RPL; 327} 328 329 330ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc, 331 SourceLocation rparenloc, 332 ParmVarDecl *catchVarDecl, Stmt *atCatchStmt, 333 Stmt *atCatchList) 334: Stmt(ObjCAtCatchStmtClass) { 335 ExceptionDecl = catchVarDecl; 336 SubExprs[BODY] = atCatchStmt; 337 SubExprs[NEXT_CATCH] = NULL; 338 // FIXME: O(N^2) in number of catch blocks. 339 if (atCatchList) { 340 ObjCAtCatchStmt *AtCatchList = static_cast<ObjCAtCatchStmt*>(atCatchList); 341 342 while (ObjCAtCatchStmt* NextCatch = AtCatchList->getNextCatchStmt()) 343 AtCatchList = NextCatch; 344 345 AtCatchList->SubExprs[NEXT_CATCH] = this; 346 } 347 AtCatchLoc = atCatchLoc; 348 RParenLoc = rparenloc; 349} 350 351 352//===----------------------------------------------------------------------===// 353// Child Iterators for iterating over subexpressions/substatements 354//===----------------------------------------------------------------------===// 355 356// DeclStmt 357Stmt::child_iterator DeclStmt::child_begin() { 358 return StmtIterator(DG.begin(), DG.end()); 359} 360 361Stmt::child_iterator DeclStmt::child_end() { 362 return StmtIterator(DG.end(), DG.end()); 363} 364 365// NullStmt 366Stmt::child_iterator NullStmt::child_begin() { return child_iterator(); } 367Stmt::child_iterator NullStmt::child_end() { return child_iterator(); } 368 369// CompoundStmt 370Stmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; } 371Stmt::child_iterator CompoundStmt::child_end() { return &Body[0]+NumStmts; } 372 373// CaseStmt 374Stmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; } 375Stmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; } 376 377// DefaultStmt 378Stmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; } 379Stmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; } 380 381// LabelStmt 382Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; } 383Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; } 384 385// IfStmt 386Stmt::child_iterator IfStmt::child_begin() { return &SubExprs[0]; } 387Stmt::child_iterator IfStmt::child_end() { return &SubExprs[0]+END_EXPR; } 388 389// SwitchStmt 390Stmt::child_iterator SwitchStmt::child_begin() { return &SubExprs[0]; } 391Stmt::child_iterator SwitchStmt::child_end() { return &SubExprs[0]+END_EXPR; } 392 393// WhileStmt 394Stmt::child_iterator WhileStmt::child_begin() { return &SubExprs[0]; } 395Stmt::child_iterator WhileStmt::child_end() { return &SubExprs[0]+END_EXPR; } 396 397// DoStmt 398Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; } 399Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; } 400 401// ForStmt 402Stmt::child_iterator ForStmt::child_begin() { return &SubExprs[0]; } 403Stmt::child_iterator ForStmt::child_end() { return &SubExprs[0]+END_EXPR; } 404 405// ObjCForCollectionStmt 406Stmt::child_iterator ObjCForCollectionStmt::child_begin() { 407 return &SubExprs[0]; 408} 409Stmt::child_iterator ObjCForCollectionStmt::child_end() { 410 return &SubExprs[0]+END_EXPR; 411} 412 413// GotoStmt 414Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); } 415Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); } 416 417// IndirectGotoStmt 418Expr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); } 419const Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); } 420 421Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; } 422Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; } 423 424// ContinueStmt 425Stmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); } 426Stmt::child_iterator ContinueStmt::child_end() { return child_iterator(); } 427 428// BreakStmt 429Stmt::child_iterator BreakStmt::child_begin() { return child_iterator(); } 430Stmt::child_iterator BreakStmt::child_end() { return child_iterator(); } 431 432// ReturnStmt 433const Expr* ReturnStmt::getRetValue() const { 434 return cast_or_null<Expr>(RetExpr); 435} 436Expr* ReturnStmt::getRetValue() { 437 return cast_or_null<Expr>(RetExpr); 438} 439 440Stmt::child_iterator ReturnStmt::child_begin() { 441 return &RetExpr; 442} 443Stmt::child_iterator ReturnStmt::child_end() { 444 return RetExpr ? &RetExpr+1 : &RetExpr; 445} 446 447// AsmStmt 448Stmt::child_iterator AsmStmt::child_begin() { 449 return Exprs.empty() ? 0 : &Exprs[0]; 450} 451Stmt::child_iterator AsmStmt::child_end() { 452 return Exprs.empty() ? 0 : &Exprs[0] + Exprs.size(); 453} 454 455// ObjCAtCatchStmt 456Stmt::child_iterator ObjCAtCatchStmt::child_begin() { return &SubExprs[0]; } 457Stmt::child_iterator ObjCAtCatchStmt::child_end() { 458 return &SubExprs[0]+END_EXPR; 459} 460 461// ObjCAtFinallyStmt 462Stmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; } 463Stmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; } 464 465// ObjCAtTryStmt 466Stmt::child_iterator ObjCAtTryStmt::child_begin() { return &SubStmts[0]; } 467Stmt::child_iterator ObjCAtTryStmt::child_end() { 468 return &SubStmts[0]+END_EXPR; 469} 470 471// ObjCAtThrowStmt 472Stmt::child_iterator ObjCAtThrowStmt::child_begin() { 473 return &Throw; 474} 475 476Stmt::child_iterator ObjCAtThrowStmt::child_end() { 477 return &Throw+1; 478} 479 480// ObjCAtSynchronizedStmt 481Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() { 482 return &SubStmts[0]; 483} 484 485Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() { 486 return &SubStmts[0]+END_EXPR; 487} 488 489// CXXCatchStmt 490Stmt::child_iterator CXXCatchStmt::child_begin() { 491 return &HandlerBlock; 492} 493 494Stmt::child_iterator CXXCatchStmt::child_end() { 495 return &HandlerBlock + 1; 496} 497 498QualType CXXCatchStmt::getCaughtType() { 499 if (ExceptionDecl) 500 return llvm::cast<VarDecl>(ExceptionDecl)->getType(); 501 return QualType(); 502} 503 504void CXXCatchStmt::Destroy(ASTContext& C) { 505 if (ExceptionDecl) 506 ExceptionDecl->Destroy(C); 507 Stmt::Destroy(C); 508} 509 510// CXXTryStmt 511Stmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; } 512Stmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); } 513 514CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, 515 Stmt **handlers, unsigned numHandlers) 516 : Stmt(CXXTryStmtClass), TryLoc(tryLoc) { 517 Stmts.push_back(tryBlock); 518 Stmts.insert(Stmts.end(), handlers, handlers + numHandlers); 519} 520