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