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