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