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