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