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