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