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