brintos

brintos / llvm-project-archived public Read only

0
0
Text · 50.4 KiB · 11ece49 Raw
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