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