Stmt.cpp revision 193326
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(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::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 62void DeclStmt::Destroy(ASTContext &C) { 63 this->~DeclStmt(); 64 C.Deallocate((void *)this); 65} 66 67void 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 91void Stmt::addStmtClass(StmtClass s) { 92 ++getStmtInfoTableEntry(s).Counter; 93} 94 95static bool StatSwitch = false; 96 97bool Stmt::CollectingStats(bool enable) { 98 if (enable) StatSwitch = true; 99 return StatSwitch; 100} 101 102NullStmt* NullStmt::Clone(ASTContext &C) const { 103 return new (C) NullStmt(SemiLoc); 104} 105 106ContinueStmt* ContinueStmt::Clone(ASTContext &C) const { 107 return new (C) ContinueStmt(ContinueLoc); 108} 109 110BreakStmt* BreakStmt::Clone(ASTContext &C) const { 111 return new (C) BreakStmt(BreakLoc); 112} 113 114void 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 123const char *LabelStmt::getName() const { 124 return getID()->getName(); 125} 126 127// This is defined here to avoid polluting Stmt.h with importing Expr.h 128SourceRange ReturnStmt::getSourceRange() const { 129 if (RetExpr) 130 return SourceRange(RetLoc, RetExpr->getLocEnd()); 131 else 132 return SourceRange(RetLoc); 133} 134 135bool 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 157Expr *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 '+'). 164std::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. 171unsigned 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 181Expr *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. 187std::string AsmStmt::getInputConstraint(unsigned i) const { 188 return std::string(Constraints[i + NumOutputs]->getStrData(), 189 Constraints[i + NumOutputs]->getByteLength()); 190} 191 192 193void 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. 212int 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 229void 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. 237unsigned 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 368AsmStmt::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 386ObjCForCollectionStmt::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 398ObjCAtCatchStmt::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 425Stmt::child_iterator DeclStmt::child_begin() { 426 return StmtIterator(DG.begin(), DG.end()); 427} 428 429Stmt::child_iterator DeclStmt::child_end() { 430 return StmtIterator(DG.end(), DG.end()); 431} 432 433// NullStmt 434Stmt::child_iterator NullStmt::child_begin() { return child_iterator(); } 435Stmt::child_iterator NullStmt::child_end() { return child_iterator(); } 436 437// CompoundStmt 438Stmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; } 439Stmt::child_iterator CompoundStmt::child_end() { return &Body[0]+NumStmts; } 440 441// CaseStmt 442Stmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; } 443Stmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; } 444 445// DefaultStmt 446Stmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; } 447Stmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; } 448 449// LabelStmt 450Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; } 451Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; } 452 453// IfStmt 454Stmt::child_iterator IfStmt::child_begin() { return &SubExprs[0]; } 455Stmt::child_iterator IfStmt::child_end() { return &SubExprs[0]+END_EXPR; } 456 457// SwitchStmt 458Stmt::child_iterator SwitchStmt::child_begin() { return &SubExprs[0]; } 459Stmt::child_iterator SwitchStmt::child_end() { return &SubExprs[0]+END_EXPR; } 460 461// WhileStmt 462Stmt::child_iterator WhileStmt::child_begin() { return &SubExprs[0]; } 463Stmt::child_iterator WhileStmt::child_end() { return &SubExprs[0]+END_EXPR; } 464 465// DoStmt 466Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; } 467Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; } 468 469// ForStmt 470Stmt::child_iterator ForStmt::child_begin() { return &SubExprs[0]; } 471Stmt::child_iterator ForStmt::child_end() { return &SubExprs[0]+END_EXPR; } 472 473// ObjCForCollectionStmt 474Stmt::child_iterator ObjCForCollectionStmt::child_begin() { 475 return &SubExprs[0]; 476} 477Stmt::child_iterator ObjCForCollectionStmt::child_end() { 478 return &SubExprs[0]+END_EXPR; 479} 480 481// GotoStmt 482Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); } 483Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); } 484 485// IndirectGotoStmt 486Expr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); } 487const Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); } 488 489Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; } 490Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; } 491 492// ContinueStmt 493Stmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); } 494Stmt::child_iterator ContinueStmt::child_end() { return child_iterator(); } 495 496// BreakStmt 497Stmt::child_iterator BreakStmt::child_begin() { return child_iterator(); } 498Stmt::child_iterator BreakStmt::child_end() { return child_iterator(); } 499 500// ReturnStmt 501const Expr* ReturnStmt::getRetValue() const { 502 return cast_or_null<Expr>(RetExpr); 503} 504Expr* ReturnStmt::getRetValue() { 505 return cast_or_null<Expr>(RetExpr); 506} 507 508Stmt::child_iterator ReturnStmt::child_begin() { 509 return &RetExpr; 510} 511Stmt::child_iterator ReturnStmt::child_end() { 512 return RetExpr ? &RetExpr+1 : &RetExpr; 513} 514 515// AsmStmt 516Stmt::child_iterator AsmStmt::child_begin() { 517 return Exprs.empty() ? 0 : &Exprs[0]; 518} 519Stmt::child_iterator AsmStmt::child_end() { 520 return Exprs.empty() ? 0 : &Exprs[0] + Exprs.size(); 521} 522 523// ObjCAtCatchStmt 524Stmt::child_iterator ObjCAtCatchStmt::child_begin() { return &SubExprs[0]; } 525Stmt::child_iterator ObjCAtCatchStmt::child_end() { 526 return &SubExprs[0]+END_EXPR; 527} 528 529// ObjCAtFinallyStmt 530Stmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; } 531Stmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; } 532 533// ObjCAtTryStmt 534Stmt::child_iterator ObjCAtTryStmt::child_begin() { return &SubStmts[0]; } 535Stmt::child_iterator ObjCAtTryStmt::child_end() { 536 return &SubStmts[0]+END_EXPR; 537} 538 539// ObjCAtThrowStmt 540Stmt::child_iterator ObjCAtThrowStmt::child_begin() { 541 return &Throw; 542} 543 544Stmt::child_iterator ObjCAtThrowStmt::child_end() { 545 return &Throw+1; 546} 547 548// ObjCAtSynchronizedStmt 549Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() { 550 return &SubStmts[0]; 551} 552 553Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() { 554 return &SubStmts[0]+END_EXPR; 555} 556 557// CXXCatchStmt 558Stmt::child_iterator CXXCatchStmt::child_begin() { 559 return &HandlerBlock; 560} 561 562Stmt::child_iterator CXXCatchStmt::child_end() { 563 return &HandlerBlock + 1; 564} 565 566QualType CXXCatchStmt::getCaughtType() { 567 if (ExceptionDecl) 568 return ExceptionDecl->getType(); 569 return QualType(); 570} 571 572void CXXCatchStmt::Destroy(ASTContext& C) { 573 if (ExceptionDecl) 574 ExceptionDecl->Destroy(C); 575 Stmt::Destroy(C); 576} 577 578// CXXTryStmt 579Stmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; } 580Stmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); } 581 582CXXTryStmt::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