1 //===- Stmt.cpp - Statement AST Node Implementation -----------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the Stmt class and statement subclasses.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "clang/AST/Stmt.h"
15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/ASTDiagnostic.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/ExprObjC.h"
22 #include "clang/AST/ExprOpenMP.h"
23 #include "clang/AST/StmtCXX.h"
24 #include "clang/AST/StmtObjC.h"
25 #include "clang/AST/StmtOpenMP.h"
26 #include "clang/AST/Type.h"
27 #include "clang/Basic/CharInfo.h"
28 #include "clang/Basic/LLVM.h"
29 #include "clang/Basic/SourceLocation.h"
30 #include "clang/Basic/TargetInfo.h"
31 #include "clang/Lex/Token.h"
32 #include "llvm/ADT/SmallVector.h"
33 #include "llvm/ADT/StringExtras.h"
34 #include "llvm/ADT/StringRef.h"
35 #include "llvm/Support/Casting.h"
36 #include "llvm/Support/Compiler.h"
37 #include "llvm/Support/ErrorHandling.h"
38 #include "llvm/Support/MathExtras.h"
39 #include "llvm/Support/raw_ostream.h"
40 #include <algorithm>
41 #include <cassert>
42 #include <cstring>
43 #include <string>
44 #include <utility>
45 
46 using namespace clang;
47 
48 static struct StmtClassNameTable {
49   const char *Name;
50   unsigned Counter;
51   unsigned Size;
52 } StmtClassInfo[Stmt::lastStmtConstant+1];
53 
getStmtInfoTableEntry(Stmt::StmtClass E)54 static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
55   static bool Initialized = false;
56   if (Initialized)
57     return StmtClassInfo[E];
58 
59   // Initialize the table on the first use.
60   Initialized = true;
61 #define ABSTRACT_STMT(STMT)
62 #define STMT(CLASS, PARENT) \
63   StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS;    \
64   StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
65 #include "clang/AST/StmtNodes.inc"
66 
67   return StmtClassInfo[E];
68 }
69 
operator new(size_t bytes,const ASTContext & C,unsigned alignment)70 void *Stmt::operator new(size_t bytes, const ASTContext& C,
71                          unsigned alignment) {
72   return ::operator new(bytes, C, alignment);
73 }
74 
getStmtClassName() const75 const char *Stmt::getStmtClassName() const {
76   return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name;
77 }
78 
PrintStats()79 void Stmt::PrintStats() {
80   // Ensure the table is primed.
81   getStmtInfoTableEntry(Stmt::NullStmtClass);
82 
83   unsigned sum = 0;
84   llvm::errs() << "\n*** Stmt/Expr Stats:\n";
85   for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
86     if (StmtClassInfo[i].Name == nullptr) continue;
87     sum += StmtClassInfo[i].Counter;
88   }
89   llvm::errs() << "  " << sum << " stmts/exprs total.\n";
90   sum = 0;
91   for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
92     if (StmtClassInfo[i].Name == nullptr) continue;
93     if (StmtClassInfo[i].Counter == 0) continue;
94     llvm::errs() << "    " << StmtClassInfo[i].Counter << " "
95                  << StmtClassInfo[i].Name << ", " << StmtClassInfo[i].Size
96                  << " each (" << StmtClassInfo[i].Counter*StmtClassInfo[i].Size
97                  << " bytes)\n";
98     sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
99   }
100 
101   llvm::errs() << "Total bytes = " << sum << "\n";
102 }
103 
addStmtClass(StmtClass s)104 void Stmt::addStmtClass(StmtClass s) {
105   ++getStmtInfoTableEntry(s).Counter;
106 }
107 
108 bool Stmt::StatisticsEnabled = false;
EnableStatistics()109 void Stmt::EnableStatistics() {
110   StatisticsEnabled = true;
111 }
112 
IgnoreImplicit()113 Stmt *Stmt::IgnoreImplicit() {
114   Stmt *s = this;
115 
116   if (auto *ewc = dyn_cast<ExprWithCleanups>(s))
117     s = ewc->getSubExpr();
118 
119   if (auto *mte = dyn_cast<MaterializeTemporaryExpr>(s))
120     s = mte->GetTemporaryExpr();
121 
122   if (auto *bte = dyn_cast<CXXBindTemporaryExpr>(s))
123     s = bte->getSubExpr();
124 
125   while (auto *ice = dyn_cast<ImplicitCastExpr>(s))
126     s = ice->getSubExpr();
127 
128   return s;
129 }
130 
131 /// Skip no-op (attributed, compound) container stmts and skip captured
132 /// stmt at the top, if \a IgnoreCaptured is true.
IgnoreContainers(bool IgnoreCaptured)133 Stmt *Stmt::IgnoreContainers(bool IgnoreCaptured) {
134   Stmt *S = this;
135   if (IgnoreCaptured)
136     if (auto CapS = dyn_cast_or_null<CapturedStmt>(S))
137       S = CapS->getCapturedStmt();
138   while (true) {
139     if (auto AS = dyn_cast_or_null<AttributedStmt>(S))
140       S = AS->getSubStmt();
141     else if (auto CS = dyn_cast_or_null<CompoundStmt>(S)) {
142       if (CS->size() != 1)
143         break;
144       S = CS->body_back();
145     } else
146       break;
147   }
148   return S;
149 }
150 
151 /// Strip off all label-like statements.
152 ///
153 /// This will strip off label statements, case statements, attributed
154 /// statements and default statements recursively.
stripLabelLikeStatements() const155 const Stmt *Stmt::stripLabelLikeStatements() const {
156   const Stmt *S = this;
157   while (true) {
158     if (const auto *LS = dyn_cast<LabelStmt>(S))
159       S = LS->getSubStmt();
160     else if (const auto *SC = dyn_cast<SwitchCase>(S))
161       S = SC->getSubStmt();
162     else if (const auto *AS = dyn_cast<AttributedStmt>(S))
163       S = AS->getSubStmt();
164     else
165       return S;
166   }
167 }
168 
169 namespace {
170 
171   struct good {};
172   struct bad {};
173 
174   // These silly little functions have to be static inline to suppress
175   // unused warnings, and they have to be defined to suppress other
176   // warnings.
is_good(good)177   static good is_good(good) { return good(); }
178 
179   typedef Stmt::child_range children_t();
implements_children(children_t T::*)180   template <class T> good implements_children(children_t T::*) {
181     return good();
182   }
183   LLVM_ATTRIBUTE_UNUSED
implements_children(children_t Stmt::*)184   static bad implements_children(children_t Stmt::*) {
185     return bad();
186   }
187 
188   typedef SourceLocation getLocStart_t() const;
implements_getLocStart(getLocStart_t T::*)189   template <class T> good implements_getLocStart(getLocStart_t T::*) {
190     return good();
191   }
192   LLVM_ATTRIBUTE_UNUSED
implements_getLocStart(getLocStart_t Stmt::*)193   static bad implements_getLocStart(getLocStart_t Stmt::*) {
194     return bad();
195   }
196 
197   typedef SourceLocation getLocEnd_t() const;
implements_getLocEnd(getLocEnd_t T::*)198   template <class T> good implements_getLocEnd(getLocEnd_t T::*) {
199     return good();
200   }
201   LLVM_ATTRIBUTE_UNUSED
implements_getLocEnd(getLocEnd_t Stmt::*)202   static bad implements_getLocEnd(getLocEnd_t Stmt::*) {
203     return bad();
204   }
205 
206 #define ASSERT_IMPLEMENTS_children(type) \
207   (void) is_good(implements_children(&type::children))
208 #define ASSERT_IMPLEMENTS_getLocStart(type) \
209   (void) is_good(implements_getLocStart(&type::getLocStart))
210 #define ASSERT_IMPLEMENTS_getLocEnd(type) \
211   (void) is_good(implements_getLocEnd(&type::getLocEnd))
212 
213 } // namespace
214 
215 /// Check whether the various Stmt classes implement their member
216 /// functions.
217 LLVM_ATTRIBUTE_UNUSED
check_implementations()218 static inline void check_implementations() {
219 #define ABSTRACT_STMT(type)
220 #define STMT(type, base) \
221   ASSERT_IMPLEMENTS_children(type); \
222   ASSERT_IMPLEMENTS_getLocStart(type); \
223   ASSERT_IMPLEMENTS_getLocEnd(type);
224 #include "clang/AST/StmtNodes.inc"
225 }
226 
children()227 Stmt::child_range Stmt::children() {
228   switch (getStmtClass()) {
229   case Stmt::NoStmtClass: llvm_unreachable("statement without class");
230 #define ABSTRACT_STMT(type)
231 #define STMT(type, base) \
232   case Stmt::type##Class: \
233     return static_cast<type*>(this)->children();
234 #include "clang/AST/StmtNodes.inc"
235   }
236   llvm_unreachable("unknown statement kind!");
237 }
238 
239 // Amusing macro metaprogramming hack: check whether a class provides
240 // a more specific implementation of getSourceRange.
241 //
242 // See also Expr.cpp:getExprLoc().
243 namespace {
244 
245   /// This implementation is used when a class provides a custom
246   /// implementation of getSourceRange.
247   template <class S, class T>
getSourceRangeImpl(const Stmt * stmt,SourceRange (T::* v)()const)248   SourceRange getSourceRangeImpl(const Stmt *stmt,
249                                  SourceRange (T::*v)() const) {
250     return static_cast<const S*>(stmt)->getSourceRange();
251   }
252 
253   /// This implementation is used when a class doesn't provide a custom
254   /// implementation of getSourceRange.  Overload resolution should pick it over
255   /// the implementation above because it's more specialized according to
256   /// function template partial ordering.
257   template <class S>
getSourceRangeImpl(const Stmt * stmt,SourceRange (Stmt::* v)()const)258   SourceRange getSourceRangeImpl(const Stmt *stmt,
259                                  SourceRange (Stmt::*v)() const) {
260     return SourceRange(static_cast<const S*>(stmt)->getLocStart(),
261                        static_cast<const S*>(stmt)->getLocEnd());
262   }
263 
264 } // namespace
265 
getSourceRange() const266 SourceRange Stmt::getSourceRange() const {
267   switch (getStmtClass()) {
268   case Stmt::NoStmtClass: llvm_unreachable("statement without class");
269 #define ABSTRACT_STMT(type)
270 #define STMT(type, base) \
271   case Stmt::type##Class: \
272     return getSourceRangeImpl<type>(this, &type::getSourceRange);
273 #include "clang/AST/StmtNodes.inc"
274   }
275   llvm_unreachable("unknown statement kind!");
276 }
277 
getBeginLoc() const278 SourceLocation Stmt::getBeginLoc() const {
279   //  llvm::errs() << "getBeginLoc() for " << getStmtClassName() << "\n";
280   switch (getStmtClass()) {
281   case Stmt::NoStmtClass: llvm_unreachable("statement without class");
282 #define ABSTRACT_STMT(type)
283 #define STMT(type, base) \
284   case Stmt::type##Class: \
285     return static_cast<const type*>(this)->getLocStart();
286 #include "clang/AST/StmtNodes.inc"
287   }
288   llvm_unreachable("unknown statement kind");
289 }
290 
getEndLoc() const291 SourceLocation Stmt::getEndLoc() const {
292   switch (getStmtClass()) {
293   case Stmt::NoStmtClass: llvm_unreachable("statement without class");
294 #define ABSTRACT_STMT(type)
295 #define STMT(type, base) \
296   case Stmt::type##Class: \
297     return static_cast<const type*>(this)->getLocEnd();
298 #include "clang/AST/StmtNodes.inc"
299   }
300   llvm_unreachable("unknown statement kind");
301 }
302 
CompoundStmt(ArrayRef<Stmt * > Stmts,SourceLocation LB,SourceLocation RB)303 CompoundStmt::CompoundStmt(ArrayRef<Stmt *> Stmts, SourceLocation LB,
304                            SourceLocation RB)
305     : Stmt(CompoundStmtClass), LBraceLoc(LB), RBraceLoc(RB) {
306   CompoundStmtBits.NumStmts = Stmts.size();
307   setStmts(Stmts);
308 }
309 
setStmts(ArrayRef<Stmt * > Stmts)310 void CompoundStmt::setStmts(ArrayRef<Stmt *> Stmts) {
311   assert(CompoundStmtBits.NumStmts == Stmts.size() &&
312          "NumStmts doesn't fit in bits of CompoundStmtBits.NumStmts!");
313 
314   std::copy(Stmts.begin(), Stmts.end(), body_begin());
315 }
316 
Create(const ASTContext & C,ArrayRef<Stmt * > Stmts,SourceLocation LB,SourceLocation RB)317 CompoundStmt *CompoundStmt::Create(const ASTContext &C, ArrayRef<Stmt *> Stmts,
318                                    SourceLocation LB, SourceLocation RB) {
319   void *Mem =
320       C.Allocate(totalSizeToAlloc<Stmt *>(Stmts.size()), alignof(CompoundStmt));
321   return new (Mem) CompoundStmt(Stmts, LB, RB);
322 }
323 
CreateEmpty(const ASTContext & C,unsigned NumStmts)324 CompoundStmt *CompoundStmt::CreateEmpty(const ASTContext &C,
325                                         unsigned NumStmts) {
326   void *Mem =
327       C.Allocate(totalSizeToAlloc<Stmt *>(NumStmts), alignof(CompoundStmt));
328   CompoundStmt *New = new (Mem) CompoundStmt(EmptyShell());
329   New->CompoundStmtBits.NumStmts = NumStmts;
330   return New;
331 }
332 
getName() const333 const char *LabelStmt::getName() const {
334   return getDecl()->getIdentifier()->getNameStart();
335 }
336 
Create(const ASTContext & C,SourceLocation Loc,ArrayRef<const Attr * > Attrs,Stmt * SubStmt)337 AttributedStmt *AttributedStmt::Create(const ASTContext &C, SourceLocation Loc,
338                                        ArrayRef<const Attr*> Attrs,
339                                        Stmt *SubStmt) {
340   assert(!Attrs.empty() && "Attrs should not be empty");
341   void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(Attrs.size()),
342                          alignof(AttributedStmt));
343   return new (Mem) AttributedStmt(Loc, Attrs, SubStmt);
344 }
345 
CreateEmpty(const ASTContext & C,unsigned NumAttrs)346 AttributedStmt *AttributedStmt::CreateEmpty(const ASTContext &C,
347                                             unsigned NumAttrs) {
348   assert(NumAttrs > 0 && "NumAttrs should be greater than zero");
349   void *Mem = C.Allocate(totalSizeToAlloc<const Attr *>(NumAttrs),
350                          alignof(AttributedStmt));
351   return new (Mem) AttributedStmt(EmptyShell(), NumAttrs);
352 }
353 
generateAsmString(const ASTContext & C) const354 std::string AsmStmt::generateAsmString(const ASTContext &C) const {
355   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
356     return gccAsmStmt->generateAsmString(C);
357   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
358     return msAsmStmt->generateAsmString(C);
359   llvm_unreachable("unknown asm statement kind!");
360 }
361 
getOutputConstraint(unsigned i) const362 StringRef AsmStmt::getOutputConstraint(unsigned i) const {
363   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
364     return gccAsmStmt->getOutputConstraint(i);
365   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
366     return msAsmStmt->getOutputConstraint(i);
367   llvm_unreachable("unknown asm statement kind!");
368 }
369 
getOutputExpr(unsigned i) const370 const Expr *AsmStmt::getOutputExpr(unsigned i) const {
371   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
372     return gccAsmStmt->getOutputExpr(i);
373   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
374     return msAsmStmt->getOutputExpr(i);
375   llvm_unreachable("unknown asm statement kind!");
376 }
377 
getInputConstraint(unsigned i) const378 StringRef AsmStmt::getInputConstraint(unsigned i) const {
379   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
380     return gccAsmStmt->getInputConstraint(i);
381   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
382     return msAsmStmt->getInputConstraint(i);
383   llvm_unreachable("unknown asm statement kind!");
384 }
385 
getInputExpr(unsigned i) const386 const Expr *AsmStmt::getInputExpr(unsigned i) const {
387   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
388     return gccAsmStmt->getInputExpr(i);
389   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
390     return msAsmStmt->getInputExpr(i);
391   llvm_unreachable("unknown asm statement kind!");
392 }
393 
getClobber(unsigned i) const394 StringRef AsmStmt::getClobber(unsigned i) const {
395   if (const auto *gccAsmStmt = dyn_cast<GCCAsmStmt>(this))
396     return gccAsmStmt->getClobber(i);
397   if (const auto *msAsmStmt = dyn_cast<MSAsmStmt>(this))
398     return msAsmStmt->getClobber(i);
399   llvm_unreachable("unknown asm statement kind!");
400 }
401 
402 /// getNumPlusOperands - Return the number of output operands that have a "+"
403 /// constraint.
getNumPlusOperands() const404 unsigned AsmStmt::getNumPlusOperands() const {
405   unsigned Res = 0;
406   for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)
407     if (isOutputPlusConstraint(i))
408       ++Res;
409   return Res;
410 }
411 
getModifier() const412 char GCCAsmStmt::AsmStringPiece::getModifier() const {
413   assert(isOperand() && "Only Operands can have modifiers.");
414   return isLetter(Str[0]) ? Str[0] : '\0';
415 }
416 
getClobber(unsigned i) const417 StringRef GCCAsmStmt::getClobber(unsigned i) const {
418   return getClobberStringLiteral(i)->getString();
419 }
420 
getOutputExpr(unsigned i)421 Expr *GCCAsmStmt::getOutputExpr(unsigned i) {
422   return cast<Expr>(Exprs[i]);
423 }
424 
425 /// getOutputConstraint - Return the constraint string for the specified
426 /// output operand.  All output constraints are known to be non-empty (either
427 /// '=' or '+').
getOutputConstraint(unsigned i) const428 StringRef GCCAsmStmt::getOutputConstraint(unsigned i) const {
429   return getOutputConstraintLiteral(i)->getString();
430 }
431 
getInputExpr(unsigned i)432 Expr *GCCAsmStmt::getInputExpr(unsigned i) {
433   return cast<Expr>(Exprs[i + NumOutputs]);
434 }
435 
setInputExpr(unsigned i,Expr * E)436 void GCCAsmStmt::setInputExpr(unsigned i, Expr *E) {
437   Exprs[i + NumOutputs] = E;
438 }
439 
440 /// getInputConstraint - Return the specified input constraint.  Unlike output
441 /// constraints, these can be empty.
getInputConstraint(unsigned i) const442 StringRef GCCAsmStmt::getInputConstraint(unsigned i) const {
443   return getInputConstraintLiteral(i)->getString();
444 }
445 
setOutputsAndInputsAndClobbers(const ASTContext & C,IdentifierInfo ** Names,StringLiteral ** Constraints,Stmt ** Exprs,unsigned NumOutputs,unsigned NumInputs,StringLiteral ** Clobbers,unsigned NumClobbers)446 void GCCAsmStmt::setOutputsAndInputsAndClobbers(const ASTContext &C,
447                                                 IdentifierInfo **Names,
448                                                 StringLiteral **Constraints,
449                                                 Stmt **Exprs,
450                                                 unsigned NumOutputs,
451                                                 unsigned NumInputs,
452                                                 StringLiteral **Clobbers,
453                                                 unsigned NumClobbers) {
454   this->NumOutputs = NumOutputs;
455   this->NumInputs = NumInputs;
456   this->NumClobbers = NumClobbers;
457 
458   unsigned NumExprs = NumOutputs + NumInputs;
459 
460   C.Deallocate(this->Names);
461   this->Names = new (C) IdentifierInfo*[NumExprs];
462   std::copy(Names, Names + NumExprs, this->Names);
463 
464   C.Deallocate(this->Exprs);
465   this->Exprs = new (C) Stmt*[NumExprs];
466   std::copy(Exprs, Exprs + NumExprs, this->Exprs);
467 
468   C.Deallocate(this->Constraints);
469   this->Constraints = new (C) StringLiteral*[NumExprs];
470   std::copy(Constraints, Constraints + NumExprs, this->Constraints);
471 
472   C.Deallocate(this->Clobbers);
473   this->Clobbers = new (C) StringLiteral*[NumClobbers];
474   std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers);
475 }
476 
477 /// getNamedOperand - Given a symbolic operand reference like %[foo],
478 /// translate this into a numeric value needed to reference the same operand.
479 /// This returns -1 if the operand name is invalid.
getNamedOperand(StringRef SymbolicName) const480 int GCCAsmStmt::getNamedOperand(StringRef SymbolicName) const {
481   unsigned NumPlusOperands = 0;
482 
483   // Check if this is an output operand.
484   for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) {
485     if (getOutputName(i) == SymbolicName)
486       return i;
487   }
488 
489   for (unsigned i = 0, e = getNumInputs(); i != e; ++i)
490     if (getInputName(i) == SymbolicName)
491       return getNumOutputs() + NumPlusOperands + i;
492 
493   // Not found.
494   return -1;
495 }
496 
497 /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
498 /// it into pieces.  If the asm string is erroneous, emit errors and return
499 /// true, otherwise return false.
AnalyzeAsmString(SmallVectorImpl<AsmStringPiece> & Pieces,const ASTContext & C,unsigned & DiagOffs) const500 unsigned GCCAsmStmt::AnalyzeAsmString(SmallVectorImpl<AsmStringPiece>&Pieces,
501                                 const ASTContext &C, unsigned &DiagOffs) const {
502   StringRef Str = getAsmString()->getString();
503   const char *StrStart = Str.begin();
504   const char *StrEnd = Str.end();
505   const char *CurPtr = StrStart;
506 
507   // "Simple" inline asms have no constraints or operands, just convert the asm
508   // string to escape $'s.
509   if (isSimple()) {
510     std::string Result;
511     for (; CurPtr != StrEnd; ++CurPtr) {
512       switch (*CurPtr) {
513       case '$':
514         Result += "$$";
515         break;
516       default:
517         Result += *CurPtr;
518         break;
519       }
520     }
521     Pieces.push_back(AsmStringPiece(Result));
522     return 0;
523   }
524 
525   // CurStringPiece - The current string that we are building up as we scan the
526   // asm string.
527   std::string CurStringPiece;
528 
529   bool HasVariants = !C.getTargetInfo().hasNoAsmVariants();
530 
531   unsigned LastAsmStringToken = 0;
532   unsigned LastAsmStringOffset = 0;
533 
534   while (true) {
535     // Done with the string?
536     if (CurPtr == StrEnd) {
537       if (!CurStringPiece.empty())
538         Pieces.push_back(AsmStringPiece(CurStringPiece));
539       return 0;
540     }
541 
542     char CurChar = *CurPtr++;
543     switch (CurChar) {
544     case '$': CurStringPiece += "$$"; continue;
545     case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue;
546     case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue;
547     case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue;
548     case '%':
549       break;
550     default:
551       CurStringPiece += CurChar;
552       continue;
553     }
554 
555     // Escaped "%" character in asm string.
556     if (CurPtr == StrEnd) {
557       // % at end of string is invalid (no escape).
558       DiagOffs = CurPtr-StrStart-1;
559       return diag::err_asm_invalid_escape;
560     }
561     // Handle escaped char and continue looping over the asm string.
562     char EscapedChar = *CurPtr++;
563     switch (EscapedChar) {
564     default:
565       break;
566     case '%': // %% -> %
567     case '{': // %{ -> {
568     case '}': // %} -> }
569       CurStringPiece += EscapedChar;
570       continue;
571     case '=': // %= -> Generate a unique ID.
572       CurStringPiece += "${:uid}";
573       continue;
574     }
575 
576     // Otherwise, we have an operand.  If we have accumulated a string so far,
577     // add it to the Pieces list.
578     if (!CurStringPiece.empty()) {
579       Pieces.push_back(AsmStringPiece(CurStringPiece));
580       CurStringPiece.clear();
581     }
582 
583     // Handle operands that have asmSymbolicName (e.g., %x[foo]) and those that
584     // don't (e.g., %x4). 'x' following the '%' is the constraint modifier.
585 
586     const char *Begin = CurPtr - 1; // Points to the character following '%'.
587     const char *Percent = Begin - 1; // Points to '%'.
588 
589     if (isLetter(EscapedChar)) {
590       if (CurPtr == StrEnd) { // Premature end.
591         DiagOffs = CurPtr-StrStart-1;
592         return diag::err_asm_invalid_escape;
593       }
594       EscapedChar = *CurPtr++;
595     }
596 
597     const TargetInfo &TI = C.getTargetInfo();
598     const SourceManager &SM = C.getSourceManager();
599     const LangOptions &LO = C.getLangOpts();
600 
601     // Handle operands that don't have asmSymbolicName (e.g., %x4).
602     if (isDigit(EscapedChar)) {
603       // %n - Assembler operand n
604       unsigned N = 0;
605 
606       --CurPtr;
607       while (CurPtr != StrEnd && isDigit(*CurPtr))
608         N = N*10 + ((*CurPtr++)-'0');
609 
610       unsigned NumOperands =
611         getNumOutputs() + getNumPlusOperands() + getNumInputs();
612       if (N >= NumOperands) {
613         DiagOffs = CurPtr-StrStart-1;
614         return diag::err_asm_invalid_operand_number;
615       }
616 
617       // Str contains "x4" (Operand without the leading %).
618       std::string Str(Begin, CurPtr - Begin);
619 
620       // (BeginLoc, EndLoc) represents the range of the operand we are currently
621       // processing. Unlike Str, the range includes the leading '%'.
622       SourceLocation BeginLoc = getAsmString()->getLocationOfByte(
623           Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
624           &LastAsmStringOffset);
625       SourceLocation EndLoc = getAsmString()->getLocationOfByte(
626           CurPtr - StrStart, SM, LO, TI, &LastAsmStringToken,
627           &LastAsmStringOffset);
628 
629       Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
630       continue;
631     }
632 
633     // Handle operands that have asmSymbolicName (e.g., %x[foo]).
634     if (EscapedChar == '[') {
635       DiagOffs = CurPtr-StrStart-1;
636 
637       // Find the ']'.
638       const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
639       if (NameEnd == nullptr)
640         return diag::err_asm_unterminated_symbolic_operand_name;
641       if (NameEnd == CurPtr)
642         return diag::err_asm_empty_symbolic_operand_name;
643 
644       StringRef SymbolicName(CurPtr, NameEnd - CurPtr);
645 
646       int N = getNamedOperand(SymbolicName);
647       if (N == -1) {
648         // Verify that an operand with that name exists.
649         DiagOffs = CurPtr-StrStart;
650         return diag::err_asm_unknown_symbolic_operand_name;
651       }
652 
653       // Str contains "x[foo]" (Operand without the leading %).
654       std::string Str(Begin, NameEnd + 1 - Begin);
655 
656       // (BeginLoc, EndLoc) represents the range of the operand we are currently
657       // processing. Unlike Str, the range includes the leading '%'.
658       SourceLocation BeginLoc = getAsmString()->getLocationOfByte(
659           Percent - StrStart, SM, LO, TI, &LastAsmStringToken,
660           &LastAsmStringOffset);
661       SourceLocation EndLoc = getAsmString()->getLocationOfByte(
662           NameEnd + 1 - StrStart, SM, LO, TI, &LastAsmStringToken,
663           &LastAsmStringOffset);
664 
665       Pieces.emplace_back(N, std::move(Str), BeginLoc, EndLoc);
666 
667       CurPtr = NameEnd+1;
668       continue;
669     }
670 
671     DiagOffs = CurPtr-StrStart-1;
672     return diag::err_asm_invalid_escape;
673   }
674 }
675 
676 /// Assemble final IR asm string (GCC-style).
generateAsmString(const ASTContext & C) const677 std::string GCCAsmStmt::generateAsmString(const ASTContext &C) const {
678   // Analyze the asm string to decompose it into its pieces.  We know that Sema
679   // has already done this, so it is guaranteed to be successful.
680   SmallVector<GCCAsmStmt::AsmStringPiece, 4> Pieces;
681   unsigned DiagOffs;
682   AnalyzeAsmString(Pieces, C, DiagOffs);
683 
684   std::string AsmString;
685   for (const auto &Piece : Pieces) {
686     if (Piece.isString())
687       AsmString += Piece.getString();
688     else if (Piece.getModifier() == '\0')
689       AsmString += '$' + llvm::utostr(Piece.getOperandNo());
690     else
691       AsmString += "${" + llvm::utostr(Piece.getOperandNo()) + ':' +
692                    Piece.getModifier() + '}';
693   }
694   return AsmString;
695 }
696 
697 /// Assemble final IR asm string (MS-style).
generateAsmString(const ASTContext & C) const698 std::string MSAsmStmt::generateAsmString(const ASTContext &C) const {
699   // FIXME: This needs to be translated into the IR string representation.
700   return AsmStr;
701 }
702 
getOutputExpr(unsigned i)703 Expr *MSAsmStmt::getOutputExpr(unsigned i) {
704   return cast<Expr>(Exprs[i]);
705 }
706 
getInputExpr(unsigned i)707 Expr *MSAsmStmt::getInputExpr(unsigned i) {
708   return cast<Expr>(Exprs[i + NumOutputs]);
709 }
710 
setInputExpr(unsigned i,Expr * E)711 void MSAsmStmt::setInputExpr(unsigned i, Expr *E) {
712   Exprs[i + NumOutputs] = E;
713 }
714 
715 //===----------------------------------------------------------------------===//
716 // Constructors
717 //===----------------------------------------------------------------------===//
718 
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,SourceLocation rparenloc)719 GCCAsmStmt::GCCAsmStmt(const ASTContext &C, SourceLocation asmloc,
720                        bool issimple, bool isvolatile, unsigned numoutputs,
721                        unsigned numinputs, IdentifierInfo **names,
722                        StringLiteral **constraints, Expr **exprs,
723                        StringLiteral *asmstr, unsigned numclobbers,
724                        StringLiteral **clobbers, SourceLocation rparenloc)
725     : AsmStmt(GCCAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
726               numinputs, numclobbers), RParenLoc(rparenloc), AsmStr(asmstr) {
727   unsigned NumExprs = NumOutputs + NumInputs;
728 
729   Names = new (C) IdentifierInfo*[NumExprs];
730   std::copy(names, names + NumExprs, Names);
731 
732   Exprs = new (C) Stmt*[NumExprs];
733   std::copy(exprs, exprs + NumExprs, Exprs);
734 
735   Constraints = new (C) StringLiteral*[NumExprs];
736   std::copy(constraints, constraints + NumExprs, Constraints);
737 
738   Clobbers = new (C) StringLiteral*[NumClobbers];
739   std::copy(clobbers, clobbers + NumClobbers, Clobbers);
740 }
741 
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)742 MSAsmStmt::MSAsmStmt(const ASTContext &C, SourceLocation asmloc,
743                      SourceLocation lbraceloc, bool issimple, bool isvolatile,
744                      ArrayRef<Token> asmtoks, unsigned numoutputs,
745                      unsigned numinputs,
746                      ArrayRef<StringRef> constraints, ArrayRef<Expr*> exprs,
747                      StringRef asmstr, ArrayRef<StringRef> clobbers,
748                      SourceLocation endloc)
749     : AsmStmt(MSAsmStmtClass, asmloc, issimple, isvolatile, numoutputs,
750               numinputs, clobbers.size()), LBraceLoc(lbraceloc),
751               EndLoc(endloc), NumAsmToks(asmtoks.size()) {
752   initialize(C, asmstr, asmtoks, constraints, exprs, clobbers);
753 }
754 
copyIntoContext(const ASTContext & C,StringRef str)755 static StringRef copyIntoContext(const ASTContext &C, StringRef str) {
756   return str.copy(C);
757 }
758 
initialize(const ASTContext & C,StringRef asmstr,ArrayRef<Token> asmtoks,ArrayRef<StringRef> constraints,ArrayRef<Expr * > exprs,ArrayRef<StringRef> clobbers)759 void MSAsmStmt::initialize(const ASTContext &C, StringRef asmstr,
760                            ArrayRef<Token> asmtoks,
761                            ArrayRef<StringRef> constraints,
762                            ArrayRef<Expr*> exprs,
763                            ArrayRef<StringRef> clobbers) {
764   assert(NumAsmToks == asmtoks.size());
765   assert(NumClobbers == clobbers.size());
766 
767   assert(exprs.size() == NumOutputs + NumInputs);
768   assert(exprs.size() == constraints.size());
769 
770   AsmStr = copyIntoContext(C, asmstr);
771 
772   Exprs = new (C) Stmt*[exprs.size()];
773   std::copy(exprs.begin(), exprs.end(), Exprs);
774 
775   AsmToks = new (C) Token[asmtoks.size()];
776   std::copy(asmtoks.begin(), asmtoks.end(), AsmToks);
777 
778   Constraints = new (C) StringRef[exprs.size()];
779   std::transform(constraints.begin(), constraints.end(), Constraints,
780                  [&](StringRef Constraint) {
781                    return copyIntoContext(C, Constraint);
782                  });
783 
784   Clobbers = new (C) StringRef[NumClobbers];
785   // FIXME: Avoid the allocation/copy if at all possible.
786   std::transform(clobbers.begin(), clobbers.end(), Clobbers,
787                  [&](StringRef Clobber) {
788                    return copyIntoContext(C, Clobber);
789                  });
790 }
791 
IfStmt(const ASTContext & C,SourceLocation IL,bool IsConstexpr,Stmt * init,VarDecl * var,Expr * cond,Stmt * then,SourceLocation EL,Stmt * elsev)792 IfStmt::IfStmt(const ASTContext &C, SourceLocation IL, bool IsConstexpr,
793                Stmt *init, VarDecl *var, Expr *cond, Stmt *then,
794                SourceLocation EL, Stmt *elsev)
795     : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL) {
796   setConstexpr(IsConstexpr);
797   setConditionVariable(C, var);
798   SubExprs[INIT] = init;
799   SubExprs[COND] = cond;
800   SubExprs[THEN] = then;
801   SubExprs[ELSE] = elsev;
802 }
803 
getConditionVariable() const804 VarDecl *IfStmt::getConditionVariable() const {
805   if (!SubExprs[VAR])
806     return nullptr;
807 
808   auto *DS = cast<DeclStmt>(SubExprs[VAR]);
809   return cast<VarDecl>(DS->getSingleDecl());
810 }
811 
setConditionVariable(const ASTContext & C,VarDecl * V)812 void IfStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
813   if (!V) {
814     SubExprs[VAR] = nullptr;
815     return;
816   }
817 
818   SourceRange VarRange = V->getSourceRange();
819   SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
820                                    VarRange.getEnd());
821 }
822 
isObjCAvailabilityCheck() const823 bool IfStmt::isObjCAvailabilityCheck() const {
824   return isa<ObjCAvailabilityCheckExpr>(SubExprs[COND]);
825 }
826 
ForStmt(const ASTContext & C,Stmt * Init,Expr * Cond,VarDecl * condVar,Expr * Inc,Stmt * Body,SourceLocation FL,SourceLocation LP,SourceLocation RP)827 ForStmt::ForStmt(const ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
828                  Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
829                  SourceLocation RP)
830   : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP)
831 {
832   SubExprs[INIT] = Init;
833   setConditionVariable(C, condVar);
834   SubExprs[COND] = Cond;
835   SubExprs[INC] = Inc;
836   SubExprs[BODY] = Body;
837 }
838 
getConditionVariable() const839 VarDecl *ForStmt::getConditionVariable() const {
840   if (!SubExprs[CONDVAR])
841     return nullptr;
842 
843   auto *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
844   return cast<VarDecl>(DS->getSingleDecl());
845 }
846 
setConditionVariable(const ASTContext & C,VarDecl * V)847 void ForStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
848   if (!V) {
849     SubExprs[CONDVAR] = nullptr;
850     return;
851   }
852 
853   SourceRange VarRange = V->getSourceRange();
854   SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
855                                        VarRange.getEnd());
856 }
857 
SwitchStmt(const ASTContext & C,Stmt * init,VarDecl * Var,Expr * cond)858 SwitchStmt::SwitchStmt(const ASTContext &C, Stmt *init, VarDecl *Var,
859                        Expr *cond)
860     : Stmt(SwitchStmtClass), FirstCase(nullptr, false) {
861   setConditionVariable(C, Var);
862   SubExprs[INIT] = init;
863   SubExprs[COND] = cond;
864   SubExprs[BODY] = nullptr;
865 }
866 
getConditionVariable() const867 VarDecl *SwitchStmt::getConditionVariable() const {
868   if (!SubExprs[VAR])
869     return nullptr;
870 
871   auto *DS = cast<DeclStmt>(SubExprs[VAR]);
872   return cast<VarDecl>(DS->getSingleDecl());
873 }
874 
setConditionVariable(const ASTContext & C,VarDecl * V)875 void SwitchStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
876   if (!V) {
877     SubExprs[VAR] = nullptr;
878     return;
879   }
880 
881   SourceRange VarRange = V->getSourceRange();
882   SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
883                                    VarRange.getEnd());
884 }
885 
getSubStmt()886 Stmt *SwitchCase::getSubStmt() {
887   if (isa<CaseStmt>(this))
888     return cast<CaseStmt>(this)->getSubStmt();
889   return cast<DefaultStmt>(this)->getSubStmt();
890 }
891 
WhileStmt(const ASTContext & C,VarDecl * Var,Expr * cond,Stmt * body,SourceLocation WL)892 WhileStmt::WhileStmt(const ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
893                      SourceLocation WL)
894   : Stmt(WhileStmtClass) {
895   setConditionVariable(C, Var);
896   SubExprs[COND] = cond;
897   SubExprs[BODY] = body;
898   WhileLoc = WL;
899 }
900 
getConditionVariable() const901 VarDecl *WhileStmt::getConditionVariable() const {
902   if (!SubExprs[VAR])
903     return nullptr;
904 
905   auto *DS = cast<DeclStmt>(SubExprs[VAR]);
906   return cast<VarDecl>(DS->getSingleDecl());
907 }
908 
setConditionVariable(const ASTContext & C,VarDecl * V)909 void WhileStmt::setConditionVariable(const ASTContext &C, VarDecl *V) {
910   if (!V) {
911     SubExprs[VAR] = nullptr;
912     return;
913   }
914 
915   SourceRange VarRange = V->getSourceRange();
916   SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V), VarRange.getBegin(),
917                                    VarRange.getEnd());
918 }
919 
920 // IndirectGotoStmt
getConstantTarget()921 LabelDecl *IndirectGotoStmt::getConstantTarget() {
922   if (auto *E = dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
923     return E->getLabel();
924   return nullptr;
925 }
926 
927 // ReturnStmt
getRetValue() const928 const Expr* ReturnStmt::getRetValue() const {
929   return cast_or_null<Expr>(RetExpr);
930 }
getRetValue()931 Expr* ReturnStmt::getRetValue() {
932   return cast_or_null<Expr>(RetExpr);
933 }
934 
SEHTryStmt(bool IsCXXTry,SourceLocation TryLoc,Stmt * TryBlock,Stmt * Handler)935 SEHTryStmt::SEHTryStmt(bool IsCXXTry, SourceLocation TryLoc, Stmt *TryBlock,
936                        Stmt *Handler)
937     : Stmt(SEHTryStmtClass), IsCXXTry(IsCXXTry), TryLoc(TryLoc) {
938   Children[TRY]     = TryBlock;
939   Children[HANDLER] = Handler;
940 }
941 
Create(const ASTContext & C,bool IsCXXTry,SourceLocation TryLoc,Stmt * TryBlock,Stmt * Handler)942 SEHTryStmt* SEHTryStmt::Create(const ASTContext &C, bool IsCXXTry,
943                                SourceLocation TryLoc, Stmt *TryBlock,
944                                Stmt *Handler) {
945   return new(C) SEHTryStmt(IsCXXTry,TryLoc,TryBlock,Handler);
946 }
947 
getExceptHandler() const948 SEHExceptStmt* SEHTryStmt::getExceptHandler() const {
949   return dyn_cast<SEHExceptStmt>(getHandler());
950 }
951 
getFinallyHandler() const952 SEHFinallyStmt* SEHTryStmt::getFinallyHandler() const {
953   return dyn_cast<SEHFinallyStmt>(getHandler());
954 }
955 
SEHExceptStmt(SourceLocation Loc,Expr * FilterExpr,Stmt * Block)956 SEHExceptStmt::SEHExceptStmt(SourceLocation Loc, Expr *FilterExpr, Stmt *Block)
957     : Stmt(SEHExceptStmtClass), Loc(Loc) {
958   Children[FILTER_EXPR] = FilterExpr;
959   Children[BLOCK]       = Block;
960 }
961 
Create(const ASTContext & C,SourceLocation Loc,Expr * FilterExpr,Stmt * Block)962 SEHExceptStmt* SEHExceptStmt::Create(const ASTContext &C, SourceLocation Loc,
963                                      Expr *FilterExpr, Stmt *Block) {
964   return new(C) SEHExceptStmt(Loc,FilterExpr,Block);
965 }
966 
SEHFinallyStmt(SourceLocation Loc,Stmt * Block)967 SEHFinallyStmt::SEHFinallyStmt(SourceLocation Loc, Stmt *Block)
968     : Stmt(SEHFinallyStmtClass), Loc(Loc), Block(Block) {}
969 
Create(const ASTContext & C,SourceLocation Loc,Stmt * Block)970 SEHFinallyStmt* SEHFinallyStmt::Create(const ASTContext &C, SourceLocation Loc,
971                                        Stmt *Block) {
972   return new(C)SEHFinallyStmt(Loc,Block);
973 }
974 
Capture(SourceLocation Loc,VariableCaptureKind Kind,VarDecl * Var)975 CapturedStmt::Capture::Capture(SourceLocation Loc, VariableCaptureKind Kind,
976                                VarDecl *Var)
977     : VarAndKind(Var, Kind), Loc(Loc) {
978   switch (Kind) {
979   case VCK_This:
980     assert(!Var && "'this' capture cannot have a variable!");
981     break;
982   case VCK_ByRef:
983     assert(Var && "capturing by reference must have a variable!");
984     break;
985   case VCK_ByCopy:
986     assert(Var && "capturing by copy must have a variable!");
987     assert(
988         (Var->getType()->isScalarType() || (Var->getType()->isReferenceType() &&
989                                             Var->getType()
990                                                 ->castAs<ReferenceType>()
991                                                 ->getPointeeType()
992                                                 ->isScalarType())) &&
993         "captures by copy are expected to have a scalar type!");
994     break;
995   case VCK_VLAType:
996     assert(!Var &&
997            "Variable-length array type capture cannot have a variable!");
998     break;
999   }
1000 }
1001 
1002 CapturedStmt::VariableCaptureKind
getCaptureKind() const1003 CapturedStmt::Capture::getCaptureKind() const {
1004   return VarAndKind.getInt();
1005 }
1006 
getCapturedVar() const1007 VarDecl *CapturedStmt::Capture::getCapturedVar() const {
1008   assert((capturesVariable() || capturesVariableByCopy()) &&
1009          "No variable available for 'this' or VAT capture");
1010   return VarAndKind.getPointer();
1011 }
1012 
getStoredCaptures() const1013 CapturedStmt::Capture *CapturedStmt::getStoredCaptures() const {
1014   unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
1015 
1016   // Offset of the first Capture object.
1017   unsigned FirstCaptureOffset = llvm::alignTo(Size, alignof(Capture));
1018 
1019   return reinterpret_cast<Capture *>(
1020       reinterpret_cast<char *>(const_cast<CapturedStmt *>(this))
1021       + FirstCaptureOffset);
1022 }
1023 
CapturedStmt(Stmt * S,CapturedRegionKind Kind,ArrayRef<Capture> Captures,ArrayRef<Expr * > CaptureInits,CapturedDecl * CD,RecordDecl * RD)1024 CapturedStmt::CapturedStmt(Stmt *S, CapturedRegionKind Kind,
1025                            ArrayRef<Capture> Captures,
1026                            ArrayRef<Expr *> CaptureInits,
1027                            CapturedDecl *CD,
1028                            RecordDecl *RD)
1029   : Stmt(CapturedStmtClass), NumCaptures(Captures.size()),
1030     CapDeclAndKind(CD, Kind), TheRecordDecl(RD) {
1031   assert( S && "null captured statement");
1032   assert(CD && "null captured declaration for captured statement");
1033   assert(RD && "null record declaration for captured statement");
1034 
1035   // Copy initialization expressions.
1036   Stmt **Stored = getStoredStmts();
1037   for (unsigned I = 0, N = NumCaptures; I != N; ++I)
1038     *Stored++ = CaptureInits[I];
1039 
1040   // Copy the statement being captured.
1041   *Stored = S;
1042 
1043   // Copy all Capture objects.
1044   Capture *Buffer = getStoredCaptures();
1045   std::copy(Captures.begin(), Captures.end(), Buffer);
1046 }
1047 
CapturedStmt(EmptyShell Empty,unsigned NumCaptures)1048 CapturedStmt::CapturedStmt(EmptyShell Empty, unsigned NumCaptures)
1049   : Stmt(CapturedStmtClass, Empty), NumCaptures(NumCaptures),
1050     CapDeclAndKind(nullptr, CR_Default) {
1051   getStoredStmts()[NumCaptures] = nullptr;
1052 }
1053 
Create(const ASTContext & Context,Stmt * S,CapturedRegionKind Kind,ArrayRef<Capture> Captures,ArrayRef<Expr * > CaptureInits,CapturedDecl * CD,RecordDecl * RD)1054 CapturedStmt *CapturedStmt::Create(const ASTContext &Context, Stmt *S,
1055                                    CapturedRegionKind Kind,
1056                                    ArrayRef<Capture> Captures,
1057                                    ArrayRef<Expr *> CaptureInits,
1058                                    CapturedDecl *CD,
1059                                    RecordDecl *RD) {
1060   // The layout is
1061   //
1062   // -----------------------------------------------------------
1063   // | CapturedStmt, Init, ..., Init, S, Capture, ..., Capture |
1064   // ----------------^-------------------^----------------------
1065   //                 getStoredStmts()    getStoredCaptures()
1066   //
1067   // where S is the statement being captured.
1068   //
1069   assert(CaptureInits.size() == Captures.size() && "wrong number of arguments");
1070 
1071   unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (Captures.size() + 1);
1072   if (!Captures.empty()) {
1073     // Realign for the following Capture array.
1074     Size = llvm::alignTo(Size, alignof(Capture));
1075     Size += sizeof(Capture) * Captures.size();
1076   }
1077 
1078   void *Mem = Context.Allocate(Size);
1079   return new (Mem) CapturedStmt(S, Kind, Captures, CaptureInits, CD, RD);
1080 }
1081 
CreateDeserialized(const ASTContext & Context,unsigned NumCaptures)1082 CapturedStmt *CapturedStmt::CreateDeserialized(const ASTContext &Context,
1083                                                unsigned NumCaptures) {
1084   unsigned Size = sizeof(CapturedStmt) + sizeof(Stmt *) * (NumCaptures + 1);
1085   if (NumCaptures > 0) {
1086     // Realign for the following Capture array.
1087     Size = llvm::alignTo(Size, alignof(Capture));
1088     Size += sizeof(Capture) * NumCaptures;
1089   }
1090 
1091   void *Mem = Context.Allocate(Size);
1092   return new (Mem) CapturedStmt(EmptyShell(), NumCaptures);
1093 }
1094 
children()1095 Stmt::child_range CapturedStmt::children() {
1096   // Children are captured field initializers.
1097   return child_range(getStoredStmts(), getStoredStmts() + NumCaptures);
1098 }
1099 
getCapturedDecl()1100 CapturedDecl *CapturedStmt::getCapturedDecl() {
1101   return CapDeclAndKind.getPointer();
1102 }
1103 
getCapturedDecl() const1104 const CapturedDecl *CapturedStmt::getCapturedDecl() const {
1105   return CapDeclAndKind.getPointer();
1106 }
1107 
1108 /// Set the outlined function declaration.
setCapturedDecl(CapturedDecl * D)1109 void CapturedStmt::setCapturedDecl(CapturedDecl *D) {
1110   assert(D && "null CapturedDecl");
1111   CapDeclAndKind.setPointer(D);
1112 }
1113 
1114 /// Retrieve the captured region kind.
getCapturedRegionKind() const1115 CapturedRegionKind CapturedStmt::getCapturedRegionKind() const {
1116   return CapDeclAndKind.getInt();
1117 }
1118 
1119 /// Set the captured region kind.
setCapturedRegionKind(CapturedRegionKind Kind)1120 void CapturedStmt::setCapturedRegionKind(CapturedRegionKind Kind) {
1121   CapDeclAndKind.setInt(Kind);
1122 }
1123 
capturesVariable(const VarDecl * Var) const1124 bool CapturedStmt::capturesVariable(const VarDecl *Var) const {
1125   for (const auto &I : captures()) {
1126     if (!I.capturesVariable() && !I.capturesVariableByCopy())
1127       continue;
1128     if (I.getCapturedVar()->getCanonicalDecl() == Var->getCanonicalDecl())
1129       return true;
1130   }
1131 
1132   return false;
1133 }
1134