xref: /openbsd-src/gnu/llvm/clang/lib/AST/Stmt.cpp (revision 12c855180aad702bbcca06e0398d774beeafb155)
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