Stmt.cpp revision 93b2bdb866d49e3dab4623a822db281042e87382
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/Type.h"
18#include "clang/AST/ASTContext.h"
19using namespace clang;
20
21static struct StmtClassNameTable {
22  const char *Name;
23  unsigned Counter;
24  unsigned Size;
25} StmtClassInfo[Stmt::lastExprConstant+1];
26
27static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
28  static bool Initialized = false;
29  if (Initialized)
30    return StmtClassInfo[E];
31
32  // Intialize the table on the first use.
33  Initialized = true;
34#define STMT(CLASS, PARENT) \
35  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS;    \
36  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
37#include "clang/AST/StmtNodes.def"
38
39  return StmtClassInfo[E];
40}
41
42const char *Stmt::getStmtClassName() const {
43  return getStmtInfoTableEntry(sClass).Name;
44}
45
46void Stmt::DestroyChildren(ASTContext& C) {
47  for (child_iterator I = child_begin(), E = child_end(); I !=E; ) {
48    if (Stmt* Child = *I++) Child->Destroy(C);
49  }
50}
51
52void Stmt::Destroy(ASTContext& C) {
53  DestroyChildren(C);
54  // FIXME: Eventually all Stmts should be allocated with the allocator
55  //  in ASTContext, just like with Decls.
56  this->~Stmt();
57  C.Deallocate((void *)this);
58}
59
60void DeclStmt::Destroy(ASTContext& C) {
61  this->~DeclStmt();
62  C.Deallocate((void *)this);
63}
64
65void Stmt::PrintStats() {
66  // Ensure the table is primed.
67  getStmtInfoTableEntry(Stmt::NullStmtClass);
68
69  unsigned sum = 0;
70  fprintf(stderr, "*** Stmt/Expr Stats:\n");
71  for (int i = 0; i != Stmt::lastExprConstant+1; i++) {
72    if (StmtClassInfo[i].Name == 0) continue;
73    sum += StmtClassInfo[i].Counter;
74  }
75  fprintf(stderr, "  %d stmts/exprs total.\n", sum);
76  sum = 0;
77  for (int i = 0; i != Stmt::lastExprConstant+1; i++) {
78    if (StmtClassInfo[i].Name == 0) continue;
79    fprintf(stderr, "    %d %s, %d each (%d bytes)\n",
80            StmtClassInfo[i].Counter, StmtClassInfo[i].Name,
81            StmtClassInfo[i].Size,
82            StmtClassInfo[i].Counter*StmtClassInfo[i].Size);
83    sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
84  }
85  fprintf(stderr, "Total bytes = %d\n", sum);
86}
87
88void Stmt::addStmtClass(StmtClass s) {
89  ++getStmtInfoTableEntry(s).Counter;
90}
91
92static bool StatSwitch = false;
93
94bool Stmt::CollectingStats(bool enable) {
95  if (enable) StatSwitch = true;
96  return StatSwitch;
97}
98
99
100const char *LabelStmt::getName() const {
101  return getID()->getName();
102}
103
104// This is defined here to avoid polluting Stmt.h with importing Expr.h
105SourceRange ReturnStmt::getSourceRange() const {
106  if (RetExpr)
107    return SourceRange(RetLoc, RetExpr->getLocEnd());
108  else
109    return SourceRange(RetLoc);
110}
111
112bool Stmt::hasImplicitControlFlow() const {
113  switch (sClass) {
114    default:
115      return false;
116
117    case CallExprClass:
118    case ConditionalOperatorClass:
119    case ChooseExprClass:
120    case StmtExprClass:
121    case DeclStmtClass:
122      return true;
123
124    case Stmt::BinaryOperatorClass: {
125      const BinaryOperator* B = cast<BinaryOperator>(this);
126      if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma)
127        return true;
128      else
129        return false;
130    }
131  }
132}
133
134const Expr* AsmStmt::getOutputExpr(unsigned i) const {
135  return cast<Expr>(Exprs[i]);
136}
137Expr* AsmStmt::getOutputExpr(unsigned i) {
138  return cast<Expr>(Exprs[i]);
139}
140Expr* AsmStmt::getInputExpr(unsigned i) {
141  return cast<Expr>(Exprs[i + NumOutputs]);
142}
143const Expr* AsmStmt::getInputExpr(unsigned i) const {
144  return cast<Expr>(Exprs[i + NumOutputs]);
145}
146
147//===----------------------------------------------------------------------===//
148// Constructors
149//===----------------------------------------------------------------------===//
150
151AsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
152                 unsigned numoutputs, unsigned numinputs,
153                 std::string *names, StringLiteral **constraints,
154                 Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
155                 StringLiteral **clobbers, SourceLocation rparenloc)
156  : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
157  , IsSimple(issimple), IsVolatile(isvolatile)
158  , NumOutputs(numoutputs), NumInputs(numinputs) {
159  for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) {
160    Names.push_back(names[i]);
161    Exprs.push_back(exprs[i]);
162    Constraints.push_back(constraints[i]);
163  }
164
165  for (unsigned i = 0; i != numclobbers; i++)
166    Clobbers.push_back(clobbers[i]);
167}
168
169ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
170                                             Stmt *Body,  SourceLocation FCL,
171                                             SourceLocation RPL)
172: Stmt(ObjCForCollectionStmtClass) {
173  SubExprs[ELEM] = Elem;
174  SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect);
175  SubExprs[BODY] = Body;
176  ForLoc = FCL;
177  RParenLoc = RPL;
178}
179
180
181ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc,
182                                 SourceLocation rparenloc,
183                                 DeclStmt *catchVarStmtDecl, Stmt *atCatchStmt,
184                                 Stmt *atCatchList)
185: Stmt(ObjCAtCatchStmtClass) {
186  SubExprs[SELECTOR] = catchVarStmtDecl;
187  SubExprs[BODY] = atCatchStmt;
188  SubExprs[NEXT_CATCH] = NULL;
189  // FIXME: O(N^2) in number of catch blocks.
190  if (atCatchList) {
191    ObjCAtCatchStmt *AtCatchList = static_cast<ObjCAtCatchStmt*>(atCatchList);
192
193    while (ObjCAtCatchStmt* NextCatch = AtCatchList->getNextCatchStmt())
194      AtCatchList = NextCatch;
195
196    AtCatchList->SubExprs[NEXT_CATCH] = this;
197  }
198  AtCatchLoc = atCatchLoc;
199  RParenLoc = rparenloc;
200}
201
202
203//===----------------------------------------------------------------------===//
204//  Child Iterators for iterating over subexpressions/substatements
205//===----------------------------------------------------------------------===//
206
207// DeclStmt
208Stmt::child_iterator DeclStmt::child_begin() {
209  return StmtIterator(DG.begin(), DG.end());
210}
211
212Stmt::child_iterator DeclStmt::child_end() {
213  return StmtIterator(DG.end(), DG.end());
214}
215
216// NullStmt
217Stmt::child_iterator NullStmt::child_begin() { return child_iterator(); }
218Stmt::child_iterator NullStmt::child_end() { return child_iterator(); }
219
220// CompoundStmt
221Stmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; }
222Stmt::child_iterator CompoundStmt::child_end() { return &Body[0]+NumStmts; }
223
224// CaseStmt
225Stmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; }
226Stmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; }
227
228// DefaultStmt
229Stmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; }
230Stmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; }
231
232// LabelStmt
233Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; }
234Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; }
235
236// IfStmt
237Stmt::child_iterator IfStmt::child_begin() { return &SubExprs[0]; }
238Stmt::child_iterator IfStmt::child_end() { return &SubExprs[0]+END_EXPR; }
239
240// SwitchStmt
241Stmt::child_iterator SwitchStmt::child_begin() { return &SubExprs[0]; }
242Stmt::child_iterator SwitchStmt::child_end() { return &SubExprs[0]+END_EXPR; }
243
244// WhileStmt
245Stmt::child_iterator WhileStmt::child_begin() { return &SubExprs[0]; }
246Stmt::child_iterator WhileStmt::child_end() { return &SubExprs[0]+END_EXPR; }
247
248// DoStmt
249Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; }
250Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; }
251
252// ForStmt
253Stmt::child_iterator ForStmt::child_begin() { return &SubExprs[0]; }
254Stmt::child_iterator ForStmt::child_end() { return &SubExprs[0]+END_EXPR; }
255
256// ObjCForCollectionStmt
257Stmt::child_iterator ObjCForCollectionStmt::child_begin() {
258  return &SubExprs[0];
259}
260Stmt::child_iterator ObjCForCollectionStmt::child_end() {
261  return &SubExprs[0]+END_EXPR;
262}
263
264// GotoStmt
265Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); }
266Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); }
267
268// IndirectGotoStmt
269Expr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); }
270const Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); }
271
272Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; }
273Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; }
274
275// ContinueStmt
276Stmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); }
277Stmt::child_iterator ContinueStmt::child_end() { return child_iterator(); }
278
279// BreakStmt
280Stmt::child_iterator BreakStmt::child_begin() { return child_iterator(); }
281Stmt::child_iterator BreakStmt::child_end() { return child_iterator(); }
282
283// ReturnStmt
284const Expr* ReturnStmt::getRetValue() const {
285  return cast_or_null<Expr>(RetExpr);
286}
287Expr* ReturnStmt::getRetValue() {
288  return cast_or_null<Expr>(RetExpr);
289}
290
291Stmt::child_iterator ReturnStmt::child_begin() {
292  return &RetExpr;
293}
294Stmt::child_iterator ReturnStmt::child_end() {
295  return RetExpr ? &RetExpr+1 : &RetExpr;
296}
297
298// AsmStmt
299Stmt::child_iterator AsmStmt::child_begin() {
300  return Exprs.empty() ? 0 : &Exprs[0];
301}
302Stmt::child_iterator AsmStmt::child_end() {
303  return Exprs.empty() ? 0 : &Exprs[0] + Exprs.size();
304}
305
306// ObjCAtCatchStmt
307Stmt::child_iterator ObjCAtCatchStmt::child_begin() { return &SubExprs[0]; }
308Stmt::child_iterator ObjCAtCatchStmt::child_end() {
309  return &SubExprs[0]+END_EXPR;
310}
311
312// ObjCAtFinallyStmt
313Stmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; }
314Stmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; }
315
316// ObjCAtTryStmt
317Stmt::child_iterator ObjCAtTryStmt::child_begin() { return &SubStmts[0]; }
318Stmt::child_iterator ObjCAtTryStmt::child_end()   {
319  return &SubStmts[0]+END_EXPR;
320}
321
322// ObjCAtThrowStmt
323Stmt::child_iterator ObjCAtThrowStmt::child_begin() {
324  return &Throw;
325}
326
327Stmt::child_iterator ObjCAtThrowStmt::child_end() {
328  return &Throw+1;
329}
330
331// ObjCAtSynchronizedStmt
332Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() {
333  return &SubStmts[0];
334}
335
336Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() {
337  return &SubStmts[0]+END_EXPR;
338}
339
340// CXXCatchStmt
341Stmt::child_iterator CXXCatchStmt::child_begin() {
342  return &HandlerBlock;
343}
344
345Stmt::child_iterator CXXCatchStmt::child_end() {
346  return &HandlerBlock + 1;
347}
348
349QualType CXXCatchStmt::getCaughtType() {
350  if (ExceptionDecl)
351    return llvm::cast<VarDecl>(ExceptionDecl)->getType();
352  return QualType();
353}
354
355void CXXCatchStmt::Destroy(ASTContext& C) {
356  if (ExceptionDecl)
357    ExceptionDecl->Destroy(C);
358  Stmt::Destroy(C);
359}
360
361// CXXTryStmt
362Stmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; }
363Stmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); }
364
365CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
366                       Stmt **handlers, unsigned numHandlers)
367  : Stmt(CXXTryStmtClass), TryLoc(tryLoc) {
368  Stmts.push_back(tryBlock);
369  Stmts.insert(Stmts.end(), handlers, handlers + numHandlers);
370}
371