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