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