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 llvm::copy(Stmts, body_begin()); 388 } 389 390 CompoundStmt *CompoundStmt::Create(const ASTContext &C, ArrayRef<Stmt *> Stmts, 391 FPOptionsOverride FPFeatures, 392 SourceLocation LB, SourceLocation RB) { 393 void *Mem = 394 C.Allocate(totalSizeToAlloc<Stmt *, FPOptionsOverride>( 395 Stmts.size(), FPFeatures.requiresTrailingStorage()), 396 alignof(CompoundStmt)); 397 return new (Mem) CompoundStmt(Stmts, FPFeatures, LB, RB); 398 } 399 400 CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C, unsigned NumStmts, 401 bool HasFPFeatures) { 402 void *Mem = C.Allocate( 403 totalSizeToAlloc<Stmt *, FPOptionsOverride>(NumStmts, HasFPFeatures), 404 alignof(CompoundStmt)); 405 CompoundStmt *New = new (Mem) CompoundStmt(EmptyShell()); 406 New->CompoundStmtBits.NumStmts = NumStmts; 407 New->CompoundStmtBits.HasFPFeatures = HasFPFeatures; 408 return New; 409 } 410 411 const Expr *ValueStmt::getExprStmt() const { 412 const Stmt *S = this; 413 do { 414 if (const auto *E = dyn_cast<Expr>(S)) 415 return E; 416 417 if (const auto *LS = dyn_cast<LabelStmt>(S)) 418 S = LS->getSubStmt(); 419 else if (const auto *AS = dyn_cast<AttributedStmt>(S)) 420 S = AS->getSubStmt(); 421 else 422 llvm_unreachable("unknown kind of ValueStmt"); 423 } while (isa<ValueStmt>(S)); 424 425 return nullptr; 426 } 427 428 const char *LabelStmt::getName() const { 429 return getDecl()->getIdentifier()->getNameStart(); 430 } 431 432 AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc, 433 ArrayRef<const Attr*> Attrs, 434 Stmt *SubStmt) { 435 assert(!Attrs.empty() && "Attrs should not be empty"); 436 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(Attrs.size()), 437 alignof(AttributedStmt)); 438 return new (Mem) AttributedStmt(Loc, Attrs, SubStmt); 439 } 440 441 AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C, 442 unsigned NumAttrs) { 443 assert(NumAttrs > 0 && "NumAttrs should be greater than zero"); 444 void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(NumAttrs), 445 alignof(AttributedStmt)); 446 return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); 447 } 448 449 std::string AsmStmt::generateAsmString(const ASTContext &C) const { 450 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 451 return gccAsmStmt->generateAsmString(C); 452 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 453 return msAsmStmt->generateAsmString(C); 454 llvm_unreachable("unknown asm statement kind!"); 455 } 456 457 std::string AsmStmt::getOutputConstraint(unsigned i) const { 458 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 459 return gccAsmStmt->getOutputConstraint(i); 460 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 461 return msAsmStmt->getOutputConstraint(i).str(); 462 llvm_unreachable("unknown asm statement kind!"); 463 } 464 465 const Expr *AsmStmt::getOutputExpr(unsigned i) const { 466 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 467 return gccAsmStmt->getOutputExpr(i); 468 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 469 return msAsmStmt->getOutputExpr(i); 470 llvm_unreachable("unknown asm statement kind!"); 471 } 472 473 std::string AsmStmt::getInputConstraint(unsigned i) const { 474 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 475 return gccAsmStmt->getInputConstraint(i); 476 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 477 return msAsmStmt->getInputConstraint(i).str(); 478 llvm_unreachable("unknown asm statement kind!"); 479 } 480 481 const Expr *AsmStmt::getInputExpr(unsigned i) const { 482 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 483 return gccAsmStmt->getInputExpr(i); 484 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 485 return msAsmStmt->getInputExpr(i); 486 llvm_unreachable("unknown asm statement kind!"); 487 } 488 489 std::string AsmStmt::getClobber(unsigned i) const { 490 if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this)) 491 return gccAsmStmt->getClobber(i); 492 if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this)) 493 return msAsmStmt->getClobber(i).str(); 494 llvm_unreachable("unknown asm statement kind!"); 495 } 496 497 /// getNumPlusOperands - Return the number of output operands that have a "+" 498 /// constraint. 499 unsigned AsmStmt::getNumPlusOperands() const { 500 unsigned Res = 0; 501 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) 502 if (isOutputPlusConstraint(i)) 503 ++Res; 504 return Res; 505 } 506 507 char GCCAsmStmt::AsmStringPiece::getModifier() const { 508 assert(isOperand() && "Only Operands can have modifiers."); 509 return isLetter(Str[0]) ? Str[0] : '\0'; 510 } 511 512 std::string GCCAsmStmt::ExtractStringFromGCCAsmStmtComponent(const Expr *E) { 513 if (auto *SL = llvm::dyn_cast<StringLiteral>(E)) 514 return SL->getString().str(); 515 assert(E->getDependence() == ExprDependence::None && 516 "cannot extract a string from a dependent expression"); 517 auto *CE = cast<ConstantExpr>(E); 518 APValue Res = CE->getAPValueResult(); 519 assert(Res.isArray() && "expected an array"); 520 521 std::string Out; 522 Out.reserve(Res.getArraySize()); 523 for (unsigned I = 0; I < Res.getArraySize(); ++I) { 524 APValue C = Res.getArrayInitializedElt(I); 525 assert(C.isInt()); 526 auto Ch = static_cast<char>(C.getInt().getExtValue()); 527 Out.push_back(Ch); 528 } 529 return Out; 530 } 531 532 std::string GCCAsmStmt::getAsmString() const { 533 return ExtractStringFromGCCAsmStmtComponent(getAsmStringExpr()); 534 } 535 536 std::string GCCAsmStmt::getClobber(unsigned i) const { 537 return ExtractStringFromGCCAsmStmtComponent(getClobberExpr(i)); 538 } 539 540 Expr *GCCAsmStmt::getOutputExpr(unsigned i) { 541 return cast<Expr>(Exprs[i]); 542 } 543 544 /// getOutputConstraint - Return the constraint string for the specified 545 /// output operand. All output constraints are known to be non-empty (either 546 /// '=' or '+'). 547 std::string GCCAsmStmt::getOutputConstraint(unsigned i) const { 548 return ExtractStringFromGCCAsmStmtComponent(getOutputConstraintExpr(i)); 549 } 550 551 Expr *GCCAsmStmt::getInputExpr(unsigned i) { 552 return cast<Expr>(Exprs[i + NumOutputs]); 553 } 554 555 void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) { 556 Exprs[i + NumOutputs] = E; 557 } 558 559 AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const { 560 return cast<AddrLabelExpr>(Exprs[i + NumOutputs + NumInputs]); 561 } 562 563 StringRef GCCAsmStmt::getLabelName(unsigned i) const { 564 return getLabelExpr(i)->getLabel()->getName(); 565 } 566 567 /// getInputConstraint - Return the specified input constraint. Unlike output 568 /// constraints, these can be empty. 569 std::string GCCAsmStmt::getInputConstraint(unsigned i) const { 570 return ExtractStringFromGCCAsmStmtComponent(getInputConstraintExpr(i)); 571 } 572 573 void GCCAsmStmt::setOutputsAndInputsAndClobbers( 574 const ASTContext &C, IdentifierInfo **Names, Expr **Constraints, 575 Stmt **Exprs, unsigned NumOutputs, unsigned NumInputs, unsigned NumLabels, 576 Expr **Clobbers, unsigned NumClobbers) { 577 this->NumOutputs = NumOutputs; 578 this->NumInputs = NumInputs; 579 this->NumClobbers = NumClobbers; 580 this->NumLabels = NumLabels; 581 582 unsigned NumExprs = NumOutputs + NumInputs + NumLabels; 583 584 C.Deallocate(this->Names); 585 this->Names = new (C) IdentifierInfo*[NumExprs]; 586 std::copy(Names, Names + NumExprs, this->Names); 587 588 C.Deallocate(this->Exprs); 589 this->Exprs = new (C) Stmt*[NumExprs]; 590 std::copy(Exprs, Exprs + NumExprs, this->Exprs); 591 592 unsigned NumConstraints = NumOutputs + NumInputs; 593 C.Deallocate(this->Constraints); 594 this->Constraints = new (C) Expr *[NumConstraints]; 595 std::copy(Constraints, Constraints + NumConstraints, this->Constraints); 596 597 C.Deallocate(this->Clobbers); 598 this->Clobbers = new (C) Expr *[NumClobbers]; 599 std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers); 600 } 601 602 /// getNamedOperand - Given a symbolic operand reference like %[foo], 603 /// translate this into a numeric value needed to reference the same operand. 604 /// This returns -1 if the operand name is invalid. 605 int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const { 606 // Check if this is an output operand. 607 unsigned NumOutputs = getNumOutputs(); 608 for (unsigned i = 0; i != NumOutputs; ++i) 609 if (getOutputName(i) == SymbolicName) 610 return i; 611 612 unsigned NumInputs = getNumInputs(); 613 for (unsigned i = 0; i != NumInputs; ++i) 614 if (getInputName(i) == SymbolicName) 615 return NumOutputs + i; 616 617 for (unsigned i = 0, e = getNumLabels(); i != e; ++i) 618 if (getLabelName(i) == SymbolicName) 619 return NumOutputs + NumInputs + getNumPlusOperands() + i; 620 621 // Not found. 622 return -1; 623 } 624 625 /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing 626 /// it into pieces. If the asm string is erroneous, emit errors and return 627 /// true, otherwise return false. 628 unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces, 629 const ASTContext &C, unsigned &DiagOffs) const { 630 631 std::string Str = getAsmString(); 632 const char *StrStart = Str.data(); 633 const char *StrEnd = Str.data() + Str.size(); 634 const char *CurPtr = StrStart; 635 636 // "Simple" inline asms have no constraints or operands, just convert the asm 637 // string to escape $'s. 638 if (isSimple()) { 639 std::string Result; 640 for (; CurPtr != StrEnd; ++CurPtr) { 641 switch (*CurPtr) { 642 case '$': 643 Result += "$$"; 644 break; 645 default: 646 Result += *CurPtr; 647 break; 648 } 649 } 650 Pieces.push_back(AsmStringPiece(Result)); 651 return 0; 652 } 653 654 // CurStringPiece - The current string that we are building up as we scan the 655 // asm string. 656 std::string CurStringPiece; 657 658 bool HasVariants = !C.getTargetInfo().hasNoAsmVariants(); 659 660 unsigned LastAsmStringToken = 0; 661 unsigned LastAsmStringOffset = 0; 662 663 while (true) { 664 // Done with the string? 665 if (CurPtr == StrEnd) { 666 if (!CurStringPiece.empty()) 667 Pieces.push_back(AsmStringPiece(CurStringPiece)); 668 return 0; 669 } 670 671 char CurChar = *CurPtr++; 672 switch (CurChar) { 673 case '$': CurStringPiece += "$$"; continue; 674 case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue; 675 case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue; 676 case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue; 677 case '%': 678 break; 679 default: 680 CurStringPiece += CurChar; 681 continue; 682 } 683 684 const TargetInfo &TI = C.getTargetInfo(); 685 686 // Escaped "%" character in asm string. 687 if (CurPtr == StrEnd) { 688 // % at end of string is invalid (no escape). 689 DiagOffs = CurPtr-StrStart-1; 690 return diag::err_asm_invalid_escape; 691 } 692 // Handle escaped char and continue looping over the asm string. 693 char EscapedChar = *CurPtr++; 694 switch (EscapedChar) { 695 default: 696 // Handle target-specific escaped characters. 697 if (auto MaybeReplaceStr = TI.handleAsmEscapedChar(EscapedChar)) { 698 CurStringPiece += *MaybeReplaceStr; 699 continue; 700 } 701 break; 702 case '%': // %% -> % 703 case '{': // %{ -> { 704 case '}': // %} -> } 705 CurStringPiece += EscapedChar; 706 continue; 707 case '=': // %= -> Generate a unique ID. 708 CurStringPiece += "${:uid}"; 709 continue; 710 } 711 712 // Otherwise, we have an operand. If we have accumulated a string so far, 713 // add it to the Pieces list. 714 if (!CurStringPiece.empty()) { 715 Pieces.push_back(AsmStringPiece(CurStringPiece)); 716 CurStringPiece.clear(); 717 } 718 719 // Handle operands that have asmSymbolicName (e.g., %x[foo]) and those that 720 // don't (e.g., %x4). 'x' following the '%' is the constraint modifier. 721 722 const char *Begin = CurPtr - 1; // Points to the character following '%'. 723 const char *Percent = Begin - 1; // Points to '%'. 724 725 if (isLetter(EscapedChar)) { 726 if (CurPtr == StrEnd) { // Premature end. 727 DiagOffs = CurPtr-StrStart-1; 728 return diag::err_asm_invalid_escape; 729 } 730 731 // Specifically handle `cc` which we will alias to `c`. 732 // Note this is the only operand modifier that exists which has two 733 // characters. 734 if (EscapedChar == 'c' && *CurPtr == 'c') 735 CurPtr++; 736 737 EscapedChar = *CurPtr++; 738 } 739 740 const SourceManager &SM = C.getSourceManager(); 741 const LangOptions &LO = C.getLangOpts(); 742 743 // Handle operands that don't have asmSymbolicName (e.g., %x4). 744 if (isDigit(EscapedChar)) { 745 // %n - Assembler operand n 746 unsigned N = 0; 747 748 --CurPtr; 749 while (CurPtr != StrEnd && isDigit(*CurPtr)) 750 N = N*10 + ((*CurPtr++)-'0'); 751 752 unsigned NumOperands = getNumOutputs() + getNumPlusOperands() + 753 getNumInputs() + getNumLabels(); 754 if (N >= NumOperands) { 755 DiagOffs = CurPtr-StrStart-1; 756 return diag::err_asm_invalid_operand_number; 757 } 758 759 // Str contains "x4" (Operand without the leading %). 760 std::string Str(Begin, CurPtr - Begin); 761 // (BeginLoc, EndLoc) represents the range of the operand we are currently 762 // processing. Unlike Str, the range includes the leading '%'. 763 SourceLocation BeginLoc, EndLoc; 764 if (auto *SL = dyn_cast<StringLiteral>(getAsmStringExpr())) { 765 BeginLoc = 766 SL->getLocationOfByte(Percent - StrStart, SM, LO, TI, 767 &LastAsmStringToken, &LastAsmStringOffset); 768 EndLoc = 769 SL->getLocationOfByte(CurPtr - StrStart, SM, LO, TI, 770 &LastAsmStringToken, &LastAsmStringOffset); 771 } else { 772 BeginLoc = getAsmStringExpr()->getBeginLoc(); 773 EndLoc = getAsmStringExpr()->getEndLoc(); 774 } 775 776 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); 777 continue; 778 } 779 780 // Handle operands that have asmSymbolicName (e.g., %x[foo]). 781 if (EscapedChar == '[') { 782 DiagOffs = CurPtr-StrStart-1; 783 784 // Find the ']'. 785 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr); 786 if (NameEnd == nullptr) 787 return diag::err_asm_unterminated_symbolic_operand_name; 788 if (NameEnd == CurPtr) 789 return diag::err_asm_empty_symbolic_operand_name; 790 791 StringRef SymbolicName(CurPtr, NameEnd - CurPtr); 792 793 int N = getNamedOperand(SymbolicName); 794 if (N == -1) { 795 // Verify that an operand with that name exists. 796 DiagOffs = CurPtr-StrStart; 797 return diag::err_asm_unknown_symbolic_operand_name; 798 } 799 800 // Str contains "x[foo]" (Operand without the leading %). 801 std::string Str(Begin, NameEnd + 1 - Begin); 802 803 // (BeginLoc, EndLoc) represents the range of the operand we are currently 804 // processing. Unlike Str, the range includes the leading '%'. 805 SourceLocation BeginLoc, EndLoc; 806 if (auto *SL = dyn_cast<StringLiteral>(getAsmStringExpr())) { 807 BeginLoc = 808 SL->getLocationOfByte(Percent - StrStart, SM, LO, TI, 809 &LastAsmStringToken, &LastAsmStringOffset); 810 EndLoc = 811 SL->getLocationOfByte(NameEnd + 1 - StrStart, SM, LO, TI, 812 &LastAsmStringToken, &LastAsmStringOffset); 813 } else { 814 BeginLoc = getAsmStringExpr()->getBeginLoc(); 815 EndLoc = getAsmStringExpr()->getEndLoc(); 816 } 817 818 Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc); 819 820 CurPtr = NameEnd+1; 821 continue; 822 } 823 824 DiagOffs = CurPtr-StrStart-1; 825 return diag::err_asm_invalid_escape; 826 } 827 } 828 829 /// Assemble final IR asm string (GCC-style). 830 std::string GCCAsmStmt::generateAsmString(const ASTContext &C) const { 831 // Analyze the asm string to decompose it into its pieces. We know that Sema 832 // has already done this, so it is guaranteed to be successful. 833 SmallVector<GCCAsmStmt::AsmStringPiece, 4> Pieces; 834 unsigned DiagOffs; 835 AnalyzeAsmString(Pieces, C, DiagOffs); 836 837 std::string AsmString; 838 for (const auto &Piece : Pieces) { 839 if (Piece.isString()) 840 AsmString += Piece.getString(); 841 else if (Piece.getModifier() == '\0') 842 AsmString += '$' + llvm::utostr(Piece.getOperandNo()); 843 else 844 AsmString += "${" + llvm::utostr(Piece.getOperandNo()) + ':' + 845 Piece.getModifier() + '}'; 846 } 847 return AsmString; 848 } 849 850 /// Assemble final IR asm string (MS-style). 851 std::string MSAsmStmt::generateAsmString(const ASTContext &C) const { 852 // FIXME: This needs to be translated into the IR string representation. 853 SmallVector<StringRef, 8> Pieces; 854 AsmStr.split(Pieces, "\n\t"); 855 std::string MSAsmString; 856 for (size_t I = 0, E = Pieces.size(); I < E; ++I) { 857 StringRef Instruction = Pieces[I]; 858 // For vex/vex2/vex3/evex masm style prefix, convert it to att style 859 // since we don't support masm style prefix in backend. 860 if (Instruction.starts_with("vex ")) 861 MSAsmString += '{' + Instruction.substr(0, 3).str() + '}' + 862 Instruction.substr(3).str(); 863 else if (Instruction.starts_with("vex2 ") || 864 Instruction.starts_with("vex3 ") || 865 Instruction.starts_with("evex ")) 866 MSAsmString += '{' + Instruction.substr(0, 4).str() + '}' + 867 Instruction.substr(4).str(); 868 else 869 MSAsmString += Instruction.str(); 870 // If this is not the last instruction, adding back the '\n\t'. 871 if (I < E - 1) 872 MSAsmString += "\n\t"; 873 } 874 return MSAsmString; 875 } 876 877 Expr *MSAsmStmt::getOutputExpr(unsigned i) { 878 return cast<Expr>(Exprs[i]); 879 } 880 881 Expr *MSAsmStmt::getInputExpr(unsigned i) { 882 return cast<Expr>(Exprs[i + NumOutputs]); 883 } 884 885 void MSAsmStmt::setInputExpr(unsigned i, Expr *E) { 886 Exprs[i + NumOutputs] = E; 887 } 888 889 //===----------------------------------------------------------------------===// 890 // Constructors 891 //===----------------------------------------------------------------------===// 892 893 GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc, 894 bool issimple, bool isvolatile, unsigned numoutputs, 895 unsigned numinputs, IdentifierInfo **names, 896 Expr **constraints, Expr **exprs, Expr *asmstr, 897 unsigned numclobbers, Expr **clobbers, 898 unsigned numlabels, SourceLocation rparenloc) 899 : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, 900 numinputs, numclobbers), 901 RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) { 902 unsigned NumExprs = NumOutputs + NumInputs + NumLabels; 903 904 Names = new (C) IdentifierInfo*[NumExprs]; 905 std::copy(names, names + NumExprs, Names); 906 907 Exprs = new (C) Stmt*[NumExprs]; 908 std::copy(exprs, exprs + NumExprs, Exprs); 909 910 unsigned NumConstraints = NumOutputs + NumInputs; 911 Constraints = new (C) Expr *[NumConstraints]; 912 std::copy(constraints, constraints + NumConstraints, Constraints); 913 914 Clobbers = new (C) Expr *[NumClobbers]; 915 std::copy(clobbers, clobbers + NumClobbers, Clobbers); 916 } 917 918 MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc, 919 SourceLocation lbraceloc, bool issimple, bool isvolatile, 920 ArrayRef<Token> asmtoks, unsigned numoutputs, 921 unsigned numinputs, 922 ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs, 923 StringRef asmstr, ArrayRef<StringRef> clobbers, 924 SourceLocation endloc) 925 : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs, 926 numinputs, clobbers.size()), LBraceLoc(lbraceloc), 927 EndLoc(endloc), NumAsmToks(asmtoks.size()) { 928 initialize(C, asmstr, asmtoks, constraints, exprs, clobbers); 929 } 930 931 static StringRef copyIntoContext(const ASTContext &C, StringRef str) { 932 return str.copy(C); 933 } 934 935 void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr, 936 ArrayRef<Token> asmtoks, 937 ArrayRef<StringRef> constraints, 938 ArrayRef<Expr*> exprs, 939 ArrayRef<StringRef> clobbers) { 940 assert(NumAsmToks == asmtoks.size()); 941 assert(NumClobbers == clobbers.size()); 942 943 assert(exprs.size() == NumOutputs + NumInputs); 944 assert(exprs.size() == constraints.size()); 945 946 AsmStr = copyIntoContext(C, asmstr); 947 948 Exprs = new (C) Stmt*[exprs.size()]; 949 llvm::copy(exprs, Exprs); 950 951 AsmToks = new (C) Token[asmtoks.size()]; 952 llvm::copy(asmtoks, AsmToks); 953 954 Constraints = new (C) StringRef[exprs.size()]; 955 std::transform(constraints.begin(), constraints.end(), Constraints, 956 [&](StringRef Constraint) { 957 return copyIntoContext(C, Constraint); 958 }); 959 960 Clobbers = new (C) StringRef[NumClobbers]; 961 // FIXME: Avoid the allocation/copy if at all possible. 962 std::transform(clobbers.begin(), clobbers.end(), Clobbers, 963 [&](StringRef Clobber) { 964 return copyIntoContext(C, Clobber); 965 }); 966 } 967 968 IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind, 969 Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL, 970 SourceLocation RPL, Stmt *Then, SourceLocation EL, Stmt *Else) 971 : Stmt(IfStmtClass), LParenLoc(LPL), RParenLoc(RPL) { 972 bool HasElse = Else != nullptr; 973 bool HasVar = Var != nullptr; 974 bool HasInit = Init != nullptr; 975 IfStmtBits.HasElse = HasElse; 976 IfStmtBits.HasVar = HasVar; 977 IfStmtBits.HasInit = HasInit; 978 979 setStatementKind(Kind); 980 981 setCond(Cond); 982 setThen(Then); 983 if (HasElse) 984 setElse(Else); 985 if (HasVar) 986 setConditionVariable(Ctx, Var); 987 if (HasInit) 988 setInit(Init); 989 990 setIfLoc(IL); 991 if (HasElse) 992 setElseLoc(EL); 993 } 994 995 IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit) 996 : Stmt(IfStmtClass, Empty) { 997 IfStmtBits.HasElse = HasElse; 998 IfStmtBits.HasVar = HasVar; 999 IfStmtBits.HasInit = HasInit; 1000 } 1001 1002 IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL, 1003 IfStatementKind Kind, Stmt *Init, VarDecl *Var, 1004 Expr *Cond, SourceLocation LPL, SourceLocation RPL, 1005 Stmt *Then, SourceLocation EL, Stmt *Else) { 1006 bool HasElse = Else != nullptr; 1007 bool HasVar = Var != nullptr; 1008 bool HasInit = Init != nullptr; 1009 void *Mem = Ctx.Allocate( 1010 totalSizeToAlloc<Stmt *, SourceLocation>( 1011 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse), 1012 alignof(IfStmt)); 1013 return new (Mem) 1014 IfStmt(Ctx, IL, Kind, Init, Var, Cond, LPL, RPL, Then, EL, Else); 1015 } 1016 1017 IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar, 1018 bool HasInit) { 1019 void *Mem = Ctx.Allocate( 1020 totalSizeToAlloc<Stmt *, SourceLocation>( 1021 NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse), 1022 alignof(IfStmt)); 1023 return new (Mem) IfStmt(EmptyShell(), HasElse, HasVar, HasInit); 1024 } 1025 1026 VarDecl *IfStmt::getConditionVariable() { 1027 auto *DS = getConditionVariableDeclStmt(); 1028 if (!DS) 1029 return nullptr; 1030 return cast<VarDecl>(DS->getSingleDecl()); 1031 } 1032 1033 void IfStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { 1034 assert(hasVarStorage() && 1035 "This if statement has no storage for a condition variable!"); 1036 1037 if (!V) { 1038 getTrailingObjects<Stmt *>()[varOffset()] = nullptr; 1039 return; 1040 } 1041 1042 SourceRange VarRange = V->getSourceRange(); 1043 getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx) 1044 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); 1045 } 1046 1047 bool IfStmt::isObjCAvailabilityCheck() const { 1048 return isa<ObjCAvailabilityCheckExpr>(getCond()); 1049 } 1050 1051 std::optional<Stmt *> IfStmt::getNondiscardedCase(const ASTContext &Ctx) { 1052 if (!isConstexpr() || getCond()->isValueDependent()) 1053 return std::nullopt; 1054 return !getCond()->EvaluateKnownConstInt(Ctx) ? getElse() : getThen(); 1055 } 1056 1057 std::optional<const Stmt *> 1058 IfStmt::getNondiscardedCase(const ASTContext &Ctx) const { 1059 if (std::optional<Stmt *> Result = 1060 const_cast<IfStmt *>(this)->getNondiscardedCase(Ctx)) 1061 return *Result; 1062 return std::nullopt; 1063 } 1064 1065 ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar, 1066 Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP, 1067 SourceLocation RP) 1068 : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP) 1069 { 1070 SubExprs[INIT] = Init; 1071 setConditionVariable(C, condVar); 1072 SubExprs[COND] = Cond; 1073 SubExprs[INC] = Inc; 1074 SubExprs[BODY] = Body; 1075 ForStmtBits.ForLoc = FL; 1076 } 1077 1078 VarDecl *ForStmt::getConditionVariable() const { 1079 if (!SubExprs[CONDVAR]) 1080 return nullptr; 1081 1082 auto *DS = cast<DeclStmt>(SubExprs[CONDVAR]); 1083 return cast<VarDecl>(DS->getSingleDecl()); 1084 } 1085 1086 void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) { 1087 if (!V) { 1088 SubExprs[CONDVAR] = nullptr; 1089 return; 1090 } 1091 1092 SourceRange VarRange = V->getSourceRange(); 1093 SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(), 1094 VarRange.getEnd()); 1095 } 1096 1097 SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, 1098 Expr *Cond, SourceLocation LParenLoc, 1099 SourceLocation RParenLoc) 1100 : Stmt(SwitchStmtClass), FirstCase(nullptr), LParenLoc(LParenLoc), 1101 RParenLoc(RParenLoc) { 1102 bool HasInit = Init != nullptr; 1103 bool HasVar = Var != nullptr; 1104 SwitchStmtBits.HasInit = HasInit; 1105 SwitchStmtBits.HasVar = HasVar; 1106 SwitchStmtBits.AllEnumCasesCovered = false; 1107 1108 setCond(Cond); 1109 setBody(nullptr); 1110 if (HasInit) 1111 setInit(Init); 1112 if (HasVar) 1113 setConditionVariable(Ctx, Var); 1114 1115 setSwitchLoc(SourceLocation{}); 1116 } 1117 1118 SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar) 1119 : Stmt(SwitchStmtClass, Empty) { 1120 SwitchStmtBits.HasInit = HasInit; 1121 SwitchStmtBits.HasVar = HasVar; 1122 SwitchStmtBits.AllEnumCasesCovered = false; 1123 } 1124 1125 SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var, 1126 Expr *Cond, SourceLocation LParenLoc, 1127 SourceLocation RParenLoc) { 1128 bool HasInit = Init != nullptr; 1129 bool HasVar = Var != nullptr; 1130 void *Mem = Ctx.Allocate( 1131 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar), 1132 alignof(SwitchStmt)); 1133 return new (Mem) SwitchStmt(Ctx, Init, Var, Cond, LParenLoc, RParenLoc); 1134 } 1135 1136 SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit, 1137 bool HasVar) { 1138 void *Mem = Ctx.Allocate( 1139 totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar), 1140 alignof(SwitchStmt)); 1141 return new (Mem) SwitchStmt(EmptyShell(), HasInit, HasVar); 1142 } 1143 1144 VarDecl *SwitchStmt::getConditionVariable() { 1145 auto *DS = getConditionVariableDeclStmt(); 1146 if (!DS) 1147 return nullptr; 1148 return cast<VarDecl>(DS->getSingleDecl()); 1149 } 1150 1151 void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { 1152 assert(hasVarStorage() && 1153 "This switch statement has no storage for a condition variable!"); 1154 1155 if (!V) { 1156 getTrailingObjects()[varOffset()] = nullptr; 1157 return; 1158 } 1159 1160 SourceRange VarRange = V->getSourceRange(); 1161 getTrailingObjects()[varOffset()] = new (Ctx) 1162 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); 1163 } 1164 1165 WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, 1166 Stmt *Body, SourceLocation WL, SourceLocation LParenLoc, 1167 SourceLocation RParenLoc) 1168 : Stmt(WhileStmtClass) { 1169 bool HasVar = Var != nullptr; 1170 WhileStmtBits.HasVar = HasVar; 1171 1172 setCond(Cond); 1173 setBody(Body); 1174 if (HasVar) 1175 setConditionVariable(Ctx, Var); 1176 1177 setWhileLoc(WL); 1178 setLParenLoc(LParenLoc); 1179 setRParenLoc(RParenLoc); 1180 } 1181 1182 WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar) 1183 : Stmt(WhileStmtClass, Empty) { 1184 WhileStmtBits.HasVar = HasVar; 1185 } 1186 1187 WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond, 1188 Stmt *Body, SourceLocation WL, 1189 SourceLocation LParenLoc, 1190 SourceLocation RParenLoc) { 1191 bool HasVar = Var != nullptr; 1192 void *Mem = 1193 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), 1194 alignof(WhileStmt)); 1195 return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL, LParenLoc, RParenLoc); 1196 } 1197 1198 WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) { 1199 void *Mem = 1200 Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar), 1201 alignof(WhileStmt)); 1202 return new (Mem) WhileStmt(EmptyShell(), HasVar); 1203 } 1204 1205 VarDecl *WhileStmt::getConditionVariable() { 1206 auto *DS = getConditionVariableDeclStmt(); 1207 if (!DS) 1208 return nullptr; 1209 return cast<VarDecl>(DS->getSingleDecl()); 1210 } 1211 1212 void WhileStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) { 1213 assert(hasVarStorage() && 1214 "This while statement has no storage for a condition variable!"); 1215 1216 if (!V) { 1217 getTrailingObjects()[varOffset()] = nullptr; 1218 return; 1219 } 1220 1221 SourceRange VarRange = V->getSourceRange(); 1222 getTrailingObjects()[varOffset()] = new (Ctx) 1223 DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd()); 1224 } 1225 1226 // IndirectGotoStmt 1227 LabelDecl *IndirectGotoStmt::getConstantTarget() { 1228 if (auto *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts())) 1229 return E->getLabel(); 1230 return nullptr; 1231 } 1232 1233 // ReturnStmt 1234 ReturnStmt::ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate) 1235 : Stmt(ReturnStmtClass), RetExpr(E) { 1236 bool HasNRVOCandidate = NRVOCandidate != nullptr; 1237 ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate; 1238 if (HasNRVOCandidate) 1239 setNRVOCandidate(NRVOCandidate); 1240 setReturnLoc(RL); 1241 } 1242 1243 ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate) 1244 : Stmt(ReturnStmtClass, Empty) { 1245 ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate; 1246 } 1247 1248 ReturnStmt *ReturnStmt::Create(const ASTContext &Ctx, SourceLocation RL, 1249 Expr *E, const VarDecl *NRVOCandidate) { 1250 bool HasNRVOCandidate = NRVOCandidate != nullptr; 1251 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate), 1252 alignof(ReturnStmt)); 1253 return new (Mem) ReturnStmt(RL, E, NRVOCandidate); 1254 } 1255 1256 ReturnStmt *ReturnStmt::CreateEmpty(const ASTContext &Ctx, 1257 bool HasNRVOCandidate) { 1258 void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate), 1259 alignof(ReturnStmt)); 1260 return new (Mem) ReturnStmt(EmptyShell(), HasNRVOCandidate); 1261 } 1262 1263 // CaseStmt 1264 CaseStmt *CaseStmt::Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs, 1265 SourceLocation caseLoc, SourceLocation ellipsisLoc, 1266 SourceLocation colonLoc) { 1267 bool CaseStmtIsGNURange = rhs != nullptr; 1268 void *Mem = Ctx.Allocate( 1269 totalSizeToAlloc<Stmt *, SourceLocation>( 1270 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange), 1271 alignof(CaseStmt)); 1272 return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc); 1273 } 1274 1275 CaseStmt *CaseStmt::CreateEmpty(const ASTContext &Ctx, 1276 bool CaseStmtIsGNURange) { 1277 void *Mem = Ctx.Allocate( 1278 totalSizeToAlloc<Stmt *, SourceLocation>( 1279 NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange), 1280 alignof(CaseStmt)); 1281 return new (Mem) CaseStmt(EmptyShell(), CaseStmtIsGNURange); 1282 } 1283 1284 SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock, 1285 Stmt *Handler) 1286 : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) { 1287 Children[TRY] = TryBlock; 1288 Children[HANDLER] = Handler; 1289 } 1290 1291 SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry, 1292 SourceLocation TryLoc, Stmt *TryBlock, 1293 Stmt *Handler) { 1294 return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler); 1295 } 1296 1297 SEHExceptStmt* SEHTryStmt::getExceptHandler() const { 1298 return dyn_cast<SEHExceptStmt>(getHandler()); 1299 } 1300 1301 SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const { 1302 return dyn_cast<SEHFinallyStmt>(getHandler()); 1303 } 1304 1305 SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block) 1306 : Stmt(SEHExceptStmtClass), Loc(Loc) { 1307 Children[FILTER_EXPR] = FilterExpr; 1308 Children[BLOCK] = Block; 1309 } 1310 1311 SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc, 1312 Expr *FilterExpr, Stmt *Block) { 1313 return new(C) SEHExceptStmt(Loc,FilterExpr,Block); 1314 } 1315 1316 SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block) 1317 : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {} 1318 1319 SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc, 1320 Stmt *Block) { 1321 return new(C)SEHFinallyStmt(Loc,Block); 1322 } 1323 1324 CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind, 1325 VarDecl *Var) 1326 : VarAndKind(Var, Kind), Loc(Loc) { 1327 switch (Kind) { 1328 case VCK_This: 1329 assert(!Var && "'this' capture cannot have a variable!"); 1330 break; 1331 case VCK_ByRef: 1332 assert(Var && "capturing by reference must have a variable!"); 1333 break; 1334 case VCK_ByCopy: 1335 assert(Var && "capturing by copy must have a variable!"); 1336 break; 1337 case VCK_VLAType: 1338 assert(!Var && 1339 "Variable-length array type capture cannot have a variable!"); 1340 break; 1341 } 1342 } 1343 1344 CapturedStmt::VariableCaptureKind 1345 CapturedStmt::Capture::getCaptureKind() const { 1346 return VarAndKind.getInt(); 1347 } 1348 1349 VarDecl *CapturedStmt::Capture::getCapturedVar() const { 1350 assert((capturesVariable() || capturesVariableByCopy()) && 1351 "No variable available for 'this' or VAT capture"); 1352 return VarAndKind.getPointer(); 1353 } 1354 1355 CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const { 1356 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); 1357 1358 // Offset of the first Capture object. 1359 unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture)); 1360 1361 return reinterpret_cast<Capture *>( 1362 reinterpret_cast<char *>(const_cast<CapturedStmt *>(this)) 1363 + FirstCaptureOffset); 1364 } 1365 1366 CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind, 1367 ArrayRef<Capture> Captures, 1368 ArrayRef<Expr *> CaptureInits, 1369 CapturedDecl *CD, 1370 RecordDecl *RD) 1371 : Stmt(CapturedStmtClass), NumCaptures(Captures.size()), 1372 CapDeclAndKind(CD, Kind), TheRecordDecl(RD) { 1373 assert( S && "null captured statement"); 1374 assert(CD && "null captured declaration for captured statement"); 1375 assert(RD && "null record declaration for captured statement"); 1376 1377 // Copy initialization expressions. 1378 Stmt **Stored = getStoredStmts(); 1379 for (unsigned I = 0, N = NumCaptures; I != N; ++I) 1380 *Stored++ = CaptureInits[I]; 1381 1382 // Copy the statement being captured. 1383 *Stored = S; 1384 1385 // Copy all Capture objects. 1386 Capture *Buffer = getStoredCaptures(); 1387 llvm::copy(Captures, Buffer); 1388 } 1389 1390 CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures) 1391 : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures), 1392 CapDeclAndKind(nullptr, CR_Default) { 1393 getStoredStmts()[NumCaptures] = nullptr; 1394 1395 // Construct default capture objects. 1396 Capture *Buffer = getStoredCaptures(); 1397 for (unsigned I = 0, N = NumCaptures; I != N; ++I) 1398 new (Buffer++) Capture(); 1399 } 1400 1401 CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S, 1402 CapturedRegionKind Kind, 1403 ArrayRef<Capture> Captures, 1404 ArrayRef<Expr *> CaptureInits, 1405 CapturedDecl *CD, 1406 RecordDecl *RD) { 1407 // The layout is 1408 // 1409 // ----------------------------------------------------------- 1410 // | CapturedStmt, Init, ..., Init, S, Capture, ..., Capture | 1411 // ----------------^-------------------^---------------------- 1412 // getStoredStmts() getStoredCaptures() 1413 // 1414 // where S is the statement being captured. 1415 // 1416 assert(CaptureInits.size() == Captures.size() && "wrong number of arguments"); 1417 1418 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1); 1419 if (!Captures.empty()) { 1420 // Realign for the following Capture array. 1421 Size = llvm::alignTo(Size, alignof(Capture)); 1422 Size += sizeof(Capture) * Captures.size(); 1423 } 1424 1425 void *Mem = Context.Allocate(Size); 1426 return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD); 1427 } 1428 1429 CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context, 1430 unsigned NumCaptures) { 1431 unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1); 1432 if (NumCaptures > 0) { 1433 // Realign for the following Capture array. 1434 Size = llvm::alignTo(Size, alignof(Capture)); 1435 Size += sizeof(Capture) * NumCaptures; 1436 } 1437 1438 void *Mem = Context.Allocate(Size); 1439 return new (Mem) CapturedStmt(EmptyShell(), NumCaptures); 1440 } 1441 1442 Stmt::child_range CapturedStmt::children() { 1443 // Children are captured field initializers. 1444 return child_range(getStoredStmts(), getStoredStmts() + NumCaptures); 1445 } 1446 1447 Stmt::const_child_range CapturedStmt::children() const { 1448 return const_child_range(getStoredStmts(), getStoredStmts() + NumCaptures); 1449 } 1450 1451 CapturedDecl *CapturedStmt::getCapturedDecl() { 1452 return CapDeclAndKind.getPointer(); 1453 } 1454 1455 const CapturedDecl *CapturedStmt::getCapturedDecl() const { 1456 return CapDeclAndKind.getPointer(); 1457 } 1458 1459 /// Set the outlined function declaration. 1460 void CapturedStmt::setCapturedDecl(CapturedDecl *D) { 1461 assert(D && "null CapturedDecl"); 1462 CapDeclAndKind.setPointer(D); 1463 } 1464 1465 /// Retrieve the captured region kind. 1466 CapturedRegionKind CapturedStmt::getCapturedRegionKind() const { 1467 return CapDeclAndKind.getInt(); 1468 } 1469 1470 /// Set the captured region kind. 1471 void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) { 1472 CapDeclAndKind.setInt(Kind); 1473 } 1474 1475 bool CapturedStmt::capturesVariable(const VarDecl *Var) const { 1476 for (const auto &I : captures()) { 1477 if (!I.capturesVariable() && !I.capturesVariableByCopy()) 1478 continue; 1479 if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl()) 1480 return true; 1481 } 1482 1483 return false; 1484 } 1485