]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/clang/lib/AST/Stmt.cpp
Merge ACPICA 20110112. Switch to BSD/GPLv2 dual license[1].
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / clang / lib / AST / Stmt.cpp
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>
24 using namespace clang;
25
26 static struct StmtClassNameTable {
27   const char *Name;
28   unsigned Counter;
29   unsigned Size;
30 } StmtClassInfo[Stmt::lastStmtConstant+1];
31
32 static 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
48 const char *Stmt::getStmtClassName() const {
49   return getStmtInfoTableEntry((StmtClass)sClass).Name;
50 }
51
52 void 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
76 void Stmt::addStmtClass(StmtClass s) {
77   ++getStmtInfoTableEntry(s).Counter;
78 }
79
80 static bool StatSwitch = false;
81
82 bool Stmt::CollectingStats(bool Enable) {
83   if (Enable) StatSwitch = true;
84   return StatSwitch;
85 }
86
87 void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
88   if (this->Body)
89     C.Deallocate(Body);
90   this->NumStmts = NumStmts;
91
92   Body = new (C) Stmt*[NumStmts];
93   memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts);
94 }
95
96 const char *LabelStmt::getName() const {
97   return getID()->getNameStart();
98 }
99
100 // This is defined here to avoid polluting Stmt.h with importing Expr.h
101 SourceRange ReturnStmt::getSourceRange() const {
102   if (RetExpr)
103     return SourceRange(RetLoc, RetExpr->getLocEnd());
104   else
105     return SourceRange(RetLoc);
106 }
107
108 bool Stmt::hasImplicitControlFlow() const {
109   switch (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
130 Expr *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 '+').
137 llvm::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.
143 unsigned 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
151 Expr *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.
157 llvm::StringRef AsmStmt::getInputConstraint(unsigned i) const {
158   return getInputConstraintLiteral(i)->getString();
159 }
160
161
162 void 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.
196 int 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.
216 unsigned 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
350 QualType CXXCatchStmt::getCaughtType() const {
351   if (ExceptionDecl)
352     return ExceptionDecl->getType();
353   return QualType();
354 }
355
356 //===----------------------------------------------------------------------===//
357 // Constructors
358 //===----------------------------------------------------------------------===//
359
360 AsmStmt::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
385 ObjCForCollectionStmt::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
396 ObjCAtTryStmt::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
411 ObjCAtTryStmt *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
424 ObjCAtTryStmt *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
433 SourceRange 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
445 CXXTryStmt *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
455 CXXTryStmt *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
464 CXXTryStmt::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
472 IfStmt::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
482 VarDecl *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
490 void 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
501 ForStmt::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
513 VarDecl *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
521 void 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
532 SwitchStmt::SwitchStmt(ASTContext &C, VarDecl *Var, Expr *cond) 
533   : Stmt(SwitchStmtClass), FirstCase(0) 
534 {
535   setConditionVariable(C, Var);
536   SubExprs[COND] = reinterpret_cast<Stmt*>(cond);
537   SubExprs[BODY] = NULL;
538 }
539
540 VarDecl *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
548 void 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
559 WhileStmt::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
569 VarDecl *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
577 void 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
593 Stmt::child_iterator DeclStmt::child_begin() {
594   return StmtIterator(DG.begin(), DG.end());
595 }
596
597 Stmt::child_iterator DeclStmt::child_end() {
598   return StmtIterator(DG.end(), DG.end());
599 }
600
601 // NullStmt
602 Stmt::child_iterator NullStmt::child_begin() { return child_iterator(); }
603 Stmt::child_iterator NullStmt::child_end() { return child_iterator(); }
604
605 // CompoundStmt
606 Stmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; }
607 Stmt::child_iterator CompoundStmt::child_end() { return &Body[0]+NumStmts; }
608
609 // CaseStmt
610 Stmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; }
611 Stmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; }
612
613 // DefaultStmt
614 Stmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; }
615 Stmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; }
616
617 // LabelStmt
618 Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; }
619 Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; }
620
621 // IfStmt
622 Stmt::child_iterator IfStmt::child_begin() {
623   return &SubExprs[0];
624 }
625 Stmt::child_iterator IfStmt::child_end() {
626   return &SubExprs[0]+END_EXPR;
627 }
628
629 // SwitchStmt
630 Stmt::child_iterator SwitchStmt::child_begin() {
631   return &SubExprs[0];
632 }
633 Stmt::child_iterator SwitchStmt::child_end() {
634   return &SubExprs[0]+END_EXPR;
635 }
636
637 // WhileStmt
638 Stmt::child_iterator WhileStmt::child_begin() {
639   return &SubExprs[0];
640 }
641 Stmt::child_iterator WhileStmt::child_end() {
642   return &SubExprs[0]+END_EXPR;
643 }
644
645 // DoStmt
646 Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; }
647 Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; }
648
649 // ForStmt
650 Stmt::child_iterator ForStmt::child_begin() {
651   return &SubExprs[0];
652 }
653 Stmt::child_iterator ForStmt::child_end() {
654   return &SubExprs[0]+END_EXPR;
655 }
656
657 // ObjCForCollectionStmt
658 Stmt::child_iterator ObjCForCollectionStmt::child_begin() {
659   return &SubExprs[0];
660 }
661 Stmt::child_iterator ObjCForCollectionStmt::child_end() {
662   return &SubExprs[0]+END_EXPR;
663 }
664
665 // GotoStmt
666 Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); }
667 Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); }
668
669 // IndirectGotoStmt
670 Expr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); }
671 const Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); }
672
673 Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; }
674 Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; }
675
676 // ContinueStmt
677 Stmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); }
678 Stmt::child_iterator ContinueStmt::child_end() { return child_iterator(); }
679
680 // BreakStmt
681 Stmt::child_iterator BreakStmt::child_begin() { return child_iterator(); }
682 Stmt::child_iterator BreakStmt::child_end() { return child_iterator(); }
683
684 // ReturnStmt
685 const Expr* ReturnStmt::getRetValue() const {
686   return cast_or_null<Expr>(RetExpr);
687 }
688 Expr* ReturnStmt::getRetValue() {
689   return cast_or_null<Expr>(RetExpr);
690 }
691
692 Stmt::child_iterator ReturnStmt::child_begin() {
693   return &RetExpr;
694 }
695 Stmt::child_iterator ReturnStmt::child_end() {
696   return RetExpr ? &RetExpr+1 : &RetExpr;
697 }
698
699 // AsmStmt
700 Stmt::child_iterator AsmStmt::child_begin() {
701   return NumOutputs + NumInputs == 0 ? 0 : &Exprs[0];
702 }
703 Stmt::child_iterator AsmStmt::child_end() {
704   return NumOutputs + NumInputs == 0 ? 0 : &Exprs[0] + NumOutputs + NumInputs;
705 }
706
707 // ObjCAtCatchStmt
708 Stmt::child_iterator ObjCAtCatchStmt::child_begin() { return &Body; }
709 Stmt::child_iterator ObjCAtCatchStmt::child_end() { return &Body + 1; }
710
711 // ObjCAtFinallyStmt
712 Stmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; }
713 Stmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; }
714
715 // ObjCAtTryStmt
716 Stmt::child_iterator ObjCAtTryStmt::child_begin() { return getStmts(); }
717
718 Stmt::child_iterator ObjCAtTryStmt::child_end() {
719   return getStmts() + 1 + NumCatchStmts + HasFinally;
720 }
721
722 // ObjCAtThrowStmt
723 Stmt::child_iterator ObjCAtThrowStmt::child_begin() {
724   return &Throw;
725 }
726
727 Stmt::child_iterator ObjCAtThrowStmt::child_end() {
728   return &Throw+1;
729 }
730
731 // ObjCAtSynchronizedStmt
732 Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() {
733   return &SubStmts[0];
734 }
735
736 Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() {
737   return &SubStmts[0]+END_EXPR;
738 }
739
740 // CXXCatchStmt
741 Stmt::child_iterator CXXCatchStmt::child_begin() {
742   return &HandlerBlock;
743 }
744
745 Stmt::child_iterator CXXCatchStmt::child_end() {
746   return &HandlerBlock + 1;
747 }
748
749 // CXXTryStmt
750 Stmt::child_iterator CXXTryStmt::child_begin() {
751   return reinterpret_cast<Stmt **>(this + 1);
752 }
753
754 Stmt::child_iterator CXXTryStmt::child_end() {
755   return reinterpret_cast<Stmt **>(this + 1) + NumHandlers + 1;
756 }