10b57cec5SDimitry Andric //===- Stmt.cpp - Statement AST Node Implementation -----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements the Stmt class and statement subclasses.
100b57cec5SDimitry Andric //
110b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "clang/AST/Stmt.h"
140b57cec5SDimitry Andric #include "clang/AST/ASTContext.h"
150b57cec5SDimitry Andric #include "clang/AST/ASTDiagnostic.h"
16e8d8bef9SDimitry Andric #include "clang/AST/Attr.h"
170b57cec5SDimitry Andric #include "clang/AST/Decl.h"
180b57cec5SDimitry Andric #include "clang/AST/DeclGroup.h"
190b57cec5SDimitry Andric #include "clang/AST/Expr.h"
200b57cec5SDimitry Andric #include "clang/AST/ExprCXX.h"
21e8d8bef9SDimitry Andric #include "clang/AST/ExprConcepts.h"
220b57cec5SDimitry Andric #include "clang/AST/ExprObjC.h"
230b57cec5SDimitry Andric #include "clang/AST/ExprOpenMP.h"
240b57cec5SDimitry Andric #include "clang/AST/StmtCXX.h"
250b57cec5SDimitry Andric #include "clang/AST/StmtObjC.h"
260b57cec5SDimitry Andric #include "clang/AST/StmtOpenMP.h"
270b57cec5SDimitry Andric #include "clang/AST/Type.h"
280b57cec5SDimitry Andric #include "clang/Basic/CharInfo.h"
290b57cec5SDimitry Andric #include "clang/Basic/LLVM.h"
300b57cec5SDimitry Andric #include "clang/Basic/SourceLocation.h"
310b57cec5SDimitry Andric #include "clang/Basic/TargetInfo.h"
320b57cec5SDimitry Andric #include "clang/Lex/Token.h"
330b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
340b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
350b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
360b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
370b57cec5SDimitry Andric #include "llvm/Support/Compiler.h"
380b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
390b57cec5SDimitry Andric #include "llvm/Support/MathExtras.h"
400b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
410b57cec5SDimitry Andric #include <algorithm>
420b57cec5SDimitry Andric #include <cassert>
430b57cec5SDimitry Andric #include <cstring>
44bdd1243dSDimitry Andric #include <optional>
450b57cec5SDimitry Andric #include <string>
46a7dea167SDimitry Andric #include <type_traits>
47e8d8bef9SDimitry Andric #include <utility>
480b57cec5SDimitry Andric 
490b57cec5SDimitry Andric using namespace clang;
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric static struct StmtClassNameTable {
520b57cec5SDimitry Andric   const char *Name;
530b57cec5SDimitry Andric   unsigned Counter;
540b57cec5SDimitry Andric   unsigned Size;
550b57cec5SDimitry Andric } StmtClassInfo[Stmt::lastStmtConstant+1];
560b57cec5SDimitry Andric 
getStmtInfoTableEntry(Stmt::StmtClass E)570b57cec5SDimitry Andric static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
580b57cec5SDimitry Andric   static bool Initialized = false;
590b57cec5SDimitry Andric   if (Initialized)
600b57cec5SDimitry Andric     return StmtClassInfo[E];
610b57cec5SDimitry Andric 
620b57cec5SDimitry Andric   // Initialize the table on the first use.
630b57cec5SDimitry Andric   Initialized = true;
640b57cec5SDimitry Andric #define ABSTRACT_STMT(STMT)
650b57cec5SDimitry Andric #define STMT(CLASS, PARENT) \
660b57cec5SDimitry Andric   StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS;    \
670b57cec5SDimitry Andric   StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
680b57cec5SDimitry Andric #include "clang/AST/StmtNodes.inc"
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric   return StmtClassInfo[E];
710b57cec5SDimitry Andric }
720b57cec5SDimitry Andric 
operator new(size_t bytes,const ASTContext & C,unsigned alignment)730b57cec5SDimitry Andric void *Stmt::operator new(size_t bytes, const ASTContext& C,
740b57cec5SDimitry Andric                          unsigned alignment) {
750b57cec5SDimitry Andric   return ::operator new(bytes, C, alignment);
760b57cec5SDimitry Andric }
770b57cec5SDimitry Andric 
getStmtClassName() const780b57cec5SDimitry Andric const char *Stmt::getStmtClassName() const {
790b57cec5SDimitry Andric   return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name;
800b57cec5SDimitry Andric }
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric // Check that no statement / expression class is polymorphic. LLVM style RTTI
830b57cec5SDimitry Andric // should be used instead. If absolutely needed an exception can still be added
840b57cec5SDimitry Andric // here by defining the appropriate macro (but please don't do this).
850b57cec5SDimitry Andric #define STMT(CLASS, PARENT) \
860b57cec5SDimitry Andric   static_assert(!std::is_polymorphic<CLASS>::value, \
870b57cec5SDimitry Andric                 #CLASS " should not be polymorphic!");
880b57cec5SDimitry Andric #include "clang/AST/StmtNodes.inc"
890b57cec5SDimitry Andric 
90a7dea167SDimitry Andric // Check that no statement / expression class has a non-trival destructor.
91a7dea167SDimitry Andric // Statements and expressions are allocated with the BumpPtrAllocator from
92a7dea167SDimitry Andric // ASTContext and therefore their destructor is not executed.
93a7dea167SDimitry Andric #define STMT(CLASS, PARENT)                                                    \
94a7dea167SDimitry Andric   static_assert(std::is_trivially_destructible<CLASS>::value,                  \
95a7dea167SDimitry Andric                 #CLASS " should be trivially destructible!");
96a7dea167SDimitry Andric // FIXME: InitListExpr is not trivially destructible due to its ASTVector.
97a7dea167SDimitry Andric #define INITLISTEXPR(CLASS, PARENT)
98a7dea167SDimitry Andric #include "clang/AST/StmtNodes.inc"
99a7dea167SDimitry Andric 
PrintStats()1000b57cec5SDimitry Andric void Stmt::PrintStats() {
1010b57cec5SDimitry Andric   // Ensure the table is primed.
1020b57cec5SDimitry Andric   getStmtInfoTableEntry(Stmt::NullStmtClass);
1030b57cec5SDimitry Andric 
1040b57cec5SDimitry Andric   unsigned sum = 0;
1050b57cec5SDimitry Andric   llvm::errs() << "\n*** Stmt/Expr Stats:\n";
1060b57cec5SDimitry Andric   for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
1070b57cec5SDimitry Andric     if (StmtClassInfo[i].Name == nullptr) continue;
1080b57cec5SDimitry Andric     sum += StmtClassInfo[i].Counter;
1090b57cec5SDimitry Andric   }
1100b57cec5SDimitry Andric   llvm::errs() << "  " << sum << " stmts/exprs total.\n";
1110b57cec5SDimitry Andric   sum = 0;
1120b57cec5SDimitry Andric   for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
1130b57cec5SDimitry Andric     if (StmtClassInfo[i].Name == nullptr) continue;
1140b57cec5SDimitry Andric     if (StmtClassInfo[i].Counter == 0) continue;
1150b57cec5SDimitry Andric     llvm::errs() << "    " << StmtClassInfo[i].Counter << " "
1160b57cec5SDimitry Andric                  << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size
1170b57cec5SDimitry Andric                  << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size
1180b57cec5SDimitry Andric                  << " bytes)\n";
1190b57cec5SDimitry Andric     sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   llvm::errs() << "Total bytes = " << sum << "\n";
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
addStmtClass(StmtClass s)1250b57cec5SDimitry Andric void Stmt::addStmtClass(StmtClass s) {
1260b57cec5SDimitry Andric   ++getStmtInfoTableEntry(s).Counter;
1270b57cec5SDimitry Andric }
1280b57cec5SDimitry Andric 
1290b57cec5SDimitry Andric bool Stmt::StatisticsEnabled = false;
EnableStatistics()1300b57cec5SDimitry Andric void Stmt::EnableStatistics() {
1310b57cec5SDimitry Andric   StatisticsEnabled = true;
1320b57cec5SDimitry Andric }
1330b57cec5SDimitry Andric 
134e8d8bef9SDimitry Andric static std::pair<Stmt::Likelihood, const Attr *>
getLikelihood(ArrayRef<const Attr * > Attrs)135e8d8bef9SDimitry Andric getLikelihood(ArrayRef<const Attr *> Attrs) {
136e8d8bef9SDimitry Andric   for (const auto *A : Attrs) {
137e8d8bef9SDimitry Andric     if (isa<LikelyAttr>(A))
138e8d8bef9SDimitry Andric       return std::make_pair(Stmt::LH_Likely, A);
139e8d8bef9SDimitry Andric 
140e8d8bef9SDimitry Andric     if (isa<UnlikelyAttr>(A))
141e8d8bef9SDimitry Andric       return std::make_pair(Stmt::LH_Unlikely, A);
142e8d8bef9SDimitry Andric   }
143e8d8bef9SDimitry Andric 
144e8d8bef9SDimitry Andric   return std::make_pair(Stmt::LH_None, nullptr);
145e8d8bef9SDimitry Andric }
146e8d8bef9SDimitry Andric 
getLikelihood(const Stmt * S)147e8d8bef9SDimitry Andric static std::pair<Stmt::Likelihood, const Attr *> getLikelihood(const Stmt *S) {
148e8d8bef9SDimitry Andric   if (const auto *AS = dyn_cast_or_null<AttributedStmt>(S))
149e8d8bef9SDimitry Andric     return getLikelihood(AS->getAttrs());
150e8d8bef9SDimitry Andric 
151e8d8bef9SDimitry Andric   return std::make_pair(Stmt::LH_None, nullptr);
152e8d8bef9SDimitry Andric }
153e8d8bef9SDimitry Andric 
getLikelihood(ArrayRef<const Attr * > Attrs)154e8d8bef9SDimitry Andric Stmt::Likelihood Stmt::getLikelihood(ArrayRef<const Attr *> Attrs) {
155e8d8bef9SDimitry Andric   return ::getLikelihood(Attrs).first;
156e8d8bef9SDimitry Andric }
157e8d8bef9SDimitry Andric 
getLikelihood(const Stmt * S)158e8d8bef9SDimitry Andric Stmt::Likelihood Stmt::getLikelihood(const Stmt *S) {
159e8d8bef9SDimitry Andric   return ::getLikelihood(S).first;
160e8d8bef9SDimitry Andric }
161e8d8bef9SDimitry Andric 
getLikelihoodAttr(const Stmt * S)162e8d8bef9SDimitry Andric const Attr *Stmt::getLikelihoodAttr(const Stmt *S) {
163e8d8bef9SDimitry Andric   return ::getLikelihood(S).second;
164e8d8bef9SDimitry Andric }
165e8d8bef9SDimitry Andric 
getLikelihood(const Stmt * Then,const Stmt * Else)166e8d8bef9SDimitry Andric Stmt::Likelihood Stmt::getLikelihood(const Stmt *Then, const Stmt *Else) {
167e8d8bef9SDimitry Andric   Likelihood LHT = ::getLikelihood(Then).first;
168e8d8bef9SDimitry Andric   Likelihood LHE = ::getLikelihood(Else).first;
169e8d8bef9SDimitry Andric   if (LHE == LH_None)
170e8d8bef9SDimitry Andric     return LHT;
171e8d8bef9SDimitry Andric 
172e8d8bef9SDimitry Andric   // If the same attribute is used on both branches there's a conflict.
173e8d8bef9SDimitry Andric   if (LHT == LHE)
174e8d8bef9SDimitry Andric     return LH_None;
175e8d8bef9SDimitry Andric 
176e8d8bef9SDimitry Andric   if (LHT != LH_None)
177e8d8bef9SDimitry Andric     return LHT;
178e8d8bef9SDimitry Andric 
179e8d8bef9SDimitry Andric   // Invert the value of Else to get the value for Then.
180e8d8bef9SDimitry Andric   return LHE == LH_Likely ? LH_Unlikely : LH_Likely;
181e8d8bef9SDimitry Andric }
182e8d8bef9SDimitry Andric 
183e8d8bef9SDimitry Andric std::tuple<bool, const Attr *, const Attr *>
determineLikelihoodConflict(const Stmt * Then,const Stmt * Else)184e8d8bef9SDimitry Andric Stmt::determineLikelihoodConflict(const Stmt *Then, const Stmt *Else) {
185e8d8bef9SDimitry Andric   std::pair<Likelihood, const Attr *> LHT = ::getLikelihood(Then);
186e8d8bef9SDimitry Andric   std::pair<Likelihood, const Attr *> LHE = ::getLikelihood(Else);
187e8d8bef9SDimitry Andric   // If the same attribute is used on both branches there's a conflict.
188e8d8bef9SDimitry Andric   if (LHT.first != LH_None && LHT.first == LHE.first)
189e8d8bef9SDimitry Andric     return std::make_tuple(true, LHT.second, LHE.second);
190e8d8bef9SDimitry Andric 
191e8d8bef9SDimitry Andric   return std::make_tuple(false, nullptr, nullptr);
192e8d8bef9SDimitry Andric }
193e8d8bef9SDimitry Andric 
1940b57cec5SDimitry Andric /// Skip no-op (attributed, compound) container stmts and skip captured
1950b57cec5SDimitry Andric /// stmt at the top, if \a IgnoreCaptured is true.
IgnoreContainers(bool IgnoreCaptured)1960b57cec5SDimitry Andric Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) {
1970b57cec5SDimitry Andric   Stmt *S = this;
1980b57cec5SDimitry Andric   if (IgnoreCaptured)
1990b57cec5SDimitry Andric     if (auto CapS = dyn_cast_or_null<CapturedStmt>(S))
2000b57cec5SDimitry Andric       S = CapS->getCapturedStmt();
2010b57cec5SDimitry Andric   while (true) {
2020b57cec5SDimitry Andric     if (auto AS = dyn_cast_or_null<AttributedStmt>(S))
2030b57cec5SDimitry Andric       S = AS->getSubStmt();
2040b57cec5SDimitry Andric     else if (auto CS = dyn_cast_or_null<CompoundStmt>(S)) {
2050b57cec5SDimitry Andric       if (CS->size() != 1)
2060b57cec5SDimitry Andric         break;
2070b57cec5SDimitry Andric       S = CS->body_back();
2080b57cec5SDimitry Andric     } else
2090b57cec5SDimitry Andric       break;
2100b57cec5SDimitry Andric   }
2110b57cec5SDimitry Andric   return S;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
2140b57cec5SDimitry Andric /// Strip off all label-like statements.
2150b57cec5SDimitry Andric ///
2160b57cec5SDimitry Andric /// This will strip off label statements, case statements, attributed
2170b57cec5SDimitry Andric /// statements and default statements recursively.
stripLabelLikeStatements() const2180b57cec5SDimitry Andric const Stmt *Stmt::stripLabelLikeStatements() const {
2190b57cec5SDimitry Andric   const Stmt *S = this;
2200b57cec5SDimitry Andric   while (true) {
2210b57cec5SDimitry Andric     if (const auto *LS = dyn_cast<LabelStmt>(S))
2220b57cec5SDimitry Andric       S = LS->getSubStmt();
2230b57cec5SDimitry Andric     else if (const auto *SC = dyn_cast<SwitchCase>(S))
2240b57cec5SDimitry Andric       S = SC->getSubStmt();
2250b57cec5SDimitry Andric     else if (const auto *AS = dyn_cast<AttributedStmt>(S))
2260b57cec5SDimitry Andric       S = AS->getSubStmt();
2270b57cec5SDimitry Andric     else
2280b57cec5SDimitry Andric       return S;
2290b57cec5SDimitry Andric   }
2300b57cec5SDimitry Andric }
2310b57cec5SDimitry Andric 
2320b57cec5SDimitry Andric namespace {
2330b57cec5SDimitry Andric 
2340b57cec5SDimitry Andric   struct good {};
2350b57cec5SDimitry Andric   struct bad {};
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric   // These silly little functions have to be static inline to suppress
2380b57cec5SDimitry Andric   // unused warnings, and they have to be defined to suppress other
2390b57cec5SDimitry Andric   // warnings.
is_good(good)2400b57cec5SDimitry Andric   static good is_good(good) { return good(); }
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric   typedef Stmt::child_range children_t();
implements_children(children_t T::*)2430b57cec5SDimitry Andric   template <class T> good implements_children(children_t T::*) {
2440b57cec5SDimitry Andric     return good();
2450b57cec5SDimitry Andric   }
2460b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
implements_children(children_t Stmt::*)2470b57cec5SDimitry Andric   static bad implements_children(children_t Stmt::*) {
2480b57cec5SDimitry Andric     return bad();
2490b57cec5SDimitry Andric   }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   typedef SourceLocation getBeginLoc_t() const;
implements_getBeginLoc(getBeginLoc_t T::*)2520b57cec5SDimitry Andric   template <class T> good implements_getBeginLoc(getBeginLoc_t T::*) {
2530b57cec5SDimitry Andric     return good();
2540b57cec5SDimitry Andric   }
2550b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
implements_getBeginLoc(getBeginLoc_t Stmt::*)2560b57cec5SDimitry Andric   static bad implements_getBeginLoc(getBeginLoc_t Stmt::*) { return bad(); }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   typedef SourceLocation getLocEnd_t() const;
implements_getEndLoc(getLocEnd_t T::*)2590b57cec5SDimitry Andric   template <class T> good implements_getEndLoc(getLocEnd_t T::*) {
2600b57cec5SDimitry Andric     return good();
2610b57cec5SDimitry Andric   }
2620b57cec5SDimitry Andric   LLVM_ATTRIBUTE_UNUSED
implements_getEndLoc(getLocEnd_t Stmt::*)2630b57cec5SDimitry Andric   static bad implements_getEndLoc(getLocEnd_t Stmt::*) { return bad(); }
2640b57cec5SDimitry Andric 
2650b57cec5SDimitry Andric #define ASSERT_IMPLEMENTS_children(type) \
2660b57cec5SDimitry Andric   (void) is_good(implements_children(&type::children))
2670b57cec5SDimitry Andric #define ASSERT_IMPLEMENTS_getBeginLoc(type)                                    \
2680b57cec5SDimitry Andric   (void)is_good(implements_getBeginLoc(&type::getBeginLoc))
2690b57cec5SDimitry Andric #define ASSERT_IMPLEMENTS_getEndLoc(type)                                      \
2700b57cec5SDimitry Andric   (void)is_good(implements_getEndLoc(&type::getEndLoc))
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric } // namespace
2730b57cec5SDimitry Andric 
2740b57cec5SDimitry Andric /// Check whether the various Stmt classes implement their member
2750b57cec5SDimitry Andric /// functions.
2760b57cec5SDimitry Andric LLVM_ATTRIBUTE_UNUSED
check_implementations()2770b57cec5SDimitry Andric static inline void check_implementations() {
2780b57cec5SDimitry Andric #define ABSTRACT_STMT(type)
2790b57cec5SDimitry Andric #define STMT(type, base)                                                       \
2800b57cec5SDimitry Andric   ASSERT_IMPLEMENTS_children(type);                                            \
2810b57cec5SDimitry Andric   ASSERT_IMPLEMENTS_getBeginLoc(type);                                         \
2820b57cec5SDimitry Andric   ASSERT_IMPLEMENTS_getEndLoc(type);
2830b57cec5SDimitry Andric #include "clang/AST/StmtNodes.inc"
2840b57cec5SDimitry Andric }
2850b57cec5SDimitry Andric 
children()2860b57cec5SDimitry Andric Stmt::child_range Stmt::children() {
2870b57cec5SDimitry Andric   switch (getStmtClass()) {
2880b57cec5SDimitry Andric   case Stmt::NoStmtClass: llvm_unreachable("statement without class");
2890b57cec5SDimitry Andric #define ABSTRACT_STMT(type)
2900b57cec5SDimitry Andric #define STMT(type, base) \
2910b57cec5SDimitry Andric   case Stmt::type##Class: \
2920b57cec5SDimitry Andric     return static_cast<type*>(this)->children();
2930b57cec5SDimitry Andric #include "clang/AST/StmtNodes.inc"
2940b57cec5SDimitry Andric   }
2950b57cec5SDimitry Andric   llvm_unreachable("unknown statement kind!");
2960b57cec5SDimitry Andric }
2970b57cec5SDimitry Andric 
2980b57cec5SDimitry Andric // Amusing macro metaprogramming hack: check whether a class provides
2990b57cec5SDimitry Andric // a more specific implementation of getSourceRange.
3000b57cec5SDimitry Andric //
3010b57cec5SDimitry Andric // See also Expr.cpp:getExprLoc().
3020b57cec5SDimitry Andric namespace {
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric   /// This implementation is used when a class provides a custom
3050b57cec5SDimitry Andric   /// implementation of getSourceRange.
3060b57cec5SDimitry Andric   template <class S, class T>
getSourceRangeImpl(const Stmt * stmt,SourceRange (T::* v)()const)3070b57cec5SDimitry Andric   SourceRange getSourceRangeImpl(const Stmt *stmt,
3080b57cec5SDimitry Andric                                  SourceRange (T::*v)() const) {
3090b57cec5SDimitry Andric     return static_cast<const S*>(stmt)->getSourceRange();
3100b57cec5SDimitry Andric   }
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   /// This implementation is used when a class doesn't provide a custom
3130b57cec5SDimitry Andric   /// implementation of getSourceRange.  Overload resolution should pick it over
3140b57cec5SDimitry Andric   /// the implementation above because it's more specialized according to
3150b57cec5SDimitry Andric   /// function template partial ordering.
3160b57cec5SDimitry Andric   template <class S>
getSourceRangeImpl(const Stmt * stmt,SourceRange (Stmt::* v)()const)3170b57cec5SDimitry Andric   SourceRange getSourceRangeImpl(const Stmt *stmt,
3180b57cec5SDimitry Andric                                  SourceRange (Stmt::*v)() const) {
3190b57cec5SDimitry Andric     return SourceRange(static_cast<const S *>(stmt)->getBeginLoc(),
3200b57cec5SDimitry Andric                        static_cast<const S *>(stmt)->getEndLoc());
3210b57cec5SDimitry Andric   }
3220b57cec5SDimitry Andric 
3230b57cec5SDimitry Andric } // namespace
3240b57cec5SDimitry Andric 
getSourceRange() const3250b57cec5SDimitry Andric SourceRange Stmt::getSourceRange() const {
3260b57cec5SDimitry Andric   switch (getStmtClass()) {
3270b57cec5SDimitry Andric   case Stmt::NoStmtClass: llvm_unreachable("statement without class");
3280b57cec5SDimitry Andric #define ABSTRACT_STMT(type)
3290b57cec5SDimitry Andric #define STMT(type, base) \
3300b57cec5SDimitry Andric   case Stmt::type##Class: \
3310b57cec5SDimitry Andric     return getSourceRangeImpl<type>(this, &type::getSourceRange);
3320b57cec5SDimitry Andric #include "clang/AST/StmtNodes.inc"
3330b57cec5SDimitry Andric   }
3340b57cec5SDimitry Andric   llvm_unreachable("unknown statement kind!");
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric 
getBeginLoc() const3370b57cec5SDimitry Andric SourceLocation Stmt::getBeginLoc() const {
3380b57cec5SDimitry Andric   switch (getStmtClass()) {
3390b57cec5SDimitry Andric   case Stmt::NoStmtClass: llvm_unreachable("statement without class");
3400b57cec5SDimitry Andric #define ABSTRACT_STMT(type)
3410b57cec5SDimitry Andric #define STMT(type, base)                                                       \
3420b57cec5SDimitry Andric   case Stmt::type##Class:                                                      \
3430b57cec5SDimitry Andric     return static_cast<const type *>(this)->getBeginLoc();
3440b57cec5SDimitry Andric #include "clang/AST/StmtNodes.inc"
3450b57cec5SDimitry Andric   }
3460b57cec5SDimitry Andric   llvm_unreachable("unknown statement kind");
3470b57cec5SDimitry Andric }
3480b57cec5SDimitry Andric 
getEndLoc() const3490b57cec5SDimitry Andric SourceLocation Stmt::getEndLoc() const {
3500b57cec5SDimitry Andric   switch (getStmtClass()) {
3510b57cec5SDimitry Andric   case Stmt::NoStmtClass: llvm_unreachable("statement without class");
3520b57cec5SDimitry Andric #define ABSTRACT_STMT(type)
3530b57cec5SDimitry Andric #define STMT(type, base)                                                       \
3540b57cec5SDimitry Andric   case Stmt::type##Class:                                                      \
3550b57cec5SDimitry Andric     return static_cast<const type *>(this)->getEndLoc();
3560b57cec5SDimitry Andric #include "clang/AST/StmtNodes.inc"
3570b57cec5SDimitry Andric   }
3580b57cec5SDimitry Andric   llvm_unreachable("unknown statement kind");
3590b57cec5SDimitry Andric }
3600b57cec5SDimitry Andric 
getID(const ASTContext & Context) const3610b57cec5SDimitry Andric int64_t Stmt::getID(const ASTContext &Context) const {
3620b57cec5SDimitry Andric   return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this);
3630b57cec5SDimitry Andric }
3640b57cec5SDimitry Andric 
CompoundStmt(ArrayRef<Stmt * > Stmts,FPOptionsOverride FPFeatures,SourceLocation LB,SourceLocation RB)36581ad6265SDimitry Andric CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, FPOptionsOverride FPFeatures,
36681ad6265SDimitry Andric                            SourceLocation LB, SourceLocation RB)
36781ad6265SDimitry Andric     : Stmt(CompoundStmtClass), LBraceLoc(LB), RBraceLoc(RB) {
3680b57cec5SDimitry Andric   CompoundStmtBits.NumStmts = Stmts.size();
36981ad6265SDimitry Andric   CompoundStmtBits.HasFPFeatures = FPFeatures.requiresTrailingStorage();
3700b57cec5SDimitry Andric   setStmts(Stmts);
37181ad6265SDimitry Andric   if (hasStoredFPFeatures())
37281ad6265SDimitry Andric     setStoredFPFeatures(FPFeatures);
3730b57cec5SDimitry Andric }
3740b57cec5SDimitry Andric 
setStmts(ArrayRef<Stmt * > Stmts)3750b57cec5SDimitry Andric void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) {
3760b57cec5SDimitry Andric   assert(CompoundStmtBits.NumStmts == Stmts.size() &&
3770b57cec5SDimitry Andric          "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
3780b57cec5SDimitry Andric 
3790b57cec5SDimitry Andric   std::copy(Stmts.begin(), Stmts.end(), body_begin());
3800b57cec5SDimitry Andric }
3810b57cec5SDimitry Andric 
Create(const ASTContext & C,ArrayRef<Stmt * > Stmts,FPOptionsOverride FPFeatures,SourceLocation LB,SourceLocation RB)3820b57cec5SDimitry Andric CompoundStmt *CompoundStmt::Create(const ASTContext &C, ArrayRef<Stmt *> Stmts,
38381ad6265SDimitry Andric                                    FPOptionsOverride FPFeatures,
3840b57cec5SDimitry Andric                                    SourceLocation LB, SourceLocation RB) {
3850b57cec5SDimitry Andric   void *Mem =
38681ad6265SDimitry Andric       C.Allocate(totalSizeToAlloc<Stmt *, FPOptionsOverride>(
38781ad6265SDimitry Andric                      Stmts.size(), FPFeatures.requiresTrailingStorage()),
38881ad6265SDimitry Andric                  alignof(CompoundStmt));
38981ad6265SDimitry Andric   return new (Mem) CompoundStmt(Stmts, FPFeatures, LB, RB);
3900b57cec5SDimitry Andric }
3910b57cec5SDimitry Andric 
CreateEmpty(const ASTContext & C,unsigned NumStmts,bool HasFPFeatures)39281ad6265SDimitry Andric CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C, unsigned NumStmts,
39381ad6265SDimitry Andric                                         bool HasFPFeatures) {
39481ad6265SDimitry Andric   void *Mem = C.Allocate(
39581ad6265SDimitry Andric       totalSizeToAlloc<Stmt *, FPOptionsOverride>(NumStmts, HasFPFeatures),
39681ad6265SDimitry Andric       alignof(CompoundStmt));
3970b57cec5SDimitry Andric   CompoundStmt *New = new (Mem) CompoundStmt(EmptyShell());
3980b57cec5SDimitry Andric   New->CompoundStmtBits.NumStmts = NumStmts;
39981ad6265SDimitry Andric   New->CompoundStmtBits.HasFPFeatures = HasFPFeatures;
4000b57cec5SDimitry Andric   return New;
4010b57cec5SDimitry Andric }
4020b57cec5SDimitry Andric 
getExprStmt() const4030b57cec5SDimitry Andric const Expr *ValueStmt::getExprStmt() const {
4040b57cec5SDimitry Andric   const Stmt *S = this;
4050b57cec5SDimitry Andric   do {
4060b57cec5SDimitry Andric     if (const auto *E = dyn_cast<Expr>(S))
4070b57cec5SDimitry Andric       return E;
4080b57cec5SDimitry Andric 
4090b57cec5SDimitry Andric     if (const auto *LS = dyn_cast<LabelStmt>(S))
4100b57cec5SDimitry Andric       S = LS->getSubStmt();
4110b57cec5SDimitry Andric     else if (const auto *AS = dyn_cast<AttributedStmt>(S))
4120b57cec5SDimitry Andric       S = AS->getSubStmt();
4130b57cec5SDimitry Andric     else
4140b57cec5SDimitry Andric       llvm_unreachable("unknown kind of ValueStmt");
4150b57cec5SDimitry Andric   } while (isa<ValueStmt>(S));
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   return nullptr;
4180b57cec5SDimitry Andric }
4190b57cec5SDimitry Andric 
getName() const4200b57cec5SDimitry Andric const char *LabelStmt::getName() const {
4210b57cec5SDimitry Andric   return getDecl()->getIdentifier()->getNameStart();
4220b57cec5SDimitry Andric }
4230b57cec5SDimitry Andric 
Create(const ASTContext & C,SourceLocation Loc,ArrayRef<const Attr * > Attrs,Stmt * SubStmt)4240b57cec5SDimitry Andric AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc,
4250b57cec5SDimitry Andric                                        ArrayRef<const Attr*> Attrs,
4260b57cec5SDimitry Andric                                        Stmt *SubStmt) {
4270b57cec5SDimitry Andric   assert(!Attrs.empty() && "Attrs should not be empty");
4280b57cec5SDimitry Andric   void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(Attrs.size()),
4290b57cec5SDimitry Andric                          alignof(AttributedStmt));
4300b57cec5SDimitry Andric   return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
4310b57cec5SDimitry Andric }
4320b57cec5SDimitry Andric 
CreateEmpty(const ASTContext & C,unsigned NumAttrs)4330b57cec5SDimitry Andric AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C,
4340b57cec5SDimitry Andric                                             unsigned NumAttrs) {
4350b57cec5SDimitry Andric   assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
4360b57cec5SDimitry Andric   void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(NumAttrs),
4370b57cec5SDimitry Andric                          alignof(AttributedStmt));
4380b57cec5SDimitry Andric   return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
4390b57cec5SDimitry Andric }
4400b57cec5SDimitry Andric 
generateAsmString(const ASTContext & C) const4410b57cec5SDimitry Andric std::string AsmStmt::generateAsmString(const ASTContext &C) const {
4420b57cec5SDimitry Andric   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
4430b57cec5SDimitry Andric     return gccAsmStmt->generateAsmString(C);
4440b57cec5SDimitry Andric   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
4450b57cec5SDimitry Andric     return msAsmStmt->generateAsmString(C);
4460b57cec5SDimitry Andric   llvm_unreachable("unknown asm statement kind!");
4470b57cec5SDimitry Andric }
4480b57cec5SDimitry Andric 
getOutputConstraint(unsigned i) const4490b57cec5SDimitry Andric StringRef AsmStmt::getOutputConstraint(unsigned i) const {
4500b57cec5SDimitry Andric   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
4510b57cec5SDimitry Andric     return gccAsmStmt->getOutputConstraint(i);
4520b57cec5SDimitry Andric   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
4530b57cec5SDimitry Andric     return msAsmStmt->getOutputConstraint(i);
4540b57cec5SDimitry Andric   llvm_unreachable("unknown asm statement kind!");
4550b57cec5SDimitry Andric }
4560b57cec5SDimitry Andric 
getOutputExpr(unsigned i) const4570b57cec5SDimitry Andric const Expr *AsmStmt::getOutputExpr(unsigned i) const {
4580b57cec5SDimitry Andric   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
4590b57cec5SDimitry Andric     return gccAsmStmt->getOutputExpr(i);
4600b57cec5SDimitry Andric   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
4610b57cec5SDimitry Andric     return msAsmStmt->getOutputExpr(i);
4620b57cec5SDimitry Andric   llvm_unreachable("unknown asm statement kind!");
4630b57cec5SDimitry Andric }
4640b57cec5SDimitry Andric 
getInputConstraint(unsigned i) const4650b57cec5SDimitry Andric StringRef AsmStmt::getInputConstraint(unsigned i) const {
4660b57cec5SDimitry Andric   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
4670b57cec5SDimitry Andric     return gccAsmStmt->getInputConstraint(i);
4680b57cec5SDimitry Andric   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
4690b57cec5SDimitry Andric     return msAsmStmt->getInputConstraint(i);
4700b57cec5SDimitry Andric   llvm_unreachable("unknown asm statement kind!");
4710b57cec5SDimitry Andric }
4720b57cec5SDimitry Andric 
getInputExpr(unsigned i) const4730b57cec5SDimitry Andric const Expr *AsmStmt::getInputExpr(unsigned i) const {
4740b57cec5SDimitry Andric   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
4750b57cec5SDimitry Andric     return gccAsmStmt->getInputExpr(i);
4760b57cec5SDimitry Andric   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
4770b57cec5SDimitry Andric     return msAsmStmt->getInputExpr(i);
4780b57cec5SDimitry Andric   llvm_unreachable("unknown asm statement kind!");
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric 
getClobber(unsigned i) const4810b57cec5SDimitry Andric StringRef AsmStmt::getClobber(unsigned i) const {
4820b57cec5SDimitry Andric   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
4830b57cec5SDimitry Andric     return gccAsmStmt->getClobber(i);
4840b57cec5SDimitry Andric   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
4850b57cec5SDimitry Andric     return msAsmStmt->getClobber(i);
4860b57cec5SDimitry Andric   llvm_unreachable("unknown asm statement kind!");
4870b57cec5SDimitry Andric }
4880b57cec5SDimitry Andric 
4890b57cec5SDimitry Andric /// getNumPlusOperands - Return the number of output operands that have a "+"
4900b57cec5SDimitry Andric /// constraint.
getNumPlusOperands() const4910b57cec5SDimitry Andric unsigned AsmStmt::getNumPlusOperands() const {
4920b57cec5SDimitry Andric   unsigned Res = 0;
4930b57cec5SDimitry Andric   for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)
4940b57cec5SDimitry Andric     if (isOutputPlusConstraint(i))
4950b57cec5SDimitry Andric       ++Res;
4960b57cec5SDimitry Andric   return Res;
4970b57cec5SDimitry Andric }
4980b57cec5SDimitry Andric 
getModifier() const4990b57cec5SDimitry Andric char GCCAsmStmt::AsmStringPiece::getModifier() const {
5000b57cec5SDimitry Andric   assert(isOperand() && "Only Operands can have modifiers.");
5010b57cec5SDimitry Andric   return isLetter(Str[0]) ? Str[0] : '\0';
5020b57cec5SDimitry Andric }
5030b57cec5SDimitry Andric 
getClobber(unsigned i) const5040b57cec5SDimitry Andric StringRef GCCAsmStmt::getClobber(unsigned i) const {
5050b57cec5SDimitry Andric   return getClobberStringLiteral(i)->getString();
5060b57cec5SDimitry Andric }
5070b57cec5SDimitry Andric 
getOutputExpr(unsigned i)5080b57cec5SDimitry Andric Expr *GCCAsmStmt::getOutputExpr(unsigned i) {
5090b57cec5SDimitry Andric   return cast<Expr>(Exprs[i]);
5100b57cec5SDimitry Andric }
5110b57cec5SDimitry Andric 
5120b57cec5SDimitry Andric /// getOutputConstraint - Return the constraint string for the specified
5130b57cec5SDimitry Andric /// output operand.  All output constraints are known to be non-empty (either
5140b57cec5SDimitry Andric /// '=' or '+').
getOutputConstraint(unsigned i) const5150b57cec5SDimitry Andric StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const {
5160b57cec5SDimitry Andric   return getOutputConstraintLiteral(i)->getString();
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric 
getInputExpr(unsigned i)5190b57cec5SDimitry Andric Expr *GCCAsmStmt::getInputExpr(unsigned i) {
5200b57cec5SDimitry Andric   return cast<Expr>(Exprs[i + NumOutputs]);
5210b57cec5SDimitry Andric }
5220b57cec5SDimitry Andric 
setInputExpr(unsigned i,Expr * E)5230b57cec5SDimitry Andric void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) {
5240b57cec5SDimitry Andric   Exprs[i + NumOutputs] = E;
5250b57cec5SDimitry Andric }
5260b57cec5SDimitry Andric 
getLabelExpr(unsigned i) const5270b57cec5SDimitry Andric AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const {
5285ffd83dbSDimitry Andric   return cast<AddrLabelExpr>(Exprs[i + NumOutputs + NumInputs]);
5290b57cec5SDimitry Andric }
5300b57cec5SDimitry Andric 
getLabelName(unsigned i) const5310b57cec5SDimitry Andric StringRef GCCAsmStmt::getLabelName(unsigned i) const {
5320b57cec5SDimitry Andric   return getLabelExpr(i)->getLabel()->getName();
5330b57cec5SDimitry Andric }
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric /// getInputConstraint - Return the specified input constraint.  Unlike output
5360b57cec5SDimitry Andric /// constraints, these can be empty.
getInputConstraint(unsigned i) const5370b57cec5SDimitry Andric StringRef GCCAsmStmt::getInputConstraint(unsigned i) const {
5380b57cec5SDimitry Andric   return getInputConstraintLiteral(i)->getString();
5390b57cec5SDimitry Andric }
5400b57cec5SDimitry Andric 
setOutputsAndInputsAndClobbers(const ASTContext & C,IdentifierInfo ** Names,StringLiteral ** Constraints,Stmt ** Exprs,unsigned NumOutputs,unsigned NumInputs,unsigned NumLabels,StringLiteral ** Clobbers,unsigned NumClobbers)5410b57cec5SDimitry Andric void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C,
5420b57cec5SDimitry Andric                                                 IdentifierInfo **Names,
5430b57cec5SDimitry Andric                                                 StringLiteral **Constraints,
5440b57cec5SDimitry Andric                                                 Stmt **Exprs,
5450b57cec5SDimitry Andric                                                 unsigned NumOutputs,
5460b57cec5SDimitry Andric                                                 unsigned NumInputs,
5470b57cec5SDimitry Andric                                                 unsigned NumLabels,
5480b57cec5SDimitry Andric                                                 StringLiteral **Clobbers,
5490b57cec5SDimitry Andric                                                 unsigned NumClobbers) {
5500b57cec5SDimitry Andric   this->NumOutputs = NumOutputs;
5510b57cec5SDimitry Andric   this->NumInputs = NumInputs;
5520b57cec5SDimitry Andric   this->NumClobbers = NumClobbers;
5530b57cec5SDimitry Andric   this->NumLabels = NumLabels;
5540b57cec5SDimitry Andric 
5550b57cec5SDimitry Andric   unsigned NumExprs = NumOutputs + NumInputs + NumLabels;
5560b57cec5SDimitry Andric 
5570b57cec5SDimitry Andric   C.Deallocate(this->Names);
5580b57cec5SDimitry Andric   this->Names = new (C) IdentifierInfo*[NumExprs];
5590b57cec5SDimitry Andric   std::copy(Names, Names + NumExprs, this->Names);
5600b57cec5SDimitry Andric 
5610b57cec5SDimitry Andric   C.Deallocate(this->Exprs);
5620b57cec5SDimitry Andric   this->Exprs = new (C) Stmt*[NumExprs];
5630b57cec5SDimitry Andric   std::copy(Exprs, Exprs + NumExprs, this->Exprs);
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric   unsigned NumConstraints = NumOutputs + NumInputs;
5660b57cec5SDimitry Andric   C.Deallocate(this->Constraints);
5670b57cec5SDimitry Andric   this->Constraints = new (C) StringLiteral*[NumConstraints];
5680b57cec5SDimitry Andric   std::copy(Constraints, Constraints + NumConstraints, this->Constraints);
5690b57cec5SDimitry Andric 
5700b57cec5SDimitry Andric   C.Deallocate(this->Clobbers);
5710b57cec5SDimitry Andric   this->Clobbers = new (C) StringLiteral*[NumClobbers];
5720b57cec5SDimitry Andric   std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers);
5730b57cec5SDimitry Andric }
5740b57cec5SDimitry Andric 
5750b57cec5SDimitry Andric /// getNamedOperand - Given a symbolic operand reference like %[foo],
5760b57cec5SDimitry Andric /// translate this into a numeric value needed to reference the same operand.
5770b57cec5SDimitry Andric /// This returns -1 if the operand name is invalid.
getNamedOperand(StringRef SymbolicName) const5780b57cec5SDimitry Andric int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const {
5790b57cec5SDimitry Andric   // Check if this is an output operand.
58004eeddc0SDimitry Andric   unsigned NumOutputs = getNumOutputs();
58104eeddc0SDimitry Andric   for (unsigned i = 0; i != NumOutputs; ++i)
5820b57cec5SDimitry Andric     if (getOutputName(i) == SymbolicName)
5830b57cec5SDimitry Andric       return i;
5840b57cec5SDimitry Andric 
58504eeddc0SDimitry Andric   unsigned NumInputs = getNumInputs();
58604eeddc0SDimitry Andric   for (unsigned i = 0; i != NumInputs; ++i)
5870b57cec5SDimitry Andric     if (getInputName(i) == SymbolicName)
58804eeddc0SDimitry Andric       return NumOutputs + i;
5890b57cec5SDimitry Andric 
5900b57cec5SDimitry Andric   for (unsigned i = 0, e = getNumLabels(); i != e; ++i)
5910b57cec5SDimitry Andric     if (getLabelName(i) == SymbolicName)
59204eeddc0SDimitry Andric       return NumOutputs + NumInputs + getNumPlusOperands() + i;
5930b57cec5SDimitry Andric 
5940b57cec5SDimitry Andric   // Not found.
5950b57cec5SDimitry Andric   return -1;
5960b57cec5SDimitry Andric }
5970b57cec5SDimitry Andric 
5980b57cec5SDimitry Andric /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
5990b57cec5SDimitry Andric /// it into pieces.  If the asm string is erroneous, emit errors and return
6000b57cec5SDimitry Andric /// true, otherwise return false.
AnalyzeAsmString(SmallVectorImpl<AsmStringPiece> & Pieces,const ASTContext & C,unsigned & DiagOffs) const6010b57cec5SDimitry Andric unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
6020b57cec5SDimitry Andric                                 const ASTContext &C, unsigned &DiagOffs) const {
6030b57cec5SDimitry Andric   StringRef Str = getAsmString()->getString();
6040b57cec5SDimitry Andric   const char *StrStart = Str.begin();
6050b57cec5SDimitry Andric   const char *StrEnd = Str.end();
6060b57cec5SDimitry Andric   const char *CurPtr = StrStart;
6070b57cec5SDimitry Andric 
6080b57cec5SDimitry Andric   // "Simple" inline asms have no constraints or operands, just convert the asm
6090b57cec5SDimitry Andric   // string to escape $'s.
6100b57cec5SDimitry Andric   if (isSimple()) {
6110b57cec5SDimitry Andric     std::string Result;
6120b57cec5SDimitry Andric     for (; CurPtr != StrEnd; ++CurPtr) {
6130b57cec5SDimitry Andric       switch (*CurPtr) {
6140b57cec5SDimitry Andric       case '$':
6150b57cec5SDimitry Andric         Result += "$$";
6160b57cec5SDimitry Andric         break;
6170b57cec5SDimitry Andric       default:
6180b57cec5SDimitry Andric         Result += *CurPtr;
6190b57cec5SDimitry Andric         break;
6200b57cec5SDimitry Andric       }
6210b57cec5SDimitry Andric     }
6220b57cec5SDimitry Andric     Pieces.push_back(AsmStringPiece(Result));
6230b57cec5SDimitry Andric     return 0;
6240b57cec5SDimitry Andric   }
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   // CurStringPiece - The current string that we are building up as we scan the
6270b57cec5SDimitry Andric   // asm string.
6280b57cec5SDimitry Andric   std::string CurStringPiece;
6290b57cec5SDimitry Andric 
6300b57cec5SDimitry Andric   bool HasVariants = !C.getTargetInfo().hasNoAsmVariants();
6310b57cec5SDimitry Andric 
6320b57cec5SDimitry Andric   unsigned LastAsmStringToken = 0;
6330b57cec5SDimitry Andric   unsigned LastAsmStringOffset = 0;
6340b57cec5SDimitry Andric 
6350b57cec5SDimitry Andric   while (true) {
6360b57cec5SDimitry Andric     // Done with the string?
6370b57cec5SDimitry Andric     if (CurPtr == StrEnd) {
6380b57cec5SDimitry Andric       if (!CurStringPiece.empty())
6390b57cec5SDimitry Andric         Pieces.push_back(AsmStringPiece(CurStringPiece));
6400b57cec5SDimitry Andric       return 0;
6410b57cec5SDimitry Andric     }
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric     char CurChar = *CurPtr++;
6440b57cec5SDimitry Andric     switch (CurChar) {
6450b57cec5SDimitry Andric     case '$': CurStringPiece += "$$"; continue;
6460b57cec5SDimitry Andric     case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue;
6470b57cec5SDimitry Andric     case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue;
6480b57cec5SDimitry Andric     case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue;
6490b57cec5SDimitry Andric     case '%':
6500b57cec5SDimitry Andric       break;
6510b57cec5SDimitry Andric     default:
6520b57cec5SDimitry Andric       CurStringPiece += CurChar;
6530b57cec5SDimitry Andric       continue;
6540b57cec5SDimitry Andric     }
6550b57cec5SDimitry Andric 
656fe6060f1SDimitry Andric     const TargetInfo &TI = C.getTargetInfo();
657fe6060f1SDimitry Andric 
6580b57cec5SDimitry Andric     // Escaped "%" character in asm string.
6590b57cec5SDimitry Andric     if (CurPtr == StrEnd) {
6600b57cec5SDimitry Andric       // % at end of string is invalid (no escape).
6610b57cec5SDimitry Andric       DiagOffs = CurPtr-StrStart-1;
6620b57cec5SDimitry Andric       return diag::err_asm_invalid_escape;
6630b57cec5SDimitry Andric     }
6640b57cec5SDimitry Andric     // Handle escaped char and continue looping over the asm string.
6650b57cec5SDimitry Andric     char EscapedChar = *CurPtr++;
6660b57cec5SDimitry Andric     switch (EscapedChar) {
6670b57cec5SDimitry Andric     default:
668fe6060f1SDimitry Andric       // Handle target-specific escaped characters.
669fe6060f1SDimitry Andric       if (auto MaybeReplaceStr = TI.handleAsmEscapedChar(EscapedChar)) {
670fe6060f1SDimitry Andric         CurStringPiece += *MaybeReplaceStr;
671fe6060f1SDimitry Andric         continue;
672fe6060f1SDimitry Andric       }
6730b57cec5SDimitry Andric       break;
6740b57cec5SDimitry Andric     case '%': // %% -> %
6750b57cec5SDimitry Andric     case '{': // %{ -> {
6760b57cec5SDimitry Andric     case '}': // %} -> }
6770b57cec5SDimitry Andric       CurStringPiece += EscapedChar;
6780b57cec5SDimitry Andric       continue;
6790b57cec5SDimitry Andric     case '=': // %= -> Generate a unique ID.
6800b57cec5SDimitry Andric       CurStringPiece += "${:uid}";
6810b57cec5SDimitry Andric       continue;
6820b57cec5SDimitry Andric     }
6830b57cec5SDimitry Andric 
6840b57cec5SDimitry Andric     // Otherwise, we have an operand.  If we have accumulated a string so far,
6850b57cec5SDimitry Andric     // add it to the Pieces list.
6860b57cec5SDimitry Andric     if (!CurStringPiece.empty()) {
6870b57cec5SDimitry Andric       Pieces.push_back(AsmStringPiece(CurStringPiece));
6880b57cec5SDimitry Andric       CurStringPiece.clear();
6890b57cec5SDimitry Andric     }
6900b57cec5SDimitry Andric 
6910b57cec5SDimitry Andric     // Handle operands that have asmSymbolicName (e.g., %x[foo]) and those that
6920b57cec5SDimitry Andric     // don't (e.g., %x4). 'x' following the '%' is the constraint modifier.
6930b57cec5SDimitry Andric 
6940b57cec5SDimitry Andric     const char *Begin = CurPtr - 1; // Points to the character following '%'.
6950b57cec5SDimitry Andric     const char *Percent = Begin - 1; // Points to '%'.
6960b57cec5SDimitry Andric 
6970b57cec5SDimitry Andric     if (isLetter(EscapedChar)) {
6980b57cec5SDimitry Andric       if (CurPtr == StrEnd) { // Premature end.
6990b57cec5SDimitry Andric         DiagOffs = CurPtr-StrStart-1;
7000b57cec5SDimitry Andric         return diag::err_asm_invalid_escape;
7010b57cec5SDimitry Andric       }
7020b57cec5SDimitry Andric       EscapedChar = *CurPtr++;
7030b57cec5SDimitry Andric     }
7040b57cec5SDimitry Andric 
7050b57cec5SDimitry Andric     const SourceManager &SM = C.getSourceManager();
7060b57cec5SDimitry Andric     const LangOptions &LO = C.getLangOpts();
7070b57cec5SDimitry Andric 
7080b57cec5SDimitry Andric     // Handle operands that don't have asmSymbolicName (e.g., %x4).
7090b57cec5SDimitry Andric     if (isDigit(EscapedChar)) {
7100b57cec5SDimitry Andric       // %n - Assembler operand n
7110b57cec5SDimitry Andric       unsigned N = 0;
7120b57cec5SDimitry Andric 
7130b57cec5SDimitry Andric       --CurPtr;
7140b57cec5SDimitry Andric       while (CurPtr != StrEnd && isDigit(*CurPtr))
7150b57cec5SDimitry Andric         N = N*10 + ((*CurPtr++)-'0');
7160b57cec5SDimitry Andric 
7170b57cec5SDimitry Andric       unsigned NumOperands = getNumOutputs() + getNumPlusOperands() +
7180b57cec5SDimitry Andric                              getNumInputs() + getNumLabels();
7190b57cec5SDimitry Andric       if (N >= NumOperands) {
7200b57cec5SDimitry Andric         DiagOffs = CurPtr-StrStart-1;
7210b57cec5SDimitry Andric         return diag::err_asm_invalid_operand_number;
7220b57cec5SDimitry Andric       }
7230b57cec5SDimitry Andric 
7240b57cec5SDimitry Andric       // Str contains "x4" (Operand without the leading %).
7250b57cec5SDimitry Andric       std::string Str(Begin, CurPtr - Begin);
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric       // (BeginLoc, EndLoc) represents the range of the operand we are currently
7280b57cec5SDimitry Andric       // processing. Unlike Str, the range includes the leading '%'.
7290b57cec5SDimitry Andric       SourceLocation BeginLoc = getAsmString()->getLocationOfByte(
7300b57cec5SDimitry Andric           Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
7310b57cec5SDimitry Andric           &LastAsmStringOffset);
7320b57cec5SDimitry Andric       SourceLocation EndLoc = getAsmString()->getLocationOfByte(
7330b57cec5SDimitry Andric           CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken,
7340b57cec5SDimitry Andric           &LastAsmStringOffset);
7350b57cec5SDimitry Andric 
7360b57cec5SDimitry Andric       Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
7370b57cec5SDimitry Andric       continue;
7380b57cec5SDimitry Andric     }
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric     // Handle operands that have asmSymbolicName (e.g., %x[foo]).
7410b57cec5SDimitry Andric     if (EscapedChar == '[') {
7420b57cec5SDimitry Andric       DiagOffs = CurPtr-StrStart-1;
7430b57cec5SDimitry Andric 
7440b57cec5SDimitry Andric       // Find the ']'.
7450b57cec5SDimitry Andric       const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
7460b57cec5SDimitry Andric       if (NameEnd == nullptr)
7470b57cec5SDimitry Andric         return diag::err_asm_unterminated_symbolic_operand_name;
7480b57cec5SDimitry Andric       if (NameEnd == CurPtr)
7490b57cec5SDimitry Andric         return diag::err_asm_empty_symbolic_operand_name;
7500b57cec5SDimitry Andric 
7510b57cec5SDimitry Andric       StringRef SymbolicName(CurPtr, NameEnd - CurPtr);
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric       int N = getNamedOperand(SymbolicName);
7540b57cec5SDimitry Andric       if (N == -1) {
7550b57cec5SDimitry Andric         // Verify that an operand with that name exists.
7560b57cec5SDimitry Andric         DiagOffs = CurPtr-StrStart;
7570b57cec5SDimitry Andric         return diag::err_asm_unknown_symbolic_operand_name;
7580b57cec5SDimitry Andric       }
7590b57cec5SDimitry Andric 
7600b57cec5SDimitry Andric       // Str contains "x[foo]" (Operand without the leading %).
7610b57cec5SDimitry Andric       std::string Str(Begin, NameEnd + 1 - Begin);
7620b57cec5SDimitry Andric 
7630b57cec5SDimitry Andric       // (BeginLoc, EndLoc) represents the range of the operand we are currently
7640b57cec5SDimitry Andric       // processing. Unlike Str, the range includes the leading '%'.
7650b57cec5SDimitry Andric       SourceLocation BeginLoc = getAsmString()->getLocationOfByte(
7660b57cec5SDimitry Andric           Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
7670b57cec5SDimitry Andric           &LastAsmStringOffset);
7680b57cec5SDimitry Andric       SourceLocation EndLoc = getAsmString()->getLocationOfByte(
7690b57cec5SDimitry Andric           NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken,
7700b57cec5SDimitry Andric           &LastAsmStringOffset);
7710b57cec5SDimitry Andric 
7720b57cec5SDimitry Andric       Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
7730b57cec5SDimitry Andric 
7740b57cec5SDimitry Andric       CurPtr = NameEnd+1;
7750b57cec5SDimitry Andric       continue;
7760b57cec5SDimitry Andric     }
7770b57cec5SDimitry Andric 
7780b57cec5SDimitry Andric     DiagOffs = CurPtr-StrStart-1;
7790b57cec5SDimitry Andric     return diag::err_asm_invalid_escape;
7800b57cec5SDimitry Andric   }
7810b57cec5SDimitry Andric }
7820b57cec5SDimitry Andric 
7830b57cec5SDimitry Andric /// Assemble final IR asm string (GCC-style).
generateAsmString(const ASTContext & C) const7840b57cec5SDimitry Andric std::string GCCAsmStmt::generateAsmString(const ASTContext &C) const {
7850b57cec5SDimitry Andric   // Analyze the asm string to decompose it into its pieces.  We know that Sema
7860b57cec5SDimitry Andric   // has already done this, so it is guaranteed to be successful.
7870b57cec5SDimitry Andric   SmallVector<GCCAsmStmt::AsmStringPiece, 4> Pieces;
7880b57cec5SDimitry Andric   unsigned DiagOffs;
7890b57cec5SDimitry Andric   AnalyzeAsmString(Pieces, C, DiagOffs);
7900b57cec5SDimitry Andric 
7910b57cec5SDimitry Andric   std::string AsmString;
7920b57cec5SDimitry Andric   for (const auto &Piece : Pieces) {
7930b57cec5SDimitry Andric     if (Piece.isString())
7940b57cec5SDimitry Andric       AsmString += Piece.getString();
7950b57cec5SDimitry Andric     else if (Piece.getModifier() == '\0')
7960b57cec5SDimitry Andric       AsmString += '$' + llvm::utostr(Piece.getOperandNo());
7970b57cec5SDimitry Andric     else
7980b57cec5SDimitry Andric       AsmString += "${" + llvm::utostr(Piece.getOperandNo()) + ':' +
7990b57cec5SDimitry Andric                    Piece.getModifier() + '}';
8000b57cec5SDimitry Andric   }
8010b57cec5SDimitry Andric   return AsmString;
8020b57cec5SDimitry Andric }
8030b57cec5SDimitry Andric 
8040b57cec5SDimitry Andric /// Assemble final IR asm string (MS-style).
generateAsmString(const ASTContext & C) const8050b57cec5SDimitry Andric std::string MSAsmStmt::generateAsmString(const ASTContext &C) const {
8060b57cec5SDimitry Andric   // FIXME: This needs to be translated into the IR string representation.
807e8d8bef9SDimitry Andric   SmallVector<StringRef, 8> Pieces;
808e8d8bef9SDimitry Andric   AsmStr.split(Pieces, "\n\t");
809e8d8bef9SDimitry Andric   std::string MSAsmString;
810e8d8bef9SDimitry Andric   for (size_t I = 0, E = Pieces.size(); I < E; ++I) {
811e8d8bef9SDimitry Andric     StringRef Instruction = Pieces[I];
812e8d8bef9SDimitry Andric     // For vex/vex2/vex3/evex masm style prefix, convert it to att style
813e8d8bef9SDimitry Andric     // since we don't support masm style prefix in backend.
8145f757f3fSDimitry Andric     if (Instruction.starts_with("vex "))
815e8d8bef9SDimitry Andric       MSAsmString += '{' + Instruction.substr(0, 3).str() + '}' +
816e8d8bef9SDimitry Andric                      Instruction.substr(3).str();
8175f757f3fSDimitry Andric     else if (Instruction.starts_with("vex2 ") ||
8185f757f3fSDimitry Andric              Instruction.starts_with("vex3 ") ||
8195f757f3fSDimitry Andric              Instruction.starts_with("evex "))
820e8d8bef9SDimitry Andric       MSAsmString += '{' + Instruction.substr(0, 4).str() + '}' +
821e8d8bef9SDimitry Andric                      Instruction.substr(4).str();
822e8d8bef9SDimitry Andric     else
823e8d8bef9SDimitry Andric       MSAsmString += Instruction.str();
824e8d8bef9SDimitry Andric     // If this is not the last instruction, adding back the '\n\t'.
825e8d8bef9SDimitry Andric     if (I < E - 1)
826e8d8bef9SDimitry Andric       MSAsmString += "\n\t";
827e8d8bef9SDimitry Andric   }
828e8d8bef9SDimitry Andric   return MSAsmString;
8290b57cec5SDimitry Andric }
8300b57cec5SDimitry Andric 
getOutputExpr(unsigned i)8310b57cec5SDimitry Andric Expr *MSAsmStmt::getOutputExpr(unsigned i) {
8320b57cec5SDimitry Andric   return cast<Expr>(Exprs[i]);
8330b57cec5SDimitry Andric }
8340b57cec5SDimitry Andric 
getInputExpr(unsigned i)8350b57cec5SDimitry Andric Expr *MSAsmStmt::getInputExpr(unsigned i) {
8360b57cec5SDimitry Andric   return cast<Expr>(Exprs[i + NumOutputs]);
8370b57cec5SDimitry Andric }
8380b57cec5SDimitry Andric 
setInputExpr(unsigned i,Expr * E)8390b57cec5SDimitry Andric void MSAsmStmt::setInputExpr(unsigned i, Expr *E) {
8400b57cec5SDimitry Andric   Exprs[i + NumOutputs] = E;
8410b57cec5SDimitry Andric }
8420b57cec5SDimitry Andric 
8430b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8440b57cec5SDimitry Andric // Constructors
8450b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
8460b57cec5SDimitry Andric 
GCCAsmStmt(const ASTContext & C,SourceLocation asmloc,bool issimple,bool isvolatile,unsigned numoutputs,unsigned numinputs,IdentifierInfo ** names,StringLiteral ** constraints,Expr ** exprs,StringLiteral * asmstr,unsigned numclobbers,StringLiteral ** clobbers,unsigned numlabels,SourceLocation rparenloc)8470b57cec5SDimitry Andric GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc,
8480b57cec5SDimitry Andric                        bool issimple, bool isvolatile, unsigned numoutputs,
8490b57cec5SDimitry Andric                        unsigned numinputs, IdentifierInfo **names,
8500b57cec5SDimitry Andric                        StringLiteral **constraints, Expr **exprs,
8510b57cec5SDimitry Andric                        StringLiteral *asmstr, unsigned numclobbers,
8520b57cec5SDimitry Andric                        StringLiteral **clobbers, unsigned numlabels,
8530b57cec5SDimitry Andric                        SourceLocation rparenloc)
8540b57cec5SDimitry Andric     : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
8550b57cec5SDimitry Andric               numinputs, numclobbers),
8560b57cec5SDimitry Andric               RParenLoc(rparenloc), AsmStr(asmstr), NumLabels(numlabels) {
8570b57cec5SDimitry Andric   unsigned NumExprs = NumOutputs + NumInputs + NumLabels;
8580b57cec5SDimitry Andric 
8590b57cec5SDimitry Andric   Names = new (C) IdentifierInfo*[NumExprs];
8600b57cec5SDimitry Andric   std::copy(names, names + NumExprs, Names);
8610b57cec5SDimitry Andric 
8620b57cec5SDimitry Andric   Exprs = new (C) Stmt*[NumExprs];
8630b57cec5SDimitry Andric   std::copy(exprs, exprs + NumExprs, Exprs);
8640b57cec5SDimitry Andric 
8650b57cec5SDimitry Andric   unsigned NumConstraints = NumOutputs + NumInputs;
8660b57cec5SDimitry Andric   Constraints = new (C) StringLiteral*[NumConstraints];
8670b57cec5SDimitry Andric   std::copy(constraints, constraints + NumConstraints, Constraints);
8680b57cec5SDimitry Andric 
8690b57cec5SDimitry Andric   Clobbers = new (C) StringLiteral*[NumClobbers];
8700b57cec5SDimitry Andric   std::copy(clobbers, clobbers + NumClobbers, Clobbers);
8710b57cec5SDimitry Andric }
8720b57cec5SDimitry Andric 
MSAsmStmt(const ASTContext & C,SourceLocation asmloc,SourceLocation lbraceloc,bool issimple,bool isvolatile,ArrayRef<Token> asmtoks,unsigned numoutputs,unsigned numinputs,ArrayRef<StringRef> constraints,ArrayRef<Expr * > exprs,StringRef asmstr,ArrayRef<StringRef> clobbers,SourceLocation endloc)8730b57cec5SDimitry Andric MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc,
8740b57cec5SDimitry Andric                      SourceLocation lbraceloc, bool issimple, bool isvolatile,
8750b57cec5SDimitry Andric                      ArrayRef<Token> asmtoks, unsigned numoutputs,
8760b57cec5SDimitry Andric                      unsigned numinputs,
8770b57cec5SDimitry Andric                      ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs,
8780b57cec5SDimitry Andric                      StringRef asmstr, ArrayRef<StringRef> clobbers,
8790b57cec5SDimitry Andric                      SourceLocation endloc)
8800b57cec5SDimitry Andric     : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
8810b57cec5SDimitry Andric               numinputs, clobbers.size()), LBraceLoc(lbraceloc),
8820b57cec5SDimitry Andric               EndLoc(endloc), NumAsmToks(asmtoks.size()) {
8830b57cec5SDimitry Andric   initialize(C, asmstr, asmtoks, constraints, exprs, clobbers);
8840b57cec5SDimitry Andric }
8850b57cec5SDimitry Andric 
copyIntoContext(const ASTContext & C,StringRef str)8860b57cec5SDimitry Andric static StringRef copyIntoContext(const ASTContext &C, StringRef str) {
8870b57cec5SDimitry Andric   return str.copy(C);
8880b57cec5SDimitry Andric }
8890b57cec5SDimitry Andric 
initialize(const ASTContext & C,StringRef asmstr,ArrayRef<Token> asmtoks,ArrayRef<StringRef> constraints,ArrayRef<Expr * > exprs,ArrayRef<StringRef> clobbers)8900b57cec5SDimitry Andric void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr,
8910b57cec5SDimitry Andric                            ArrayRef<Token> asmtoks,
8920b57cec5SDimitry Andric                            ArrayRef<StringRef> constraints,
8930b57cec5SDimitry Andric                            ArrayRef<Expr*> exprs,
8940b57cec5SDimitry Andric                            ArrayRef<StringRef> clobbers) {
8950b57cec5SDimitry Andric   assert(NumAsmToks == asmtoks.size());
8960b57cec5SDimitry Andric   assert(NumClobbers == clobbers.size());
8970b57cec5SDimitry Andric 
8980b57cec5SDimitry Andric   assert(exprs.size() == NumOutputs + NumInputs);
8990b57cec5SDimitry Andric   assert(exprs.size() == constraints.size());
9000b57cec5SDimitry Andric 
9010b57cec5SDimitry Andric   AsmStr = copyIntoContext(C, asmstr);
9020b57cec5SDimitry Andric 
9030b57cec5SDimitry Andric   Exprs = new (C) Stmt*[exprs.size()];
9040b57cec5SDimitry Andric   std::copy(exprs.begin(), exprs.end(), Exprs);
9050b57cec5SDimitry Andric 
9060b57cec5SDimitry Andric   AsmToks = new (C) Token[asmtoks.size()];
9070b57cec5SDimitry Andric   std::copy(asmtoks.begin(), asmtoks.end(), AsmToks);
9080b57cec5SDimitry Andric 
9090b57cec5SDimitry Andric   Constraints = new (C) StringRef[exprs.size()];
9100b57cec5SDimitry Andric   std::transform(constraints.begin(), constraints.end(), Constraints,
9110b57cec5SDimitry Andric                  [&](StringRef Constraint) {
9120b57cec5SDimitry Andric                    return copyIntoContext(C, Constraint);
9130b57cec5SDimitry Andric                  });
9140b57cec5SDimitry Andric 
9150b57cec5SDimitry Andric   Clobbers = new (C) StringRef[NumClobbers];
9160b57cec5SDimitry Andric   // FIXME: Avoid the allocation/copy if at all possible.
9170b57cec5SDimitry Andric   std::transform(clobbers.begin(), clobbers.end(), Clobbers,
9180b57cec5SDimitry Andric                  [&](StringRef Clobber) {
9190b57cec5SDimitry Andric                    return copyIntoContext(C, Clobber);
9200b57cec5SDimitry Andric                  });
9210b57cec5SDimitry Andric }
9220b57cec5SDimitry Andric 
IfStmt(const ASTContext & Ctx,SourceLocation IL,IfStatementKind Kind,Stmt * Init,VarDecl * Var,Expr * Cond,SourceLocation LPL,SourceLocation RPL,Stmt * Then,SourceLocation EL,Stmt * Else)923349cc55cSDimitry Andric IfStmt::IfStmt(const ASTContext &Ctx, SourceLocation IL, IfStatementKind Kind,
924e8d8bef9SDimitry Andric                Stmt *Init, VarDecl *Var, Expr *Cond, SourceLocation LPL,
925e8d8bef9SDimitry Andric                SourceLocation RPL, Stmt *Then, SourceLocation EL, Stmt *Else)
926e8d8bef9SDimitry Andric     : Stmt(IfStmtClass), LParenLoc(LPL), RParenLoc(RPL) {
9270b57cec5SDimitry Andric   bool HasElse = Else != nullptr;
9280b57cec5SDimitry Andric   bool HasVar = Var != nullptr;
9290b57cec5SDimitry Andric   bool HasInit = Init != nullptr;
9300b57cec5SDimitry Andric   IfStmtBits.HasElse = HasElse;
9310b57cec5SDimitry Andric   IfStmtBits.HasVar = HasVar;
9320b57cec5SDimitry Andric   IfStmtBits.HasInit = HasInit;
9330b57cec5SDimitry Andric 
934349cc55cSDimitry Andric   setStatementKind(Kind);
9350b57cec5SDimitry Andric 
9360b57cec5SDimitry Andric   setCond(Cond);
9370b57cec5SDimitry Andric   setThen(Then);
9380b57cec5SDimitry Andric   if (HasElse)
9390b57cec5SDimitry Andric     setElse(Else);
9400b57cec5SDimitry Andric   if (HasVar)
9410b57cec5SDimitry Andric     setConditionVariable(Ctx, Var);
9420b57cec5SDimitry Andric   if (HasInit)
9430b57cec5SDimitry Andric     setInit(Init);
9440b57cec5SDimitry Andric 
9450b57cec5SDimitry Andric   setIfLoc(IL);
9460b57cec5SDimitry Andric   if (HasElse)
9470b57cec5SDimitry Andric     setElseLoc(EL);
9480b57cec5SDimitry Andric }
9490b57cec5SDimitry Andric 
IfStmt(EmptyShell Empty,bool HasElse,bool HasVar,bool HasInit)9500b57cec5SDimitry Andric IfStmt::IfStmt(EmptyShell Empty, bool HasElse, bool HasVar, bool HasInit)
9510b57cec5SDimitry Andric     : Stmt(IfStmtClass, Empty) {
9520b57cec5SDimitry Andric   IfStmtBits.HasElse = HasElse;
9530b57cec5SDimitry Andric   IfStmtBits.HasVar = HasVar;
9540b57cec5SDimitry Andric   IfStmtBits.HasInit = HasInit;
9550b57cec5SDimitry Andric }
9560b57cec5SDimitry Andric 
Create(const ASTContext & Ctx,SourceLocation IL,IfStatementKind Kind,Stmt * Init,VarDecl * Var,Expr * Cond,SourceLocation LPL,SourceLocation RPL,Stmt * Then,SourceLocation EL,Stmt * Else)9570b57cec5SDimitry Andric IfStmt *IfStmt::Create(const ASTContext &Ctx, SourceLocation IL,
958349cc55cSDimitry Andric                        IfStatementKind Kind, Stmt *Init, VarDecl *Var,
959349cc55cSDimitry Andric                        Expr *Cond, SourceLocation LPL, SourceLocation RPL,
960349cc55cSDimitry Andric                        Stmt *Then, SourceLocation EL, Stmt *Else) {
9610b57cec5SDimitry Andric   bool HasElse = Else != nullptr;
9620b57cec5SDimitry Andric   bool HasVar = Var != nullptr;
9630b57cec5SDimitry Andric   bool HasInit = Init != nullptr;
9640b57cec5SDimitry Andric   void *Mem = Ctx.Allocate(
9650b57cec5SDimitry Andric       totalSizeToAlloc<Stmt *, SourceLocation>(
9660b57cec5SDimitry Andric           NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),
9670b57cec5SDimitry Andric       alignof(IfStmt));
9680b57cec5SDimitry Andric   return new (Mem)
969349cc55cSDimitry Andric       IfStmt(Ctx, IL, Kind, Init, Var, Cond, LPL, RPL, Then, EL, Else);
9700b57cec5SDimitry Andric }
9710b57cec5SDimitry Andric 
CreateEmpty(const ASTContext & Ctx,bool HasElse,bool HasVar,bool HasInit)9720b57cec5SDimitry Andric IfStmt *IfStmt::CreateEmpty(const ASTContext &Ctx, bool HasElse, bool HasVar,
9730b57cec5SDimitry Andric                             bool HasInit) {
9740b57cec5SDimitry Andric   void *Mem = Ctx.Allocate(
9750b57cec5SDimitry Andric       totalSizeToAlloc<Stmt *, SourceLocation>(
9760b57cec5SDimitry Andric           NumMandatoryStmtPtr + HasElse + HasVar + HasInit, HasElse),
9770b57cec5SDimitry Andric       alignof(IfStmt));
9780b57cec5SDimitry Andric   return new (Mem) IfStmt(EmptyShell(), HasElse, HasVar, HasInit);
9790b57cec5SDimitry Andric }
9800b57cec5SDimitry Andric 
getConditionVariable()9810b57cec5SDimitry Andric VarDecl *IfStmt::getConditionVariable() {
9820b57cec5SDimitry Andric   auto *DS = getConditionVariableDeclStmt();
9830b57cec5SDimitry Andric   if (!DS)
9840b57cec5SDimitry Andric     return nullptr;
9850b57cec5SDimitry Andric   return cast<VarDecl>(DS->getSingleDecl());
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric 
setConditionVariable(const ASTContext & Ctx,VarDecl * V)9880b57cec5SDimitry Andric void IfStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
9890b57cec5SDimitry Andric   assert(hasVarStorage() &&
9900b57cec5SDimitry Andric          "This if statement has no storage for a condition variable!");
9910b57cec5SDimitry Andric 
9920b57cec5SDimitry Andric   if (!V) {
9930b57cec5SDimitry Andric     getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
9940b57cec5SDimitry Andric     return;
9950b57cec5SDimitry Andric   }
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric   SourceRange VarRange = V->getSourceRange();
9980b57cec5SDimitry Andric   getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
9990b57cec5SDimitry Andric       DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
10000b57cec5SDimitry Andric }
10010b57cec5SDimitry Andric 
isObjCAvailabilityCheck() const10020b57cec5SDimitry Andric bool IfStmt::isObjCAvailabilityCheck() const {
10030b57cec5SDimitry Andric   return isa<ObjCAvailabilityCheckExpr>(getCond());
10040b57cec5SDimitry Andric }
10050b57cec5SDimitry Andric 
getNondiscardedCase(const ASTContext & Ctx)1006bdd1243dSDimitry Andric std::optional<Stmt *> IfStmt::getNondiscardedCase(const ASTContext &Ctx) {
1007480093f4SDimitry Andric   if (!isConstexpr() || getCond()->isValueDependent())
1008bdd1243dSDimitry Andric     return std::nullopt;
1009480093f4SDimitry Andric   return !getCond()->EvaluateKnownConstInt(Ctx) ? getElse() : getThen();
1010480093f4SDimitry Andric }
1011480093f4SDimitry Andric 
1012bdd1243dSDimitry Andric std::optional<const Stmt *>
getNondiscardedCase(const ASTContext & Ctx) const1013fe6060f1SDimitry Andric IfStmt::getNondiscardedCase(const ASTContext &Ctx) const {
1014bdd1243dSDimitry Andric   if (std::optional<Stmt *> Result =
1015fe6060f1SDimitry Andric           const_cast<IfStmt *>(this)->getNondiscardedCase(Ctx))
1016fe6060f1SDimitry Andric     return *Result;
1017bdd1243dSDimitry Andric   return std::nullopt;
1018fe6060f1SDimitry Andric }
1019fe6060f1SDimitry Andric 
ForStmt(const ASTContext & C,Stmt * Init,Expr * Cond,VarDecl * condVar,Expr * Inc,Stmt * Body,SourceLocation FL,SourceLocation LP,SourceLocation RP)10200b57cec5SDimitry Andric ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
10210b57cec5SDimitry Andric                  Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
10220b57cec5SDimitry Andric                  SourceLocation RP)
10230b57cec5SDimitry Andric   : Stmt(ForStmtClass), LParenLoc(LP), RParenLoc(RP)
10240b57cec5SDimitry Andric {
10250b57cec5SDimitry Andric   SubExprs[INIT] = Init;
10260b57cec5SDimitry Andric   setConditionVariable(C, condVar);
10270b57cec5SDimitry Andric   SubExprs[COND] = Cond;
10280b57cec5SDimitry Andric   SubExprs[INC] = Inc;
10290b57cec5SDimitry Andric   SubExprs[BODY] = Body;
10300b57cec5SDimitry Andric   ForStmtBits.ForLoc = FL;
10310b57cec5SDimitry Andric }
10320b57cec5SDimitry Andric 
getConditionVariable() const10330b57cec5SDimitry Andric VarDecl *ForStmt::getConditionVariable() const {
10340b57cec5SDimitry Andric   if (!SubExprs[CONDVAR])
10350b57cec5SDimitry Andric     return nullptr;
10360b57cec5SDimitry Andric 
10370b57cec5SDimitry Andric   auto *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
10380b57cec5SDimitry Andric   return cast<VarDecl>(DS->getSingleDecl());
10390b57cec5SDimitry Andric }
10400b57cec5SDimitry Andric 
setConditionVariable(const ASTContext & C,VarDecl * V)10410b57cec5SDimitry Andric void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
10420b57cec5SDimitry Andric   if (!V) {
10430b57cec5SDimitry Andric     SubExprs[CONDVAR] = nullptr;
10440b57cec5SDimitry Andric     return;
10450b57cec5SDimitry Andric   }
10460b57cec5SDimitry Andric 
10470b57cec5SDimitry Andric   SourceRange VarRange = V->getSourceRange();
10480b57cec5SDimitry Andric   SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
10490b57cec5SDimitry Andric                                        VarRange.getEnd());
10500b57cec5SDimitry Andric }
10510b57cec5SDimitry Andric 
SwitchStmt(const ASTContext & Ctx,Stmt * Init,VarDecl * Var,Expr * Cond,SourceLocation LParenLoc,SourceLocation RParenLoc)10520b57cec5SDimitry Andric SwitchStmt::SwitchStmt(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
1053e8d8bef9SDimitry Andric                        Expr *Cond, SourceLocation LParenLoc,
1054e8d8bef9SDimitry Andric                        SourceLocation RParenLoc)
1055e8d8bef9SDimitry Andric     : Stmt(SwitchStmtClass), FirstCase(nullptr), LParenLoc(LParenLoc),
1056e8d8bef9SDimitry Andric       RParenLoc(RParenLoc) {
10570b57cec5SDimitry Andric   bool HasInit = Init != nullptr;
10580b57cec5SDimitry Andric   bool HasVar = Var != nullptr;
10590b57cec5SDimitry Andric   SwitchStmtBits.HasInit = HasInit;
10600b57cec5SDimitry Andric   SwitchStmtBits.HasVar = HasVar;
10610b57cec5SDimitry Andric   SwitchStmtBits.AllEnumCasesCovered = false;
10620b57cec5SDimitry Andric 
10630b57cec5SDimitry Andric   setCond(Cond);
10640b57cec5SDimitry Andric   setBody(nullptr);
10650b57cec5SDimitry Andric   if (HasInit)
10660b57cec5SDimitry Andric     setInit(Init);
10670b57cec5SDimitry Andric   if (HasVar)
10680b57cec5SDimitry Andric     setConditionVariable(Ctx, Var);
10690b57cec5SDimitry Andric 
10700b57cec5SDimitry Andric   setSwitchLoc(SourceLocation{});
10710b57cec5SDimitry Andric }
10720b57cec5SDimitry Andric 
SwitchStmt(EmptyShell Empty,bool HasInit,bool HasVar)10730b57cec5SDimitry Andric SwitchStmt::SwitchStmt(EmptyShell Empty, bool HasInit, bool HasVar)
10740b57cec5SDimitry Andric     : Stmt(SwitchStmtClass, Empty) {
10750b57cec5SDimitry Andric   SwitchStmtBits.HasInit = HasInit;
10760b57cec5SDimitry Andric   SwitchStmtBits.HasVar = HasVar;
10770b57cec5SDimitry Andric   SwitchStmtBits.AllEnumCasesCovered = false;
10780b57cec5SDimitry Andric }
10790b57cec5SDimitry Andric 
Create(const ASTContext & Ctx,Stmt * Init,VarDecl * Var,Expr * Cond,SourceLocation LParenLoc,SourceLocation RParenLoc)10800b57cec5SDimitry Andric SwitchStmt *SwitchStmt::Create(const ASTContext &Ctx, Stmt *Init, VarDecl *Var,
1081e8d8bef9SDimitry Andric                                Expr *Cond, SourceLocation LParenLoc,
1082e8d8bef9SDimitry Andric                                SourceLocation RParenLoc) {
10830b57cec5SDimitry Andric   bool HasInit = Init != nullptr;
10840b57cec5SDimitry Andric   bool HasVar = Var != nullptr;
10850b57cec5SDimitry Andric   void *Mem = Ctx.Allocate(
10860b57cec5SDimitry Andric       totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
10870b57cec5SDimitry Andric       alignof(SwitchStmt));
1088e8d8bef9SDimitry Andric   return new (Mem) SwitchStmt(Ctx, Init, Var, Cond, LParenLoc, RParenLoc);
10890b57cec5SDimitry Andric }
10900b57cec5SDimitry Andric 
CreateEmpty(const ASTContext & Ctx,bool HasInit,bool HasVar)10910b57cec5SDimitry Andric SwitchStmt *SwitchStmt::CreateEmpty(const ASTContext &Ctx, bool HasInit,
10920b57cec5SDimitry Andric                                     bool HasVar) {
10930b57cec5SDimitry Andric   void *Mem = Ctx.Allocate(
10940b57cec5SDimitry Andric       totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasInit + HasVar),
10950b57cec5SDimitry Andric       alignof(SwitchStmt));
10960b57cec5SDimitry Andric   return new (Mem) SwitchStmt(EmptyShell(), HasInit, HasVar);
10970b57cec5SDimitry Andric }
10980b57cec5SDimitry Andric 
getConditionVariable()10990b57cec5SDimitry Andric VarDecl *SwitchStmt::getConditionVariable() {
11000b57cec5SDimitry Andric   auto *DS = getConditionVariableDeclStmt();
11010b57cec5SDimitry Andric   if (!DS)
11020b57cec5SDimitry Andric     return nullptr;
11030b57cec5SDimitry Andric   return cast<VarDecl>(DS->getSingleDecl());
11040b57cec5SDimitry Andric }
11050b57cec5SDimitry Andric 
setConditionVariable(const ASTContext & Ctx,VarDecl * V)11060b57cec5SDimitry Andric void SwitchStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
11070b57cec5SDimitry Andric   assert(hasVarStorage() &&
11080b57cec5SDimitry Andric          "This switch statement has no storage for a condition variable!");
11090b57cec5SDimitry Andric 
11100b57cec5SDimitry Andric   if (!V) {
11110b57cec5SDimitry Andric     getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
11120b57cec5SDimitry Andric     return;
11130b57cec5SDimitry Andric   }
11140b57cec5SDimitry Andric 
11150b57cec5SDimitry Andric   SourceRange VarRange = V->getSourceRange();
11160b57cec5SDimitry Andric   getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
11170b57cec5SDimitry Andric       DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
11180b57cec5SDimitry Andric }
11190b57cec5SDimitry Andric 
WhileStmt(const ASTContext & Ctx,VarDecl * Var,Expr * Cond,Stmt * Body,SourceLocation WL,SourceLocation LParenLoc,SourceLocation RParenLoc)11200b57cec5SDimitry Andric WhileStmt::WhileStmt(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
11215ffd83dbSDimitry Andric                      Stmt *Body, SourceLocation WL, SourceLocation LParenLoc,
11225ffd83dbSDimitry Andric                      SourceLocation RParenLoc)
11230b57cec5SDimitry Andric     : Stmt(WhileStmtClass) {
11240b57cec5SDimitry Andric   bool HasVar = Var != nullptr;
11250b57cec5SDimitry Andric   WhileStmtBits.HasVar = HasVar;
11260b57cec5SDimitry Andric 
11270b57cec5SDimitry Andric   setCond(Cond);
11280b57cec5SDimitry Andric   setBody(Body);
11290b57cec5SDimitry Andric   if (HasVar)
11300b57cec5SDimitry Andric     setConditionVariable(Ctx, Var);
11310b57cec5SDimitry Andric 
11320b57cec5SDimitry Andric   setWhileLoc(WL);
11335ffd83dbSDimitry Andric   setLParenLoc(LParenLoc);
11345ffd83dbSDimitry Andric   setRParenLoc(RParenLoc);
11350b57cec5SDimitry Andric }
11360b57cec5SDimitry Andric 
WhileStmt(EmptyShell Empty,bool HasVar)11370b57cec5SDimitry Andric WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar)
11380b57cec5SDimitry Andric     : Stmt(WhileStmtClass, Empty) {
11390b57cec5SDimitry Andric   WhileStmtBits.HasVar = HasVar;
11400b57cec5SDimitry Andric }
11410b57cec5SDimitry Andric 
Create(const ASTContext & Ctx,VarDecl * Var,Expr * Cond,Stmt * Body,SourceLocation WL,SourceLocation LParenLoc,SourceLocation RParenLoc)11420b57cec5SDimitry Andric WhileStmt *WhileStmt::Create(const ASTContext &Ctx, VarDecl *Var, Expr *Cond,
11435ffd83dbSDimitry Andric                              Stmt *Body, SourceLocation WL,
11445ffd83dbSDimitry Andric                              SourceLocation LParenLoc,
11455ffd83dbSDimitry Andric                              SourceLocation RParenLoc) {
11460b57cec5SDimitry Andric   bool HasVar = Var != nullptr;
11470b57cec5SDimitry Andric   void *Mem =
11480b57cec5SDimitry Andric       Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
11490b57cec5SDimitry Andric                    alignof(WhileStmt));
11505ffd83dbSDimitry Andric   return new (Mem) WhileStmt(Ctx, Var, Cond, Body, WL, LParenLoc, RParenLoc);
11510b57cec5SDimitry Andric }
11520b57cec5SDimitry Andric 
CreateEmpty(const ASTContext & Ctx,bool HasVar)11530b57cec5SDimitry Andric WhileStmt *WhileStmt::CreateEmpty(const ASTContext &Ctx, bool HasVar) {
11540b57cec5SDimitry Andric   void *Mem =
11550b57cec5SDimitry Andric       Ctx.Allocate(totalSizeToAlloc<Stmt *>(NumMandatoryStmtPtr + HasVar),
11560b57cec5SDimitry Andric                    alignof(WhileStmt));
11570b57cec5SDimitry Andric   return new (Mem) WhileStmt(EmptyShell(), HasVar);
11580b57cec5SDimitry Andric }
11590b57cec5SDimitry Andric 
getConditionVariable()11600b57cec5SDimitry Andric VarDecl *WhileStmt::getConditionVariable() {
11610b57cec5SDimitry Andric   auto *DS = getConditionVariableDeclStmt();
11620b57cec5SDimitry Andric   if (!DS)
11630b57cec5SDimitry Andric     return nullptr;
11640b57cec5SDimitry Andric   return cast<VarDecl>(DS->getSingleDecl());
11650b57cec5SDimitry Andric }
11660b57cec5SDimitry Andric 
setConditionVariable(const ASTContext & Ctx,VarDecl * V)11670b57cec5SDimitry Andric void WhileStmt::setConditionVariable(const ASTContext &Ctx, VarDecl *V) {
11680b57cec5SDimitry Andric   assert(hasVarStorage() &&
11690b57cec5SDimitry Andric          "This while statement has no storage for a condition variable!");
11700b57cec5SDimitry Andric 
11710b57cec5SDimitry Andric   if (!V) {
11720b57cec5SDimitry Andric     getTrailingObjects<Stmt *>()[varOffset()] = nullptr;
11730b57cec5SDimitry Andric     return;
11740b57cec5SDimitry Andric   }
11750b57cec5SDimitry Andric 
11760b57cec5SDimitry Andric   SourceRange VarRange = V->getSourceRange();
11770b57cec5SDimitry Andric   getTrailingObjects<Stmt *>()[varOffset()] = new (Ctx)
11780b57cec5SDimitry Andric       DeclStmt(DeclGroupRef(V), VarRange.getBegin(), VarRange.getEnd());
11790b57cec5SDimitry Andric }
11800b57cec5SDimitry Andric 
11810b57cec5SDimitry Andric // IndirectGotoStmt
getConstantTarget()11820b57cec5SDimitry Andric LabelDecl *IndirectGotoStmt::getConstantTarget() {
11830b57cec5SDimitry Andric   if (auto *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
11840b57cec5SDimitry Andric     return E->getLabel();
11850b57cec5SDimitry Andric   return nullptr;
11860b57cec5SDimitry Andric }
11870b57cec5SDimitry Andric 
11880b57cec5SDimitry Andric // ReturnStmt
ReturnStmt(SourceLocation RL,Expr * E,const VarDecl * NRVOCandidate)11890b57cec5SDimitry Andric ReturnStmt::ReturnStmt(SourceLocation RL, Expr *E, const VarDecl *NRVOCandidate)
11900b57cec5SDimitry Andric     : Stmt(ReturnStmtClass), RetExpr(E) {
11910b57cec5SDimitry Andric   bool HasNRVOCandidate = NRVOCandidate != nullptr;
11920b57cec5SDimitry Andric   ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate;
11930b57cec5SDimitry Andric   if (HasNRVOCandidate)
11940b57cec5SDimitry Andric     setNRVOCandidate(NRVOCandidate);
11950b57cec5SDimitry Andric   setReturnLoc(RL);
11960b57cec5SDimitry Andric }
11970b57cec5SDimitry Andric 
ReturnStmt(EmptyShell Empty,bool HasNRVOCandidate)11980b57cec5SDimitry Andric ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate)
11990b57cec5SDimitry Andric     : Stmt(ReturnStmtClass, Empty) {
12000b57cec5SDimitry Andric   ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate;
12010b57cec5SDimitry Andric }
12020b57cec5SDimitry Andric 
Create(const ASTContext & Ctx,SourceLocation RL,Expr * E,const VarDecl * NRVOCandidate)12030b57cec5SDimitry Andric ReturnStmt *ReturnStmt::Create(const ASTContext &Ctx, SourceLocation RL,
12040b57cec5SDimitry Andric                                Expr *E, const VarDecl *NRVOCandidate) {
12050b57cec5SDimitry Andric   bool HasNRVOCandidate = NRVOCandidate != nullptr;
12060b57cec5SDimitry Andric   void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate),
12070b57cec5SDimitry Andric                            alignof(ReturnStmt));
12080b57cec5SDimitry Andric   return new (Mem) ReturnStmt(RL, E, NRVOCandidate);
12090b57cec5SDimitry Andric }
12100b57cec5SDimitry Andric 
CreateEmpty(const ASTContext & Ctx,bool HasNRVOCandidate)12110b57cec5SDimitry Andric ReturnStmt *ReturnStmt::CreateEmpty(const ASTContext &Ctx,
12120b57cec5SDimitry Andric                                     bool HasNRVOCandidate) {
12130b57cec5SDimitry Andric   void *Mem = Ctx.Allocate(totalSizeToAlloc<const VarDecl *>(HasNRVOCandidate),
12140b57cec5SDimitry Andric                            alignof(ReturnStmt));
12150b57cec5SDimitry Andric   return new (Mem) ReturnStmt(EmptyShell(), HasNRVOCandidate);
12160b57cec5SDimitry Andric }
12170b57cec5SDimitry Andric 
12180b57cec5SDimitry Andric // CaseStmt
Create(const ASTContext & Ctx,Expr * lhs,Expr * rhs,SourceLocation caseLoc,SourceLocation ellipsisLoc,SourceLocation colonLoc)12190b57cec5SDimitry Andric CaseStmt *CaseStmt::Create(const ASTContext &Ctx, Expr *lhs, Expr *rhs,
12200b57cec5SDimitry Andric                            SourceLocation caseLoc, SourceLocation ellipsisLoc,
12210b57cec5SDimitry Andric                            SourceLocation colonLoc) {
12220b57cec5SDimitry Andric   bool CaseStmtIsGNURange = rhs != nullptr;
12230b57cec5SDimitry Andric   void *Mem = Ctx.Allocate(
12240b57cec5SDimitry Andric       totalSizeToAlloc<Stmt *, SourceLocation>(
12250b57cec5SDimitry Andric           NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),
12260b57cec5SDimitry Andric       alignof(CaseStmt));
12270b57cec5SDimitry Andric   return new (Mem) CaseStmt(lhs, rhs, caseLoc, ellipsisLoc, colonLoc);
12280b57cec5SDimitry Andric }
12290b57cec5SDimitry Andric 
CreateEmpty(const ASTContext & Ctx,bool CaseStmtIsGNURange)12300b57cec5SDimitry Andric CaseStmt *CaseStmt::CreateEmpty(const ASTContext &Ctx,
12310b57cec5SDimitry Andric                                 bool CaseStmtIsGNURange) {
12320b57cec5SDimitry Andric   void *Mem = Ctx.Allocate(
12330b57cec5SDimitry Andric       totalSizeToAlloc<Stmt *, SourceLocation>(
12340b57cec5SDimitry Andric           NumMandatoryStmtPtr + CaseStmtIsGNURange, CaseStmtIsGNURange),
12350b57cec5SDimitry Andric       alignof(CaseStmt));
12360b57cec5SDimitry Andric   return new (Mem) CaseStmt(EmptyShell(), CaseStmtIsGNURange);
12370b57cec5SDimitry Andric }
12380b57cec5SDimitry Andric 
SEHTryStmt(bool IsCXXTry,SourceLocation TryLoc,Stmt * TryBlock,Stmt * Handler)12390b57cec5SDimitry Andric SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock,
12400b57cec5SDimitry Andric                        Stmt *Handler)
12410b57cec5SDimitry Andric     : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) {
12420b57cec5SDimitry Andric   Children[TRY]     = TryBlock;
12430b57cec5SDimitry Andric   Children[HANDLER] = Handler;
12440b57cec5SDimitry Andric }
12450b57cec5SDimitry Andric 
Create(const ASTContext & C,bool IsCXXTry,SourceLocation TryLoc,Stmt * TryBlock,Stmt * Handler)12460b57cec5SDimitry Andric SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry,
12470b57cec5SDimitry Andric                                SourceLocation TryLoc, Stmt *TryBlock,
12480b57cec5SDimitry Andric                                Stmt *Handler) {
12490b57cec5SDimitry Andric   return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler);
12500b57cec5SDimitry Andric }
12510b57cec5SDimitry Andric 
getExceptHandler() const12520b57cec5SDimitry Andric SEHExceptStmt* SEHTryStmt::getExceptHandler() const {
12530b57cec5SDimitry Andric   return dyn_cast<SEHExceptStmt>(getHandler());
12540b57cec5SDimitry Andric }
12550b57cec5SDimitry Andric 
getFinallyHandler() const12560b57cec5SDimitry Andric SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const {
12570b57cec5SDimitry Andric   return dyn_cast<SEHFinallyStmt>(getHandler());
12580b57cec5SDimitry Andric }
12590b57cec5SDimitry Andric 
SEHExceptStmt(SourceLocation Loc,Expr * FilterExpr,Stmt * Block)12600b57cec5SDimitry Andric SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block)
12610b57cec5SDimitry Andric     : Stmt(SEHExceptStmtClass), Loc(Loc) {
12620b57cec5SDimitry Andric   Children[FILTER_EXPR] = FilterExpr;
12630b57cec5SDimitry Andric   Children[BLOCK]       = Block;
12640b57cec5SDimitry Andric }
12650b57cec5SDimitry Andric 
Create(const ASTContext & C,SourceLocation Loc,Expr * FilterExpr,Stmt * Block)12660b57cec5SDimitry Andric SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc,
12670b57cec5SDimitry Andric                                      Expr *FilterExpr, Stmt *Block) {
12680b57cec5SDimitry Andric   return new(C) SEHExceptStmt(Loc,FilterExpr,Block);
12690b57cec5SDimitry Andric }
12700b57cec5SDimitry Andric 
SEHFinallyStmt(SourceLocation Loc,Stmt * Block)12710b57cec5SDimitry Andric SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block)
12720b57cec5SDimitry Andric     : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {}
12730b57cec5SDimitry Andric 
Create(const ASTContext & C,SourceLocation Loc,Stmt * Block)12740b57cec5SDimitry Andric SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc,
12750b57cec5SDimitry Andric                                        Stmt *Block) {
12760b57cec5SDimitry Andric   return new(C)SEHFinallyStmt(Loc,Block);
12770b57cec5SDimitry Andric }
12780b57cec5SDimitry Andric 
Capture(SourceLocation Loc,VariableCaptureKind Kind,VarDecl * Var)12790b57cec5SDimitry Andric CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind,
12800b57cec5SDimitry Andric                                VarDecl *Var)
12810b57cec5SDimitry Andric     : VarAndKind(Var, Kind), Loc(Loc) {
12820b57cec5SDimitry Andric   switch (Kind) {
12830b57cec5SDimitry Andric   case VCK_This:
12840b57cec5SDimitry Andric     assert(!Var && "'this' capture cannot have a variable!");
12850b57cec5SDimitry Andric     break;
12860b57cec5SDimitry Andric   case VCK_ByRef:
12870b57cec5SDimitry Andric     assert(Var && "capturing by reference must have a variable!");
12880b57cec5SDimitry Andric     break;
12890b57cec5SDimitry Andric   case VCK_ByCopy:
12900b57cec5SDimitry Andric     assert(Var && "capturing by copy must have a variable!");
12910b57cec5SDimitry Andric     break;
12920b57cec5SDimitry Andric   case VCK_VLAType:
12930b57cec5SDimitry Andric     assert(!Var &&
12940b57cec5SDimitry Andric            "Variable-length array type capture cannot have a variable!");
12950b57cec5SDimitry Andric     break;
12960b57cec5SDimitry Andric   }
12970b57cec5SDimitry Andric }
12980b57cec5SDimitry Andric 
12990b57cec5SDimitry Andric CapturedStmt::VariableCaptureKind
getCaptureKind() const13000b57cec5SDimitry Andric CapturedStmt::Capture::getCaptureKind() const {
13010b57cec5SDimitry Andric   return VarAndKind.getInt();
13020b57cec5SDimitry Andric }
13030b57cec5SDimitry Andric 
getCapturedVar() const13040b57cec5SDimitry Andric VarDecl *CapturedStmt::Capture::getCapturedVar() const {
13050b57cec5SDimitry Andric   assert((capturesVariable() || capturesVariableByCopy()) &&
13060b57cec5SDimitry Andric          "No variable available for 'this' or VAT capture");
13070b57cec5SDimitry Andric   return VarAndKind.getPointer();
13080b57cec5SDimitry Andric }
13090b57cec5SDimitry Andric 
getStoredCaptures() const13100b57cec5SDimitry Andric CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const {
13110b57cec5SDimitry Andric   unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
13120b57cec5SDimitry Andric 
13130b57cec5SDimitry Andric   // Offset of the first Capture object.
13140b57cec5SDimitry Andric   unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture));
13150b57cec5SDimitry Andric 
13160b57cec5SDimitry Andric   return reinterpret_cast<Capture *>(
13170b57cec5SDimitry Andric       reinterpret_cast<char *>(const_cast<CapturedStmt *>(this))
13180b57cec5SDimitry Andric       + FirstCaptureOffset);
13190b57cec5SDimitry Andric }
13200b57cec5SDimitry Andric 
CapturedStmt(Stmt * S,CapturedRegionKind Kind,ArrayRef<Capture> Captures,ArrayRef<Expr * > CaptureInits,CapturedDecl * CD,RecordDecl * RD)13210b57cec5SDimitry Andric CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind,
13220b57cec5SDimitry Andric                            ArrayRef<Capture> Captures,
13230b57cec5SDimitry Andric                            ArrayRef<Expr *> CaptureInits,
13240b57cec5SDimitry Andric                            CapturedDecl *CD,
13250b57cec5SDimitry Andric                            RecordDecl *RD)
13260b57cec5SDimitry Andric   : Stmt(CapturedStmtClass), NumCaptures(Captures.size()),
13270b57cec5SDimitry Andric     CapDeclAndKind(CD, Kind), TheRecordDecl(RD) {
13280b57cec5SDimitry Andric   assert( S && "null captured statement");
13290b57cec5SDimitry Andric   assert(CD && "null captured declaration for captured statement");
13300b57cec5SDimitry Andric   assert(RD && "null record declaration for captured statement");
13310b57cec5SDimitry Andric 
13320b57cec5SDimitry Andric   // Copy initialization expressions.
13330b57cec5SDimitry Andric   Stmt **Stored = getStoredStmts();
13340b57cec5SDimitry Andric   for (unsigned I = 0, N = NumCaptures; I != N; ++I)
13350b57cec5SDimitry Andric     *Stored++ = CaptureInits[I];
13360b57cec5SDimitry Andric 
13370b57cec5SDimitry Andric   // Copy the statement being captured.
13380b57cec5SDimitry Andric   *Stored = S;
13390b57cec5SDimitry Andric 
13400b57cec5SDimitry Andric   // Copy all Capture objects.
13410b57cec5SDimitry Andric   Capture *Buffer = getStoredCaptures();
13420b57cec5SDimitry Andric   std::copy(Captures.begin(), Captures.end(), Buffer);
13430b57cec5SDimitry Andric }
13440b57cec5SDimitry Andric 
CapturedStmt(EmptyShell Empty,unsigned NumCaptures)13450b57cec5SDimitry Andric CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures)
13460b57cec5SDimitry Andric   : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures),
13470b57cec5SDimitry Andric     CapDeclAndKind(nullptr, CR_Default) {
13480b57cec5SDimitry Andric   getStoredStmts()[NumCaptures] = nullptr;
134906c3fb27SDimitry Andric 
135006c3fb27SDimitry Andric   // Construct default capture objects.
135106c3fb27SDimitry Andric   Capture *Buffer = getStoredCaptures();
135206c3fb27SDimitry Andric   for (unsigned I = 0, N = NumCaptures; I != N; ++I)
135306c3fb27SDimitry Andric     new (Buffer++) Capture();
13540b57cec5SDimitry Andric }
13550b57cec5SDimitry Andric 
Create(const ASTContext & Context,Stmt * S,CapturedRegionKind Kind,ArrayRef<Capture> Captures,ArrayRef<Expr * > CaptureInits,CapturedDecl * CD,RecordDecl * RD)13560b57cec5SDimitry Andric CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S,
13570b57cec5SDimitry Andric                                    CapturedRegionKind Kind,
13580b57cec5SDimitry Andric                                    ArrayRef<Capture> Captures,
13590b57cec5SDimitry Andric                                    ArrayRef<Expr *> CaptureInits,
13600b57cec5SDimitry Andric                                    CapturedDecl *CD,
13610b57cec5SDimitry Andric                                    RecordDecl *RD) {
13620b57cec5SDimitry Andric   // The layout is
13630b57cec5SDimitry Andric   //
13640b57cec5SDimitry Andric   // -----------------------------------------------------------
13650b57cec5SDimitry Andric   // | CapturedStmt, Init, ..., Init, S, Capture, ..., Capture |
13660b57cec5SDimitry Andric   // ----------------^-------------------^----------------------
13670b57cec5SDimitry Andric   //                 getStoredStmts()    getStoredCaptures()
13680b57cec5SDimitry Andric   //
13690b57cec5SDimitry Andric   // where S is the statement being captured.
13700b57cec5SDimitry Andric   //
13710b57cec5SDimitry Andric   assert(CaptureInits.size() == Captures.size() && "wrong number of arguments");
13720b57cec5SDimitry Andric 
13730b57cec5SDimitry Andric   unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1);
13740b57cec5SDimitry Andric   if (!Captures.empty()) {
13750b57cec5SDimitry Andric     // Realign for the following Capture array.
13760b57cec5SDimitry Andric     Size = llvm::alignTo(Size, alignof(Capture));
13770b57cec5SDimitry Andric     Size += sizeof(Capture) * Captures.size();
13780b57cec5SDimitry Andric   }
13790b57cec5SDimitry Andric 
13800b57cec5SDimitry Andric   void *Mem = Context.Allocate(Size);
13810b57cec5SDimitry Andric   return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD);
13820b57cec5SDimitry Andric }
13830b57cec5SDimitry Andric 
CreateDeserialized(const ASTContext & Context,unsigned NumCaptures)13840b57cec5SDimitry Andric CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context,
13850b57cec5SDimitry Andric                                                unsigned NumCaptures) {
13860b57cec5SDimitry Andric   unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
13870b57cec5SDimitry Andric   if (NumCaptures > 0) {
13880b57cec5SDimitry Andric     // Realign for the following Capture array.
13890b57cec5SDimitry Andric     Size = llvm::alignTo(Size, alignof(Capture));
13900b57cec5SDimitry Andric     Size += sizeof(Capture) * NumCaptures;
13910b57cec5SDimitry Andric   }
13920b57cec5SDimitry Andric 
13930b57cec5SDimitry Andric   void *Mem = Context.Allocate(Size);
13940b57cec5SDimitry Andric   return new (Mem) CapturedStmt(EmptyShell(), NumCaptures);
13950b57cec5SDimitry Andric }
13960b57cec5SDimitry Andric 
children()13970b57cec5SDimitry Andric Stmt::child_range CapturedStmt::children() {
13980b57cec5SDimitry Andric   // Children are captured field initializers.
13990b57cec5SDimitry Andric   return child_range(getStoredStmts(), getStoredStmts() + NumCaptures);
14000b57cec5SDimitry Andric }
14010b57cec5SDimitry Andric 
children() const14020b57cec5SDimitry Andric Stmt::const_child_range CapturedStmt::children() const {
14030b57cec5SDimitry Andric   return const_child_range(getStoredStmts(), getStoredStmts() + NumCaptures);
14040b57cec5SDimitry Andric }
14050b57cec5SDimitry Andric 
getCapturedDecl()14060b57cec5SDimitry Andric CapturedDecl *CapturedStmt::getCapturedDecl() {
14070b57cec5SDimitry Andric   return CapDeclAndKind.getPointer();
14080b57cec5SDimitry Andric }
14090b57cec5SDimitry Andric 
getCapturedDecl() const14100b57cec5SDimitry Andric const CapturedDecl *CapturedStmt::getCapturedDecl() const {
14110b57cec5SDimitry Andric   return CapDeclAndKind.getPointer();
14120b57cec5SDimitry Andric }
14130b57cec5SDimitry Andric 
14140b57cec5SDimitry Andric /// Set the outlined function declaration.
setCapturedDecl(CapturedDecl * D)14150b57cec5SDimitry Andric void CapturedStmt::setCapturedDecl(CapturedDecl *D) {
14160b57cec5SDimitry Andric   assert(D && "null CapturedDecl");
14170b57cec5SDimitry Andric   CapDeclAndKind.setPointer(D);
14180b57cec5SDimitry Andric }
14190b57cec5SDimitry Andric 
14200b57cec5SDimitry Andric /// Retrieve the captured region kind.
getCapturedRegionKind() const14210b57cec5SDimitry Andric CapturedRegionKind CapturedStmt::getCapturedRegionKind() const {
14220b57cec5SDimitry Andric   return CapDeclAndKind.getInt();
14230b57cec5SDimitry Andric }
14240b57cec5SDimitry Andric 
14250b57cec5SDimitry Andric /// Set the captured region kind.
setCapturedRegionKind(CapturedRegionKind Kind)14260b57cec5SDimitry Andric void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) {
14270b57cec5SDimitry Andric   CapDeclAndKind.setInt(Kind);
14280b57cec5SDimitry Andric }
14290b57cec5SDimitry Andric 
capturesVariable(const VarDecl * Var) const14300b57cec5SDimitry Andric bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
14310b57cec5SDimitry Andric   for (const auto &I : captures()) {
14320b57cec5SDimitry Andric     if (!I.capturesVariable() && !I.capturesVariableByCopy())
14330b57cec5SDimitry Andric       continue;
14340b57cec5SDimitry Andric     if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl())
14350b57cec5SDimitry Andric       return true;
14360b57cec5SDimitry Andric   }
14370b57cec5SDimitry Andric 
14380b57cec5SDimitry Andric   return false;
14390b57cec5SDimitry Andric }
1440