1 //===- Stmt.cpp - Statement AST Node Implementation -----------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This file implements the Stmt class and statement subclasses. 10 // 11 //===----------------------------------------------------------------------===// 12 13 #include "clang/AST/Stmt.h" 14 #include "clang/AST/ASTContext.h" 15 #include "clang/AST/ASTDiagnostic.h" 16 #include "clang/AST/Attr.h" 17 #include "clang/AST/Decl.h" 18 #include "clang/AST/DeclGroup.h" 19 #include "clang/AST/Expr.h" 20 #include "clang/AST/ExprCXX.h" 21 #include "clang/AST/ExprConcepts.h" 22 #include "clang/AST/ExprObjC.h" 23 #include "clang/AST/ExprOpenMP.h" 24 #include "clang/AST/StmtCXX.h" 25 #include "clang/AST/StmtObjC.h" 26 #include "clang/AST/StmtOpenMP.h" 27 #include "clang/AST/Type.h" 28 #include "clang/Basic/CharInfo.h" 29 #include "clang/Basic/LLVM.h" 30 #include "clang/Basic/SourceLocation.h" 31 #include "clang/Basic/TargetInfo.h" 32 #include "clang/Lex/Token.h" 33 #include "llvm/ADT/SmallVector.h" 34 #include "llvm/ADT/StringExtras.h" 35 #include "llvm/ADT/StringRef.h" 36 #include "llvm/Support/Casting.h" 37 #include "llvm/Support/Compiler.h" 38 #include "llvm/Support/ErrorHandling.h" 39 #include "llvm/Support/MathExtras.h" 40 #include "llvm/Support/raw_ostream.h" 41 #include <algorithm> 42 #include <cassert> 43 #include <cstring> 44 #include <string> 45 #include <type_traits> 46 #include <utility> 47 48 using namespace clang; 49 50 static struct StmtClassNameTable { 51 const char *Name; 52 unsigned Counter; 53 unsigned Size; 54 } StmtClassInfo[Stmt::lastStmtConstant+1]; 55 56 static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) { 57 static bool Initialized = false; 58 if (Initialized) 59 return StmtClassInfo[E]; 60 61 // Initialize the table on the first use. 62 Initialized = true; 63 #define ABSTRACT_STMT(STMT) 64 #define STMT(CLASS, PARENT) \ 65 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \ 66 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS); 67 #include "clang/AST/StmtNodes.inc" 68 69 return StmtClassInfo[E]; 70 } 71 72 void *Stmt::operator new(size_t bytes, const ASTContext& C, 73 unsigned alignment) { 74 return ::operator new(bytes, C, alignment); 75 } 76 77 const char *Stmt::getStmtClassName() const { 78 return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name; 79 } 80 81 // Check that no statement / expression class is polymorphic. LLVM style RTTI 82 // should be used instead. If absolutely needed an exception can still be added 83 // here by defining the appropriate macro (but please don't do this). 84 #define STMT(CLASS, PARENT) \ 85 static_assert(!std::is_polymorphic<CLASS>::value, \ 86 #CLASS " should not be polymorphic!"); 87 #include "clang/AST/StmtNodes.inc" 88 89 // Check that no statement / expression class has a non-trival destructor. 90 // Statements and expressions are allocated with the BumpPtrAllocator from 91 // ASTContext and therefore their destructor is not executed. 92 #define STMT(CLASS, PARENT) \ 93 static_assert(std::is_trivially_destructible<CLASS>::value, \ 94 #CLASS " should be trivially destructible!"); 95 // FIXME: InitListExpr is not trivially destructible due to its ASTVector. 96 #define INITLISTEXPR(CLASS, PARENT) 97 #include "clang/AST/StmtNodes.inc" 98 99 void Stmt::PrintStats() { 100 // Ensure the table is primed. 101 getStmtInfoTableEntry(Stmt::NullStmtClass); 102 103 unsigned sum = 0; 104 llvm::errs() << "\n*** Stmt/Expr Stats:\n"; 105 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { 106 if (StmtClassInfo[i].Name == nullptr) continue; 107 sum += StmtClassInfo[i].Counter; 108 } 109 llvm::errs() << " " << sum << " stmts/exprs total.\n"; 110 sum = 0; 111 for (int i = 0; i != Stmt::lastStmtConstant+1; i++) { 112 if (StmtClassInfo[i].Name == nullptr) continue; 113 if (StmtClassInfo[i].Counter == 0) continue; 114 llvm::errs() << " " << StmtClassInfo[i].Counter << " " 115 << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size 116 << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size 117 << " bytes)\n"; 118 sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size; 119 } 120 121 llvm::errs() << "Total bytes = " << sum << "\n"; 122 } 123 124 void Stmt::addStmtClass(StmtClass s) { 125 ++getStmtInfoTableEntry(s).Counter; 126 } 127 128 bool Stmt::StatisticsEnabled = false; 129 void Stmt::EnableStatistics() { 130 StatisticsEnabled = true; 131 } 132 133 static std::pair<Stmt::Likelihood, const Attr *> 134 getLikelihood(ArrayRef<const Attr *> Attrs) { 135 for (const auto *A : Attrs) { 136 if (isa<LikelyAttr>(A)) 137 return std::make_pair(Stmt::LH_Likely, A); 138 139 if (isa<UnlikelyAttr>(A)) 140 return std::make_pair(Stmt::LH_Unlikely, A); 141 } 142 143 return std::make_pair(Stmt::LH_None, nullptr); 144 } 145 146 static std::pair<Stmt::Likelihood, const Attr *> getLikelihood(const Stmt *S) { 147 if (const auto *AS = dyn_cast_or_null<AttributedStmt>(S)) 148 return getLikelihood(AS->getAttrs()); 149 150 return std::make_pair(Stmt::LH_None, nullptr); 151 } 152 153 Stmt::Likelihood Stmt::getLikelihood(ArrayRef<const Attr *> Attrs) { 154 return ::getLikelihood(Attrs).first; 155 } 156 157 Stmt::Likelihood Stmt::getLikelihood(const Stmt *S) { 158 return ::getLikelihood(S).first; 159 } 160 161 Stmt::Likelihood Stmt::getLikelihood(const Stmt *Then, const Stmt *Else) { 162 Likelihood LHT = ::getLikelihood(Then).first; 163 Likelihood LHE = ::getLikelihood(Else).first; 164 if (LHE == LH_None) 165 return LHT; 166 167 // If the same attribute is used on both branches there's a conflict. 168 if (LHT == LHE) 169 return LH_None; 170 171 if (LHT != LH_None) 172 return LHT; 173 174 // Invert the value of Else to get the value for Then. 175 return LHE == LH_Likely ? LH_Unlikely : LH_Likely; 176 } 177 178 std::tuple<bool, const Attr *, const Attr *> 179 Stmt::determineLikelihoodConflict(const Stmt *Then, const Stmt *Else) { 180 std::pair<Likelihood, const Attr *> LHT = ::getLikelihood(Then); 181 std::pair<Likelihood, const Attr *> LHE = ::getLikelihood(Else); 182 // If the same attribute is used on both branches there's a conflict. 183 if (LHT.first != LH_None && LHT.first == LHE.first) 184 return std::make_tuple(true, LHT.second, LHE.second); 185 186 return std::make_tuple(false, nullptr, nullptr); 187 } 188 189 /// Skip no-op (attributed, compound) container stmts and skip captured 190 /// stmt at the top, if \a IgnoreCaptured is true. 191 Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) { 192 Stmt *S = this; 193 if (IgnoreCaptured) 194 if (auto CapS = dyn_cast_or_null<CapturedStmt>(S)) 195 S = CapS->getCapturedStmt(); 196 while (true) { 197 if (auto AS = dyn_cast_or_null<AttributedStmt>(S)) 198 S = AS->getSubStmt(); 199 else if (auto CS = dyn_cast_or_null<CompoundStmt>(S)) { 200 if (CS->size() != 1) 201 break; 202 S = CS->body_back(); 203 } else 204 break; 205 } 206 return S; 207 } 208 209 /// Strip off all label-like statements. 210 /// 211 /// This will strip off label statements, case statements, attributed 212 /// statements and default statements recursively. 213 const Stmt *Stmt::stripLabelLikeStatements() const { 214 const Stmt *S = this; 215 while (true) { 216 if (const auto *LS = dyn_cast<LabelStmt>(S)) 217 S = LS->getSubStmt(); 218 else if (const auto *SC = dyn_cast<SwitchCase>(S)) 219 S = SC->getSubStmt(); 220 else if (const auto *AS = dyn_cast<AttributedStmt>(S)) 221 S = AS->getSubStmt(); 222 else 223 return S; 224 } 225 } 226 227 namespace { 228 229 struct good {}; 230 struct bad {}; 231 232 // These silly little functions have to be static inline to suppress 233 // unused warnings, and they have to be defined to suppress other 234 // warnings. 235 static good is_good(good) { return good(); } 236 237 typedef Stmt::child_range children_t(); 238 template <class T> good implements_children(children_t T::*) { 239 return good(); 240 } 241 LLVM_ATTRIBUTE_UNUSED 242 static bad implements_children(children_t Stmt::*) { 243 return bad(); 244 } 245 246 typedef SourceLocation getBeginLoc_t() const; 247 template <class T> good implements_getBeginLoc(getBeginLoc_t T::*) { 248 return good(); 249 } 250 LLVM_ATTRIBUTE_UNUSED 251 static bad implements_getBeginLoc(getBeginLoc_t Stmt::*) { return bad(); } 252 253 typedef SourceLocation getLocEnd_t() const; 254 template <class T> good implements_getEndLoc(getLocEnd_t T::*) { 255 return good(); 256 } 257 LLVM_ATTRIBUTE_UNUSED 258 static bad implements_getEndLoc(getLocEnd_t Stmt::*) { return bad(); } 259 260 #define ASSERT_IMPLEMENTS_children(type) \ 261 (void) is_good(implements_children(&type::children)) 262 #define ASSERT_IMPLEMENTS_getBeginLoc(type) \ 263 (void)is_good(implements_getBeginLoc(&type::getBeginLoc)) 264 #define ASSERT_IMPLEMENTS_getEndLoc(type) \ 265 (void)is_good(implements_getEndLoc(&type::getEndLoc)) 266 267 } // namespace 268 269 /// Check whether the various Stmt classes implement their member 270 /// functions. 271 LLVM_ATTRIBUTE_UNUSED 272 static inline void check_implementations() { 273 #define ABSTRACT_STMT(type) 274 #define STMT(type, base) \ 275 ASSERT_IMPLEMENTS_children(type); \ 276 ASSERT_IMPLEMENTS_getBeginLoc(type); \ 277 ASSERT_IMPLEMENTS_getEndLoc(type); 278 #include "clang/AST/StmtNodes.inc" 279 } 280 281 Stmt::child_range Stmt::children() { 282 switch (getStmtClass()) { 283 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 284 #define ABSTRACT_STMT(type) 285 #define STMT(type, base) \ 286 case Stmt::type##Class: \ 287 return static_cast<type*>(this)->children(); 288 #include "clang/AST/StmtNodes.inc" 289 } 290 llvm_unreachable("unknown statement kind!"); 291 } 292 293 // Amusing macro metaprogramming hack: check whether a class provides 294 // a more specific implementation of getSourceRange. 295 // 296 // See also Expr.cpp:getExprLoc(). 297 namespace { 298 299 /// This implementation is used when a class provides a custom 300 /// implementation of getSourceRange. 301 template <class S, class T> 302 SourceRange getSourceRangeImpl(const Stmt *stmt, 303 SourceRange (T::*v)() const) { 304 return static_cast<const S*>(stmt)->getSourceRange(); 305 } 306 307 /// This implementation is used when a class doesn't provide a custom 308 /// implementation of getSourceRange. Overload resolution should pick it over 309 /// the implementation above because it's more specialized according to 310 /// function template partial ordering. 311 template <class S> 312 SourceRange getSourceRangeImpl(const Stmt *stmt, 313 SourceRange (Stmt::*v)() const) { 314 return SourceRange(static_cast<const S *>(stmt)->getBeginLoc(), 315 static_cast<const S *>(stmt)->getEndLoc()); 316 } 317 318 } // namespace 319 320 SourceRange Stmt::getSourceRange() const { 321 switch (getStmtClass()) { 322 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 323 #define ABSTRACT_STMT(type) 324 #define STMT(type, base) \ 325 case Stmt::type##Class: \ 326 return getSourceRangeImpl<type>(this, &type::getSourceRange); 327 #include "clang/AST/StmtNodes.inc" 328 } 329 llvm_unreachable("unknown statement kind!"); 330 } 331 332 SourceLocation Stmt::getBeginLoc() const { 333 switch (getStmtClass()) { 334 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 335 #define ABSTRACT_STMT(type) 336 #define STMT(type, base) \ 337 case Stmt::type##Class: \ 338 return static_cast<const type *>(this)->getBeginLoc(); 339 #include "clang/AST/StmtNodes.inc" 340 } 341 llvm_unreachable("unknown statement kind"); 342 } 343 344 SourceLocation Stmt::getEndLoc() const { 345 switch (getStmtClass()) { 346 case Stmt::NoStmtClass: llvm_unreachable("statement without class"); 347 #define ABSTRACT_STMT(type) 348 #define STMT(type, base) \ 349 case Stmt::type##Class: \ 350 return static_cast<const type *>(this)->getEndLoc(); 351 #include "clang/AST/StmtNodes.inc" 352 } 353 llvm_unreachable("unknown statement kind"); 354 } 355 356 int64_t Stmt::getID(const ASTContext &Context) const { 357 return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this); 358 } 359 360 CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB, 361 SourceLocation RB) 362 : Stmt(CompoundStmtClass), RBraceLoc(RB) { 363 CompoundStmtBits.NumStmts = Stmts.size(); 364 setStmts(Stmts); 365 CompoundStmtBits.LBraceLoc = LB; 366 } 367 368 void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) { 369 assert(CompoundStmtBits.NumStmts == Stmts.size() && 370 "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!"); 371 372 std::copy(Stmts.begin(), Stmts.end(), body_begin()); 373 } 374 375 CompoundStmt *CompoundStmt::Create(const ASTContext &C, ArrayRef<Stmt *> Stmts, 376 SourceLocation LB, SourceLocation RB) { 377 void *Mem = 378 C.Allocate(totalSizeToAlloc<Stmt *>(Stmts.size()), alignof(CompoundStmt)); 379 return new (Mem) CompoundStmt(Stmts, LB, RB); 380 } 381 382 CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C, 383 unsigned NumStmts) { 384 void *Mem = 385 C.Allocate(totalSizeToAlloc<Stmt *>(NumStmts), alignof(CompoundStmt)); 386 CompoundStmt *New = new (Mem) CompoundStmt(EmptyShell()); 387 New->CompoundStmtBits.NumStmts = NumStmts; 388 return New; 389 } 390 391 const Expr *ValueStmt::getExprStmt() const { 392 const Stmt *S = this; 393 do { 394 if (const auto *E = dyn_cast<Expr>(S)) 395 return E; 396 397 if (const auto *LS = dyn_cast<LabelStmt>(S)) 398 S = LS->getSubStmt(); 399 else if (const auto *AS = dyn_cast<AttributedStmt>(S)) 400 S = AS->getSubStmt(); 401 else 402 llvm_unreachable("unknown kind of ValueStmt"); 403 } while (isa<ValueStmt>(S)); 404 405 return nullptr; 406 } 407 408 const char *LabelStmt::getName() const { 409 return getDecl()->getIdentifier()->getNameStart(); 410 } 411 412 AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc, 413 ArrayRef<const Attr*> Attrs, 414 Stmt *SubStmt) { 415 assert(!Attrs.empty() && "Attrs should not be empty"); 416 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(Attrs.size()), 417 alignof(AttributedStmt)); 418 return new (Mem) AttributedStmt(Loc, Attrs, SubStmt); 419 } 420 421 AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C, 422 unsigned NumAttrs) { 423 assert(NumAttrs > 0 && "NumAttrs should be greater than zero"); 424 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(NumAttrs), 425 alignof(AttributedStmt)); 426 return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); 427 } 428 429 std::string AsmStmt::generateAsmString(const ASTContext &C) const { 430 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 431 return gccAsmStmt->generateAsmString(C); 432 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 433 return msAsmStmt->generateAsmString(C); 434 llvm_unreachable("unknown asm statement kind!"); 435 } 436 437 StringRef AsmStmt::getOutputConstraint(unsigned i) const { 438 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 439 return gccAsmStmt->getOutputConstraint(i); 440 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 441 return msAsmStmt->getOutputConstraint(i); 442 llvm_unreachable("unknown asm statement kind!"); 443 } 444 445 const Expr *AsmStmt::getOutputExpr(unsigned i) const { 446 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 447 return gccAsmStmt->getOutputExpr(i); 448 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 449 return msAsmStmt->getOutputExpr(i); 450 llvm_unreachable("unknown asm statement kind!"); 451 } 452 453 StringRef AsmStmt::getInputConstraint(unsigned i) const { 454 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 455 return gccAsmStmt->getInputConstraint(i); 456 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 457 return msAsmStmt->getInputConstraint(i); 458 llvm_unreachable("unknown asm statement kind!"); 459 } 460 461 const Expr *AsmStmt::getInputExpr(unsigned i) const { 462 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 463 return gccAsmStmt->getInputExpr(i); 464 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 465 return msAsmStmt->getInputExpr(i); 466 llvm_unreachable("unknown asm statement kind!"); 467 } 468 469 StringRef AsmStmt::getClobber(unsigned i) const { 470 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 471 return gccAsmStmt->getClobber(i); 472 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 473 return msAsmStmt->getClobber(i); 474 llvm_unreachable("unknown asm statement kind!"); 475 } 476 477 /// getNumPlusOperands - Return the number of output operands that have a "+" 478 /// constraint. 479 unsigned AsmStmt::getNumPlusOperands() const { 480 unsigned Res = 0; 481 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) 482 if (isOutputPlusConstraint(i)) 483 ++Res; 484 return Res; 485 } 486 487 char GCCAsmStmt::AsmStringPiece::getModifier() const { 488 assert(isOperand() && "Only Operands can have modifiers."); 489 return isLetter(Str[0]) ? Str[0] : '\0'; 490 } 491 492 StringRef GCCAsmStmt::getClobber(unsigned i) const { 493 return getClobberStringLiteral(i)->getString(); 494 } 495 496 Expr *GCCAsmStmt::getOutputExpr(unsigned i) { 497 return cast<Expr>(Exprs[i]); 498 } 499 500 /// getOutputConstraint - Return the constraint string for the specified 501 /// output operand. All output constraints are known to be non-empty (either 502 /// '=' or '+'). 503 StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const { 504 return getOutputConstraintLiteral(i)->getString(); 505 } 506 507 Expr *GCCAsmStmt::getInputExpr(unsigned i) { 508 return cast<Expr>(Exprs[i + NumOutputs]); 509 } 510 511 void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) { 512 Exprs[i + NumOutputs] = E; 513 } 514 515 AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const { 516 return cast<AddrLabelExpr>(Exprs[i + NumOutputs + NumInputs]); 517 } 518 519 StringRef GCCAsmStmt::getLabelName(unsigned i) const { 520 return getLabelExpr(i)->getLabel()->getName(); 521 } 522 523 /// getInputConstraint - Return the specified input constraint. Unlike output 524 /// constraints, these can be empty. 525 StringRef GCCAsmStmt::getInputConstraint(unsigned i) const { 526 return getInputConstraintLiteral(i)->getString(); 527 } 528 529 void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C, 530 IdentifierInfo **Names, 531 StringLiteral **Constraints, 532 Stmt **Exprs, 533 unsigned NumOutputs, 534 unsigned NumInputs, 535 unsigned NumLabels, 536 StringLiteral **Clobbers, 537 unsigned NumClobbers) { 538 this->NumOutputs = NumOutputs; 539 this->NumInputs = NumInputs; 540 this->NumClobbers = NumClobbers; 541 this->NumLabels = NumLabels; 542 543 unsigned NumExprs = NumOutputs + NumInputs + NumLabels; 544 545 C.Deallocate(this->Names); 546 this->Names = new (C) IdentifierInfo*[NumExprs]; 547 std::copy(Names, Names + NumExprs, this->Names); 548 549 C.Deallocate(this->Exprs); 550 this->Exprs = new (C) Stmt*[NumExprs]; 551 std::copy(Exprs, Exprs + NumExprs, this->Exprs); 552 553 unsigned NumConstraints = NumOutputs + NumInputs; 554 C.Deallocate(this->Constraints); 555 this->Constraints = new (C) StringLiteral*[NumConstraints]; 556 std::copy(Constraints, Constraints + NumConstraints, this->Constraints); 557 558 C.Deallocate(this->Clobbers); 559 this->Clobbers = new (C) StringLiteral*[NumClobbers]; 560 std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers); 561 } 562 563 /// getNamedOperand - Given a symbolic operand reference like %[foo], 564 /// translate this into a numeric value needed to reference the same operand. 565 /// This returns -1 if the operand name is invalid. 566 int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const { 567 unsigned NumPlusOperands = 0; 568 569 // Check if this is an output operand. 570 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) { 571 if (getOutputName(i) == SymbolicName) 572 return i; 573 } 574 575 for (unsigned i = 0, e = getNumInputs(); i != e; ++i) 576 if (getInputName(i) == SymbolicName) 577 return getNumOutputs() + NumPlusOperands + i; 578 579 for (unsigned i = 0, e = getNumLabels(); i != e; ++i) 580 if (getLabelName(i) == SymbolicName) 581 return i + getNumOutputs() + getNumInputs(); 582 583 // Not found. 584 return -1; 585 } 586 587 /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing 588 /// it into pieces. If the asm string is erroneous, emit errors and return 589 /// true, otherwise return false. 590 unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, 591 const ASTContext &C, unsigned &DiagOffs) const { 592 StringRef Str = getAsmString()->getString(); 593 const char *StrStart = Str.begin(); 594 const char *StrEnd = Str.end(); 595 const char *CurPtr = StrStart; 596 597 // "Simple" inline asms have no constraints or operands, just convert the asm 598 // string to escape $'s. 599 if (isSimple()) { 600 std::string Result; 601 for (; CurPtr != StrEnd; ++CurPtr) { 602 switch (*CurPtr) { 603 case '$': 604 Result += "$$"; 605 break; 606 default: 607 Result += *CurPtr; 608 break; 609 } 610 } 611 Pieces.push_back(AsmStringPiece(Result)); 612 return 0; 613 } 614 615 // CurStringPiece - The current string that we are building up as we scan the 616 // asm string. 617 std::string CurStringPiece; 618 619 bool HasVariants = !C.getTargetInfo().hasNoAsmVariants(); 620 621 unsigned LastAsmStringToken = 0; 622 unsigned LastAsmStringOffset = 0; 623 624 while (true) { 625 // Done with the string? 626 if (CurPtr == StrEnd) { 627 if (!CurStringPiece.empty()) 628 Pieces.push_back(AsmStringPiece(CurStringPiece)); 629 return 0; 630 } 631 632 char CurChar = *CurPtr++; 633 switch (CurChar) { 634 case '$': CurStringPiece += "$$"; continue; 635 case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue; 636 case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue; 637 case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue; 638 case '%': 639 break; 640 default: 641 CurStringPiece += CurChar; 642 continue; 643 } 644 645 // Escaped "%" character in asm string. 646 if (CurPtr == StrEnd) { 647 // % at end of string is invalid (no escape). 648 DiagOffs = CurPtr-StrStart-1; 649 return diag::err_asm_invalid_escape; 650 } 651 // Handle escaped char and continue looping over the asm string. 652 char EscapedChar = *CurPtr++; 653 switch (EscapedChar) { 654 default: 655 break; 656 case '%': // %% -> % 657 case '{': // %{ -> { 658 case '}': // %} -> } 659 CurStringPiece += EscapedChar; 660 continue; 661 case '=': // %= -> Generate a unique ID. 662 CurStringPiece += "${:uid}"; 663 continue; 664 } 665 666 // Otherwise, we have an operand. If we have accumulated a string so far, 667 // add it to the Pieces list. 668 if (!CurStringPiece.empty()) { 669 Pieces.push_back(AsmStringPiece(CurStringPiece)); 670 CurStringPiece.clear(); 671 } 672 673 // Handle operands that have asmSymbolicName (e.g., %x[foo]) and those that 674 // don't (e.g., %x4). 'x' following the '%' is the constraint modifier. 675 676 const char *Begin = CurPtr - 1; // Points to the character following '%'. 677 const char *Percent = Begin - 1; // Points to '%'. 678 679 if (isLetter(EscapedChar)) { 680 if (CurPtr == StrEnd) { // Premature end. 681 DiagOffs = CurPtr-StrStart-1; 682 return diag::err_asm_invalid_escape; 683 } 684 EscapedChar = *CurPtr++; 685 } 686 687 const TargetInfo &TI = C.getTargetInfo(); 688 const SourceManager &SM = C.getSourceManager(); 689 const LangOptions &LO = C.getLangOpts(); 690 691 // Handle operands that don't have asmSymbolicName (e.g., %x4). 692 if (isDigit(EscapedChar)) { 693 // %n - Assembler operand n 694 unsigned N = 0; 695 696 --CurPtr; 697 while (CurPtr != StrEnd && isDigit(*CurPtr)) 698 N = N*10 + ((*CurPtr++)-'0'); 699 700 unsigned NumOperands = getNumOutputs() + getNumPlusOperands() + 701 getNumInputs() + getNumLabels(); 702 if (N >= NumOperands) { 703 DiagOffs = CurPtr-StrStart-1; 704 return diag::err_asm_invalid_operand_number; 705 } 706 707 // Str contains "x4" (Operand without the leading %). 708 std::string Str(Begin, CurPtr - Begin); 709 710 // (BeginLoc, EndLoc) represents the range of the operand we are currently 711 // processing. Unlike Str, the range includes the leading '%'. 712 SourceLocation BeginLoc = getAsmString()->getLocationOfByte( 713 Percent - StrStart, SM, LO, TI, &LastAsmStringToken, 714 &LastAsmStringOffset); 715 SourceLocation EndLoc = getAsmString()->getLocationOfByte( 716 CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken, 717 &LastAsmStringOffset); 718 719 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); 720 continue; 721 } 722 723 // Handle operands that have asmSymbolicName (e.g., %x[foo]). 724 if (EscapedChar == '[') { 725 DiagOffs = CurPtr-StrStart-1; 726 727 // Find the ']'. 728 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr); 729 if (NameEnd == nullptr) 730 return diag::err_asm_unterminated_symbolic_operand_name; 731 if (NameEnd == CurPtr) 732 return diag::err_asm_empty_symbolic_operand_name; 733 734 StringRef SymbolicName(CurPtr, NameEnd - CurPtr); 735 736 int N = getNamedOperand(SymbolicName); 737 if (N == -1) { 738 // Verify that an operand with that name exists. 739 DiagOffs = CurPtr-StrStart; 740 return diag::err_asm_unknown_symbolic_operand_name; 741 } 742 743 // Str contains "x[foo]" (Operand without the leading %). 744 std::string Str(Begin, NameEnd + 1 - Begin); 745 746 // (BeginLoc, EndLoc) represents the range of the operand we are currently 747 // processing. Unlike Str, the range includes the leading '%'. 748 SourceLocation BeginLoc = getAsmString()->getLocationOfByte( 749 Percent - StrStart, SM, LO, TI, &LastAsmStringToken, 750 &LastAsmStringOffset); 751 SourceLocation EndLoc = getAsmString()->getLocationOfByte( 752 NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken, 753 &LastAsmStringOffset); 754 755 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); 756 757 CurPtr = NameEnd+1; 758 continue; 759 } 760 761 DiagOffs = CurPtr-StrStart-1; 762 return diag::err_asm_invalid_escape; 763 } 764 } 765 766 /// Assemble final IR asm string (GCC-style). 767 std::string GCCAsmStmt::generateAsmString(const ASTContext &C) const { 768 // Analyze the asm string to decompose it into its pieces. We know that Sema 769 // has already done this, so it is guaranteed to be successful. 770 SmallVector<GCCAsmStmt::AsmStringPiece, 4> Pieces; 771 unsigned DiagOffs; 772 AnalyzeAsmString(Pieces, C, DiagOffs); 773 774 std::string AsmString; 775 for (const auto &Piece : Pieces) { 776 if (Piece.isString()) 777 AsmString += Piece.getString(); 778 else if (Piece.getModifier() == '\0') 779 AsmString += '$' + llvm::utostr(Piece.getOperandNo()); 780 else 781 AsmString += "${" + llvm::utostr(Piece.getOperandNo()) + ':' + 782 Piece.getModifier() + '}'; 783 } 784 return AsmString; 785 } 786 787 /// Assemble final IR asm string (MS-style). 788 std::string MSAsmStmt::generateAsmString(const ASTContext &C) const { 789 // FIXME: This needs to be translated into the IR string representation. 790 return std::string(AsmStr); 791 } 792 793 Expr *MSAsmStmt::getOutputExpr(unsigned i) { 794 return cast<Expr>(Exprs[i]); 795 } 796 797 Expr *MSAsmStmt::getInputExpr(unsigned i) { 798 return cast<Expr>(Exprs[i + NumOutputs]); 799 } 800 801 void MSAsmStmt::setInputExpr(unsigned i, Expr *E) { 802 Exprs[i + NumOutputs] = E; 803 } 804 805 //===----------------------------------------------------------------------===// 806 // Constructors 807 //===----------------------------------------------------------------------===// 808 809 GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, 810 bool issimple, bool isvolatile, unsigned numoutputs, 811 unsigned numinputs, IdentifierInfo **names, 812 StringLiteral **constraints, Expr **exprs, 813 StringLiteral *asmstr, unsigned numclobbers, 814 StringLiteral **clobbers, unsigned numlabels, 815 SourceLocation rparenloc) 816 : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, 817 numinputs, numclobbers), 818 RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) { 819 unsigned NumExprs = NumOutputs + NumInputs + NumLabels; 820 821 Names = new (C) IdentifierInfo*[NumExprs]; 822 std::copy(names, names + NumExprs, Names); 823 824 Exprs = new (C) Stmt*[NumExprs]; 825 std::copy(exprs, exprs + NumExprs, Exprs); 826 827 unsigned NumConstraints = NumOutputs + NumInputs; 828 Constraints = new (C) StringLiteral*[NumConstraints]; 829 std::copy(constraints, constraints + NumConstraints, Constraints); 830 831 Clobbers = new (C) StringLiteral*[NumClobbers]; 832 std::copy(clobbers, clobbers + NumClobbers, Clobbers); 833 } 834 835 MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc, 836 SourceLocation lbraceloc, bool issimple, bool isvolatile, 837 ArrayRef<Token> asmtoks, unsigned numoutputs, 838 unsigned numinputs, 839 ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs, 840 StringRef asmstr, ArrayRef<StringRef> clobbers, 841 SourceLocation endloc) 842 : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, 843 numinputs, clobbers.size()), LBraceLoc(lbraceloc), 844 EndLoc(endloc), NumAsmToks(asmtoks.size()) { 845 initialize(C, asmstr, asmtoks, constraints, exprs, clobbers); 846 } 847 848 static StringRef copyIntoContext(const ASTContext &C, StringRef str) { 849 return str.copy(C); 850 } 851 852 void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr, 853 ArrayRef<Token> asmtoks, 854 ArrayRef<StringRef> constraints, 855 ArrayRef<Expr*> exprs, 856 ArrayRef<StringRef> clobbers) { 857 assert(NumAsmToks == asmtoks.size()); 858 assert(NumClobbers == clobbers.size()); 859 860 assert(exprs.size() == NumOutputs + NumInputs); 861 assert(exprs.size() == constraints.size()); 862 863 AsmStr = copyIntoContext(C, asmstr); 864 865 Exprs = new (C) Stmt*[exprs.size()]; 866 std::copy(exprs.begin(), exprs.end(), Exprs); 867 868 AsmToks = new (C) Token[asmtoks.size()]; 869 std::copy(asmtoks.begin(), asmtoks.end(), AsmToks); 870 871 Constraints = new (C) StringRef[exprs.size()]; 872 std::transform(constraints.begin(), constraints.end(), Constraints, 873 [&](StringRef Constraint) { 874 return copyIntoContext(C, Constraint); 875 }); 876 877 Clobbers = new (C) StringRef[NumClobbers]; 878 // FIXME: Avoid the allocation/copy if at all possible. 879 std::transform(clobbers.begin(), clobbers.end(), Clobbers, 880 [&](StringRef Clobber) { 881 return copyIntoContext(C, Clobber); 882 }); 883 } 884 885 IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, bool IsConstexpr, 886 Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL, 887 SourceLocation RPL, Stmt *Then, SourceLocation EL, Stmt *Else) 888 : Stmt(IfStmtClass), LParenLoc(LPL), RParenLoc(RPL) { 889 bool HasElse = Else != nullptr; 890 bool HasVar = Var != nullptr; 891 bool HasInit = Init != nullptr; 892 IfStmtBits.HasElse = HasElse; 893 IfStmtBits.HasVar = HasVar; 894 IfStmtBits.HasInit = HasInit; 895 896 setConstexpr(IsConstexpr); 897 898 setCond(Cond); 899 setThen(Then); 900 if (HasElse) 901 setElse(Else); 902 if (HasVar) 903 setConditionVariable(Ctx, Var); 904 if (HasInit) 905 setInit(Init); 906 907 setIfLoc(IL); 908 if (HasElse) 909 setElseLoc(EL); 910 } 911 912 IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit) 913 : Stmt(IfStmtClass, Empty) { 914 IfStmtBits.HasElse = HasElse; 915 IfStmtBits.HasVar = HasVar; 916 IfStmtBits.HasInit = HasInit; 917 } 918 919 IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL, 920 bool IsConstexpr, Stmt *Init, VarDecl *Var, Expr *Cond, 921 SourceLocation LPL, SourceLocation RPL, Stmt *Then, 922 SourceLocation EL, Stmt *Else) { 923 bool HasElse = Else != nullptr; 924 bool HasVar = Var != nullptr; 925 bool HasInit = Init != nullptr; 926 void *Mem = Ctx.Allocate( 927 totalSizeToAlloc<Stmt *, SourceLocation>( 928 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse), 929 alignof(IfStmt)); 930 return new (Mem) 931 IfStmt(Ctx, IL, IsConstexpr, Init, Var, Cond, LPL, RPL, Then, EL, Else); 932 } 933 934 IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar, 935 bool HasInit) { 936 void *Mem = Ctx.Allocate( 937 totalSizeToAlloc<Stmt *, SourceLocation>( 938 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse), 939 alignof(IfStmt)); 940 return new (Mem) IfStmt(EmptyShell(), HasElse, HasVar, HasInit); 941 } 942 943 VarDecl *IfStmt::getConditionVariable() { 944 auto *DS = getConditionVariableDeclStmt(); 945 if (!DS) 946 return nullptr; 947 return cast<VarDecl>(DS->getSingleDecl()); 948 } 949 950 void IfStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { 951 assert(hasVarStorage() && 952 "This if statement has no storage for a condition variable!"); 953 954 if (!V) { 955 getTrailingObjects<Stmt *>()[varOffset()] = nullptr; 956 return; 957 } 958 959 SourceRange VarRange = V->getSourceRange(); 960 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) 961 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); 962 } 963 964 bool IfStmt::isObjCAvailabilityCheck() const { 965 return isa<ObjCAvailabilityCheckExpr>(getCond()); 966 } 967 968 Optional<const Stmt*> IfStmt::getNondiscardedCase(const ASTContext &Ctx) const { 969 if (!isConstexpr() || getCond()->isValueDependent()) 970 return None; 971 return !getCond()->EvaluateKnownConstInt(Ctx) ? getElse() : getThen(); 972 } 973 974 ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, 975 Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, 976 SourceLocation RP) 977 : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP) 978 { 979 SubExprs[INIT] = Init; 980 setConditionVariable(C, condVar); 981 SubExprs[COND] = Cond; 982 SubExprs[INC] = Inc; 983 SubExprs[BODY] = Body; 984 ForStmtBits.ForLoc = FL; 985 } 986 987 VarDecl *ForStmt::getConditionVariable() const { 988 if (!SubExprs[CONDVAR]) 989 return nullptr; 990 991 auto *DS = cast<DeclStmt>(SubExprs[CONDVAR]); 992 return cast<VarDecl>(DS->getSingleDecl()); 993 } 994 995 void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { 996 if (!V) { 997 SubExprs[CONDVAR] = nullptr; 998 return; 999 } 1000 1001 SourceRange VarRange = V->getSourceRange(); 1002 SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), 1003 VarRange.getEnd()); 1004 } 1005 1006 SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, 1007 Expr *Cond, SourceLocation LParenLoc, 1008 SourceLocation RParenLoc) 1009 : Stmt(SwitchStmtClass), FirstCase(nullptr), LParenLoc(LParenLoc), 1010 RParenLoc(RParenLoc) { 1011 bool HasInit = Init != nullptr; 1012 bool HasVar = Var != nullptr; 1013 SwitchStmtBits.HasInit = HasInit; 1014 SwitchStmtBits.HasVar = HasVar; 1015 SwitchStmtBits.AllEnumCasesCovered = false; 1016 1017 setCond(Cond); 1018 setBody(nullptr); 1019 if (HasInit) 1020 setInit(Init); 1021 if (HasVar) 1022 setConditionVariable(Ctx, Var); 1023 1024 setSwitchLoc(SourceLocation{}); 1025 } 1026 1027 SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar) 1028 : Stmt(SwitchStmtClass, Empty) { 1029 SwitchStmtBits.HasInit = HasInit; 1030 SwitchStmtBits.HasVar = HasVar; 1031 SwitchStmtBits.AllEnumCasesCovered = false; 1032 } 1033 1034 SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, 1035 Expr *Cond, SourceLocation LParenLoc, 1036 SourceLocation RParenLoc) { 1037 bool HasInit = Init != nullptr; 1038 bool HasVar = Var != nullptr; 1039 void *Mem = Ctx.Allocate( 1040 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar), 1041 alignof(SwitchStmt)); 1042 return new (Mem) SwitchStmt(Ctx, Init, Var, Cond, LParenLoc, RParenLoc); 1043 } 1044 1045 SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit, 1046 bool HasVar) { 1047 void *Mem = Ctx.Allocate( 1048 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar), 1049 alignof(SwitchStmt)); 1050 return new (Mem) SwitchStmt(EmptyShell(), HasInit, HasVar); 1051 } 1052 1053 VarDecl *SwitchStmt::getConditionVariable() { 1054 auto *DS = getConditionVariableDeclStmt(); 1055 if (!DS) 1056 return nullptr; 1057 return cast<VarDecl>(DS->getSingleDecl()); 1058 } 1059 1060 void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { 1061 assert(hasVarStorage() && 1062 "This switch statement has no storage for a condition variable!"); 1063 1064 if (!V) { 1065 getTrailingObjects<Stmt *>()[varOffset()] = nullptr; 1066 return; 1067 } 1068 1069 SourceRange VarRange = V->getSourceRange(); 1070 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) 1071 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); 1072 } 1073 1074 WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, 1075 Stmt *Body, SourceLocation WL, SourceLocation LParenLoc, 1076 SourceLocation RParenLoc) 1077 : Stmt(WhileStmtClass) { 1078 bool HasVar = Var != nullptr; 1079 WhileStmtBits.HasVar = HasVar; 1080 1081 setCond(Cond); 1082 setBody(Body); 1083 if (HasVar) 1084 setConditionVariable(Ctx, Var); 1085 1086 setWhileLoc(WL); 1087 setLParenLoc(LParenLoc); 1088 setRParenLoc(RParenLoc); 1089 } 1090 1091 WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar) 1092 : Stmt(WhileStmtClass, Empty) { 1093 WhileStmtBits.HasVar = HasVar; 1094 } 1095 1096 WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, 1097 Stmt *Body, SourceLocation WL, 1098 SourceLocation LParenLoc, 1099 SourceLocation RParenLoc) { 1100 bool HasVar = Var != nullptr; 1101 void *Mem = 1102 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), 1103 alignof(WhileStmt)); 1104 return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL, LParenLoc, RParenLoc); 1105 } 1106 1107 WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) { 1108 void *Mem = 1109 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), 1110 alignof(WhileStmt)); 1111 return new (Mem) WhileStmt(EmptyShell(), HasVar); 1112 } 1113 1114 VarDecl *WhileStmt::getConditionVariable() { 1115 auto *DS = getConditionVariableDeclStmt(); 1116 if (!DS) 1117 return nullptr; 1118 return cast<VarDecl>(DS->getSingleDecl()); 1119 } 1120 1121 void WhileStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { 1122 assert(hasVarStorage() && 1123 "This while statement has no storage for a condition variable!"); 1124 1125 if (!V) { 1126 getTrailingObjects<Stmt *>()[varOffset()] = nullptr; 1127 return; 1128 } 1129 1130 SourceRange VarRange = V->getSourceRange(); 1131 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) 1132 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); 1133 } 1134 1135 // IndirectGotoStmt 1136 LabelDecl *IndirectGotoStmt::getConstantTarget() { 1137 if (auto *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts())) 1138 return E->getLabel(); 1139 return nullptr; 1140 } 1141 1142 // ReturnStmt 1143 ReturnStmt::ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate) 1144 : Stmt(ReturnStmtClass), RetExpr(E) { 1145 bool HasNRVOCandidate = NRVOCandidate != nullptr; 1146 ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate; 1147 if (HasNRVOCandidate) 1148 setNRVOCandidate(NRVOCandidate); 1149 setReturnLoc(RL); 1150 } 1151 1152 ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate) 1153 : Stmt(ReturnStmtClass, Empty) { 1154 ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate; 1155 } 1156 1157 ReturnStmt *ReturnStmt::Create(const ASTContext &Ctx, SourceLocation RL, 1158 Expr *E, const VarDecl *NRVOCandidate) { 1159 bool HasNRVOCandidate = NRVOCandidate != nullptr; 1160 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate), 1161 alignof(ReturnStmt)); 1162 return new (Mem) ReturnStmt(RL, E, NRVOCandidate); 1163 } 1164 1165 ReturnStmt *ReturnStmt::CreateEmpty(const ASTContext &Ctx, 1166 bool HasNRVOCandidate) { 1167 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate), 1168 alignof(ReturnStmt)); 1169 return new (Mem) ReturnStmt(EmptyShell(), HasNRVOCandidate); 1170 } 1171 1172 // CaseStmt 1173 CaseStmt *CaseStmt::Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs, 1174 SourceLocation caseLoc, SourceLocation ellipsisLoc, 1175 SourceLocation colonLoc) { 1176 bool CaseStmtIsGNURange = rhs != nullptr; 1177 void *Mem = Ctx.Allocate( 1178 totalSizeToAlloc<Stmt *, SourceLocation>( 1179 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange), 1180 alignof(CaseStmt)); 1181 return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc); 1182 } 1183 1184 CaseStmt *CaseStmt::CreateEmpty(const ASTContext &Ctx, 1185 bool CaseStmtIsGNURange) { 1186 void *Mem = Ctx.Allocate( 1187 totalSizeToAlloc<Stmt *, SourceLocation>( 1188 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange), 1189 alignof(CaseStmt)); 1190 return new (Mem) CaseStmt(EmptyShell(), CaseStmtIsGNURange); 1191 } 1192 1193 SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, 1194 Stmt *Handler) 1195 : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) { 1196 Children[TRY] = TryBlock; 1197 Children[HANDLER] = Handler; 1198 } 1199 1200 SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry, 1201 SourceLocation TryLoc, Stmt *TryBlock, 1202 Stmt *Handler) { 1203 return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler); 1204 } 1205 1206 SEHExceptStmt* SEHTryStmt::getExceptHandler() const { 1207 return dyn_cast<SEHExceptStmt>(getHandler()); 1208 } 1209 1210 SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const { 1211 return dyn_cast<SEHFinallyStmt>(getHandler()); 1212 } 1213 1214 SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block) 1215 : Stmt(SEHExceptStmtClass), Loc(Loc) { 1216 Children[FILTER_EXPR] = FilterExpr; 1217 Children[BLOCK] = Block; 1218 } 1219 1220 SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc, 1221 Expr *FilterExpr, Stmt *Block) { 1222 return new(C) SEHExceptStmt(Loc,FilterExpr,Block); 1223 } 1224 1225 SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block) 1226 : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {} 1227 1228 SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc, 1229 Stmt *Block) { 1230 return new(C)SEHFinallyStmt(Loc,Block); 1231 } 1232 1233 CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind, 1234 VarDecl *Var) 1235 : VarAndKind(Var, Kind), Loc(Loc) { 1236 switch (Kind) { 1237 case VCK_This: 1238 assert(!Var && "'this' capture cannot have a variable!"); 1239 break; 1240 case VCK_ByRef: 1241 assert(Var && "capturing by reference must have a variable!"); 1242 break; 1243 case VCK_ByCopy: 1244 assert(Var && "capturing by copy must have a variable!"); 1245 assert( 1246 (Var->getType()->isScalarType() || (Var->getType()->isReferenceType() && 1247 Var->getType() 1248 ->castAs<ReferenceType>() 1249 ->getPointeeType() 1250 ->isScalarType())) && 1251 "captures by copy are expected to have a scalar type!"); 1252 break; 1253 case VCK_VLAType: 1254 assert(!Var && 1255 "Variable-length array type capture cannot have a variable!"); 1256 break; 1257 } 1258 } 1259 1260 CapturedStmt::VariableCaptureKind 1261 CapturedStmt::Capture::getCaptureKind() const { 1262 return VarAndKind.getInt(); 1263 } 1264 1265 VarDecl *CapturedStmt::Capture::getCapturedVar() const { 1266 assert((capturesVariable() || capturesVariableByCopy()) && 1267 "No variable available for 'this' or VAT capture"); 1268 return VarAndKind.getPointer(); 1269 } 1270 1271 CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const { 1272 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); 1273 1274 // Offset of the first Capture object. 1275 unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture)); 1276 1277 return reinterpret_cast<Capture *>( 1278 reinterpret_cast<char *>(const_cast<CapturedStmt *>(this)) 1279 + FirstCaptureOffset); 1280 } 1281 1282 CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind, 1283 ArrayRef<Capture> Captures, 1284 ArrayRef<Expr *> CaptureInits, 1285 CapturedDecl *CD, 1286 RecordDecl *RD) 1287 : Stmt(CapturedStmtClass), NumCaptures(Captures.size()), 1288 CapDeclAndKind(CD, Kind), TheRecordDecl(RD) { 1289 assert( S && "null captured statement"); 1290 assert(CD && "null captured declaration for captured statement"); 1291 assert(RD && "null record declaration for captured statement"); 1292 1293 // Copy initialization expressions. 1294 Stmt **Stored = getStoredStmts(); 1295 for (unsigned I = 0, N = NumCaptures; I != N; ++I) 1296 *Stored++ = CaptureInits[I]; 1297 1298 // Copy the statement being captured. 1299 *Stored = S; 1300 1301 // Copy all Capture objects. 1302 Capture *Buffer = getStoredCaptures(); 1303 std::copy(Captures.begin(), Captures.end(), Buffer); 1304 } 1305 1306 CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures) 1307 : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures), 1308 CapDeclAndKind(nullptr, CR_Default) { 1309 getStoredStmts()[NumCaptures] = nullptr; 1310 } 1311 1312 CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S, 1313 CapturedRegionKind Kind, 1314 ArrayRef<Capture> Captures, 1315 ArrayRef<Expr *> CaptureInits, 1316 CapturedDecl *CD, 1317 RecordDecl *RD) { 1318 // The layout is 1319 // 1320 // ----------------------------------------------------------- 1321 // | CapturedStmt, Init, ..., Init, S, Capture, ..., Capture | 1322 // ----------------^-------------------^---------------------- 1323 // getStoredStmts() getStoredCaptures() 1324 // 1325 // where S is the statement being captured. 1326 // 1327 assert(CaptureInits.size() == Captures.size() && "wrong number of arguments"); 1328 1329 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1); 1330 if (!Captures.empty()) { 1331 // Realign for the following Capture array. 1332 Size = llvm::alignTo(Size, alignof(Capture)); 1333 Size += sizeof(Capture) * Captures.size(); 1334 } 1335 1336 void *Mem = Context.Allocate(Size); 1337 return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD); 1338 } 1339 1340 CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context, 1341 unsigned NumCaptures) { 1342 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); 1343 if (NumCaptures > 0) { 1344 // Realign for the following Capture array. 1345 Size = llvm::alignTo(Size, alignof(Capture)); 1346 Size += sizeof(Capture) * NumCaptures; 1347 } 1348 1349 void *Mem = Context.Allocate(Size); 1350 return new (Mem) CapturedStmt(EmptyShell(), NumCaptures); 1351 } 1352 1353 Stmt::child_range CapturedStmt::children() { 1354 // Children are captured field initializers. 1355 return child_range(getStoredStmts(), getStoredStmts() + NumCaptures); 1356 } 1357 1358 Stmt::const_child_range CapturedStmt::children() const { 1359 return const_child_range(getStoredStmts(), getStoredStmts() + NumCaptures); 1360 } 1361 1362 CapturedDecl *CapturedStmt::getCapturedDecl() { 1363 return CapDeclAndKind.getPointer(); 1364 } 1365 1366 const CapturedDecl *CapturedStmt::getCapturedDecl() const { 1367 return CapDeclAndKind.getPointer(); 1368 } 1369 1370 /// Set the outlined function declaration. 1371 void CapturedStmt::setCapturedDecl(CapturedDecl *D) { 1372 assert(D && "null CapturedDecl"); 1373 CapDeclAndKind.setPointer(D); 1374 } 1375 1376 /// Retrieve the captured region kind. 1377 CapturedRegionKind CapturedStmt::getCapturedRegionKind() const { 1378 return CapDeclAndKind.getInt(); 1379 } 1380 1381 /// Set the captured region kind. 1382 void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) { 1383 CapDeclAndKind.setInt(Kind); 1384 } 1385 1386 bool CapturedStmt::capturesVariable(const VarDecl *Var) const { 1387 for (const auto &I : captures()) { 1388 if (!I.capturesVariable() && !I.capturesVariableByCopy()) 1389 continue; 1390 if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl()) 1391 return true; 1392 } 1393 1394 return false; 1395 } 1396