Clang Project

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