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