Stmt.cpp revision 44aa1f397855f130e88e62ffc1029f7f83bb5d2e
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/ExprCXX.h"
16#include "clang/AST/ExprObjC.h"
17#include "clang/AST/StmtCXX.h"
18#include "clang/AST/StmtObjC.h"
19#include "clang/AST/Type.h"
20#include "clang/AST/ASTContext.h"
21#include "clang/AST/ASTDiagnostic.h"
22#include "clang/Basic/TargetInfo.h"
23#include <cstdio>
24using namespace clang;
25
26static struct StmtClassNameTable {
27  const char *Name;
28  unsigned Counter;
29  unsigned Size;
30} StmtClassInfo[Stmt::lastStmtConstant+1];
31
32static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
33  static bool Initialized = false;
34  if (Initialized)
35    return StmtClassInfo[E];
36
37  // Intialize the table on the first use.
38  Initialized = true;
39#define ABSTRACT_STMT(STMT)
40#define STMT(CLASS, PARENT) \
41  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS;    \
42  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
43#include "clang/AST/StmtNodes.inc"
44
45  return StmtClassInfo[E];
46}
47
48const char *Stmt::getStmtClassName() const {
49  return getStmtInfoTableEntry((StmtClass) StmtBits.sClass).Name;
50}
51
52void Stmt::PrintStats() {
53  // Ensure the table is primed.
54  getStmtInfoTableEntry(Stmt::NullStmtClass);
55
56  unsigned sum = 0;
57  fprintf(stderr, "*** Stmt/Expr Stats:\n");
58  for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
59    if (StmtClassInfo[i].Name == 0) continue;
60    sum += StmtClassInfo[i].Counter;
61  }
62  fprintf(stderr, "  %d stmts/exprs total.\n", sum);
63  sum = 0;
64  for (int i = 0; i != Stmt::lastStmtConstant+1; i++) {
65    if (StmtClassInfo[i].Name == 0) continue;
66    if (StmtClassInfo[i].Counter == 0) continue;
67    fprintf(stderr, "    %d %s, %d each (%d bytes)\n",
68            StmtClassInfo[i].Counter, StmtClassInfo[i].Name,
69            StmtClassInfo[i].Size,
70            StmtClassInfo[i].Counter*StmtClassInfo[i].Size);
71    sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
72  }
73  fprintf(stderr, "Total bytes = %d\n", sum);
74}
75
76void Stmt::addStmtClass(StmtClass s) {
77  ++getStmtInfoTableEntry(s).Counter;
78}
79
80static bool StatSwitch = false;
81
82bool Stmt::CollectingStats(bool Enable) {
83  if (Enable) StatSwitch = true;
84  return StatSwitch;
85}
86
87void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
88  if (this->Body)
89    C.Deallocate(Body);
90  this->CompoundStmtBits.NumStmts = NumStmts;
91
92  Body = new (C) Stmt*[NumStmts];
93  memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts);
94}
95
96const char *LabelStmt::getName() const {
97  return getID()->getNameStart();
98}
99
100// This is defined here to avoid polluting Stmt.h with importing Expr.h
101SourceRange ReturnStmt::getSourceRange() const {
102  if (RetExpr)
103    return SourceRange(RetLoc, RetExpr->getLocEnd());
104  else
105    return SourceRange(RetLoc);
106}
107
108bool Stmt::hasImplicitControlFlow() const {
109  switch (StmtBits.sClass) {
110    default:
111      return false;
112
113    case CallExprClass:
114    case ConditionalOperatorClass:
115    case ChooseExprClass:
116    case StmtExprClass:
117    case DeclStmtClass:
118      return true;
119
120    case Stmt::BinaryOperatorClass: {
121      const BinaryOperator* B = cast<BinaryOperator>(this);
122      if (B->isLogicalOp() || B->getOpcode() == BO_Comma)
123        return true;
124      else
125        return false;
126    }
127  }
128}
129
130Expr *AsmStmt::getOutputExpr(unsigned i) {
131  return cast<Expr>(Exprs[i]);
132}
133
134/// getOutputConstraint - Return the constraint string for the specified
135/// output operand.  All output constraints are known to be non-empty (either
136/// '=' or '+').
137llvm::StringRef AsmStmt::getOutputConstraint(unsigned i) const {
138  return getOutputConstraintLiteral(i)->getString();
139}
140
141/// getNumPlusOperands - Return the number of output operands that have a "+"
142/// constraint.
143unsigned AsmStmt::getNumPlusOperands() const {
144  unsigned Res = 0;
145  for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)
146    if (isOutputPlusConstraint(i))
147      ++Res;
148  return Res;
149}
150
151Expr *AsmStmt::getInputExpr(unsigned i) {
152  return cast<Expr>(Exprs[i + NumOutputs]);
153}
154
155/// getInputConstraint - Return the specified input constraint.  Unlike output
156/// constraints, these can be empty.
157llvm::StringRef AsmStmt::getInputConstraint(unsigned i) const {
158  return getInputConstraintLiteral(i)->getString();
159}
160
161
162void AsmStmt::setOutputsAndInputsAndClobbers(ASTContext &C,
163                                             IdentifierInfo **Names,
164                                             StringLiteral **Constraints,
165                                             Stmt **Exprs,
166                                             unsigned NumOutputs,
167                                             unsigned NumInputs,
168                                             StringLiteral **Clobbers,
169                                             unsigned NumClobbers) {
170  this->NumOutputs = NumOutputs;
171  this->NumInputs = NumInputs;
172  this->NumClobbers = NumClobbers;
173
174  unsigned NumExprs = NumOutputs + NumInputs;
175
176  C.Deallocate(this->Names);
177  this->Names = new (C) IdentifierInfo*[NumExprs];
178  std::copy(Names, Names + NumExprs, this->Names);
179
180  C.Deallocate(this->Exprs);
181  this->Exprs = new (C) Stmt*[NumExprs];
182  std::copy(Exprs, Exprs + NumExprs, this->Exprs);
183
184  C.Deallocate(this->Constraints);
185  this->Constraints = new (C) StringLiteral*[NumExprs];
186  std::copy(Constraints, Constraints + NumExprs, this->Constraints);
187
188  C.Deallocate(this->Clobbers);
189  this->Clobbers = new (C) StringLiteral*[NumClobbers];
190  std::copy(Clobbers, Clobbers + NumClobbers, this->Clobbers);
191}
192
193/// getNamedOperand - Given a symbolic operand reference like %[foo],
194/// translate this into a numeric value needed to reference the same operand.
195/// This returns -1 if the operand name is invalid.
196int AsmStmt::getNamedOperand(llvm::StringRef SymbolicName) const {
197  unsigned NumPlusOperands = 0;
198
199  // Check if this is an output operand.
200  for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) {
201    if (getOutputName(i) == SymbolicName)
202      return i;
203  }
204
205  for (unsigned i = 0, e = getNumInputs(); i != e; ++i)
206    if (getInputName(i) == SymbolicName)
207      return getNumOutputs() + NumPlusOperands + i;
208
209  // Not found.
210  return -1;
211}
212
213/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
214/// it into pieces.  If the asm string is erroneous, emit errors and return
215/// true, otherwise return false.
216unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
217                                   ASTContext &C, unsigned &DiagOffs) const {
218  llvm::StringRef Str = getAsmString()->getString();
219  const char *StrStart = Str.begin();
220  const char *StrEnd = Str.end();
221  const char *CurPtr = StrStart;
222
223  // "Simple" inline asms have no constraints or operands, just convert the asm
224  // string to escape $'s.
225  if (isSimple()) {
226    std::string Result;
227    for (; CurPtr != StrEnd; ++CurPtr) {
228      switch (*CurPtr) {
229      case '$':
230        Result += "$$";
231        break;
232      default:
233        Result += *CurPtr;
234        break;
235      }
236    }
237    Pieces.push_back(AsmStringPiece(Result));
238    return 0;
239  }
240
241  // CurStringPiece - The current string that we are building up as we scan the
242  // asm string.
243  std::string CurStringPiece;
244
245  bool HasVariants = !C.Target.hasNoAsmVariants();
246
247  while (1) {
248    // Done with the string?
249    if (CurPtr == StrEnd) {
250      if (!CurStringPiece.empty())
251        Pieces.push_back(AsmStringPiece(CurStringPiece));
252      return 0;
253    }
254
255    char CurChar = *CurPtr++;
256    switch (CurChar) {
257    case '$': CurStringPiece += "$$"; continue;
258    case '{': CurStringPiece += (HasVariants ? "$(" : "{"); continue;
259    case '|': CurStringPiece += (HasVariants ? "$|" : "|"); continue;
260    case '}': CurStringPiece += (HasVariants ? "$)" : "}"); continue;
261    case '%':
262      break;
263    default:
264      CurStringPiece += CurChar;
265      continue;
266    }
267
268    // Escaped "%" character in asm string.
269    if (CurPtr == StrEnd) {
270      // % at end of string is invalid (no escape).
271      DiagOffs = CurPtr-StrStart-1;
272      return diag::err_asm_invalid_escape;
273    }
274
275    char EscapedChar = *CurPtr++;
276    if (EscapedChar == '%') {  // %% -> %
277      // Escaped percentage sign.
278      CurStringPiece += '%';
279      continue;
280    }
281
282    if (EscapedChar == '=') {  // %= -> Generate an unique ID.
283      CurStringPiece += "${:uid}";
284      continue;
285    }
286
287    // Otherwise, we have an operand.  If we have accumulated a string so far,
288    // add it to the Pieces list.
289    if (!CurStringPiece.empty()) {
290      Pieces.push_back(AsmStringPiece(CurStringPiece));
291      CurStringPiece.clear();
292    }
293
294    // Handle %x4 and %x[foo] by capturing x as the modifier character.
295    char Modifier = '\0';
296    if (isalpha(EscapedChar)) {
297      Modifier = EscapedChar;
298      EscapedChar = *CurPtr++;
299    }
300
301    if (isdigit(EscapedChar)) {
302      // %n - Assembler operand n
303      unsigned N = 0;
304
305      --CurPtr;
306      while (CurPtr != StrEnd && isdigit(*CurPtr))
307        N = N*10 + ((*CurPtr++)-'0');
308
309      unsigned NumOperands =
310        getNumOutputs() + getNumPlusOperands() + getNumInputs();
311      if (N >= NumOperands) {
312        DiagOffs = CurPtr-StrStart-1;
313        return diag::err_asm_invalid_operand_number;
314      }
315
316      Pieces.push_back(AsmStringPiece(N, Modifier));
317      continue;
318    }
319
320    // Handle %[foo], a symbolic operand reference.
321    if (EscapedChar == '[') {
322      DiagOffs = CurPtr-StrStart-1;
323
324      // Find the ']'.
325      const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
326      if (NameEnd == 0)
327        return diag::err_asm_unterminated_symbolic_operand_name;
328      if (NameEnd == CurPtr)
329        return diag::err_asm_empty_symbolic_operand_name;
330
331      llvm::StringRef SymbolicName(CurPtr, NameEnd - CurPtr);
332
333      int N = getNamedOperand(SymbolicName);
334      if (N == -1) {
335        // Verify that an operand with that name exists.
336        DiagOffs = CurPtr-StrStart;
337        return diag::err_asm_unknown_symbolic_operand_name;
338      }
339      Pieces.push_back(AsmStringPiece(N, Modifier));
340
341      CurPtr = NameEnd+1;
342      continue;
343    }
344
345    DiagOffs = CurPtr-StrStart-1;
346    return diag::err_asm_invalid_escape;
347  }
348}
349
350QualType CXXCatchStmt::getCaughtType() const {
351  if (ExceptionDecl)
352    return ExceptionDecl->getType();
353  return QualType();
354}
355
356//===----------------------------------------------------------------------===//
357// Constructors
358//===----------------------------------------------------------------------===//
359
360AsmStmt::AsmStmt(ASTContext &C, SourceLocation asmloc, bool issimple,
361                 bool isvolatile, bool msasm,
362                 unsigned numoutputs, unsigned numinputs,
363                 IdentifierInfo **names, StringLiteral **constraints,
364                 Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
365                 StringLiteral **clobbers, SourceLocation rparenloc)
366  : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
367  , IsSimple(issimple), IsVolatile(isvolatile), MSAsm(msasm)
368  , NumOutputs(numoutputs), NumInputs(numinputs), NumClobbers(numclobbers) {
369
370  unsigned NumExprs = NumOutputs +NumInputs;
371
372  Names = new (C) IdentifierInfo*[NumExprs];
373  std::copy(names, names + NumExprs, Names);
374
375  Exprs = new (C) Stmt*[NumExprs];
376  std::copy(exprs, exprs + NumExprs, Exprs);
377
378  Constraints = new (C) StringLiteral*[NumExprs];
379  std::copy(constraints, constraints + NumExprs, Constraints);
380
381  Clobbers = new (C) StringLiteral*[NumClobbers];
382  std::copy(clobbers, clobbers + NumClobbers, Clobbers);
383}
384
385ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
386                                             Stmt *Body,  SourceLocation FCL,
387                                             SourceLocation RPL)
388: Stmt(ObjCForCollectionStmtClass) {
389  SubExprs[ELEM] = Elem;
390  SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect);
391  SubExprs[BODY] = Body;
392  ForLoc = FCL;
393  RParenLoc = RPL;
394}
395
396ObjCAtTryStmt::ObjCAtTryStmt(SourceLocation atTryLoc, Stmt *atTryStmt,
397                             Stmt **CatchStmts, unsigned NumCatchStmts,
398                             Stmt *atFinallyStmt)
399  : Stmt(ObjCAtTryStmtClass), AtTryLoc(atTryLoc),
400    NumCatchStmts(NumCatchStmts), HasFinally(atFinallyStmt != 0)
401{
402  Stmt **Stmts = getStmts();
403  Stmts[0] = atTryStmt;
404  for (unsigned I = 0; I != NumCatchStmts; ++I)
405    Stmts[I + 1] = CatchStmts[I];
406
407  if (HasFinally)
408    Stmts[NumCatchStmts + 1] = atFinallyStmt;
409}
410
411ObjCAtTryStmt *ObjCAtTryStmt::Create(ASTContext &Context,
412                                     SourceLocation atTryLoc,
413                                     Stmt *atTryStmt,
414                                     Stmt **CatchStmts,
415                                     unsigned NumCatchStmts,
416                                     Stmt *atFinallyStmt) {
417  unsigned Size = sizeof(ObjCAtTryStmt) +
418    (1 + NumCatchStmts + (atFinallyStmt != 0)) * sizeof(Stmt *);
419  void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
420  return new (Mem) ObjCAtTryStmt(atTryLoc, atTryStmt, CatchStmts, NumCatchStmts,
421                                 atFinallyStmt);
422}
423
424ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(ASTContext &Context,
425                                                 unsigned NumCatchStmts,
426                                                 bool HasFinally) {
427  unsigned Size = sizeof(ObjCAtTryStmt) +
428    (1 + NumCatchStmts + HasFinally) * sizeof(Stmt *);
429  void *Mem = Context.Allocate(Size, llvm::alignOf<ObjCAtTryStmt>());
430  return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally);
431}
432
433SourceRange ObjCAtTryStmt::getSourceRange() const {
434  SourceLocation EndLoc;
435  if (HasFinally)
436    EndLoc = getFinallyStmt()->getLocEnd();
437  else if (NumCatchStmts)
438    EndLoc = getCatchStmt(NumCatchStmts - 1)->getLocEnd();
439  else
440    EndLoc = getTryBody()->getLocEnd();
441
442  return SourceRange(AtTryLoc, EndLoc);
443}
444
445CXXTryStmt *CXXTryStmt::Create(ASTContext &C, SourceLocation tryLoc,
446                               Stmt *tryBlock, Stmt **handlers,
447                               unsigned numHandlers) {
448  std::size_t Size = sizeof(CXXTryStmt);
449  Size += ((numHandlers + 1) * sizeof(Stmt));
450
451  void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
452  return new (Mem) CXXTryStmt(tryLoc, tryBlock, handlers, numHandlers);
453}
454
455CXXTryStmt *CXXTryStmt::Create(ASTContext &C, EmptyShell Empty,
456                               unsigned numHandlers) {
457  std::size_t Size = sizeof(CXXTryStmt);
458  Size += ((numHandlers + 1) * sizeof(Stmt));
459
460  void *Mem = C.Allocate(Size, llvm::alignOf<CXXTryStmt>());
461  return new (Mem) CXXTryStmt(Empty, numHandlers);
462}
463
464CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
465                       Stmt **handlers, unsigned numHandlers)
466  : Stmt(CXXTryStmtClass), TryLoc(tryLoc), NumHandlers(numHandlers) {
467  Stmt **Stmts = reinterpret_cast<Stmt **>(this + 1);
468  Stmts[0] = tryBlock;
469  std::copy(handlers, handlers + NumHandlers, Stmts + 1);
470}
471
472IfStmt::IfStmt(ASTContext &C, SourceLocation IL, VarDecl *var, Expr *cond,
473               Stmt *then, SourceLocation EL, Stmt *elsev)
474  : Stmt(IfStmtClass), IfLoc(IL), ElseLoc(EL)
475{
476  setConditionVariable(C, var);
477  SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
478  SubExprs[THEN] = then;
479  SubExprs[ELSE] = elsev;
480}
481
482VarDecl *IfStmt::getConditionVariable() const {
483  if (!SubExprs[VAR])
484    return 0;
485
486  DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
487  return cast<VarDecl>(DS->getSingleDecl());
488}
489
490void IfStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
491  if (!V) {
492    SubExprs[VAR] = 0;
493    return;
494  }
495
496  SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V),
497                                   V->getSourceRange().getBegin(),
498                                   V->getSourceRange().getEnd());
499}
500
501ForStmt::ForStmt(ASTContext &C, Stmt *Init, Expr *Cond, VarDecl *condVar,
502                 Expr *Inc, Stmt *Body, SourceLocation FL, SourceLocation LP,
503                 SourceLocation RP)
504  : Stmt(ForStmtClass), ForLoc(FL), LParenLoc(LP), RParenLoc(RP)
505{
506  SubExprs[INIT] = Init;
507  setConditionVariable(C, condVar);
508  SubExprs[COND] = reinterpret_cast<Stmt*>(Cond);
509  SubExprs[INC] = reinterpret_cast<Stmt*>(Inc);
510  SubExprs[BODY] = Body;
511}
512
513VarDecl *ForStmt::getConditionVariable() const {
514  if (!SubExprs[CONDVAR])
515    return 0;
516
517  DeclStmt *DS = cast<DeclStmt>(SubExprs[CONDVAR]);
518  return cast<VarDecl>(DS->getSingleDecl());
519}
520
521void ForStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
522  if (!V) {
523    SubExprs[CONDVAR] = 0;
524    return;
525  }
526
527  SubExprs[CONDVAR] = new (C) DeclStmt(DeclGroupRef(V),
528                                       V->getSourceRange().getBegin(),
529                                       V->getSourceRange().getEnd());
530}
531
532SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond)
533  : Stmt(SwitchStmtClass), FirstCase(0), AllEnumCasesCovered(0)
534{
535  setConditionVariable(C, Var);
536  SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
537  SubExprs[BODY] = NULL;
538}
539
540VarDecl *SwitchStmt::getConditionVariable() const {
541  if (!SubExprs[VAR])
542    return 0;
543
544  DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
545  return cast<VarDecl>(DS->getSingleDecl());
546}
547
548void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
549  if (!V) {
550    SubExprs[VAR] = 0;
551    return;
552  }
553
554  SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V),
555                                   V->getSourceRange().getBegin(),
556                                   V->getSourceRange().getEnd());
557}
558
559WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body,
560                     SourceLocation WL)
561: Stmt(WhileStmtClass)
562{
563  setConditionVariable(C, Var);
564  SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
565  SubExprs[BODY] = body;
566  WhileLoc = WL;
567}
568
569VarDecl *WhileStmt::getConditionVariable() const {
570  if (!SubExprs[VAR])
571    return 0;
572
573  DeclStmt *DS = cast<DeclStmt>(SubExprs[VAR]);
574  return cast<VarDecl>(DS->getSingleDecl());
575}
576
577void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) {
578  if (!V) {
579    SubExprs[VAR] = 0;
580    return;
581  }
582
583  SubExprs[VAR] = new (C) DeclStmt(DeclGroupRef(V),
584                                   V->getSourceRange().getBegin(),
585                                   V->getSourceRange().getEnd());
586}
587
588//===----------------------------------------------------------------------===//
589//  Child Iterators for iterating over subexpressions/substatements
590//===----------------------------------------------------------------------===//
591
592// DeclStmt
593Stmt::child_iterator DeclStmt::child_begin() {
594  return StmtIterator(DG.begin(), DG.end());
595}
596
597Stmt::child_iterator DeclStmt::child_end() {
598  return StmtIterator(DG.end(), DG.end());
599}
600
601// NullStmt
602Stmt::child_iterator NullStmt::child_begin() { return child_iterator(); }
603Stmt::child_iterator NullStmt::child_end() { return child_iterator(); }
604
605// CompoundStmt
606Stmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; }
607Stmt::child_iterator CompoundStmt::child_end() {
608  return &Body[0]+CompoundStmtBits.NumStmts;
609}
610
611// CaseStmt
612Stmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; }
613Stmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; }
614
615// DefaultStmt
616Stmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; }
617Stmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; }
618
619// LabelStmt
620Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; }
621Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; }
622
623// IfStmt
624Stmt::child_iterator IfStmt::child_begin() {
625  return &SubExprs[0];
626}
627Stmt::child_iterator IfStmt::child_end() {
628  return &SubExprs[0]+END_EXPR;
629}
630
631// SwitchStmt
632Stmt::child_iterator SwitchStmt::child_begin() {
633  return &SubExprs[0];
634}
635Stmt::child_iterator SwitchStmt::child_end() {
636  return &SubExprs[0]+END_EXPR;
637}
638
639// WhileStmt
640Stmt::child_iterator WhileStmt::child_begin() {
641  return &SubExprs[0];
642}
643Stmt::child_iterator WhileStmt::child_end() {
644  return &SubExprs[0]+END_EXPR;
645}
646
647// DoStmt
648Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; }
649Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; }
650
651// ForStmt
652Stmt::child_iterator ForStmt::child_begin() {
653  return &SubExprs[0];
654}
655Stmt::child_iterator ForStmt::child_end() {
656  return &SubExprs[0]+END_EXPR;
657}
658
659// ObjCForCollectionStmt
660Stmt::child_iterator ObjCForCollectionStmt::child_begin() {
661  return &SubExprs[0];
662}
663Stmt::child_iterator ObjCForCollectionStmt::child_end() {
664  return &SubExprs[0]+END_EXPR;
665}
666
667// GotoStmt
668Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); }
669Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); }
670
671// IndirectGotoStmt
672LabelStmt *IndirectGotoStmt::getConstantTarget() {
673  if (AddrLabelExpr *E =
674        dyn_cast<AddrLabelExpr>(getTarget()->IgnoreParenImpCasts()))
675    return E->getLabel();
676  return 0;
677}
678
679Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; }
680Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; }
681
682// ContinueStmt
683Stmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); }
684Stmt::child_iterator ContinueStmt::child_end() { return child_iterator(); }
685
686// BreakStmt
687Stmt::child_iterator BreakStmt::child_begin() { return child_iterator(); }
688Stmt::child_iterator BreakStmt::child_end() { return child_iterator(); }
689
690// ReturnStmt
691const Expr* ReturnStmt::getRetValue() const {
692  return cast_or_null<Expr>(RetExpr);
693}
694Expr* ReturnStmt::getRetValue() {
695  return cast_or_null<Expr>(RetExpr);
696}
697
698Stmt::child_iterator ReturnStmt::child_begin() {
699  return &RetExpr;
700}
701Stmt::child_iterator ReturnStmt::child_end() {
702  return RetExpr ? &RetExpr+1 : &RetExpr;
703}
704
705// AsmStmt
706Stmt::child_iterator AsmStmt::child_begin() {
707  return NumOutputs + NumInputs == 0 ? 0 : &Exprs[0];
708}
709Stmt::child_iterator AsmStmt::child_end() {
710  return NumOutputs + NumInputs == 0 ? 0 : &Exprs[0] + NumOutputs + NumInputs;
711}
712
713// ObjCAtCatchStmt
714Stmt::child_iterator ObjCAtCatchStmt::child_begin() { return &Body; }
715Stmt::child_iterator ObjCAtCatchStmt::child_end() { return &Body + 1; }
716
717// ObjCAtFinallyStmt
718Stmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; }
719Stmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; }
720
721// ObjCAtTryStmt
722Stmt::child_iterator ObjCAtTryStmt::child_begin() { return getStmts(); }
723
724Stmt::child_iterator ObjCAtTryStmt::child_end() {
725  return getStmts() + 1 + NumCatchStmts + HasFinally;
726}
727
728// ObjCAtThrowStmt
729Stmt::child_iterator ObjCAtThrowStmt::child_begin() {
730  return &Throw;
731}
732
733Stmt::child_iterator ObjCAtThrowStmt::child_end() {
734  return &Throw+1;
735}
736
737// ObjCAtSynchronizedStmt
738Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() {
739  return &SubStmts[0];
740}
741
742Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() {
743  return &SubStmts[0]+END_EXPR;
744}
745
746// CXXCatchStmt
747Stmt::child_iterator CXXCatchStmt::child_begin() {
748  return &HandlerBlock;
749}
750
751Stmt::child_iterator CXXCatchStmt::child_end() {
752  return &HandlerBlock + 1;
753}
754
755// CXXTryStmt
756Stmt::child_iterator CXXTryStmt::child_begin() {
757  return reinterpret_cast<Stmt **>(this + 1);
758}
759
760Stmt::child_iterator CXXTryStmt::child_end() {
761  return reinterpret_cast<Stmt **>(this + 1) + NumHandlers + 1;
762}
763