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
getStmtInfoTableEntry(Stmt::StmtClass E)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
operator new(size_t bytes,const ASTContext & C,unsigned alignment)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
getStmtClassName() const790b57cec5SDimitry 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
PrintStats()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
addStmtClass(StmtClass s)1260b57cec5SDimitry Andric void Stmt::addStmtClass(StmtClass s) {
1270b57cec5SDimitry Andric ++getStmtInfoTableEntry(s).Counter;
1280b57cec5SDimitry Andric }
1290b57cec5SDimitry Andric
1300b57cec5SDimitry Andric bool Stmt::StatisticsEnabled = false;
EnableStatistics()1310b57cec5SDimitry Andric void Stmt::EnableStatistics() {
1320b57cec5SDimitry Andric StatisticsEnabled = true;
1330b57cec5SDimitry Andric }
1340b57cec5SDimitry Andric
135e8d8bef9SDimitry Andric static std::pair<Stmt::Likelihood, const Attr *>
getLikelihood(ArrayRef<const Attr * > Attrs)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
getLikelihood(const Stmt * S)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
getLikelihood(ArrayRef<const Attr * > Attrs)155e8d8bef9SDimitry Andric Stmt::Likelihood Stmt::getLikelihood(ArrayRef<const Attr *> Attrs) {
156e8d8bef9SDimitry Andric return ::getLikelihood(Attrs).first;
157e8d8bef9SDimitry Andric }
158e8d8bef9SDimitry Andric
getLikelihood(const Stmt * S)159e8d8bef9SDimitry Andric Stmt::Likelihood Stmt::getLikelihood(const Stmt *S) {
160e8d8bef9SDimitry Andric return ::getLikelihood(S).first;
161e8d8bef9SDimitry Andric }
162e8d8bef9SDimitry Andric
getLikelihoodAttr(const Stmt * S)163e8d8bef9SDimitry Andric const Attr *Stmt::getLikelihoodAttr(const Stmt *S) {
164e8d8bef9SDimitry Andric return ::getLikelihood(S).second;
165e8d8bef9SDimitry Andric }
166e8d8bef9SDimitry Andric
getLikelihood(const Stmt * Then,const Stmt * Else)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 *>
determineLikelihoodConflict(const Stmt * Then,const Stmt * Else)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.
IgnoreContainers(bool IgnoreCaptured)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.
stripLabelLikeStatements() const2190b57cec5SDimitry 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.
is_good(good)2410b57cec5SDimitry Andric static good is_good(good) { return good(); }
2420b57cec5SDimitry Andric
2430b57cec5SDimitry Andric typedef Stmt::child_range children_t();
implements_children(children_t T::*)2440b57cec5SDimitry Andric template <class T> good implements_children(children_t T::*) {
2450b57cec5SDimitry Andric return good();
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric LLVM_ATTRIBUTE_UNUSED
implements_children(children_t Stmt::*)2480b57cec5SDimitry Andric static bad implements_children(children_t Stmt::*) {
2490b57cec5SDimitry Andric return bad();
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric
2520b57cec5SDimitry Andric typedef SourceLocation getBeginLoc_t() const;
implements_getBeginLoc(getBeginLoc_t T::*)2530b57cec5SDimitry Andric template <class T> good implements_getBeginLoc(getBeginLoc_t T::*) {
2540b57cec5SDimitry Andric return good();
2550b57cec5SDimitry Andric }
2560b57cec5SDimitry Andric LLVM_ATTRIBUTE_UNUSED
implements_getBeginLoc(getBeginLoc_t Stmt::*)2570b57cec5SDimitry Andric static bad implements_getBeginLoc(getBeginLoc_t Stmt::*) { return bad(); }
2580b57cec5SDimitry Andric
2590b57cec5SDimitry Andric typedef SourceLocation getLocEnd_t() const;
implements_getEndLoc(getLocEnd_t T::*)2600b57cec5SDimitry Andric template <class T> good implements_getEndLoc(getLocEnd_t T::*) {
2610b57cec5SDimitry Andric return good();
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric LLVM_ATTRIBUTE_UNUSED
implements_getEndLoc(getLocEnd_t Stmt::*)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
check_implementations()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
children()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>
getSourceRangeImpl(const Stmt * stmt,SourceRange (T::* v)()const)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>
getSourceRangeImpl(const Stmt * stmt,SourceRange (Stmt::* v)()const)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
getSourceRange() const3260b57cec5SDimitry 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
getBeginLoc() const3380b57cec5SDimitry 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
getEndLoc() const3500b57cec5SDimitry 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
getID(const ASTContext & Context) const3620b57cec5SDimitry Andric int64_t Stmt::getID(const ASTContext &Context) const {
3630b57cec5SDimitry Andric return Context.getAllocator().identifyKnownAlignedObject<Stmt>(this);
3640b57cec5SDimitry Andric }
3650b57cec5SDimitry Andric
CompoundStmt(ArrayRef<Stmt * > Stmts,FPOptionsOverride FPFeatures,SourceLocation LB,SourceLocation RB)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
setStmts(ArrayRef<Stmt * > Stmts)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
Create(const ASTContext & C,ArrayRef<Stmt * > Stmts,FPOptionsOverride FPFeatures,SourceLocation LB,SourceLocation RB)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
CreateEmpty(const ASTContext & C,unsigned NumStmts,bool HasFPFeatures)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
getExprStmt() const4040b57cec5SDimitry 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
getName() const4210b57cec5SDimitry Andric const char *LabelStmt::getName() const {
4220b57cec5SDimitry Andric return getDecl()->getIdentifier()->getNameStart();
4230b57cec5SDimitry Andric }
4240b57cec5SDimitry Andric
Create(const ASTContext & C,SourceLocation Loc,ArrayRef<const Attr * > Attrs,Stmt * SubStmt)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
CreateEmpty(const ASTContext & C,unsigned NumAttrs)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
generateAsmString(const ASTContext & C) const4420b57cec5SDimitry 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
getOutputConstraint(unsigned i) const4500b57cec5SDimitry 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
getOutputExpr(unsigned i) const4580b57cec5SDimitry 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
getInputConstraint(unsigned i) const4660b57cec5SDimitry 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
getInputExpr(unsigned i) const4740b57cec5SDimitry 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
getClobber(unsigned i) const4820b57cec5SDimitry 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.
getNumPlusOperands() const4920b57cec5SDimitry 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
getModifier() const5000b57cec5SDimitry 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
getClobber(unsigned i) const5050b57cec5SDimitry Andric StringRef GCCAsmStmt::getClobber(unsigned i) const {
5060b57cec5SDimitry Andric return getClobberStringLiteral(i)->getString();
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric
getOutputExpr(unsigned i)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 '+').
getOutputConstraint(unsigned i) const5160b57cec5SDimitry Andric StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const {
5170b57cec5SDimitry Andric return getOutputConstraintLiteral(i)->getString();
5180b57cec5SDimitry Andric }
5190b57cec5SDimitry Andric
getInputExpr(unsigned i)5200b57cec5SDimitry Andric Expr *GCCAsmStmt::getInputExpr(unsigned i) {
5210b57cec5SDimitry Andric return cast<Expr>(Exprs[i + NumOutputs]);
5220b57cec5SDimitry Andric }
5230b57cec5SDimitry Andric
setInputExpr(unsigned i,Expr * E)5240b57cec5SDimitry Andric void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) {
5250b57cec5SDimitry Andric Exprs[i + NumOutputs] = E;
5260b57cec5SDimitry Andric }
5270b57cec5SDimitry Andric
getLabelExpr(unsigned i) const5280b57cec5SDimitry Andric AddrLabelExpr *GCCAsmStmt::getLabelExpr(unsigned i) const {
5295ffd83dbSDimitry Andric return cast<AddrLabelExpr>(Exprs[i + NumOutputs + NumInputs]);
5300b57cec5SDimitry Andric }
5310b57cec5SDimitry Andric
getLabelName(unsigned i) const5320b57cec5SDimitry 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.
getInputConstraint(unsigned i) const5380b57cec5SDimitry Andric StringRef GCCAsmStmt::getInputConstraint(unsigned i) const {
5390b57cec5SDimitry Andric return getInputConstraintLiteral(i)->getString();
5400b57cec5SDimitry Andric }
5410b57cec5SDimitry Andric
setOutputsAndInputsAndClobbers(const ASTContext & C,IdentifierInfo ** Names,StringLiteral ** Constraints,Stmt ** Exprs,unsigned NumOutputs,unsigned NumInputs,unsigned NumLabels,StringLiteral ** Clobbers,unsigned NumClobbers)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.
getNamedOperand(StringRef SymbolicName) const5790b57cec5SDimitry 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.
AnalyzeAsmString(SmallVectorImpl<AsmStringPiece> & Pieces,const ASTContext & C,unsigned & DiagOffs) const6020b57cec5SDimitry 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).
generateAsmString(const ASTContext & C) const7850b57cec5SDimitry 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).
generateAsmString(const ASTContext & C) const8060b57cec5SDimitry 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
getOutputExpr(unsigned i)8320b57cec5SDimitry Andric Expr *MSAsmStmt::getOutputExpr(unsigned i) {
8330b57cec5SDimitry Andric return cast<Expr>(Exprs[i]);
8340b57cec5SDimitry Andric }
8350b57cec5SDimitry Andric
getInputExpr(unsigned i)8360b57cec5SDimitry Andric Expr *MSAsmStmt::getInputExpr(unsigned i) {
8370b57cec5SDimitry Andric return cast<Expr>(Exprs[i + NumOutputs]);
8380b57cec5SDimitry Andric }
8390b57cec5SDimitry Andric
setInputExpr(unsigned i,Expr * E)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
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)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
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)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
copyIntoContext(const ASTContext & C,StringRef str)8870b57cec5SDimitry Andric static StringRef copyIntoContext(const ASTContext &C, StringRef str) {
8880b57cec5SDimitry Andric return str.copy(C);
8890b57cec5SDimitry Andric }
8900b57cec5SDimitry Andric
initialize(const ASTContext & C,StringRef asmstr,ArrayRef<Token> asmtoks,ArrayRef<StringRef> constraints,ArrayRef<Expr * > exprs,ArrayRef<StringRef> clobbers)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
IfStmt(const ASTContext & Ctx,SourceLocation IL,IfStatementKind Kind,Stmt * Init,VarDecl * Var,Expr * Cond,SourceLocation LPL,SourceLocation RPL,Stmt * Then,SourceLocation EL,Stmt * Else)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
IfStmt(EmptyShell Empty,bool HasElse,bool HasVar,bool HasInit)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
Create(const ASTContext & Ctx,SourceLocation IL,IfStatementKind Kind,Stmt * Init,VarDecl * Var,Expr * Cond,SourceLocation LPL,SourceLocation RPL,Stmt * Then,SourceLocation EL,Stmt * Else)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
CreateEmpty(const ASTContext & Ctx,bool HasElse,bool HasVar,bool HasInit)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
getConditionVariable()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
setConditionVariable(const ASTContext & Ctx,VarDecl * V)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
isObjCAvailabilityCheck() const10030b57cec5SDimitry Andric bool IfStmt::isObjCAvailabilityCheck() const {
10040b57cec5SDimitry Andric return isa<ObjCAvailabilityCheckExpr>(getCond());
10050b57cec5SDimitry Andric }
10060b57cec5SDimitry Andric
getNondiscardedCase(const ASTContext & Ctx)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 *>
getNondiscardedCase(const ASTContext & Ctx) const1014fe6060f1SDimitry 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
ForStmt(const ASTContext & C,Stmt * Init,Expr * Cond,VarDecl * condVar,Expr * Inc,Stmt * Body,SourceLocation FL,SourceLocation LP,SourceLocation RP)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
getConditionVariable() const10340b57cec5SDimitry 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
setConditionVariable(const ASTContext & C,VarDecl * V)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
SwitchStmt(const ASTContext & Ctx,Stmt * Init,VarDecl * Var,Expr * Cond,SourceLocation LParenLoc,SourceLocation RParenLoc)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
SwitchStmt(EmptyShell Empty,bool HasInit,bool HasVar)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
Create(const ASTContext & Ctx,Stmt * Init,VarDecl * Var,Expr * Cond,SourceLocation LParenLoc,SourceLocation RParenLoc)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
CreateEmpty(const ASTContext & Ctx,bool HasInit,bool HasVar)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
getConditionVariable()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
setConditionVariable(const ASTContext & Ctx,VarDecl * V)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
WhileStmt(const ASTContext & Ctx,VarDecl * Var,Expr * Cond,Stmt * Body,SourceLocation WL,SourceLocation LParenLoc,SourceLocation RParenLoc)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
WhileStmt(EmptyShell Empty,bool HasVar)11380b57cec5SDimitry Andric WhileStmt::WhileStmt(EmptyShell Empty, bool HasVar)
11390b57cec5SDimitry Andric : Stmt(WhileStmtClass, Empty) {
11400b57cec5SDimitry Andric WhileStmtBits.HasVar = HasVar;
11410b57cec5SDimitry Andric }
11420b57cec5SDimitry Andric
Create(const ASTContext & Ctx,VarDecl * Var,Expr * Cond,Stmt * Body,SourceLocation WL,SourceLocation LParenLoc,SourceLocation RParenLoc)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
CreateEmpty(const ASTContext & Ctx,bool HasVar)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
getConditionVariable()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
setConditionVariable(const ASTContext & Ctx,VarDecl * V)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
getConstantTarget()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
ReturnStmt(SourceLocation RL,Expr * E,const VarDecl * NRVOCandidate)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
ReturnStmt(EmptyShell Empty,bool HasNRVOCandidate)11990b57cec5SDimitry Andric ReturnStmt::ReturnStmt(EmptyShell Empty, bool HasNRVOCandidate)
12000b57cec5SDimitry Andric : Stmt(ReturnStmtClass, Empty) {
12010b57cec5SDimitry Andric ReturnStmtBits.HasNRVOCandidate = HasNRVOCandidate;
12020b57cec5SDimitry Andric }
12030b57cec5SDimitry Andric
Create(const ASTContext & Ctx,SourceLocation RL,Expr * E,const VarDecl * NRVOCandidate)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
CreateEmpty(const ASTContext & Ctx,bool HasNRVOCandidate)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
Create(const ASTContext & Ctx,Expr * lhs,Expr * rhs,SourceLocation caseLoc,SourceLocation ellipsisLoc,SourceLocation colonLoc)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
CreateEmpty(const ASTContext & Ctx,bool CaseStmtIsGNURange)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
SEHTryStmt(bool IsCXXTry,SourceLocation TryLoc,Stmt * TryBlock,Stmt * Handler)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
Create(const ASTContext & C,bool IsCXXTry,SourceLocation TryLoc,Stmt * TryBlock,Stmt * Handler)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
getExceptHandler() const12530b57cec5SDimitry Andric SEHExceptStmt* SEHTryStmt::getExceptHandler() const {
12540b57cec5SDimitry Andric return dyn_cast<SEHExceptStmt>(getHandler());
12550b57cec5SDimitry Andric }
12560b57cec5SDimitry Andric
getFinallyHandler() const12570b57cec5SDimitry Andric SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const {
12580b57cec5SDimitry Andric return dyn_cast<SEHFinallyStmt>(getHandler());
12590b57cec5SDimitry Andric }
12600b57cec5SDimitry Andric
SEHExceptStmt(SourceLocation Loc,Expr * FilterExpr,Stmt * Block)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
Create(const ASTContext & C,SourceLocation Loc,Expr * FilterExpr,Stmt * Block)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
SEHFinallyStmt(SourceLocation Loc,Stmt * Block)12720b57cec5SDimitry Andric SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block)
12730b57cec5SDimitry Andric : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {}
12740b57cec5SDimitry Andric
Create(const ASTContext & C,SourceLocation Loc,Stmt * Block)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
Capture(SourceLocation Loc,VariableCaptureKind Kind,VarDecl * Var)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
getCaptureKind() const13010b57cec5SDimitry Andric CapturedStmt::Capture::getCaptureKind() const {
13020b57cec5SDimitry Andric return VarAndKind.getInt();
13030b57cec5SDimitry Andric }
13040b57cec5SDimitry Andric
getCapturedVar() const13050b57cec5SDimitry 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
getStoredCaptures() const13110b57cec5SDimitry 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
CapturedStmt(Stmt * S,CapturedRegionKind Kind,ArrayRef<Capture> Captures,ArrayRef<Expr * > CaptureInits,CapturedDecl * CD,RecordDecl * RD)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
CapturedStmt(EmptyShell Empty,unsigned NumCaptures)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
Create(const ASTContext & Context,Stmt * S,CapturedRegionKind Kind,ArrayRef<Capture> Captures,ArrayRef<Expr * > CaptureInits,CapturedDecl * CD,RecordDecl * RD)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
CreateDeserialized(const ASTContext & Context,unsigned NumCaptures)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
children()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
children() const14030b57cec5SDimitry Andric Stmt::const_child_range CapturedStmt::children() const {
14040b57cec5SDimitry Andric return const_child_range(getStoredStmts(), getStoredStmts() + NumCaptures);
14050b57cec5SDimitry Andric }
14060b57cec5SDimitry Andric
getCapturedDecl()14070b57cec5SDimitry Andric CapturedDecl *CapturedStmt::getCapturedDecl() {
14080b57cec5SDimitry Andric return CapDeclAndKind.getPointer();
14090b57cec5SDimitry Andric }
14100b57cec5SDimitry Andric
getCapturedDecl() const14110b57cec5SDimitry Andric const CapturedDecl *CapturedStmt::getCapturedDecl() const {
14120b57cec5SDimitry Andric return CapDeclAndKind.getPointer();
14130b57cec5SDimitry Andric }
14140b57cec5SDimitry Andric
14150b57cec5SDimitry Andric /// Set the outlined function declaration.
setCapturedDecl(CapturedDecl * D)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.
getCapturedRegionKind() const14220b57cec5SDimitry Andric CapturedRegionKind CapturedStmt::getCapturedRegionKind() const {
14230b57cec5SDimitry Andric return CapDeclAndKind.getInt();
14240b57cec5SDimitry Andric }
14250b57cec5SDimitry Andric
14260b57cec5SDimitry Andric /// Set the captured region kind.
setCapturedRegionKind(CapturedRegionKind Kind)14270b57cec5SDimitry Andric void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) {
14280b57cec5SDimitry Andric CapDeclAndKind.setInt(Kind);
14290b57cec5SDimitry Andric }
14300b57cec5SDimitry Andric
capturesVariable(const VarDecl * Var) const14310b57cec5SDimitry 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