Stmt.cpp revision d497206844a894a0557e927adf29b34fe960dffd
1//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===// 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 implements the Stmt class and statement subclasses. 11// 12//===----------------------------------------------------------------------===// 13 14#include "clang/AST/Stmt.h" 15#include "clang/AST/ExprCXX.h" 16#include "clang/AST/ExprObjC.h" 17#include "clang/AST/StmtCXX.h" 18#include "clang/AST/StmtObjC.h" 19#include "clang/AST/Type.h" 20#include "clang/AST/ASTContext.h" 21#include "clang/AST/ASTDiagnostic.h" 22using namespace clang; 23 24static struct StmtClassNameTable { 25 const char *Name; 26 unsigned Counter; 27 unsigned Size; 28} StmtClassInfo[Stmt::lastExprConstant+1]; 29 30static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) { 31 static bool Initialized = false; 32 if (Initialized) 33 return StmtClassInfo[E]; 34 35 // Intialize the table on the first use. 36 Initialized = true; 37#define STMT(CLASS, PARENT) \ 38 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \ 39 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS); 40#include "clang/AST/StmtNodes.def" 41 42 return StmtClassInfo[E]; 43} 44 45const char *Stmt::getStmtClassName() const { 46 return getStmtInfoTableEntry((StmtClass)sClass).Name; 47} 48 49void Stmt::DestroyChildren(ASTContext &C) { 50 for (child_iterator I = child_begin(), E = child_end(); I !=E; ) 51 if (Stmt* Child = *I++) Child->Destroy(C); 52} 53 54void Stmt::DoDestroy(ASTContext &C) { 55 DestroyChildren(C); 56 this->~Stmt(); 57 C.Deallocate((void *)this); 58} 59 60void Stmt::PrintStats() { 61 // Ensure the table is primed. 62 getStmtInfoTableEntry(Stmt::NullStmtClass); 63 64 unsigned sum = 0; 65 fprintf(stderr, "*** Stmt/Expr Stats:\n"); 66 for (int i = 0; i != Stmt::lastExprConstant+1; i++) { 67 if (StmtClassInfo[i].Name == 0) continue; 68 sum += StmtClassInfo[i].Counter; 69 } 70 fprintf(stderr, " %d stmts/exprs total.\n", sum); 71 sum = 0; 72 for (int i = 0; i != Stmt::lastExprConstant+1; i++) { 73 if (StmtClassInfo[i].Name == 0) continue; 74 if (StmtClassInfo[i].Counter == 0) continue; 75 fprintf(stderr, " %d %s, %d each (%d bytes)\n", 76 StmtClassInfo[i].Counter, StmtClassInfo[i].Name, 77 StmtClassInfo[i].Size, 78 StmtClassInfo[i].Counter*StmtClassInfo[i].Size); 79 sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size; 80 } 81 fprintf(stderr, "Total bytes = %d\n", sum); 82} 83 84void Stmt::addStmtClass(StmtClass s) { 85 ++getStmtInfoTableEntry(s).Counter; 86} 87 88static bool StatSwitch = false; 89 90bool Stmt::CollectingStats(bool enable) { 91 if (enable) StatSwitch = true; 92 return StatSwitch; 93} 94 95void SwitchStmt::DoDestroy(ASTContext &Ctx) { 96 // Destroy the SwitchCase statements in this switch. In the normal 97 // case, this loop will merely decrement the reference counts from 98 // the Retain() calls in addSwitchCase(); 99 SwitchCase *SC = FirstCase; 100 while (SC) { 101 SwitchCase *Next = SC->getNextSwitchCase(); 102 SC->Destroy(Ctx); 103 SC = Next; 104 } 105 106 Stmt::DoDestroy(Ctx); 107} 108 109void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) { 110 if (this->Body) 111 C.Deallocate(Body); 112 this->NumStmts = NumStmts; 113 114 Body = new (C) Stmt*[NumStmts]; 115 memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts); 116} 117 118const char *LabelStmt::getName() const { 119 return getID()->getName(); 120} 121 122// This is defined here to avoid polluting Stmt.h with importing Expr.h 123SourceRange ReturnStmt::getSourceRange() const { 124 if (RetExpr) 125 return SourceRange(RetLoc, RetExpr->getLocEnd()); 126 else 127 return SourceRange(RetLoc); 128} 129 130bool Stmt::hasImplicitControlFlow() const { 131 switch (sClass) { 132 default: 133 return false; 134 135 case CallExprClass: 136 case ConditionalOperatorClass: 137 case ChooseExprClass: 138 case StmtExprClass: 139 case DeclStmtClass: 140 return true; 141 142 case Stmt::BinaryOperatorClass: { 143 const BinaryOperator* B = cast<BinaryOperator>(this); 144 if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma) 145 return true; 146 else 147 return false; 148 } 149 } 150} 151 152Expr *AsmStmt::getOutputExpr(unsigned i) { 153 return cast<Expr>(Exprs[i]); 154} 155 156/// getOutputConstraint - Return the constraint string for the specified 157/// output operand. All output constraints are known to be non-empty (either 158/// '=' or '+'). 159std::string AsmStmt::getOutputConstraint(unsigned i) const { 160 return std::string(Constraints[i]->getStrData(), 161 Constraints[i]->getByteLength()); 162} 163 164/// getNumPlusOperands - Return the number of output operands that have a "+" 165/// constraint. 166unsigned AsmStmt::getNumPlusOperands() const { 167 unsigned Res = 0; 168 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) 169 if (isOutputPlusConstraint(i)) 170 ++Res; 171 return Res; 172} 173 174 175 176Expr *AsmStmt::getInputExpr(unsigned i) { 177 return cast<Expr>(Exprs[i + NumOutputs]); 178} 179 180/// getInputConstraint - Return the specified input constraint. Unlike output 181/// constraints, these can be empty. 182std::string AsmStmt::getInputConstraint(unsigned i) const { 183 return std::string(Constraints[i + NumOutputs]->getStrData(), 184 Constraints[i + NumOutputs]->getByteLength()); 185} 186 187 188void AsmStmt::setOutputsAndInputs(unsigned NumOutputs, 189 unsigned NumInputs, 190 const std::string *Names, 191 StringLiteral **Constraints, 192 Stmt **Exprs) { 193 this->NumOutputs = NumOutputs; 194 this->NumInputs = NumInputs; 195 this->Names.clear(); 196 this->Names.insert(this->Names.end(), Names, Names + NumOutputs + NumInputs); 197 this->Constraints.clear(); 198 this->Constraints.insert(this->Constraints.end(), 199 Constraints, Constraints + NumOutputs + NumInputs); 200 this->Exprs.clear(); 201 this->Exprs.insert(this->Exprs.end(), Exprs, Exprs + NumOutputs + NumInputs); 202} 203 204/// getNamedOperand - Given a symbolic operand reference like %[foo], 205/// translate this into a numeric value needed to reference the same operand. 206/// This returns -1 if the operand name is invalid. 207int AsmStmt::getNamedOperand(const std::string &SymbolicName) const { 208 unsigned NumPlusOperands = 0; 209 210 // Check if this is an output operand. 211 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) { 212 if (getOutputName(i) == SymbolicName) 213 return i; 214 } 215 216 for (unsigned i = 0, e = getNumInputs(); i != e; ++i) 217 if (getInputName(i) == SymbolicName) 218 return getNumOutputs() + NumPlusOperands + i; 219 220 // Not found. 221 return -1; 222} 223 224void AsmStmt::setClobbers(StringLiteral **Clobbers, unsigned NumClobbers) { 225 this->Clobbers.clear(); 226 this->Clobbers.insert(this->Clobbers.end(), Clobbers, Clobbers + NumClobbers); 227} 228 229/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing 230/// it into pieces. If the asm string is erroneous, emit errors and return 231/// true, otherwise return false. 232unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces, 233 ASTContext &C, unsigned &DiagOffs) const { 234 const char *StrStart = getAsmString()->getStrData(); 235 const char *StrEnd = StrStart + getAsmString()->getByteLength(); 236 const char *CurPtr = StrStart; 237 238 // "Simple" inline asms have no constraints or operands, just convert the asm 239 // string to escape $'s. 240 if (isSimple()) { 241 std::string Result; 242 for (; CurPtr != StrEnd; ++CurPtr) { 243 switch (*CurPtr) { 244 case '$': 245 Result += "$$"; 246 break; 247 default: 248 Result += *CurPtr; 249 break; 250 } 251 } 252 Pieces.push_back(AsmStringPiece(Result)); 253 return 0; 254 } 255 256 // CurStringPiece - The current string that we are building up as we scan the 257 // asm string. 258 std::string CurStringPiece; 259 260 while (1) { 261 // Done with the string? 262 if (CurPtr == StrEnd) { 263 if (!CurStringPiece.empty()) 264 Pieces.push_back(AsmStringPiece(CurStringPiece)); 265 return 0; 266 } 267 268 char CurChar = *CurPtr++; 269 if (CurChar == '$') { 270 CurStringPiece += "$$"; 271 continue; 272 } else if (CurChar != '%') { 273 CurStringPiece += CurChar; 274 continue; 275 } 276 277 // Escaped "%" character in asm string. 278 if (CurPtr == StrEnd) { 279 // % at end of string is invalid (no escape). 280 DiagOffs = CurPtr-StrStart-1; 281 return diag::err_asm_invalid_escape; 282 } 283 284 char EscapedChar = *CurPtr++; 285 if (EscapedChar == '%') { // %% -> % 286 // Escaped percentage sign. 287 CurStringPiece += '%'; 288 continue; 289 } 290 291 if (EscapedChar == '=') { // %= -> Generate an unique ID. 292 CurStringPiece += "${:uid}"; 293 continue; 294 } 295 296 // Otherwise, we have an operand. If we have accumulated a string so far, 297 // add it to the Pieces list. 298 if (!CurStringPiece.empty()) { 299 Pieces.push_back(AsmStringPiece(CurStringPiece)); 300 CurStringPiece.clear(); 301 } 302 303 // Handle %x4 and %x[foo] by capturing x as the modifier character. 304 char Modifier = '\0'; 305 if (isalpha(EscapedChar)) { 306 Modifier = EscapedChar; 307 EscapedChar = *CurPtr++; 308 } 309 310 if (isdigit(EscapedChar)) { 311 // %n - Assembler operand n 312 unsigned N = 0; 313 314 --CurPtr; 315 while (CurPtr != StrEnd && isdigit(*CurPtr)) 316 N = N*10 + ((*CurPtr++)-'0'); 317 318 unsigned NumOperands = 319 getNumOutputs() + getNumPlusOperands() + getNumInputs(); 320 if (N >= NumOperands) { 321 DiagOffs = CurPtr-StrStart-1; 322 return diag::err_asm_invalid_operand_number; 323 } 324 325 Pieces.push_back(AsmStringPiece(N, Modifier)); 326 continue; 327 } 328 329 // Handle %[foo], a symbolic operand reference. 330 if (EscapedChar == '[') { 331 DiagOffs = CurPtr-StrStart-1; 332 333 // Find the ']'. 334 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr); 335 if (NameEnd == 0) 336 return diag::err_asm_unterminated_symbolic_operand_name; 337 if (NameEnd == CurPtr) 338 return diag::err_asm_empty_symbolic_operand_name; 339 340 std::string SymbolicName(CurPtr, NameEnd); 341 342 int N = getNamedOperand(SymbolicName); 343 if (N == -1) { 344 // Verify that an operand with that name exists. 345 DiagOffs = CurPtr-StrStart; 346 return diag::err_asm_unknown_symbolic_operand_name; 347 } 348 Pieces.push_back(AsmStringPiece(N, Modifier)); 349 350 CurPtr = NameEnd+1; 351 continue; 352 } 353 354 DiagOffs = CurPtr-StrStart-1; 355 return diag::err_asm_invalid_escape; 356 } 357} 358 359//===----------------------------------------------------------------------===// 360// Constructors 361//===----------------------------------------------------------------------===// 362 363AsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile, 364 unsigned numoutputs, unsigned numinputs, 365 std::string *names, StringLiteral **constraints, 366 Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, 367 StringLiteral **clobbers, SourceLocation rparenloc) 368 : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr) 369 , IsSimple(issimple), IsVolatile(isvolatile) 370 , NumOutputs(numoutputs), NumInputs(numinputs) { 371 for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) { 372 Names.push_back(names[i]); 373 Exprs.push_back(exprs[i]); 374 Constraints.push_back(constraints[i]); 375 } 376 377 for (unsigned i = 0; i != numclobbers; i++) 378 Clobbers.push_back(clobbers[i]); 379} 380 381ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, 382 Stmt *Body, SourceLocation FCL, 383 SourceLocation RPL) 384: Stmt(ObjCForCollectionStmtClass) { 385 SubExprs[ELEM] = Elem; 386 SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect); 387 SubExprs[BODY] = Body; 388 ForLoc = FCL; 389 RParenLoc = RPL; 390} 391 392 393ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc, 394 SourceLocation rparenloc, 395 ParmVarDecl *catchVarDecl, Stmt *atCatchStmt, 396 Stmt *atCatchList) 397: Stmt(ObjCAtCatchStmtClass) { 398 ExceptionDecl = catchVarDecl; 399 SubExprs[BODY] = atCatchStmt; 400 SubExprs[NEXT_CATCH] = NULL; 401 // FIXME: O(N^2) in number of catch blocks. 402 if (atCatchList) { 403 ObjCAtCatchStmt *AtCatchList = static_cast<ObjCAtCatchStmt*>(atCatchList); 404 405 while (ObjCAtCatchStmt* NextCatch = AtCatchList->getNextCatchStmt()) 406 AtCatchList = NextCatch; 407 408 AtCatchList->SubExprs[NEXT_CATCH] = this; 409 } 410 AtCatchLoc = atCatchLoc; 411 RParenLoc = rparenloc; 412} 413 414 415//===----------------------------------------------------------------------===// 416// Child Iterators for iterating over subexpressions/substatements 417//===----------------------------------------------------------------------===// 418 419// DeclStmt 420Stmt::child_iterator DeclStmt::child_begin() { 421 return StmtIterator(DG.begin(), DG.end()); 422} 423 424Stmt::child_iterator DeclStmt::child_end() { 425 return StmtIterator(DG.end(), DG.end()); 426} 427 428// NullStmt 429Stmt::child_iterator NullStmt::child_begin() { return child_iterator(); } 430Stmt::child_iterator NullStmt::child_end() { return child_iterator(); } 431 432// CompoundStmt 433Stmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; } 434Stmt::child_iterator CompoundStmt::child_end() { return &Body[0]+NumStmts; } 435 436// CaseStmt 437Stmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; } 438Stmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; } 439 440// DefaultStmt 441Stmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; } 442Stmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; } 443 444// LabelStmt 445Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; } 446Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; } 447 448// IfStmt 449Stmt::child_iterator IfStmt::child_begin() { return &SubExprs[0]; } 450Stmt::child_iterator IfStmt::child_end() { return &SubExprs[0]+END_EXPR; } 451 452// SwitchStmt 453Stmt::child_iterator SwitchStmt::child_begin() { return &SubExprs[0]; } 454Stmt::child_iterator SwitchStmt::child_end() { return &SubExprs[0]+END_EXPR; } 455 456// WhileStmt 457Stmt::child_iterator WhileStmt::child_begin() { return &SubExprs[0]; } 458Stmt::child_iterator WhileStmt::child_end() { return &SubExprs[0]+END_EXPR; } 459 460// DoStmt 461Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; } 462Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; } 463 464// ForStmt 465Stmt::child_iterator ForStmt::child_begin() { return &SubExprs[0]; } 466Stmt::child_iterator ForStmt::child_end() { return &SubExprs[0]+END_EXPR; } 467 468// ObjCForCollectionStmt 469Stmt::child_iterator ObjCForCollectionStmt::child_begin() { 470 return &SubExprs[0]; 471} 472Stmt::child_iterator ObjCForCollectionStmt::child_end() { 473 return &SubExprs[0]+END_EXPR; 474} 475 476// GotoStmt 477Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); } 478Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); } 479 480// IndirectGotoStmt 481Expr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); } 482const Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); } 483 484Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; } 485Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; } 486 487// ContinueStmt 488Stmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); } 489Stmt::child_iterator ContinueStmt::child_end() { return child_iterator(); } 490 491// BreakStmt 492Stmt::child_iterator BreakStmt::child_begin() { return child_iterator(); } 493Stmt::child_iterator BreakStmt::child_end() { return child_iterator(); } 494 495// ReturnStmt 496const Expr* ReturnStmt::getRetValue() const { 497 return cast_or_null<Expr>(RetExpr); 498} 499Expr* ReturnStmt::getRetValue() { 500 return cast_or_null<Expr>(RetExpr); 501} 502 503Stmt::child_iterator ReturnStmt::child_begin() { 504 return &RetExpr; 505} 506Stmt::child_iterator ReturnStmt::child_end() { 507 return RetExpr ? &RetExpr+1 : &RetExpr; 508} 509 510// AsmStmt 511Stmt::child_iterator AsmStmt::child_begin() { 512 return Exprs.empty() ? 0 : &Exprs[0]; 513} 514Stmt::child_iterator AsmStmt::child_end() { 515 return Exprs.empty() ? 0 : &Exprs[0] + Exprs.size(); 516} 517 518// ObjCAtCatchStmt 519Stmt::child_iterator ObjCAtCatchStmt::child_begin() { return &SubExprs[0]; } 520Stmt::child_iterator ObjCAtCatchStmt::child_end() { 521 return &SubExprs[0]+END_EXPR; 522} 523 524// ObjCAtFinallyStmt 525Stmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; } 526Stmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; } 527 528// ObjCAtTryStmt 529Stmt::child_iterator ObjCAtTryStmt::child_begin() { return &SubStmts[0]; } 530Stmt::child_iterator ObjCAtTryStmt::child_end() { 531 return &SubStmts[0]+END_EXPR; 532} 533 534// ObjCAtThrowStmt 535Stmt::child_iterator ObjCAtThrowStmt::child_begin() { 536 return &Throw; 537} 538 539Stmt::child_iterator ObjCAtThrowStmt::child_end() { 540 return &Throw+1; 541} 542 543// ObjCAtSynchronizedStmt 544Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() { 545 return &SubStmts[0]; 546} 547 548Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() { 549 return &SubStmts[0]+END_EXPR; 550} 551 552// CXXCatchStmt 553Stmt::child_iterator CXXCatchStmt::child_begin() { 554 return &HandlerBlock; 555} 556 557Stmt::child_iterator CXXCatchStmt::child_end() { 558 return &HandlerBlock + 1; 559} 560 561QualType CXXCatchStmt::getCaughtType() { 562 if (ExceptionDecl) 563 return ExceptionDecl->getType(); 564 return QualType(); 565} 566 567void CXXCatchStmt::DoDestroy(ASTContext& C) { 568 if (ExceptionDecl) 569 ExceptionDecl->Destroy(C); 570 Stmt::DoDestroy(C); 571} 572 573// CXXTryStmt 574Stmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; } 575Stmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); } 576 577CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, 578 Stmt **handlers, unsigned numHandlers) 579 : Stmt(CXXTryStmtClass), TryLoc(tryLoc) { 580 Stmts.push_back(tryBlock); 581 Stmts.insert(Stmts.end(), handlers, handlers + numHandlers); 582} 583