clang API Documentation
00001 //===--- Stmt.cpp - Statement AST Node Implementation ---------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This file implements the Stmt class and statement subclasses. 00011 // 00012 //===----------------------------------------------------------------------===// 00013 00014 #include "clang/AST/Stmt.h" 00015 #include "clang/AST/ExprCXX.h" 00016 #include "clang/AST/ExprObjC.h" 00017 #include "clang/AST/StmtCXX.h" 00018 #include "clang/AST/StmtObjC.h" 00019 #include "clang/AST/Type.h" 00020 #include "clang/AST/ASTContext.h" 00021 #include "clang/AST/ASTDiagnostic.h" 00022 #include "clang/Basic/TargetInfo.h" 00023 #include "llvm/Support/raw_ostream.h" 00024 using namespace clang; 00025 00026 static struct StmtClassNameTable { 00027 const char *Name; 00028 unsigned Counter; 00029 unsigned Size; 00030 } StmtClassInfo[Stmt::lastStmtConstant+1]; 00031 00032 static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) { 00033 static bool Initialized = false; 00034 if (Initialized) 00035 return StmtClassInfo[E]; 00036 00037 // Intialize the table on the first use. 00038 Initialized = true; 00039 #define ABSTRACT_STMT(STMT) 00040 #define STMT(CLASS, PARENT) \ 00041 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \ 00042 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS); 00043 #include "clang/AST/StmtNodes.inc" 00044 00045 return StmtClassInfo[E]; 00046 } 00047 00048 const char *Stmt::getStmtClassName() const { 00049 return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name; 00050 } 00051 00052 void Stmt::PrintStats() { 00053 // Ensure the table is primed. 00054 getStmtInfoTableEntry(Stmt::NullStmtClass); 00055 00056 unsigned sum = 0; 00057 llvm::errs() << "\n*** Stmt/Expr Stats:\n"; 00058 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { 00059 if (StmtClassInfo[i].Name == 0) continue; 00060 sum += StmtClassInfo[i].Counter; 00061 } 00062 llvm::errs() << " " << sum << " stmts/exprs total.\n"; 00063 sum = 0; 00064 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { 00065 if (StmtClassInfo[i].Name == 0) continue; 00066 if (StmtClassInfo[i].Counter == 0) continue; 00067 llvm::errs() << " " << StmtClassInfo[i].Counter << " " 00068 << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size 00069 << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size 00070 << " bytes)\n"; 00071 sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size; 00072 } 00073 00074 llvm::errs() << "Total bytes = " << sum << "\n"; 00075 } 00076 00077 void Stmt::addStmtClass(StmtClass s) { 00078 ++getStmtInfoTableEntry(s).Counter; 00079 } 00080 00081 bool Stmt::StatisticsEnabled = false; 00082 void Stmt::EnableStatistics() { 00083 StatisticsEnabled = true; 00084 } 00085 00086 Stmt *Stmt::IgnoreImplicit() { 00087 Stmt *s = this; 00088 00089 if (ExprWithCleanups *ewc = dyn_cast<ExprWithCleanups>(s)) 00090 s = ewc->getSubExpr(); 00091 00092 while (ImplicitCastExpr *ice = dyn_cast<ImplicitCastExpr>(s)) 00093 s = ice->getSubExpr(); 00094 00095 return s; 00096 } 00097 00098 /// \brief Strip off all label-like statements. 00099 /// 00100 /// This will strip off label statements, case statements, attributed 00101 /// statements and default statements recursively. 00102 const Stmt *Stmt::stripLabelLikeStatements() const { 00103 const Stmt *S = this; 00104 while (true) { 00105 if (const LabelStmt *LS = dyn_cast<LabelStmt>(S)) 00106 S = LS->getSubStmt(); 00107 else if (const SwitchCase *SC = dyn_cast<SwitchCase>(S)) 00108 S = SC->getSubStmt(); 00109 else if (const AttributedStmt *AS = dyn_cast<AttributedStmt>(S)) 00110 S = AS->getSubStmt(); 00111 else 00112 return S; 00113 } 00114 } 00115 00116 namespace { 00117 struct good {}; 00118 struct bad {}; 00119 00120 // These silly little functions have to be static inline to suppress 00121 // unused warnings, and they have to be defined to suppress other 00122 // warnings. 00123 static inline good is_good(good) { return good(); } 00124 00125 typedef Stmt::child_range children_t(); 00126 template <class T> good implements_children(children_t T::*) { 00127 return good(); 00128 } 00129 static inline bad implements_children(children_t Stmt::*) { 00130 return bad(); 00131 } 00132 00133 typedef SourceRange getSourceRange_t() const; 00134 template <class T> good implements_getSourceRange(getSourceRange_t T::*) { 00135 return good(); 00136 } 00137 static inline bad implements_getSourceRange(getSourceRange_t Stmt::*) { 00138 return bad(); 00139 } 00140 00141 #define ASSERT_IMPLEMENTS_children(type) \ 00142 (void) sizeof(is_good(implements_children(&type::children))) 00143 #define ASSERT_IMPLEMENTS_getSourceRange(type) \ 00144 (void) sizeof(is_good(implements_getSourceRange(&type::getSourceRange))) 00145 } 00146 00147 /// Check whether the various Stmt classes implement their member 00148 /// functions. 00149 static inline void check_implementations() { 00150 #define ABSTRACT_STMT(type) 00151 #define STMT(type, base) \ 00152 ASSERT_IMPLEMENTS_children(type); \ 00153 ASSERT_IMPLEMENTS_getSourceRange(type); 00154 #include "clang/AST/StmtNodes.inc" 00155 } 00156 00157 Stmt::child_range Stmt::children() { 00158 switch (getStmtClass()) { 00159 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 00160 #define ABSTRACT_STMT(type) 00161 #define STMT(type, base) \ 00162 case Stmt::type##Class: \ 00163 return static_cast<type*>(this)->children(); 00164 #include "clang/AST/StmtNodes.inc" 00165 } 00166 llvm_unreachable("unknown statement kind!"); 00167 } 00168 00169 SourceRange Stmt::getSourceRange() const { 00170 switch (getStmtClass()) { 00171 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 00172 #define ABSTRACT_STMT(type) 00173 #define STMT(type, base) \ 00174 case Stmt::type##Class: \ 00175 return static_cast<const type*>(this)->getSourceRange(); 00176 #include "clang/AST/StmtNodes.inc" 00177 } 00178 llvm_unreachable("unknown statement kind!"); 00179 } 00180 00181 // Amusing macro metaprogramming hack: check whether a class provides 00182 // a more specific implementation of getLocStart() and getLocEnd(). 00183 // 00184 // See also Expr.cpp:getExprLoc(). 00185 namespace { 00186 /// This implementation is used when a class provides a custom 00187 /// implementation of getLocStart. 00188 template <class S, class T> 00189 SourceLocation getLocStartImpl(const Stmt *stmt, 00190 SourceLocation (T::*v)() const) { 00191 return static_cast<const S*>(stmt)->getLocStart(); 00192 } 00193 00194 /// This implementation is used when a class doesn't provide a custom 00195 /// implementation of getLocStart. Overload resolution should pick it over 00196 /// the implementation above because it's more specialized according to 00197 /// function template partial ordering. 00198 template <class S> 00199 SourceLocation getLocStartImpl(const Stmt *stmt, 00200 SourceLocation (Stmt::*v)() const) { 00201 return static_cast<const S*>(stmt)->getSourceRange().getBegin(); 00202 } 00203 00204 /// This implementation is used when a class provides a custom 00205 /// implementation of getLocEnd. 00206 template <class S, class T> 00207 SourceLocation getLocEndImpl(const Stmt *stmt, 00208 SourceLocation (T::*v)() const) { 00209 return static_cast<const S*>(stmt)->getLocEnd(); 00210 } 00211 00212 /// This implementation is used when a class doesn't provide a custom 00213 /// implementation of getLocEnd. Overload resolution should pick it over 00214 /// the implementation above because it's more specialized according to 00215 /// function template partial ordering. 00216 template <class S> 00217 SourceLocation getLocEndImpl(const Stmt *stmt, 00218 SourceLocation (Stmt::*v)() const) { 00219 return static_cast<const S*>(stmt)->getSourceRange().getEnd(); 00220 } 00221 } 00222 00223 SourceLocation Stmt::getLocStart() const { 00224 switch (getStmtClass()) { 00225 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 00226 #define ABSTRACT_STMT(type) 00227 #define STMT(type, base) \ 00228 case Stmt::type##Class: \ 00229 return getLocStartImpl<type>(this, &type::getLocStart); 00230 #include "clang/AST/StmtNodes.inc" 00231 } 00232 llvm_unreachable("unknown statement kind"); 00233 } 00234 00235 SourceLocation Stmt::getLocEnd() const { 00236 switch (getStmtClass()) { 00237 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 00238 #define ABSTRACT_STMT(type) 00239 #define STMT(type, base) \ 00240 case Stmt::type##Class: \ 00241 return getLocEndImpl<type>(this, &type::getLocEnd); 00242 #include "clang/AST/StmtNodes.inc" 00243 } 00244 llvm_unreachable("unknown statement kind"); 00245 } 00246 00247 void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) { 00248 if (this->Body) 00249 C.Deallocate(Body); 00250 this->CompoundStmtBits.NumStmts = NumStmts; 00251 00252 Body = new (C) Stmt*[NumStmts]; 00253 memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts); 00254 } 00255 00256 const char *LabelStmt::getName() const { 00257 return getDecl()->getIdentifier()->getNameStart(); 00258 } 00259 00260 // This is defined here to avoid polluting Stmt.h with importing Expr.h 00261 SourceRange ReturnStmt::getSourceRange() const { 00262 if (RetExpr) 00263 return SourceRange(RetLoc, RetExpr->getLocEnd()); 00264 else 00265 return SourceRange(RetLoc); 00266 } 00267 00268 bool Stmt::hasImplicitControlFlow() const { 00269 switch (StmtBits.sClass) { 00270 default: 00271 return false; 00272 00273 case CallExprClass: 00274 case ConditionalOperatorClass: 00275 case ChooseExprClass: 00276 case StmtExprClass: 00277 case DeclStmtClass: 00278 return true; 00279 00280 case Stmt::BinaryOperatorClass: { 00281 const BinaryOperator* B = cast<BinaryOperator>(this); 00282 if (B->isLogicalOp() || B->getOpcode() == BO_Comma) 00283 return true; 00284 else 00285 return false; 00286 } 00287 } 00288 } 00289 00290 Expr *AsmStmt::getOutputExpr(unsigned i) { 00291 return cast<Expr>(Exprs[i]); 00292 } 00293 00294 /// getOutputConstraint - Return the constraint string for the specified 00295 /// output operand. All output constraints are known to be non-empty (either 00296 /// '=' or '+'). 00297 StringRef AsmStmt::getOutputConstraint(unsigned i) const { 00298 return getOutputConstraintLiteral(i)->getString(); 00299 } 00300 00301 /// getNumPlusOperands - Return the number of output operands that have a "+" 00302 /// constraint. 00303 unsigned AsmStmt::getNumPlusOperands() const { 00304 unsigned Res = 0; 00305 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) 00306 if (isOutputPlusConstraint(i)) 00307 ++Res; 00308 return Res; 00309 } 00310 00311 Expr *AsmStmt::getInputExpr(unsigned i) { 00312 return cast<Expr>(Exprs[i + NumOutputs]); 00313 } 00314 void AsmStmt::setInputExpr(unsigned i, Expr *E) { 00315 Exprs[i + NumOutputs] = E; 00316 } 00317 00318 00319 /// getInputConstraint - Return the specified input constraint. Unlike output 00320 /// constraints, these can be empty. 00321 StringRef AsmStmt::getInputConstraint(unsigned i) const { 00322 return getInputConstraintLiteral(i)->getString(); 00323 } 00324 00325 00326 void AsmStmt::setOutputsAndInputsAndClobbers(ASTContext &C, 00327 IdentifierInfo **Names, 00328 StringLiteral **Constraints, 00329 Stmt **Exprs, 00330 unsigned NumOutputs, 00331 unsigned NumInputs, 00332 StringLiteral **Clobbers, 00333 unsigned NumClobbers) { 00334 this->NumOutputs = NumOutputs; 00335 this->NumInputs = NumInputs; 00336 this->NumClobbers = NumClobbers; 00337 00338 unsigned NumExprs = NumOutputs + NumInputs; 00339 00340 C.Deallocate(this->Names); 00341 this->Names = new (C) IdentifierInfo*[NumExprs]; 00342 std::copy(Names, Names + NumExprs, this->Names); 00343 00344 C.Deallocate(this->Exprs); 00345 this->Exprs = new (C) Stmt*[NumExprs]; 00346 std::copy(Exprs, Exprs + NumExprs, this->Exprs); 00347 00348 C.Deallocate(this->Constraints); 00349 this->Constraints = new (C) StringLiteral*[NumExprs]; 00350 std::copy(Constraints, Constraints + NumExprs, this->Constraints); 00351 00352 C.Deallocate(this->Clobbers); 00353 this->Clobbers = new (C) StringLiteral*[NumClobbers]; 00354 std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers); 00355 } 00356 00357 /// getNamedOperand - Given a symbolic operand reference like %[foo], 00358 /// translate this into a numeric value needed to reference the same operand. 00359 /// This returns -1 if the operand name is invalid. 00360 int AsmStmt::getNamedOperand(StringRef SymbolicName) const { 00361 unsigned NumPlusOperands = 0; 00362 00363 // Check if this is an output operand. 00364 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) { 00365 if (getOutputName(i) == SymbolicName) 00366 return i; 00367 } 00368 00369 for (unsigned i = 0, e = getNumInputs(); i != e; ++i) 00370 if (getInputName(i) == SymbolicName) 00371 return getNumOutputs() + NumPlusOperands + i; 00372 00373 // Not found. 00374 return -1; 00375 } 00376 00377 /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing 00378 /// it into pieces. If the asm string is erroneous, emit errors and return 00379 /// true, otherwise return false. 00380 unsigned AsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, 00381 ASTContext &C, unsigned &DiagOffs) const { 00382 StringRef Str = getAsmString()->getString(); 00383 const char *StrStart = Str.begin(); 00384 const char *StrEnd = Str.end(); 00385 const char *CurPtr = StrStart; 00386 00387 // "Simple" inline asms have no constraints or operands, just convert the asm 00388 // string to escape $'s. 00389 if (isSimple()) { 00390 std::string Result; 00391 for (; CurPtr != StrEnd; ++CurPtr) { 00392 switch (*CurPtr) { 00393 case '$': 00394 Result += "$$"; 00395 break; 00396 default: 00397 Result += *CurPtr; 00398 break; 00399 } 00400 } 00401 Pieces.push_back(AsmStringPiece(Result)); 00402 return 0; 00403 } 00404 00405 // CurStringPiece - The current string that we are building up as we scan the 00406 // asm string. 00407 std::string CurStringPiece; 00408 00409 bool HasVariants = !C.getTargetInfo().hasNoAsmVariants(); 00410 00411 while (1) { 00412 // Done with the string? 00413 if (CurPtr == StrEnd) { 00414 if (!CurStringPiece.empty()) 00415 Pieces.push_back(AsmStringPiece(CurStringPiece)); 00416 return 0; 00417 } 00418 00419 char CurChar = *CurPtr++; 00420 switch (CurChar) { 00421 case '$': CurStringPiece += "$$"; continue; 00422 case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue; 00423 case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue; 00424 case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue; 00425 case '%': 00426 break; 00427 default: 00428 CurStringPiece += CurChar; 00429 continue; 00430 } 00431 00432 // Escaped "%" character in asm string. 00433 if (CurPtr == StrEnd) { 00434 // % at end of string is invalid (no escape). 00435 DiagOffs = CurPtr-StrStart-1; 00436 return diag::err_asm_invalid_escape; 00437 } 00438 00439 char EscapedChar = *CurPtr++; 00440 if (EscapedChar == '%') { // %% -> % 00441 // Escaped percentage sign. 00442 CurStringPiece += '%'; 00443 continue; 00444 } 00445 00446 if (EscapedChar == '=') { // %= -> Generate an unique ID. 00447 CurStringPiece += "${:uid}"; 00448 continue; 00449 } 00450 00451 // Otherwise, we have an operand. If we have accumulated a string so far, 00452 // add it to the Pieces list. 00453 if (!CurStringPiece.empty()) { 00454 Pieces.push_back(AsmStringPiece(CurStringPiece)); 00455 CurStringPiece.clear(); 00456 } 00457 00458 // Handle %x4 and %x[foo] by capturing x as the modifier character. 00459 char Modifier = '\0'; 00460 if (isalpha(EscapedChar)) { 00461 if (CurPtr == StrEnd) { // Premature end. 00462 DiagOffs = CurPtr-StrStart-1; 00463 return diag::err_asm_invalid_escape; 00464 } 00465 Modifier = EscapedChar; 00466 EscapedChar = *CurPtr++; 00467 } 00468 00469 if (isdigit(EscapedChar)) { 00470 // %n - Assembler operand n 00471 unsigned N = 0; 00472 00473 --CurPtr; 00474 while (CurPtr != StrEnd && isdigit(*CurPtr)) 00475 N = N*10 + ((*CurPtr++)-'0'); 00476 00477 unsigned NumOperands = 00478 getNumOutputs() + getNumPlusOperands() + getNumInputs(); 00479 if (N >= NumOperands) { 00480 DiagOffs = CurPtr-StrStart-1; 00481 return diag::err_asm_invalid_operand_number; 00482 } 00483 00484 Pieces.push_back(AsmStringPiece(N, Modifier)); 00485 continue; 00486 } 00487 00488 // Handle %[foo], a symbolic operand reference. 00489 if (EscapedChar == '[') { 00490 DiagOffs = CurPtr-StrStart-1; 00491 00492 // Find the ']'. 00493 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr); 00494 if (NameEnd == 0) 00495 return diag::err_asm_unterminated_symbolic_operand_name; 00496 if (NameEnd == CurPtr) 00497 return diag::err_asm_empty_symbolic_operand_name; 00498 00499 StringRef SymbolicName(CurPtr, NameEnd - CurPtr); 00500 00501 int N = getNamedOperand(SymbolicName); 00502 if (N == -1) { 00503 // Verify that an operand with that name exists. 00504 DiagOffs = CurPtr-StrStart; 00505 return diag::err_asm_unknown_symbolic_operand_name; 00506 } 00507 Pieces.push_back(AsmStringPiece(N, Modifier)); 00508 00509 CurPtr = NameEnd+1; 00510 continue; 00511 } 00512 00513 DiagOffs = CurPtr-StrStart-1; 00514 return diag::err_asm_invalid_escape; 00515 } 00516 } 00517 00518 QualType CXXCatchStmt::getCaughtType() const { 00519 if (ExceptionDecl) 00520 return ExceptionDecl->getType(); 00521 return QualType(); 00522 } 00523 00524 //===----------------------------------------------------------------------===// 00525 // Constructors 00526 //===----------------------------------------------------------------------===// 00527 00528 AsmStmt::AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple, 00529 bool isvolatile, bool msasm, 00530 unsigned numoutputs, unsigned numinputs, 00531 IdentifierInfo **names, StringLiteral **constraints, 00532 Expr **exprs, StringLiteral *asmstr, unsigned numclobbers, 00533 StringLiteral **clobbers, SourceLocation rparenloc) 00534 : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr) 00535 , IsSimple(issimple), IsVolatile(isvolatile), MSAsm(msasm) 00536 , NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) { 00537 00538 unsigned NumExprs = NumOutputs +NumInputs; 00539 00540 Names = new (C) IdentifierInfo*[NumExprs]; 00541 std::copy(names, names + NumExprs, Names); 00542 00543 Exprs = new (C) Stmt*[NumExprs]; 00544 std::copy(exprs, exprs + NumExprs, Exprs); 00545 00546 Constraints = new (C) StringLiteral*[NumExprs]; 00547 std::copy(constraints, constraints + NumExprs, Constraints); 00548 00549 Clobbers = new (C) StringLiteral*[NumClobbers]; 00550 std::copy(clobbers, clobbers + NumClobbers, Clobbers); 00551 } 00552 00553 ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, 00554 Stmt *Body, SourceLocation FCL, 00555 SourceLocation RPL) 00556 : Stmt(ObjCForCollectionStmtClass) { 00557 SubExprs[ELEM] = Elem; 00558 SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect); 00559 SubExprs[BODY] = Body; 00560 ForLoc = FCL; 00561 RParenLoc = RPL; 00562 } 00563 00564 ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt, 00565 Stmt **CatchStmts, unsigned NumCatchStmts, 00566 Stmt *atFinallyStmt) 00567 : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc), 00568 NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != 0) 00569 { 00570 Stmt **Stmts = getStmts(); 00571 Stmts[0] = atTryStmt; 00572 for (unsigned I = 0; I != NumCatchStmts; ++I) 00573 Stmts[I + 1] = CatchStmts[I]; 00574 00575 if (HasFinally) 00576 Stmts[NumCatchStmts + 1] = atFinallyStmt; 00577 } 00578 00579 ObjCAtTryStmt *ObjCAtTryStmt::Create(ASTContext &Context, 00580 SourceLocation atTryLoc, 00581 Stmt *atTryStmt, 00582 Stmt **CatchStmts, 00583 unsigned NumCatchStmts, 00584 Stmt *atFinallyStmt) { 00585 unsigned Size = sizeof(ObjCAtTryStmt) + 00586 (1 + NumCatchStmts + (atFinallyStmt != 0)) * sizeof(Stmt *); 00587 void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); 00588 return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts, 00589 atFinallyStmt); 00590 } 00591 00592 ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(ASTContext &Context, 00593 unsigned NumCatchStmts, 00594 bool HasFinally) { 00595 unsigned Size = sizeof(ObjCAtTryStmt) + 00596 (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *); 00597 void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>()); 00598 return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally); 00599 } 00600 00601 SourceRange ObjCAtTryStmt::getSourceRange() const { 00602 SourceLocation EndLoc; 00603 if (HasFinally) 00604 EndLoc = getFinallyStmt()->getLocEnd(); 00605 else if (NumCatchStmts) 00606 EndLoc = getCatchStmt(NumCatchStmts - 1)->getLocEnd(); 00607 else 00608 EndLoc = getTryBody()->getLocEnd(); 00609 00610 return SourceRange(AtTryLoc, EndLoc); 00611 } 00612 00613 CXXTryStmt *CXXTryStmt::Create(ASTContext &C, SourceLocation tryLoc, 00614 Stmt *tryBlock, Stmt **handlers, 00615 unsigned numHandlers) { 00616 std::size_t Size = sizeof(CXXTryStmt); 00617 Size += ((numHandlers + 1) * sizeof(Stmt)); 00618 00619 void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); 00620 return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers, numHandlers); 00621 } 00622 00623 CXXTryStmt *CXXTryStmt::Create(ASTContext &C, EmptyShell Empty, 00624 unsigned numHandlers) { 00625 std::size_t Size = sizeof(CXXTryStmt); 00626 Size += ((numHandlers + 1) * sizeof(Stmt)); 00627 00628 void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>()); 00629 return new (Mem) CXXTryStmt(Empty, numHandlers); 00630 } 00631 00632 CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock, 00633 Stmt **handlers, unsigned numHandlers) 00634 : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(numHandlers) { 00635 Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1); 00636 Stmts[0] = tryBlock; 00637 std::copy(handlers, handlers + NumHandlers, Stmts + 1); 00638 } 00639 00640 CXXForRangeStmt::CXXForRangeStmt(DeclStmt *Range, DeclStmt *BeginEndStmt, 00641 Expr *Cond, Expr *Inc, DeclStmt *LoopVar, 00642 Stmt *Body, SourceLocation FL, 00643 SourceLocation CL, SourceLocation RPL) 00644 : Stmt(CXXForRangeStmtClass), ForLoc(FL), ColonLoc(CL), RParenLoc(RPL) { 00645 SubExprs[RANGE] = Range; 00646 SubExprs[BEGINEND] = BeginEndStmt; 00647 SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); 00648 SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); 00649 SubExprs[LOOPVAR] = LoopVar; 00650 SubExprs[BODY] = Body; 00651 } 00652 00653 Expr *CXXForRangeStmt::getRangeInit() { 00654 DeclStmt *RangeStmt = getRangeStmt(); 00655 VarDecl *RangeDecl = dyn_cast_or_null<VarDecl>(RangeStmt->getSingleDecl()); 00656 assert(RangeDecl &&& "for-range should have a single var decl"); 00657 return RangeDecl->getInit(); 00658 } 00659 00660 const Expr *CXXForRangeStmt::getRangeInit() const { 00661 return const_cast<CXXForRangeStmt*>(this)->getRangeInit(); 00662 } 00663 00664 VarDecl *CXXForRangeStmt::getLoopVariable() { 00665 Decl *LV = cast<DeclStmt>(getLoopVarStmt())->getSingleDecl(); 00666 assert(LV && "No loop variable in CXXForRangeStmt"); 00667 return cast<VarDecl>(LV); 00668 } 00669 00670 const VarDecl *CXXForRangeStmt::getLoopVariable() const { 00671 return const_cast<CXXForRangeStmt*>(this)->getLoopVariable(); 00672 } 00673 00674 IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond, 00675 Stmt *then, SourceLocation EL, Stmt *elsev) 00676 : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) 00677 { 00678 setConditionVariable(C, var); 00679 SubExprs[COND] = reinterpret_cast<Stmt*>(cond); 00680 SubExprs[THEN] = then; 00681 SubExprs[ELSE] = elsev; 00682 } 00683 00684 VarDecl *IfStmt::getConditionVariable() const { 00685 if (!SubExprs[VAR]) 00686 return 0; 00687 00688 DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); 00689 return cast<VarDecl>(DS->getSingleDecl()); 00690 } 00691 00692 void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) { 00693 if (!V) { 00694 SubExprs[VAR] = 0; 00695 return; 00696 } 00697 00698 SourceRange VarRange = V->getSourceRange(); 00699 SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), 00700 VarRange.getEnd()); 00701 } 00702 00703 ForStmt::ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, 00704 Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, 00705 SourceLocation RP) 00706 : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP) 00707 { 00708 SubExprs[INIT] = Init; 00709 setConditionVariable(C, condVar); 00710 SubExprs[COND] = reinterpret_cast<Stmt*>(Cond); 00711 SubExprs[INC] = reinterpret_cast<Stmt*>(Inc); 00712 SubExprs[BODY] = Body; 00713 } 00714 00715 VarDecl *ForStmt::getConditionVariable() const { 00716 if (!SubExprs[CONDVAR]) 00717 return 0; 00718 00719 DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]); 00720 return cast<VarDecl>(DS->getSingleDecl()); 00721 } 00722 00723 void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) { 00724 if (!V) { 00725 SubExprs[CONDVAR] = 0; 00726 return; 00727 } 00728 00729 SourceRange VarRange = V->getSourceRange(); 00730 SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), 00731 VarRange.getEnd()); 00732 } 00733 00734 SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond) 00735 : Stmt(SwitchStmtClass), FirstCase(0), AllEnumCasesCovered(0) 00736 { 00737 setConditionVariable(C, Var); 00738 SubExprs[COND] = reinterpret_cast<Stmt*>(cond); 00739 SubExprs[BODY] = NULL; 00740 } 00741 00742 VarDecl *SwitchStmt::getConditionVariable() const { 00743 if (!SubExprs[VAR]) 00744 return 0; 00745 00746 DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); 00747 return cast<VarDecl>(DS->getSingleDecl()); 00748 } 00749 00750 void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) { 00751 if (!V) { 00752 SubExprs[VAR] = 0; 00753 return; 00754 } 00755 00756 SourceRange VarRange = V->getSourceRange(); 00757 SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), 00758 VarRange.getEnd()); 00759 } 00760 00761 Stmt *SwitchCase::getSubStmt() { 00762 if (isa<CaseStmt>(this)) 00763 return cast<CaseStmt>(this)->getSubStmt(); 00764 return cast<DefaultStmt>(this)->getSubStmt(); 00765 } 00766 00767 WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, 00768 SourceLocation WL) 00769 : Stmt(WhileStmtClass) { 00770 setConditionVariable(C, Var); 00771 SubExprs[COND] = reinterpret_cast<Stmt*>(cond); 00772 SubExprs[BODY] = body; 00773 WhileLoc = WL; 00774 } 00775 00776 VarDecl *WhileStmt::getConditionVariable() const { 00777 if (!SubExprs[VAR]) 00778 return 0; 00779 00780 DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]); 00781 return cast<VarDecl>(DS->getSingleDecl()); 00782 } 00783 00784 void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) { 00785 if (!V) { 00786 SubExprs[VAR] = 0; 00787 return; 00788 } 00789 00790 SourceRange VarRange = V->getSourceRange(); 00791 SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), 00792 VarRange.getEnd()); 00793 } 00794 00795 // IndirectGotoStmt 00796 LabelDecl *IndirectGotoStmt::getConstantTarget() { 00797 if (AddrLabelExpr *E = 00798 dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts())) 00799 return E->getLabel(); 00800 return 0; 00801 } 00802 00803 // ReturnStmt 00804 const Expr* ReturnStmt::getRetValue() const { 00805 return cast_or_null<Expr>(RetExpr); 00806 } 00807 Expr* ReturnStmt::getRetValue() { 00808 return cast_or_null<Expr>(RetExpr); 00809 } 00810 00811 SEHTryStmt::SEHTryStmt(bool IsCXXTry, 00812 SourceLocation TryLoc, 00813 Stmt *TryBlock, 00814 Stmt *Handler) 00815 : Stmt(SEHTryStmtClass), 00816 IsCXXTry(IsCXXTry), 00817 TryLoc(TryLoc) 00818 { 00819 Children[TRY] = TryBlock; 00820 Children[HANDLER] = Handler; 00821 } 00822 00823 SEHTryStmt* SEHTryStmt::Create(ASTContext &C, 00824 bool IsCXXTry, 00825 SourceLocation TryLoc, 00826 Stmt *TryBlock, 00827 Stmt *Handler) { 00828 return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler); 00829 } 00830 00831 SEHExceptStmt* SEHTryStmt::getExceptHandler() const { 00832 return dyn_cast<SEHExceptStmt>(getHandler()); 00833 } 00834 00835 SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const { 00836 return dyn_cast<SEHFinallyStmt>(getHandler()); 00837 } 00838 00839 SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, 00840 Expr *FilterExpr, 00841 Stmt *Block) 00842 : Stmt(SEHExceptStmtClass), 00843 Loc(Loc) 00844 { 00845 Children[FILTER_EXPR] = reinterpret_cast<Stmt*>(FilterExpr); 00846 Children[BLOCK] = Block; 00847 } 00848 00849 SEHExceptStmt* SEHExceptStmt::Create(ASTContext &C, 00850 SourceLocation Loc, 00851 Expr *FilterExpr, 00852 Stmt *Block) { 00853 return new(C) SEHExceptStmt(Loc,FilterExpr,Block); 00854 } 00855 00856 SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, 00857 Stmt *Block) 00858 : Stmt(SEHFinallyStmtClass), 00859 Loc(Loc), 00860 Block(Block) 00861 {} 00862 00863 SEHFinallyStmt* SEHFinallyStmt::Create(ASTContext &C, 00864 SourceLocation Loc, 00865 Stmt *Block) { 00866 return new(C)SEHFinallyStmt(Loc,Block); 00867 }