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