Stmt.cpp revision 201361
1106266Sjulian//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===//
2106266Sjulian//
3106266Sjulian//                     The LLVM Compiler Infrastructure
4106266Sjulian//
5106266Sjulian// This file is distributed under the University of Illinois Open Source
6106266Sjulian// License. See LICENSE.TXT for details.
7106266Sjulian//
8106266Sjulian//===----------------------------------------------------------------------===//
9106319Sjulian//
10106266Sjulian// This file implements the Stmt class and statement subclasses.
11106319Sjulian//
12106319Sjulian//===----------------------------------------------------------------------===//
13106266Sjulian
14106319Sjulian#include "clang/AST/Stmt.h"
15106319Sjulian#include "clang/AST/ExprCXX.h"
16106266Sjulian#include "clang/AST/ExprObjC.h"
17106266Sjulian#include "clang/AST/StmtCXX.h"
18106266Sjulian#include "clang/AST/StmtObjC.h"
19106319Sjulian#include "clang/AST/Type.h"
20106319Sjulian#include "clang/AST/ASTContext.h"
21106319Sjulian#include "clang/AST/ASTDiagnostic.h"
22106266Sjulian#include <cstdio>
23106266Sjulianusing namespace clang;
24106266Sjulian
25106266Sjulianstatic struct StmtClassNameTable {
26106266Sjulian  const char *Name;
27106319Sjulian  unsigned Counter;
28106266Sjulian  unsigned Size;
29106266Sjulian} StmtClassInfo[Stmt::lastExprConstant+1];
30106266Sjulian
31106266Sjulianstatic StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
32106266Sjulian  static bool Initialized = false;
33106266Sjulian  if (Initialized)
34106266Sjulian    return StmtClassInfo[E];
35106266Sjulian
36106266Sjulian  // Intialize the table on the first use.
37106266Sjulian  Initialized = true;
38106266Sjulian#define STMT(CLASS, PARENT) \
39106266Sjulian  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS;    \
40106266Sjulian  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
41106266Sjulian#include "clang/AST/StmtNodes.def"
42106266Sjulian
43106266Sjulian  return StmtClassInfo[E];
44106266Sjulian}
45106266Sjulian
46106266Sjulianconst char *Stmt::getStmtClassName() const {
47106266Sjulian  return getStmtInfoTableEntry((StmtClass)sClass).Name;
48106266Sjulian}
49106266Sjulian
50106266Sjulianvoid Stmt::PrintStats() {
51106266Sjulian  // Ensure the table is primed.
52106266Sjulian  getStmtInfoTableEntry(Stmt::NullStmtClass);
53106266Sjulian
54106266Sjulian  unsigned sum = 0;
55106266Sjulian  fprintf(stderr, "*** Stmt/Expr Stats:\n");
56106266Sjulian  for (int i = 0; i != Stmt::lastExprConstant+1; i++) {
57106266Sjulian    if (StmtClassInfo[i].Name == 0) continue;
58106266Sjulian    sum += StmtClassInfo[i].Counter;
59106266Sjulian  }
60106266Sjulian  fprintf(stderr, "  %d stmts/exprs total.\n", sum);
61106266Sjulian  sum = 0;
62106266Sjulian  for (int i = 0; i != Stmt::lastExprConstant+1; i++) {
63106266Sjulian    if (StmtClassInfo[i].Name == 0) continue;
64106266Sjulian    if (StmtClassInfo[i].Counter == 0) continue;
65106266Sjulian    fprintf(stderr, "    %d %s, %d each (%d bytes)\n",
66106266Sjulian            StmtClassInfo[i].Counter, StmtClassInfo[i].Name,
67106266Sjulian            StmtClassInfo[i].Size,
68106266Sjulian            StmtClassInfo[i].Counter*StmtClassInfo[i].Size);
69106266Sjulian    sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
70106266Sjulian  }
71106266Sjulian  fprintf(stderr, "Total bytes = %d\n", sum);
72106266Sjulian}
73106266Sjulian
74106266Sjulianvoid Stmt::addStmtClass(StmtClass s) {
75106266Sjulian  ++getStmtInfoTableEntry(s).Counter;
76106266Sjulian}
77106266Sjulian
78106266Sjulianstatic bool StatSwitch = false;
79106266Sjulian
80106266Sjulianbool Stmt::CollectingStats(bool Enable) {
81106266Sjulian  if (Enable) StatSwitch = true;
82106266Sjulian  return StatSwitch;
83106266Sjulian}
84106266Sjulian
85106266Sjulianvoid CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
86106266Sjulian  if (this->Body)
87106319Sjulian    C.Deallocate(Body);
88106266Sjulian  this->NumStmts = NumStmts;
89106266Sjulian
90106319Sjulian  Body = new (C) Stmt*[NumStmts];
91106266Sjulian  memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts);
92106266Sjulian}
93106266Sjulian
94106266Sjulianconst char *LabelStmt::getName() const {
95106266Sjulian  return getID()->getNameStart();
96106266Sjulian}
97106266Sjulian
98106266Sjulian// This is defined here to avoid polluting Stmt.h with importing Expr.h
99106266SjulianSourceRange ReturnStmt::getSourceRange() const {
100106266Sjulian  if (RetExpr)
101106266Sjulian    return SourceRange(RetLoc, RetExpr->getLocEnd());
102106266Sjulian  else
103106266Sjulian    return SourceRange(RetLoc);
104106266Sjulian}
105106266Sjulian
106106266Sjulianbool Stmt::hasImplicitControlFlow() const {
107106266Sjulian  switch (sClass) {
108106266Sjulian    default:
109106266Sjulian      return false;
110106266Sjulian
111106266Sjulian    case CallExprClass:
112106266Sjulian    case ConditionalOperatorClass:
113106266Sjulian    case ChooseExprClass:
114106266Sjulian    case StmtExprClass:
115106266Sjulian    case DeclStmtClass:
116106266Sjulian      return true;
117106266Sjulian
118106266Sjulian    case Stmt::BinaryOperatorClass: {
119106266Sjulian      const BinaryOperator* B = cast<BinaryOperator>(this);
120106266Sjulian      if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma)
121106266Sjulian        return true;
122106266Sjulian      else
123106266Sjulian        return false;
124106266Sjulian    }
125106266Sjulian  }
126106266Sjulian}
127106266Sjulian
128106266SjulianExpr *AsmStmt::getOutputExpr(unsigned i) {
129106266Sjulian  return cast<Expr>(Exprs[i]);
130106266Sjulian}
131106266Sjulian
132106266Sjulian/// getOutputConstraint - Return the constraint string for the specified
133106266Sjulian/// output operand.  All output constraints are known to be non-empty (either
134106266Sjulian/// '=' or '+').
135106266Sjulianstd::string AsmStmt::getOutputConstraint(unsigned i) const {
136106266Sjulian  return std::string(Constraints[i]->getStrData(),
137106266Sjulian                     Constraints[i]->getByteLength());
138106266Sjulian}
139106266Sjulian
140106266Sjulian/// getNumPlusOperands - Return the number of output operands that have a "+"
141106266Sjulian/// constraint.
142106266Sjulianunsigned AsmStmt::getNumPlusOperands() const {
143106266Sjulian  unsigned Res = 0;
144106266Sjulian  for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)
145106266Sjulian    if (isOutputPlusConstraint(i))
146106266Sjulian      ++Res;
147106266Sjulian  return Res;
148106266Sjulian}
149106266Sjulian
150106266Sjulian
151106266Sjulian
152106266SjulianExpr *AsmStmt::getInputExpr(unsigned i) {
153106266Sjulian  return cast<Expr>(Exprs[i + NumOutputs]);
154106266Sjulian}
155106266Sjulian
156106266Sjulian/// getInputConstraint - Return the specified input constraint.  Unlike output
157106266Sjulian/// constraints, these can be empty.
158106266Sjulianstd::string AsmStmt::getInputConstraint(unsigned i) const {
159106266Sjulian  return std::string(Constraints[i + NumOutputs]->getStrData(),
160106266Sjulian                     Constraints[i + NumOutputs]->getByteLength());
161106266Sjulian}
162106266Sjulian
163106266Sjulian
164106266Sjulianvoid AsmStmt::setOutputsAndInputs(unsigned NumOutputs,
165106266Sjulian                                  unsigned NumInputs,
166106266Sjulian                                  const std::string *Names,
167106266Sjulian                                  StringLiteral **Constraints,
168106266Sjulian                                  Stmt **Exprs) {
169106266Sjulian  this->NumOutputs = NumOutputs;
170106266Sjulian  this->NumInputs = NumInputs;
171106266Sjulian  this->Names.clear();
172106266Sjulian  this->Names.insert(this->Names.end(), Names, Names + NumOutputs + NumInputs);
173106266Sjulian  this->Constraints.clear();
174106266Sjulian  this->Constraints.insert(this->Constraints.end(),
175106266Sjulian                           Constraints, Constraints + NumOutputs + NumInputs);
176106266Sjulian  this->Exprs.clear();
177106266Sjulian  this->Exprs.insert(this->Exprs.end(), Exprs, Exprs + NumOutputs + NumInputs);
178106266Sjulian}
179106266Sjulian
180106266Sjulian/// getNamedOperand - Given a symbolic operand reference like %[foo],
181106266Sjulian/// translate this into a numeric value needed to reference the same operand.
182106266Sjulian/// This returns -1 if the operand name is invalid.
183106266Sjulianint AsmStmt::getNamedOperand(const std::string &SymbolicName) const {
184106266Sjulian  unsigned NumPlusOperands = 0;
185106266Sjulian
186106266Sjulian  // Check if this is an output operand.
187106266Sjulian  for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) {
188106266Sjulian    if (getOutputName(i) == SymbolicName)
189106266Sjulian      return i;
190106266Sjulian  }
191106266Sjulian
192106266Sjulian  for (unsigned i = 0, e = getNumInputs(); i != e; ++i)
193106266Sjulian    if (getInputName(i) == SymbolicName)
194106266Sjulian      return getNumOutputs() + NumPlusOperands + i;
195106266Sjulian
196106266Sjulian  // Not found.
197106266Sjulian  return -1;
198106266Sjulian}
199106266Sjulian
200106266Sjulianvoid AsmStmt::setClobbers(StringLiteral **Clobbers, unsigned NumClobbers) {
201106266Sjulian  this->Clobbers.clear();
202106266Sjulian  this->Clobbers.insert(this->Clobbers.end(), Clobbers, Clobbers + NumClobbers);
203106266Sjulian}
204106266Sjulian
205106266Sjulian/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
206106266Sjulian/// it into pieces.  If the asm string is erroneous, emit errors and return
207106266Sjulian/// true, otherwise return false.
208106266Sjulianunsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
209106266Sjulian                                   ASTContext &C, unsigned &DiagOffs) const {
210106266Sjulian  const char *StrStart = getAsmString()->getStrData();
211106266Sjulian  const char *StrEnd = StrStart + getAsmString()->getByteLength();
212106266Sjulian  const char *CurPtr = StrStart;
213106266Sjulian
214106266Sjulian  // "Simple" inline asms have no constraints or operands, just convert the asm
215106266Sjulian  // string to escape $'s.
216106266Sjulian  if (isSimple()) {
217106266Sjulian    std::string Result;
218106266Sjulian    for (; CurPtr != StrEnd; ++CurPtr) {
219106266Sjulian      switch (*CurPtr) {
220106266Sjulian      case '$':
221106266Sjulian        Result += "$$";
222106266Sjulian        break;
223106266Sjulian      default:
224106266Sjulian        Result += *CurPtr;
225106266Sjulian        break;
226106266Sjulian      }
227106266Sjulian    }
228106266Sjulian    Pieces.push_back(AsmStringPiece(Result));
229106266Sjulian    return 0;
230106266Sjulian  }
231106266Sjulian
232106266Sjulian  // CurStringPiece - The current string that we are building up as we scan the
233106266Sjulian  // asm string.
234106266Sjulian  std::string CurStringPiece;
235106266Sjulian
236106266Sjulian  while (1) {
237106266Sjulian    // Done with the string?
238106266Sjulian    if (CurPtr == StrEnd) {
239106266Sjulian      if (!CurStringPiece.empty())
240106266Sjulian        Pieces.push_back(AsmStringPiece(CurStringPiece));
241106266Sjulian      return 0;
242106266Sjulian    }
243106266Sjulian
244106266Sjulian    char CurChar = *CurPtr++;
245106266Sjulian    if (CurChar == '$') {
246106266Sjulian      CurStringPiece += "$$";
247106266Sjulian      continue;
248106266Sjulian    } else if (CurChar != '%') {
249106266Sjulian      CurStringPiece += CurChar;
250106266Sjulian      continue;
251106266Sjulian    }
252106266Sjulian
253106266Sjulian    // Escaped "%" character in asm string.
254106266Sjulian    if (CurPtr == StrEnd) {
255106266Sjulian      // % at end of string is invalid (no escape).
256106266Sjulian      DiagOffs = CurPtr-StrStart-1;
257106266Sjulian      return diag::err_asm_invalid_escape;
258106266Sjulian    }
259106266Sjulian
260106266Sjulian    char EscapedChar = *CurPtr++;
261106266Sjulian    if (EscapedChar == '%') {  // %% -> %
262106266Sjulian      // Escaped percentage sign.
263106266Sjulian      CurStringPiece += '%';
264106266Sjulian      continue;
265106266Sjulian    }
266106266Sjulian
267106266Sjulian    if (EscapedChar == '=') {  // %= -> Generate an unique ID.
268106266Sjulian      CurStringPiece += "${:uid}";
269106266Sjulian      continue;
270106266Sjulian    }
271106266Sjulian
272106266Sjulian    // Otherwise, we have an operand.  If we have accumulated a string so far,
273106266Sjulian    // add it to the Pieces list.
274106266Sjulian    if (!CurStringPiece.empty()) {
275106266Sjulian      Pieces.push_back(AsmStringPiece(CurStringPiece));
276106266Sjulian      CurStringPiece.clear();
277106266Sjulian    }
278106266Sjulian
279106266Sjulian    // Handle %x4 and %x[foo] by capturing x as the modifier character.
280106266Sjulian    char Modifier = '\0';
281106266Sjulian    if (isalpha(EscapedChar)) {
282106266Sjulian      Modifier = EscapedChar;
283106266Sjulian      EscapedChar = *CurPtr++;
284106266Sjulian    }
285106266Sjulian
286106266Sjulian    if (isdigit(EscapedChar)) {
287106319Sjulian      // %n - Assembler operand n
288106266Sjulian      unsigned N = 0;
289106266Sjulian
290106319Sjulian      --CurPtr;
291106266Sjulian      while (CurPtr != StrEnd && isdigit(*CurPtr))
292106319Sjulian        N = N*10 + ((*CurPtr++)-'0');
293106266Sjulian
294106319Sjulian      unsigned NumOperands =
295106266Sjulian        getNumOutputs() + getNumPlusOperands() + getNumInputs();
296106266Sjulian      if (N >= NumOperands) {
297106266Sjulian        DiagOffs = CurPtr-StrStart-1;
298106266Sjulian        return diag::err_asm_invalid_operand_number;
299106266Sjulian      }
300106266Sjulian
301106266Sjulian      Pieces.push_back(AsmStringPiece(N, Modifier));
302106266Sjulian      continue;
303106266Sjulian    }
304106266Sjulian
305106319Sjulian    // Handle %[foo], a symbolic operand reference.
306106319Sjulian    if (EscapedChar == '[') {
307106266Sjulian      DiagOffs = CurPtr-StrStart-1;
308106266Sjulian
309106266Sjulian      // Find the ']'.
310106266Sjulian      const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
311106266Sjulian      if (NameEnd == 0)
312106266Sjulian        return diag::err_asm_unterminated_symbolic_operand_name;
313106266Sjulian      if (NameEnd == CurPtr)
314106266Sjulian        return diag::err_asm_empty_symbolic_operand_name;
315106266Sjulian
316106266Sjulian      std::string SymbolicName(CurPtr, NameEnd);
317106266Sjulian
318106266Sjulian      int N = getNamedOperand(SymbolicName);
319106266Sjulian      if (N == -1) {
320106266Sjulian        // Verify that an operand with that name exists.
321106266Sjulian        DiagOffs = CurPtr-StrStart;
322106266Sjulian        return diag::err_asm_unknown_symbolic_operand_name;
323106266Sjulian      }
324106266Sjulian      Pieces.push_back(AsmStringPiece(N, Modifier));
325106266Sjulian
326106266Sjulian      CurPtr = NameEnd+1;
327106266Sjulian      continue;
328106266Sjulian    }
329106266Sjulian
330106266Sjulian    DiagOffs = CurPtr-StrStart-1;
331106266Sjulian    return diag::err_asm_invalid_escape;
332106266Sjulian  }
333106266Sjulian}
334106266Sjulian
335106266Sjulian//===----------------------------------------------------------------------===//
336106266Sjulian// Constructors
337106266Sjulian//===----------------------------------------------------------------------===//
338106266Sjulian
339106266SjulianAsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
340106266Sjulian                 unsigned numoutputs, unsigned numinputs,
341106266Sjulian                 std::string *names, StringLiteral **constraints,
342106266Sjulian                 Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
343106266Sjulian                 StringLiteral **clobbers, SourceLocation rparenloc)
344106266Sjulian  : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
345106266Sjulian  , IsSimple(issimple), IsVolatile(isvolatile)
346106266Sjulian  , NumOutputs(numoutputs), NumInputs(numinputs) {
347106266Sjulian  for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) {
348106266Sjulian    Names.push_back(names[i]);
349106266Sjulian    Exprs.push_back(exprs[i]);
350106319Sjulian    Constraints.push_back(constraints[i]);
351106266Sjulian  }
352106266Sjulian
353106319Sjulian  for (unsigned i = 0; i != numclobbers; i++)
354106266Sjulian    Clobbers.push_back(clobbers[i]);
355106266Sjulian}
356106266Sjulian
357106266SjulianObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
358106266Sjulian                                             Stmt *Body,  SourceLocation FCL,
359106266Sjulian                                             SourceLocation RPL)
360106266Sjulian: Stmt(ObjCForCollectionStmtClass) {
361106266Sjulian  SubExprs[ELEM] = Elem;
362106266Sjulian  SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect);
363106266Sjulian  SubExprs[BODY] = Body;
364106266Sjulian  ForLoc = FCL;
365106266Sjulian  RParenLoc = RPL;
366106266Sjulian}
367106266Sjulian
368106266Sjulian
369106266SjulianObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc,
370106266Sjulian                                 SourceLocation rparenloc,
371106266Sjulian                                 ParmVarDecl *catchVarDecl, Stmt *atCatchStmt,
372106266Sjulian                                 Stmt *atCatchList)
373106266Sjulian: Stmt(ObjCAtCatchStmtClass) {
374106266Sjulian  ExceptionDecl = catchVarDecl;
375106266Sjulian  SubExprs[BODY] = atCatchStmt;
376106266Sjulian  SubExprs[NEXT_CATCH] = NULL;
377106266Sjulian  // FIXME: O(N^2) in number of catch blocks.
378106266Sjulian  if (atCatchList) {
379106266Sjulian    ObjCAtCatchStmt *AtCatchList = static_cast<ObjCAtCatchStmt*>(atCatchList);
380106266Sjulian
381106266Sjulian    while (ObjCAtCatchStmt* NextCatch = AtCatchList->getNextCatchStmt())
382106266Sjulian      AtCatchList = NextCatch;
383106266Sjulian
384106266Sjulian    AtCatchList->SubExprs[NEXT_CATCH] = this;
385106266Sjulian  }
386106266Sjulian  AtCatchLoc = atCatchLoc;
387106266Sjulian  RParenLoc = rparenloc;
388106266Sjulian}
389106266Sjulian
390106266Sjulian//===----------------------------------------------------------------------===//
391106266Sjulian// AST Destruction.
392106266Sjulian//===----------------------------------------------------------------------===//
393106266Sjulian
394106266Sjulianvoid Stmt::DestroyChildren(ASTContext &C) {
395106266Sjulian  for (child_iterator I = child_begin(), E = child_end(); I !=E; )
396106266Sjulian    if (Stmt* Child = *I++) Child->Destroy(C);
397106266Sjulian}
398106266Sjulian
399106266Sjulianstatic void BranchDestroy(ASTContext &C, Stmt *S, Stmt **SubExprs,
400106266Sjulian                          unsigned NumExprs) {
401106266Sjulian  // We do not use child_iterator here because that will include
402106266Sjulian  // the expressions referenced by the condition variable.
403106266Sjulian  for (Stmt **I = SubExprs, **E = SubExprs + NumExprs; I != E; ++I)
404106266Sjulian    if (Stmt *Child = *I) Child->Destroy(C);
405106266Sjulian
406106266Sjulian  S->~Stmt();
407106266Sjulian  C.Deallocate((void *) S);
408106319Sjulian}
409106319Sjulian
410106266Sjulianvoid Stmt::DoDestroy(ASTContext &C) {
411106319Sjulian  DestroyChildren(C);
412106319Sjulian  this->~Stmt();
413106266Sjulian  C.Deallocate((void *)this);
414106266Sjulian}
415106266Sjulian
416106266Sjulianvoid CXXCatchStmt::DoDestroy(ASTContext& C) {
417106266Sjulian  if (ExceptionDecl)
418106266Sjulian    ExceptionDecl->Destroy(C);
419106266Sjulian  Stmt::DoDestroy(C);
420106266Sjulian}
421106266Sjulian
422106266Sjulianvoid DeclStmt::DoDestroy(ASTContext &C) {
423106266Sjulian  // Don't use StmtIterator to iterate over the Decls, as that can recurse
424106266Sjulian  // into VLA size expressions (which are owned by the VLA).  Further, Decls
425106266Sjulian  // are owned by the DeclContext, and will be destroyed with them.
426106266Sjulian  if (DG.isDeclGroup())
427106266Sjulian    DG.getDeclGroup().Destroy(C);
428106266Sjulian}
429106266Sjulian
430106266Sjulianvoid IfStmt::DoDestroy(ASTContext &C) {
431106266Sjulian  BranchDestroy(C, this, SubExprs, END_EXPR);
432106266Sjulian}
433106266Sjulian
434106266Sjulianvoid ForStmt::DoDestroy(ASTContext &C) {
435106266Sjulian  BranchDestroy(C, this, SubExprs, END_EXPR);
436106319Sjulian}
437106266Sjulian
438106266Sjulianvoid SwitchStmt::DoDestroy(ASTContext &C) {
439106266Sjulian  // Destroy the SwitchCase statements in this switch. In the normal
440106266Sjulian  // case, this loop will merely decrement the reference counts from
441106266Sjulian  // the Retain() calls in addSwitchCase();
442106266Sjulian  SwitchCase *SC = FirstCase;
443106266Sjulian  while (SC) {
444106266Sjulian    SwitchCase *Next = SC->getNextSwitchCase();
445106266Sjulian    SC->Destroy(C);
446106266Sjulian    SC = Next;
447106266Sjulian  }
448106266Sjulian
449106266Sjulian  BranchDestroy(C, this, SubExprs, END_EXPR);
450106266Sjulian}
451106266Sjulian
452106266Sjulianvoid WhileStmt::DoDestroy(ASTContext &C) {
453106266Sjulian  BranchDestroy(C, this, SubExprs, END_EXPR);
454106266Sjulian}
455106266Sjulian
456106266Sjulian//===----------------------------------------------------------------------===//
457106266Sjulian//  Child Iterators for iterating over subexpressions/substatements
458106266Sjulian//===----------------------------------------------------------------------===//
459106266Sjulian
460106266Sjulian// DeclStmt
461106319SjulianStmt::child_iterator DeclStmt::child_begin() {
462106266Sjulian  return StmtIterator(DG.begin(), DG.end());
463106266Sjulian}
464106266Sjulian
465106266SjulianStmt::child_iterator DeclStmt::child_end() {
466106266Sjulian  return StmtIterator(DG.end(), DG.end());
467106266Sjulian}
468106266Sjulian
469106266Sjulian// NullStmt
470106266SjulianStmt::child_iterator NullStmt::child_begin() { return child_iterator(); }
471106266SjulianStmt::child_iterator NullStmt::child_end() { return child_iterator(); }
472106266Sjulian
473106266Sjulian// CompoundStmt
474106266SjulianStmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; }
475106266SjulianStmt::child_iterator CompoundStmt::child_end() { return &Body[0]+NumStmts; }
476106319Sjulian
477106266Sjulian// CaseStmt
478106266SjulianStmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; }
479106266SjulianStmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; }
480106266Sjulian
481106266Sjulian// DefaultStmt
482106266SjulianStmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; }
483106266SjulianStmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; }
484106266Sjulian
485106266Sjulian// LabelStmt
486106266SjulianStmt::child_iterator LabelStmt::child_begin() { return &SubStmt; }
487106266SjulianStmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; }
488106266Sjulian
489106266Sjulian// IfStmt
490106266SjulianStmt::child_iterator IfStmt::child_begin() {
491106266Sjulian  return child_iterator(Var, &SubExprs[0]);
492106266Sjulian}
493106266SjulianStmt::child_iterator IfStmt::child_end() {
494106266Sjulian  return child_iterator(0, &SubExprs[0]+END_EXPR);
495106266Sjulian}
496106266Sjulian
497106266Sjulian// SwitchStmt
498106266SjulianStmt::child_iterator SwitchStmt::child_begin() {
499106266Sjulian  return child_iterator(Var, &SubExprs[0]);
500106266Sjulian}
501106266SjulianStmt::child_iterator SwitchStmt::child_end() {
502106266Sjulian  return child_iterator(0, &SubExprs[0]+END_EXPR);
503106266Sjulian}
504106266Sjulian
505106266Sjulian// WhileStmt
506106266SjulianStmt::child_iterator WhileStmt::child_begin() {
507106266Sjulian  return child_iterator(Var, &SubExprs[0]);
508106266Sjulian}
509106266SjulianStmt::child_iterator WhileStmt::child_end() {
510106266Sjulian  return child_iterator(0, &SubExprs[0]+END_EXPR);
511106266Sjulian}
512106266Sjulian
513106266Sjulian// DoStmt
514106266SjulianStmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; }
515106266SjulianStmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; }
516106266Sjulian
517106266Sjulian// ForStmt
518106266SjulianStmt::child_iterator ForStmt::child_begin() {
519106266Sjulian  return child_iterator(CondVar, &SubExprs[0]);
520106266Sjulian}
521106266SjulianStmt::child_iterator ForStmt::child_end() {
522106266Sjulian  return child_iterator(0, &SubExprs[0]+END_EXPR);
523106266Sjulian}
524106266Sjulian
525106266Sjulian// ObjCForCollectionStmt
526106266SjulianStmt::child_iterator ObjCForCollectionStmt::child_begin() {
527106266Sjulian  return &SubExprs[0];
528106266Sjulian}
529106266SjulianStmt::child_iterator ObjCForCollectionStmt::child_end() {
530106266Sjulian  return &SubExprs[0]+END_EXPR;
531106319Sjulian}
532106266Sjulian
533106266Sjulian// GotoStmt
534106266SjulianStmt::child_iterator GotoStmt::child_begin() { return child_iterator(); }
535106266SjulianStmt::child_iterator GotoStmt::child_end() { return child_iterator(); }
536106266Sjulian
537106266Sjulian// IndirectGotoStmt
538106266SjulianExpr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); }
539106266Sjulianconst Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); }
540106266Sjulian
541106266SjulianStmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; }
542106266SjulianStmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; }
543106266Sjulian
544106266Sjulian// ContinueStmt
545106266SjulianStmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); }
546106266SjulianStmt::child_iterator ContinueStmt::child_end() { return child_iterator(); }
547106266Sjulian
548106266Sjulian// BreakStmt
549106266SjulianStmt::child_iterator BreakStmt::child_begin() { return child_iterator(); }
550106266SjulianStmt::child_iterator BreakStmt::child_end() { return child_iterator(); }
551106266Sjulian
552106266Sjulian// ReturnStmt
553106266Sjulianconst Expr* ReturnStmt::getRetValue() const {
554106266Sjulian  return cast_or_null<Expr>(RetExpr);
555106266Sjulian}
556106266SjulianExpr* ReturnStmt::getRetValue() {
557106266Sjulian  return cast_or_null<Expr>(RetExpr);
558106266Sjulian}
559106266Sjulian
560106266SjulianStmt::child_iterator ReturnStmt::child_begin() {
561106266Sjulian  return &RetExpr;
562106266Sjulian}
563106266SjulianStmt::child_iterator ReturnStmt::child_end() {
564106266Sjulian  return RetExpr ? &RetExpr+1 : &RetExpr;
565106266Sjulian}
566106266Sjulian
567106266Sjulian// AsmStmt
568106266SjulianStmt::child_iterator AsmStmt::child_begin() {
569106266Sjulian  return Exprs.empty() ? 0 : &Exprs[0];
570106266Sjulian}
571106266SjulianStmt::child_iterator AsmStmt::child_end() {
572106266Sjulian  return Exprs.empty() ? 0 : &Exprs[0] + Exprs.size();
573106266Sjulian}
574106266Sjulian
575106266Sjulian// ObjCAtCatchStmt
576106266SjulianStmt::child_iterator ObjCAtCatchStmt::child_begin() { return &SubExprs[0]; }
577106266SjulianStmt::child_iterator ObjCAtCatchStmt::child_end() {
578106266Sjulian  return &SubExprs[0]+END_EXPR;
579106266Sjulian}
580106266Sjulian
581106266Sjulian// ObjCAtFinallyStmt
582106266SjulianStmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; }
583106266SjulianStmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; }
584106266Sjulian
585106266Sjulian// ObjCAtTryStmt
586106266SjulianStmt::child_iterator ObjCAtTryStmt::child_begin() { return &SubStmts[0]; }
587106266SjulianStmt::child_iterator ObjCAtTryStmt::child_end()   {
588106266Sjulian  return &SubStmts[0]+END_EXPR;
589106319Sjulian}
590106266Sjulian
591106266Sjulian// ObjCAtThrowStmt
592106266SjulianStmt::child_iterator ObjCAtThrowStmt::child_begin() {
593106266Sjulian  return &Throw;
594106266Sjulian}
595106266Sjulian
596106266SjulianStmt::child_iterator ObjCAtThrowStmt::child_end() {
597106266Sjulian  return &Throw+1;
598106266Sjulian}
599106266Sjulian
600106266Sjulian// ObjCAtSynchronizedStmt
601106266SjulianStmt::child_iterator ObjCAtSynchronizedStmt::child_begin() {
602106266Sjulian  return &SubStmts[0];
603106266Sjulian}
604106266Sjulian
605106266SjulianStmt::child_iterator ObjCAtSynchronizedStmt::child_end() {
606106266Sjulian  return &SubStmts[0]+END_EXPR;
607106266Sjulian}
608106266Sjulian
609106266Sjulian// CXXCatchStmt
610106266SjulianStmt::child_iterator CXXCatchStmt::child_begin() {
611106266Sjulian  return &HandlerBlock;
612106266Sjulian}
613106266Sjulian
614106266SjulianStmt::child_iterator CXXCatchStmt::child_end() {
615106266Sjulian  return &HandlerBlock + 1;
616106266Sjulian}
617106266Sjulian
618106266SjulianQualType CXXCatchStmt::getCaughtType() const {
619106266Sjulian  if (ExceptionDecl)
620106266Sjulian    return ExceptionDecl->getType();
621106266Sjulian  return QualType();
622106266Sjulian}
623106266Sjulian
624106266Sjulian// CXXTryStmt
625106266SjulianStmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; }
626106266SjulianStmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); }
627106266Sjulian
628106266SjulianCXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
629106266Sjulian                       Stmt **handlers, unsigned numHandlers)
630106266Sjulian  : Stmt(CXXTryStmtClass), TryLoc(tryLoc) {
631106266Sjulian  Stmts.push_back(tryBlock);
632106266Sjulian  Stmts.insert(Stmts.end(), handlers, handlers + numHandlers);
633106266Sjulian}
634106266Sjulian