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