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