Stmt.cpp revision 3182db1c8e456c4cd2180fac9d77d331b2c0621f
145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===//
245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//
345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//                     The LLVM Compiler Infrastructure
445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//
545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// This file is distributed under the University of Illinois Open Source
645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// License. See LICENSE.TXT for details.
745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//
845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//===----------------------------------------------------------------------===//
945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//
1045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org// This file implements the Stmt class and statement subclasses.
1145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//
1245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org//===----------------------------------------------------------------------===//
1345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
1445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/Stmt.h"
1545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/ExprCXX.h"
1645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/ExprObjC.h"
1745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/Type.h"
1845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/ASTContext.h"
1945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/ASTDiagnostic.h"
2045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgusing namespace clang;
2145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic struct StmtClassNameTable {
2345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  const char *Name;
2445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  unsigned Counter;
2545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  unsigned Size;
2645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org} StmtClassInfo[Stmt::lastExprConstant+1];
2745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
2845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgstatic StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
2945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  static bool Initialized = false;
3045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  if (Initialized)
3145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org    return StmtClassInfo[E];
3245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
3345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  // Intialize the table on the first use.
3445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  Initialized = true;
3545afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#define STMT(CLASS, PARENT) \
3645afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS;    \
3745afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
3845afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org#include "clang/AST/StmtNodes.def"
3945afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4045afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  return StmtClassInfo[E];
4145afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org}
4245afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org
4345afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.orgconst char *Stmt::getStmtClassName() const {
4445afe016bed87b9c6946184709058b39ede3f77ajwong@chromium.org  return getStmtInfoTableEntry(sClass).Name;
45}
46
47void Stmt::DestroyChildren(ASTContext &C) {
48  for (child_iterator I = child_begin(), E = child_end(); I !=E; )
49    if (Stmt* Child = *I++) Child->Destroy(C);
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
134Expr *AsmStmt::getOutputExpr(unsigned i) {
135  return cast<Expr>(Exprs[i]);
136}
137
138/// getOutputConstraint - Return the constraint string for the specified
139/// output operand.  All output constraints are known to be non-empty (either
140/// '=' or '+').
141std::string AsmStmt::getOutputConstraint(unsigned i) const {
142  return std::string(Constraints[i]->getStrData(),
143                     Constraints[i]->getByteLength());
144}
145
146
147Expr *AsmStmt::getInputExpr(unsigned i) {
148  return cast<Expr>(Exprs[i + NumOutputs]);
149}
150
151/// getInputConstraint - Return the specified input constraint.  Unlike output
152/// constraints, these can be empty.
153std::string AsmStmt::getInputConstraint(unsigned i) const {
154  return std::string(Constraints[i + NumOutputs]->getStrData(),
155                     Constraints[i + NumOutputs]->getByteLength());
156}
157
158
159/// getNamedOperand - Given a symbolic operand reference like %[foo],
160/// translate this into a numeric value needed to reference the same operand.
161/// This returns -1 if the operand name is invalid.
162int AsmStmt::getNamedOperand(const std::string &SymbolicName) const {
163  unsigned NumPlusOperands = 0;
164
165  // Check if this is an output operand.
166  for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) {
167    if (getOutputName(i) == SymbolicName)
168      return i;
169
170    // Keep track of the number of '+' operands.
171    if (isOutputPlusConstraint(i)) ++NumPlusOperands;
172  }
173
174  for (unsigned i = 0, e = getNumInputs(); i != e; ++i)
175    if (getInputName(i) == SymbolicName)
176      return getNumOutputs() + NumPlusOperands + i;
177
178  // Not found.
179  return -1;
180}
181
182
183/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
184/// it into pieces.  If the asm string is erroneous, emit errors and return
185/// true, otherwise return false.
186unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
187                                   ASTContext &C, unsigned &DiagOffs) const {
188  const char *StrStart = getAsmString()->getStrData();
189  const char *StrEnd = StrStart + getAsmString()->getByteLength();
190  const char *CurPtr = StrStart;
191
192  // "Simple" inline asms have no constraints or operands, just convert the asm
193  // string to escape $'s.
194  if (isSimple()) {
195    std::string Result;
196    for (; CurPtr != StrEnd; ++CurPtr) {
197      switch (*CurPtr) {
198      case '$':
199        Result += "$$";
200        break;
201      default:
202        Result += *CurPtr;
203        break;
204      }
205    }
206    Pieces.push_back(AsmStringPiece(Result));
207    return 0;
208  }
209
210  // CurStringPiece - The current string that we are building up as we scan the
211  // asm string.
212  std::string CurStringPiece;
213
214  while (1) {
215    // Done with the string?
216    if (CurPtr == StrEnd) {
217      if (!CurStringPiece.empty())
218        Pieces.push_back(AsmStringPiece(CurStringPiece));
219      return 0;
220    }
221
222    char CurChar = *CurPtr++;
223    if (CurChar == '$') {
224      CurStringPiece += "$$";
225      continue;
226    } else if (CurChar != '%') {
227      CurStringPiece += CurChar;
228      continue;
229    }
230
231    // Escaped "%" character in asm string.
232    // FIXME: This should be caught during Sema.
233    assert(CurPtr != StrEnd && "Trailing '%' in asm string.");
234
235    char EscapedChar = *CurPtr++;
236    if (EscapedChar == '%') {  // %% -> %
237      // Escaped percentage sign.
238      CurStringPiece += '%';
239      continue;
240    }
241
242    if (EscapedChar == '=') {  // %= -> Generate an unique ID.
243      CurStringPiece += "${:uid}";
244      continue;
245    }
246
247    // Otherwise, we have an operand.  If we have accumulated a string so far,
248    // add it to the Pieces list.
249    if (!CurStringPiece.empty()) {
250      Pieces.push_back(AsmStringPiece(CurStringPiece));
251      CurStringPiece.clear();
252    }
253
254    // Handle %x4 and %x[foo] by capturing x as the modifier character.
255    char Modifier = '\0';
256    if (isalpha(EscapedChar)) {
257      Modifier = EscapedChar;
258      EscapedChar = *CurPtr++;
259    }
260
261    if (isdigit(EscapedChar)) {
262      // %n - Assembler operand n
263      char *End;
264      unsigned long N = strtoul(CurPtr-1, &End, 10);
265      assert(End != CurPtr-1 && "We know that EscapedChar is a digit!");
266      CurPtr = End;
267
268      // FIXME: This should be caught during Sema.
269      //unsigned NumOperands = S.getNumOutputs() + S.getNumInputs();
270      //assert(N < NumOperands && "Operand number out of range!");
271
272      Pieces.push_back(AsmStringPiece(N, Modifier));
273      continue;
274    }
275
276    // Handle %[foo], a symbolic operand reference.
277    if (EscapedChar == '[') {
278      const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
279      // FIXME: Should be caught by sema.
280      // FIXME: Does sema catch multiple operands with the same name?
281      assert(NameEnd != 0 && "Could not parse symbolic name");
282      std::string SymbolicName(CurPtr, NameEnd);
283      CurPtr = NameEnd+1;
284
285      int N = getNamedOperand(SymbolicName);
286      assert(N != -1 && "FIXME: Catch in Sema.");
287      Pieces.push_back(AsmStringPiece(N, Modifier));
288      continue;
289    }
290
291    DiagOffs = CurPtr-StrStart;
292    return diag::err_asm_invalid_escape;
293  }
294}
295
296//===----------------------------------------------------------------------===//
297// Constructors
298//===----------------------------------------------------------------------===//
299
300AsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
301                 unsigned numoutputs, unsigned numinputs,
302                 std::string *names, StringLiteral **constraints,
303                 Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
304                 StringLiteral **clobbers, SourceLocation rparenloc)
305  : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
306  , IsSimple(issimple), IsVolatile(isvolatile)
307  , NumOutputs(numoutputs), NumInputs(numinputs) {
308  for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) {
309    Names.push_back(names[i]);
310    Exprs.push_back(exprs[i]);
311    Constraints.push_back(constraints[i]);
312  }
313
314  for (unsigned i = 0; i != numclobbers; i++)
315    Clobbers.push_back(clobbers[i]);
316}
317
318ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
319                                             Stmt *Body,  SourceLocation FCL,
320                                             SourceLocation RPL)
321: Stmt(ObjCForCollectionStmtClass) {
322  SubExprs[ELEM] = Elem;
323  SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect);
324  SubExprs[BODY] = Body;
325  ForLoc = FCL;
326  RParenLoc = RPL;
327}
328
329
330ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc,
331                                 SourceLocation rparenloc,
332                                 ParmVarDecl *catchVarDecl, Stmt *atCatchStmt,
333                                 Stmt *atCatchList)
334: Stmt(ObjCAtCatchStmtClass) {
335  ExceptionDecl = catchVarDecl;
336  SubExprs[BODY] = atCatchStmt;
337  SubExprs[NEXT_CATCH] = NULL;
338  // FIXME: O(N^2) in number of catch blocks.
339  if (atCatchList) {
340    ObjCAtCatchStmt *AtCatchList = static_cast<ObjCAtCatchStmt*>(atCatchList);
341
342    while (ObjCAtCatchStmt* NextCatch = AtCatchList->getNextCatchStmt())
343      AtCatchList = NextCatch;
344
345    AtCatchList->SubExprs[NEXT_CATCH] = this;
346  }
347  AtCatchLoc = atCatchLoc;
348  RParenLoc = rparenloc;
349}
350
351
352//===----------------------------------------------------------------------===//
353//  Child Iterators for iterating over subexpressions/substatements
354//===----------------------------------------------------------------------===//
355
356// DeclStmt
357Stmt::child_iterator DeclStmt::child_begin() {
358  return StmtIterator(DG.begin(), DG.end());
359}
360
361Stmt::child_iterator DeclStmt::child_end() {
362  return StmtIterator(DG.end(), DG.end());
363}
364
365// NullStmt
366Stmt::child_iterator NullStmt::child_begin() { return child_iterator(); }
367Stmt::child_iterator NullStmt::child_end() { return child_iterator(); }
368
369// CompoundStmt
370Stmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; }
371Stmt::child_iterator CompoundStmt::child_end() { return &Body[0]+NumStmts; }
372
373// CaseStmt
374Stmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; }
375Stmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; }
376
377// DefaultStmt
378Stmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; }
379Stmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; }
380
381// LabelStmt
382Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; }
383Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; }
384
385// IfStmt
386Stmt::child_iterator IfStmt::child_begin() { return &SubExprs[0]; }
387Stmt::child_iterator IfStmt::child_end() { return &SubExprs[0]+END_EXPR; }
388
389// SwitchStmt
390Stmt::child_iterator SwitchStmt::child_begin() { return &SubExprs[0]; }
391Stmt::child_iterator SwitchStmt::child_end() { return &SubExprs[0]+END_EXPR; }
392
393// WhileStmt
394Stmt::child_iterator WhileStmt::child_begin() { return &SubExprs[0]; }
395Stmt::child_iterator WhileStmt::child_end() { return &SubExprs[0]+END_EXPR; }
396
397// DoStmt
398Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; }
399Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; }
400
401// ForStmt
402Stmt::child_iterator ForStmt::child_begin() { return &SubExprs[0]; }
403Stmt::child_iterator ForStmt::child_end() { return &SubExprs[0]+END_EXPR; }
404
405// ObjCForCollectionStmt
406Stmt::child_iterator ObjCForCollectionStmt::child_begin() {
407  return &SubExprs[0];
408}
409Stmt::child_iterator ObjCForCollectionStmt::child_end() {
410  return &SubExprs[0]+END_EXPR;
411}
412
413// GotoStmt
414Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); }
415Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); }
416
417// IndirectGotoStmt
418Expr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); }
419const Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); }
420
421Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; }
422Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; }
423
424// ContinueStmt
425Stmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); }
426Stmt::child_iterator ContinueStmt::child_end() { return child_iterator(); }
427
428// BreakStmt
429Stmt::child_iterator BreakStmt::child_begin() { return child_iterator(); }
430Stmt::child_iterator BreakStmt::child_end() { return child_iterator(); }
431
432// ReturnStmt
433const Expr* ReturnStmt::getRetValue() const {
434  return cast_or_null<Expr>(RetExpr);
435}
436Expr* ReturnStmt::getRetValue() {
437  return cast_or_null<Expr>(RetExpr);
438}
439
440Stmt::child_iterator ReturnStmt::child_begin() {
441  return &RetExpr;
442}
443Stmt::child_iterator ReturnStmt::child_end() {
444  return RetExpr ? &RetExpr+1 : &RetExpr;
445}
446
447// AsmStmt
448Stmt::child_iterator AsmStmt::child_begin() {
449  return Exprs.empty() ? 0 : &Exprs[0];
450}
451Stmt::child_iterator AsmStmt::child_end() {
452  return Exprs.empty() ? 0 : &Exprs[0] + Exprs.size();
453}
454
455// ObjCAtCatchStmt
456Stmt::child_iterator ObjCAtCatchStmt::child_begin() { return &SubExprs[0]; }
457Stmt::child_iterator ObjCAtCatchStmt::child_end() {
458  return &SubExprs[0]+END_EXPR;
459}
460
461// ObjCAtFinallyStmt
462Stmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; }
463Stmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; }
464
465// ObjCAtTryStmt
466Stmt::child_iterator ObjCAtTryStmt::child_begin() { return &SubStmts[0]; }
467Stmt::child_iterator ObjCAtTryStmt::child_end()   {
468  return &SubStmts[0]+END_EXPR;
469}
470
471// ObjCAtThrowStmt
472Stmt::child_iterator ObjCAtThrowStmt::child_begin() {
473  return &Throw;
474}
475
476Stmt::child_iterator ObjCAtThrowStmt::child_end() {
477  return &Throw+1;
478}
479
480// ObjCAtSynchronizedStmt
481Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() {
482  return &SubStmts[0];
483}
484
485Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() {
486  return &SubStmts[0]+END_EXPR;
487}
488
489// CXXCatchStmt
490Stmt::child_iterator CXXCatchStmt::child_begin() {
491  return &HandlerBlock;
492}
493
494Stmt::child_iterator CXXCatchStmt::child_end() {
495  return &HandlerBlock + 1;
496}
497
498QualType CXXCatchStmt::getCaughtType() {
499  if (ExceptionDecl)
500    return llvm::cast<VarDecl>(ExceptionDecl)->getType();
501  return QualType();
502}
503
504void CXXCatchStmt::Destroy(ASTContext& C) {
505  if (ExceptionDecl)
506    ExceptionDecl->Destroy(C);
507  Stmt::Destroy(C);
508}
509
510// CXXTryStmt
511Stmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; }
512Stmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); }
513
514CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
515                       Stmt **handlers, unsigned numHandlers)
516  : Stmt(CXXTryStmtClass), TryLoc(tryLoc) {
517  Stmts.push_back(tryBlock);
518  Stmts.insert(Stmts.end(), handlers, handlers + numHandlers);
519}
520