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