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