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