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