Stmt.cpp revision 90e25a8b2cc5d006e4ced052bcdb40c8af999456
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#include "clang/Basic/TargetInfo.h" 23#include "llvm/Support/raw_ostream.h" 24using namespace clang; 25 26static struct StmtClassNameTable { 27 const char *Name; 28 unsigned Counter; 29 unsigned Size; 30} StmtClassInfo[Stmt::lastStmtConstant+1]; 31 32static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) { 33 static bool Initialized = false; 34 if (Initialized) 35 return StmtClassInfo[E]; 36 37 // Intialize the table on the first use. 38 Initialized = true; 39#define ABSTRACT_STMT(STMT) 40#define STMT(CLASS, PARENT) \ 41 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \ 42 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS); 43#include "clang/AST/StmtNodes.inc" 44 45 return StmtClassInfo[E]; 46} 47 48const char *Stmt::getStmtClassName() const { 49 return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name; 50} 51 52void Stmt::PrintStats() { 53 // Ensure the table is primed. 54 getStmtInfoTableEntry(Stmt::NullStmtClass); 55 56 unsigned sum = 0; 57 llvm::errs() << "\n*** Stmt/Expr Stats:\n"; 58 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { 59 if (StmtClassInfo[i].Name == 0) continue; 60 sum += StmtClassInfo[i].Counter; 61 } 62 llvm::errs() << " " << sum << " stmts/exprs total.\n"; 63 sum = 0; 64 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { 65 if (StmtClassInfo[i].Name == 0) continue; 66 if (StmtClassInfo[i].Counter == 0) continue; 67 llvm::errs() << " " << StmtClassInfo[i].Counter << " " 68 << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size 69 << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size 70 << " bytes)\n"; 71 sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size; 72 } 73 74 llvm::errs() << "Total bytes = " << sum << "\n"; 75} 76 77void Stmt::addStmtClass(StmtClass s) { 78 ++getStmtInfoTableEntry(s).Counter; 79} 80 81bool Stmt::StatisticsEnabled = false; 82void Stmt::EnableStatistics() { 83 StatisticsEnabled = true; 84} 85 86Stmt *Stmt::IgnoreImplicit() { 87 Stmt *s = this; 88 89 if (ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(s)) 90 s = ewc->getSubExpr(); 91 92 while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(s)) 93 s = ice->getSubExpr(); 94 95 return s; 96} 97 98/// \brief Strip off all label-like statements. 99/// 100/// This will strip off label statements, case statements, and default 101/// statements recursively. 102const Stmt *Stmt::stripLabelLikeStatements() const { 103 const Stmt *S = this; 104 while (true) { 105 if (const LabelStmt *LS = dyn_cast<LabelStmt>(S)) 106 S = LS->getSubStmt(); 107 else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S)) 108 S = SC->getSubStmt(); 109 else 110 return S; 111 } 112} 113 114namespace { 115 struct good {}; 116 struct bad {}; 117 118 // These silly little functions have to be static inline to suppress 119 // unused warnings, and they have to be defined to suppress other 120 // warnings. 121 static inline good is_good(good) { return good(); } 122 123 typedef Stmt::child_range children_t(); 124 template <class T> good implements_children(children_t T::*) { 125 return good(); 126 } 127 static inline bad implements_children(children_t Stmt::*) { 128 return bad(); 129 } 130 131 typedef SourceRange getSourceRange_t() const; 132 template <class T> good implements_getSourceRange(getSourceRange_t T::*) { 133 return good(); 134 } 135 static inline bad implements_getSourceRange(getSourceRange_t Stmt::*) { 136 return bad(); 137 } 138 139#define ASSERT_IMPLEMENTS_children(type) \ 140 (void) sizeof(is_good(implements_children(&type::children))) 141#define ASSERT_IMPLEMENTS_getSourceRange(type) \ 142 (void) sizeof(is_good(implements_getSourceRange(&type::getSourceRange))) 143} 144 145/// Check whether the various Stmt classes implement their member 146/// functions. 147static inline void check_implementations() { 148#define ABSTRACT_STMT(type) 149#define STMT(type, base) \ 150 ASSERT_IMPLEMENTS_children(type); \ 151 ASSERT_IMPLEMENTS_getSourceRange(type); 152#include "clang/AST/StmtNodes.inc" 153} 154 155Stmt::child_range Stmt::children() { 156 switch (getStmtClass()) { 157 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 158#define ABSTRACT_STMT(type) 159#define STMT(type, base) \ 160 case Stmt::type##Class: \ 161 return static_cast<type*>(this)->children(); 162#include "clang/AST/StmtNodes.inc" 163 } 164 llvm_unreachable("unknown statement kind!"); 165} 166 167SourceRange Stmt::getSourceRange() const { 168 switch (getStmtClass()) { 169 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 170#define ABSTRACT_STMT(type) 171#define STMT(type, base) \ 172 case Stmt::type##Class: \ 173 return static_cast<const type*>(this)->getSourceRange(); 174#include "clang/AST/StmtNodes.inc" 175 } 176 llvm_unreachable("unknown statement kind!"); 177} 178 179// Amusing macro metaprogramming hack: check whether a class provides 180// a more specific implementation of getLocStart() and getLocEnd(). 181// 182// See also Expr.cpp:getExprLoc(). 183namespace { 184 /// This implementation is used when a class provides a custom 185 /// implementation of getLocStart. 186 template <class S, class T> 187 SourceLocation getLocStartImpl(const Stmt *stmt, 188 SourceLocation (T::*v)() const) { 189 return static_cast<const S*>(stmt)->getLocStart(); 190 } 191 192 /// This implementation is used when a class doesn't provide a custom 193 /// implementation of getLocStart. Overload resolution should pick it over 194 /// the implementation above because it's more specialized according to 195 /// function template partial ordering. 196 template <class S> 197 SourceLocation getLocStartImpl(const Stmt *stmt, 198 SourceLocation (Stmt::*v)() const) { 199 return static_cast<const S*>(stmt)->getSourceRange().getBegin(); 200 } 201 202 /// This implementation is used when a class provides a custom 203 /// implementation of getLocEnd. 204 template <class S, class T> 205 SourceLocation getLocEndImpl(const Stmt *stmt, 206 SourceLocation (T::*v)() const) { 207 return static_cast<const S*>(stmt)->getLocEnd(); 208 } 209 210 /// This implementation is used when a class doesn't provide a custom 211 /// implementation of getLocEnd. Overload resolution should pick it over 212 /// the implementation above because it's more specialized according to 213 /// function template partial ordering. 214 template <class S> 215 SourceLocation getLocEndImpl(const Stmt *stmt, 216 SourceLocation (Stmt::*v)() const) { 217 return static_cast<const S*>(stmt)->getSourceRange().getEnd(); 218 } 219} 220 221SourceLocation Stmt::getLocStart() const { 222 switch (getStmtClass()) { 223 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 224#define ABSTRACT_STMT(type) 225#define STMT(type, base) \ 226 case Stmt::type##Class: \ 227 return getLocStartImpl<type>(this, &type::getLocStart); 228#include "clang/AST/StmtNodes.inc" 229 } 230 llvm_unreachable("unknown statement kind"); 231} 232 233SourceLocation Stmt::getLocEnd() const { 234 switch (getStmtClass()) { 235 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 236#define ABSTRACT_STMT(type) 237#define STMT(type, base) \ 238 case Stmt::type##Class: \ 239 return getLocEndImpl<type>(this, &type::getLocEnd); 240#include "clang/AST/StmtNodes.inc" 241 } 242 llvm_unreachable("unknown statement kind"); 243} 244 245void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) { 246 if (this->Body) 247 C.Deallocate(Body); 248 this->CompoundStmtBits.NumStmts = NumStmts; 249 250 Body = new (C) Stmt*[NumStmts]; 251 memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts); 252} 253 254const char *LabelStmt::getName() const { 255 return getDecl()->getIdentifier()->getNameStart(); 256} 257 258// This is defined here to avoid polluting Stmt.h with importing Expr.h 259SourceRange ReturnStmt::getSourceRange() const { 260 if (RetExpr) 261 return SourceRange(RetLoc, RetExpr->getLocEnd()); 262 else 263 return SourceRange(RetLoc); 264} 265 266bool Stmt::hasImplicitControlFlow() const { 267 switch (StmtBits.sClass) { 268 default: 269 return false; 270 271 case CallExprClass: 272 case ConditionalOperatorClass: 273 case ChooseExprClass: 274 case StmtExprClass: 275 case DeclStmtClass: 276 return true; 277 278 case Stmt::BinaryOperatorClass: { 279 const BinaryOperator* B = cast<BinaryOperator>(this); 280 if (B->isLogicalOp() || B->getOpcode() == BO_Comma) 281 return true; 282 else 283 return false; 284 } 285 } 286} 287 288Expr *AsmStmt::getOutputExpr(unsigned i) { 289 return cast<Expr>(Exprs[i]); 290} 291 292/// getOutputConstraint - Return the constraint string for the specified 293/// output operand. All output constraints are known to be non-empty (either 294/// '=' or '+'). 295StringRef AsmStmt::getOutputConstraint(unsigned i) const { 296 return getOutputConstraintLiteral(i)->getString(); 297} 298 299/// getNumPlusOperands - Return the number of output operands that have a "+" 300/// constraint. 301unsigned AsmStmt::getNumPlusOperands() const { 302 unsigned Res = 0; 303 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) 304 if (isOutputPlusConstraint(i)) 305 ++Res; 306 return Res; 307} 308 309Expr *AsmStmt::getInputExpr(unsigned i) { 310 return cast<Expr>(Exprs[i + NumOutputs]); 311} 312void AsmStmt::setInputExpr(unsigned i, Expr *E) { 313 Exprs[i + NumOutputs] = E; 314} 315 316 317/// getInputConstraint - Return the specified input constraint. Unlike output 318/// constraints, these can be empty. 319StringRef AsmStmt::getInputConstraint(unsigned i) const { 320 return getInputConstraintLiteral(i)->getString(); 321} 322 323 324void AsmStmt::setOutputsAndInputsAndClobbers(ASTContext &C, 325 IdentifierInfo **Names, 326 StringLiteral **Constraints, 327 Stmt **Exprs, 328 unsigned NumOutputs, 329 unsigned NumInputs, 330 StringLiteral **Clobbers, 331 unsigned NumClobbers) { 332 this->NumOutputs = NumOutputs; 333 this->NumInputs = NumInputs; 334 this->NumClobbers = NumClobbers; 335 336 unsigned NumExprs = NumOutputs + NumInputs; 337 338 C.Deallocate(this->Names); 339 this->Names = new (C) IdentifierInfo*[NumExprs]; 340 std::copy(Names, Names + NumExprs, this->Names); 341 342 C.Deallocate(this->Exprs); 343 this->Exprs = new (C) Stmt*[NumExprs]; 344 std::copy(Exprs, Exprs + NumExprs, this->Exprs); 345 346 C.Deallocate(this->Constraints); 347 this->Constraints = new (C) StringLiteral*[NumExprs]; 348 std::copy(Constraints, Constraints + NumExprs, this->Constraints); 349 350 C.Deallocate(this->Clobbers); 351 this->Clobbers = new (C) StringLiteral*[NumClobbers]; 352 std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers); 353} 354 355/// getNamedOperand - Given a symbolic operand reference like %[foo], 356/// translate this into a numeric value needed to reference the same operand. 357/// This returns -1 if the operand name is invalid. 358int AsmStmt::getNamedOperand(StringRef SymbolicName) const { 359 unsigned NumPlusOperands = 0; 360 361 // Check if this is an output operand. 362 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) { 363 if (getOutputName(i) == SymbolicName) 364 return i; 365 } 366 367 for (unsigned i = 0, e = getNumInputs(); i != e; ++i) 368 if (getInputName(i) == SymbolicName) 369 return getNumOutputs() + NumPlusOperands + i; 370 371 // Not found. 372 return -1; 373} 374 375/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing 376/// it into pieces. If the asm string is erroneous, emit errors and return 377/// true, otherwise return false. 378unsigned AsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, 379 ASTContext &C, unsigned &DiagOffs) const { 380 StringRef Str = getAsmString()->getString(); 381 const char *StrStart = Str.begin(); 382 const char *StrEnd = Str.end(); 383 const char *CurPtr = StrStart; 384 385 // "Simple" inline asms have no constraints or operands, just convert the asm 386 // string to escape $'s. 387 if (isSimple()) { 388 std::string Result; 389 for (; CurPtr != StrEnd; ++CurPtr) { 390 switch (*CurPtr) { 391 case '$': 392 Result += "$$"; 393 break; 394 default: 395 Result += *CurPtr; 396 break; 397 } 398 } 399 Pieces.push_back(AsmStringPiece(Result)); 400 return 0; 401 } 402 403 // CurStringPiece - The current string that we are building up as we scan the 404 // asm string. 405 std::string CurStringPiece; 406 407 bool HasVariants = !C.getTargetInfo().hasNoAsmVariants(); 408 409 while (1) { 410 // Done with the string? 411 if (CurPtr == StrEnd) { 412 if (!CurStringPiece.empty()) 413 Pieces.push_back(AsmStringPiece(CurStringPiece)); 414 return 0; 415 } 416 417 char CurChar = *CurPtr++; 418 switch (CurChar) { 419 case '$': CurStringPiece += "$$"; continue; 420 case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue; 421 case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue; 422 case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue; 423 case '%': 424 break; 425 default: 426 CurStringPiece += CurChar; 427 continue; 428 } 429 430 // Escaped "%" character in asm string. 431 if (CurPtr == StrEnd) { 432 // % at end of string is invalid (no escape). 433 DiagOffs = CurPtr-StrStart-1; 434 return diag::err_asm_invalid_escape; 435 } 436 437 char EscapedChar = *CurPtr++; 438 if (EscapedChar == '%') { // %% -> % 439 // Escaped percentage sign. 440 CurStringPiece += '%'; 441 continue; 442 } 443 444 if (EscapedChar == '=') { // %= -> Generate an unique ID. 445 CurStringPiece += "${:uid}"; 446 continue; 447 } 448 449 // Otherwise, we have an operand. If we have accumulated a string so far, 450 // add it to the Pieces list. 451 if (!CurStringPiece.empty()) { 452 Pieces.push_back(AsmStringPiece(CurStringPiece)); 453 CurStringPiece.clear(); 454 } 455 456 // Handle %x4 and %x[foo] by capturing x as the modifier character. 457 char Modifier = '\0'; 458 if (isalpha(EscapedChar)) { 459 if (CurPtr == StrEnd) { // Premature end. 460 DiagOffs = CurPtr-StrStart-1; 461 return diag::err_asm_invalid_escape; 462 } 463 Modifier = EscapedChar; 464 EscapedChar = *CurPtr++; 465 } 466 467 if (isdigit(EscapedChar)) { 468 // %n - Assembler operand n 469 unsigned N = 0; 470 471 --CurPtr; 472 while (CurPtr != StrEnd && isdigit(*CurPtr)) 473 N = N*10 + ((*CurPtr++)-'0'); 474 475 unsigned NumOperands = 476 getNumOutputs() + getNumPlusOperands() + getNumInputs(); 477 if (N >= NumOperands) { 478 DiagOffs = CurPtr-StrStart-1; 479 return diag::err_asm_invalid_operand_number; 480 } 481 482 Pieces.push_back(AsmStringPiece(N, Modifier)); 483 continue; 484 } 485 486 // Handle %[foo], a symbolic operand reference. 487 if (EscapedChar == '[') { 488 DiagOffs = CurPtr-StrStart-1; 489 490 // Find the ']'. 491 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr); 492 if (NameEnd == 0) 493 return diag::err_asm_unterminated_symbolic_operand_name; 494 if (NameEnd == CurPtr) 495 return diag::err_asm_empty_symbolic_operand_name; 496 497 StringRef SymbolicName(CurPtr, NameEnd - CurPtr); 498 499 int N = getNamedOperand(SymbolicName); 500 if (N == -1) { 501 // Verify that an operand with that name exists. 502 DiagOffs = CurPtr-StrStart; 503 return diag::err_asm_unknown_symbolic_operand_name; 504 } 505 Pieces.push_back(AsmStringPiece(N, Modifier)); 506 507 CurPtr = NameEnd+1; 508 continue; 509 } 510 511 DiagOffs = CurPtr-StrStart-1; 512 return diag::err_asm_invalid_escape; 513 } 514} 515 516QualType CXXCatchStmt::getCaughtType() const { 517 if (ExceptionDecl) 518 return ExceptionDecl->getType(); 519 return QualType(); 520} 521 522//===----------------------------------------------------------------------===// 523// Constructors 524//===----------------------------------------------------------------------===// 525 526AsmStmt::AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, 527 bool isvolatile, bool msasm, 528 unsigned numoutputs, unsigned numinputs, 529 IdentifierInfo **names, StringLiteral **constraints, 530 Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, 531 StringLiteral **clobbers, SourceLocation rparenloc) 532 : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr) 533 , IsSimple(issimple), IsVolatile(isvolatile), MSAsm(msasm) 534 , NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) { 535 536 unsigned NumExprs = NumOutputs +NumInputs; 537 538 Names = new (C) IdentifierInfo*[NumExprs]; 539 std::copy(names, names + NumExprs, Names); 540 541 Exprs = new (C) Stmt*[NumExprs]; 542 std::copy(exprs, exprs + NumExprs, Exprs); 543 544 Constraints = new (C) StringLiteral*[NumExprs]; 545 std::copy(constraints, constraints + NumExprs, Constraints); 546 547 Clobbers = new (C) StringLiteral*[NumClobbers]; 548 std::copy(clobbers, clobbers + NumClobbers, Clobbers); 549} 550 551ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, 552 Stmt *Body, SourceLocation FCL, 553 SourceLocation RPL) 554: Stmt(ObjCForCollectionStmtClass) { 555 SubExprs[ELEM] = Elem; 556 SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect); 557 SubExprs[BODY] = Body; 558 ForLoc = FCL; 559 RParenLoc = RPL; 560} 561 562ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, 563 Stmt **CatchStmts, unsigned NumCatchStmts, 564 Stmt *atFinallyStmt) 565 : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc), 566 NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != 0) 567{ 568 Stmt **Stmts = getStmts(); 569 Stmts[0] = atTryStmt; 570 for (unsigned I = 0; I != NumCatchStmts; ++I) 571 Stmts[I + 1] = CatchStmts[I]; 572 573 if (HasFinally) 574 Stmts[NumCatchStmts + 1] = atFinallyStmt; 575} 576 577ObjCAtTryStmt *ObjCAtTryStmt::Create(ASTContext &Context, 578 SourceLocation atTryLoc, 579 Stmt *atTryStmt, 580 Stmt **CatchStmts, 581 unsigned NumCatchStmts, 582 Stmt *atFinallyStmt) { 583 unsigned Size = sizeof(ObjCAtTryStmt) + 584 (1 + NumCatchStmts + (atFinallyStmt != 0)) * sizeof(Stmt *); 585 void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); 586 return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts, 587 atFinallyStmt); 588} 589 590ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(ASTContext &Context, 591 unsigned NumCatchStmts, 592 bool HasFinally) { 593 unsigned Size = sizeof(ObjCAtTryStmt) + 594 (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *); 595 void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); 596 return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally); 597} 598 599SourceRange ObjCAtTryStmt::getSourceRange() const { 600 SourceLocation EndLoc; 601 if (HasFinally) 602 EndLoc = getFinallyStmt()->getLocEnd(); 603 else if (NumCatchStmts) 604 EndLoc = getCatchStmt(NumCatchStmts - 1)->getLocEnd(); 605 else 606 EndLoc = getTryBody()->getLocEnd(); 607 608 return SourceRange(AtTryLoc, EndLoc); 609} 610 611CXXTryStmt *CXXTryStmt::Create(ASTContext &C, SourceLocation tryLoc, 612 Stmt *tryBlock, Stmt **handlers, 613 unsigned numHandlers) { 614 std::size_t Size = sizeof(CXXTryStmt); 615 Size += ((numHandlers + 1) * sizeof(Stmt)); 616 617 void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); 618 return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers, numHandlers); 619} 620 621CXXTryStmt *CXXTryStmt::Create(ASTContext &C, EmptyShell Empty, 622 unsigned numHandlers) { 623 std::size_t Size = sizeof(CXXTryStmt); 624 Size += ((numHandlers + 1) * sizeof(Stmt)); 625 626 void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); 627 return new (Mem) CXXTryStmt(Empty, numHandlers); 628} 629 630CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, 631 Stmt **handlers, unsigned numHandlers) 632 : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(numHandlers) { 633 Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); 634 Stmts[0] = tryBlock; 635 std::copy(handlers, handlers + NumHandlers, Stmts + 1); 636} 637 638CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt, 639 Expr *Cond, Expr *Inc, DeclStmt *LoopVar, 640 Stmt *Body, SourceLocation FL, 641 SourceLocation CL, SourceLocation RPL) 642 : Stmt(CXXForRangeStmtClass), ForLoc(FL), ColonLoc(CL), RParenLoc(RPL) { 643 SubExprs[RANGE] = Range; 644 SubExprs[BEGINEND] = BeginEndStmt; 645 SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); 646 SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); 647 SubExprs[LOOPVAR] = LoopVar; 648 SubExprs[BODY] = Body; 649} 650 651Expr *CXXForRangeStmt::getRangeInit() { 652 DeclStmt *RangeStmt = getRangeStmt(); 653 VarDecl *RangeDecl = dyn_cast_or_null<VarDecl>(RangeStmt->getSingleDecl()); 654 assert(RangeDecl &&& "for-range should have a single var decl"); 655 return RangeDecl->getInit(); 656} 657 658const Expr *CXXForRangeStmt::getRangeInit() const { 659 return const_cast<CXXForRangeStmt*>(this)->getRangeInit(); 660} 661 662VarDecl *CXXForRangeStmt::getLoopVariable() { 663 Decl *LV = cast<DeclStmt>(getLoopVarStmt())->getSingleDecl(); 664 assert(LV && "No loop variable in CXXForRangeStmt"); 665 return cast<VarDecl>(LV); 666} 667 668const VarDecl *CXXForRangeStmt::getLoopVariable() const { 669 return const_cast<CXXForRangeStmt*>(this)->getLoopVariable(); 670} 671 672IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, 673 Stmt *then, SourceLocation EL, Stmt *elsev) 674 : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) 675{ 676 setConditionVariable(C, var); 677 SubExprs[COND] = reinterpret_cast<Stmt*>(cond); 678 SubExprs[THEN] = then; 679 SubExprs[ELSE] = elsev; 680} 681 682VarDecl *IfStmt::getConditionVariable() const { 683 if (!SubExprs[VAR]) 684 return 0; 685 686 DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); 687 return cast<VarDecl>(DS->getSingleDecl()); 688} 689 690void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) { 691 if (!V) { 692 SubExprs[VAR] = 0; 693 return; 694 } 695 696 SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), 697 V->getSourceRange().getBegin(), 698 V->getSourceRange().getEnd()); 699} 700 701ForStmt::ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, 702 Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, 703 SourceLocation RP) 704 : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP) 705{ 706 SubExprs[INIT] = Init; 707 setConditionVariable(C, condVar); 708 SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); 709 SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); 710 SubExprs[BODY] = Body; 711} 712 713VarDecl *ForStmt::getConditionVariable() const { 714 if (!SubExprs[CONDVAR]) 715 return 0; 716 717 DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]); 718 return cast<VarDecl>(DS->getSingleDecl()); 719} 720 721void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) { 722 if (!V) { 723 SubExprs[CONDVAR] = 0; 724 return; 725 } 726 727 SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), 728 V->getSourceRange().getBegin(), 729 V->getSourceRange().getEnd()); 730} 731 732SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond) 733 : Stmt(SwitchStmtClass), FirstCase(0), AllEnumCasesCovered(0) 734{ 735 setConditionVariable(C, Var); 736 SubExprs[COND] = reinterpret_cast<Stmt*>(cond); 737 SubExprs[BODY] = NULL; 738} 739 740VarDecl *SwitchStmt::getConditionVariable() const { 741 if (!SubExprs[VAR]) 742 return 0; 743 744 DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); 745 return cast<VarDecl>(DS->getSingleDecl()); 746} 747 748void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) { 749 if (!V) { 750 SubExprs[VAR] = 0; 751 return; 752 } 753 754 SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), 755 V->getSourceRange().getBegin(), 756 V->getSourceRange().getEnd()); 757} 758 759Stmt *SwitchCase::getSubStmt() { 760 if (isa<CaseStmt>(this)) 761 return cast<CaseStmt>(this)->getSubStmt(); 762 return cast<DefaultStmt>(this)->getSubStmt(); 763} 764 765WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, 766 SourceLocation WL) 767 : Stmt(WhileStmtClass) { 768 setConditionVariable(C, Var); 769 SubExprs[COND] = reinterpret_cast<Stmt*>(cond); 770 SubExprs[BODY] = body; 771 WhileLoc = WL; 772} 773 774VarDecl *WhileStmt::getConditionVariable() const { 775 if (!SubExprs[VAR]) 776 return 0; 777 778 DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); 779 return cast<VarDecl>(DS->getSingleDecl()); 780} 781 782void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) { 783 if (!V) { 784 SubExprs[VAR] = 0; 785 return; 786 } 787 788 SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), 789 V->getSourceRange().getBegin(), 790 V->getSourceRange().getEnd()); 791} 792 793// IndirectGotoStmt 794LabelDecl *IndirectGotoStmt::getConstantTarget() { 795 if (AddrLabelExpr *E = 796 dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts())) 797 return E->getLabel(); 798 return 0; 799} 800 801// ReturnStmt 802const Expr* ReturnStmt::getRetValue() const { 803 return cast_or_null<Expr>(RetExpr); 804} 805Expr* ReturnStmt::getRetValue() { 806 return cast_or_null<Expr>(RetExpr); 807} 808 809SEHTryStmt::SEHTryStmt(bool IsCXXTry, 810 SourceLocation TryLoc, 811 Stmt *TryBlock, 812 Stmt *Handler) 813 : Stmt(SEHTryStmtClass), 814 IsCXXTry(IsCXXTry), 815 TryLoc(TryLoc) 816{ 817 Children[TRY] = TryBlock; 818 Children[HANDLER] = Handler; 819} 820 821SEHTryStmt* SEHTryStmt::Create(ASTContext &C, 822 bool IsCXXTry, 823 SourceLocation TryLoc, 824 Stmt *TryBlock, 825 Stmt *Handler) { 826 return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler); 827} 828 829SEHExceptStmt* SEHTryStmt::getExceptHandler() const { 830 return dyn_cast<SEHExceptStmt>(getHandler()); 831} 832 833SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const { 834 return dyn_cast<SEHFinallyStmt>(getHandler()); 835} 836 837SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, 838 Expr *FilterExpr, 839 Stmt *Block) 840 : Stmt(SEHExceptStmtClass), 841 Loc(Loc) 842{ 843 Children[FILTER_EXPR] = reinterpret_cast<Stmt*>(FilterExpr); 844 Children[BLOCK] = Block; 845} 846 847SEHExceptStmt* SEHExceptStmt::Create(ASTContext &C, 848 SourceLocation Loc, 849 Expr *FilterExpr, 850 Stmt *Block) { 851 return new(C) SEHExceptStmt(Loc,FilterExpr,Block); 852} 853 854SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, 855 Stmt *Block) 856 : Stmt(SEHFinallyStmtClass), 857 Loc(Loc), 858 Block(Block) 859{} 860 861SEHFinallyStmt* SEHFinallyStmt::Create(ASTContext &C, 862 SourceLocation Loc, 863 Stmt *Block) { 864 return new(C)SEHFinallyStmt(Loc,Block); 865} 866