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