Stmt.cpp revision 202379
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 <cstdio>
23using namespace clang;
24
25static struct StmtClassNameTable {
26  const char *Name;
27  unsigned Counter;
28  unsigned Size;
29} StmtClassInfo[Stmt::lastExprConstant+1];
30
31static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
32  static bool Initialized = false;
33  if (Initialized)
34    return StmtClassInfo[E];
35
36  // Intialize the table on the first use.
37  Initialized = true;
38#define STMT(CLASS, PARENT) \
39  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS;    \
40  StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
41#include "clang/AST/StmtNodes.def"
42
43  return StmtClassInfo[E];
44}
45
46const char *Stmt::getStmtClassName() const {
47  return getStmtInfoTableEntry((StmtClass)sClass).Name;
48}
49
50void Stmt::PrintStats() {
51  // Ensure the table is primed.
52  getStmtInfoTableEntry(Stmt::NullStmtClass);
53
54  unsigned sum = 0;
55  fprintf(stderr, "*** Stmt/Expr Stats:\n");
56  for (int i = 0; i != Stmt::lastExprConstant+1; i++) {
57    if (StmtClassInfo[i].Name == 0) continue;
58    sum += StmtClassInfo[i].Counter;
59  }
60  fprintf(stderr, "  %d stmts/exprs total.\n", sum);
61  sum = 0;
62  for (int i = 0; i != Stmt::lastExprConstant+1; i++) {
63    if (StmtClassInfo[i].Name == 0) continue;
64    if (StmtClassInfo[i].Counter == 0) continue;
65    fprintf(stderr, "    %d %s, %d each (%d bytes)\n",
66            StmtClassInfo[i].Counter, StmtClassInfo[i].Name,
67            StmtClassInfo[i].Size,
68            StmtClassInfo[i].Counter*StmtClassInfo[i].Size);
69    sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
70  }
71  fprintf(stderr, "Total bytes = %d\n", sum);
72}
73
74void Stmt::addStmtClass(StmtClass s) {
75  ++getStmtInfoTableEntry(s).Counter;
76}
77
78static bool StatSwitch = false;
79
80bool Stmt::CollectingStats(bool Enable) {
81  if (Enable) StatSwitch = true;
82  return StatSwitch;
83}
84
85void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
86  if (this->Body)
87    C.Deallocate(Body);
88  this->NumStmts = NumStmts;
89
90  Body = new (C) Stmt*[NumStmts];
91  memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts);
92}
93
94const char *LabelStmt::getName() const {
95  return getID()->getNameStart();
96}
97
98// This is defined here to avoid polluting Stmt.h with importing Expr.h
99SourceRange ReturnStmt::getSourceRange() const {
100  if (RetExpr)
101    return SourceRange(RetLoc, RetExpr->getLocEnd());
102  else
103    return SourceRange(RetLoc);
104}
105
106bool Stmt::hasImplicitControlFlow() const {
107  switch (sClass) {
108    default:
109      return false;
110
111    case CallExprClass:
112    case ConditionalOperatorClass:
113    case ChooseExprClass:
114    case StmtExprClass:
115    case DeclStmtClass:
116      return true;
117
118    case Stmt::BinaryOperatorClass: {
119      const BinaryOperator* B = cast<BinaryOperator>(this);
120      if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma)
121        return true;
122      else
123        return false;
124    }
125  }
126}
127
128Expr *AsmStmt::getOutputExpr(unsigned i) {
129  return cast<Expr>(Exprs[i]);
130}
131
132/// getOutputConstraint - Return the constraint string for the specified
133/// output operand.  All output constraints are known to be non-empty (either
134/// '=' or '+').
135std::string AsmStmt::getOutputConstraint(unsigned i) const {
136  return std::string(Constraints[i]->getStrData(),
137                     Constraints[i]->getByteLength());
138}
139
140/// getNumPlusOperands - Return the number of output operands that have a "+"
141/// constraint.
142unsigned AsmStmt::getNumPlusOperands() const {
143  unsigned Res = 0;
144  for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)
145    if (isOutputPlusConstraint(i))
146      ++Res;
147  return Res;
148}
149
150
151
152Expr *AsmStmt::getInputExpr(unsigned i) {
153  return cast<Expr>(Exprs[i + NumOutputs]);
154}
155
156/// getInputConstraint - Return the specified input constraint.  Unlike output
157/// constraints, these can be empty.
158std::string AsmStmt::getInputConstraint(unsigned i) const {
159  return std::string(Constraints[i + NumOutputs]->getStrData(),
160                     Constraints[i + NumOutputs]->getByteLength());
161}
162
163
164void AsmStmt::setOutputsAndInputs(unsigned NumOutputs,
165                                  unsigned NumInputs,
166                                  const std::string *Names,
167                                  StringLiteral **Constraints,
168                                  Stmt **Exprs) {
169  this->NumOutputs = NumOutputs;
170  this->NumInputs = NumInputs;
171  this->Names.clear();
172  this->Names.insert(this->Names.end(), Names, Names + NumOutputs + NumInputs);
173  this->Constraints.clear();
174  this->Constraints.insert(this->Constraints.end(),
175                           Constraints, Constraints + NumOutputs + NumInputs);
176  this->Exprs.clear();
177  this->Exprs.insert(this->Exprs.end(), Exprs, Exprs + NumOutputs + NumInputs);
178}
179
180/// getNamedOperand - Given a symbolic operand reference like %[foo],
181/// translate this into a numeric value needed to reference the same operand.
182/// This returns -1 if the operand name is invalid.
183int AsmStmt::getNamedOperand(const std::string &SymbolicName) const {
184  unsigned NumPlusOperands = 0;
185
186  // Check if this is an output operand.
187  for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) {
188    if (getOutputName(i) == SymbolicName)
189      return i;
190  }
191
192  for (unsigned i = 0, e = getNumInputs(); i != e; ++i)
193    if (getInputName(i) == SymbolicName)
194      return getNumOutputs() + NumPlusOperands + i;
195
196  // Not found.
197  return -1;
198}
199
200void AsmStmt::setClobbers(StringLiteral **Clobbers, unsigned NumClobbers) {
201  this->Clobbers.clear();
202  this->Clobbers.insert(this->Clobbers.end(), Clobbers, Clobbers + NumClobbers);
203}
204
205/// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
206/// it into pieces.  If the asm string is erroneous, emit errors and return
207/// true, otherwise return false.
208unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
209                                   ASTContext &C, unsigned &DiagOffs) const {
210  const char *StrStart = getAsmString()->getStrData();
211  const char *StrEnd = StrStart + getAsmString()->getByteLength();
212  const char *CurPtr = StrStart;
213
214  // "Simple" inline asms have no constraints or operands, just convert the asm
215  // string to escape $'s.
216  if (isSimple()) {
217    std::string Result;
218    for (; CurPtr != StrEnd; ++CurPtr) {
219      switch (*CurPtr) {
220      case '$':
221        Result += "$$";
222        break;
223      default:
224        Result += *CurPtr;
225        break;
226      }
227    }
228    Pieces.push_back(AsmStringPiece(Result));
229    return 0;
230  }
231
232  // CurStringPiece - The current string that we are building up as we scan the
233  // asm string.
234  std::string CurStringPiece;
235
236  while (1) {
237    // Done with the string?
238    if (CurPtr == StrEnd) {
239      if (!CurStringPiece.empty())
240        Pieces.push_back(AsmStringPiece(CurStringPiece));
241      return 0;
242    }
243
244    char CurChar = *CurPtr++;
245    if (CurChar == '$') {
246      CurStringPiece += "$$";
247      continue;
248    } else if (CurChar != '%') {
249      CurStringPiece += CurChar;
250      continue;
251    }
252
253    // Escaped "%" character in asm string.
254    if (CurPtr == StrEnd) {
255      // % at end of string is invalid (no escape).
256      DiagOffs = CurPtr-StrStart-1;
257      return diag::err_asm_invalid_escape;
258    }
259
260    char EscapedChar = *CurPtr++;
261    if (EscapedChar == '%') {  // %% -> %
262      // Escaped percentage sign.
263      CurStringPiece += '%';
264      continue;
265    }
266
267    if (EscapedChar == '=') {  // %= -> Generate an unique ID.
268      CurStringPiece += "${:uid}";
269      continue;
270    }
271
272    // Otherwise, we have an operand.  If we have accumulated a string so far,
273    // add it to the Pieces list.
274    if (!CurStringPiece.empty()) {
275      Pieces.push_back(AsmStringPiece(CurStringPiece));
276      CurStringPiece.clear();
277    }
278
279    // Handle %x4 and %x[foo] by capturing x as the modifier character.
280    char Modifier = '\0';
281    if (isalpha(EscapedChar)) {
282      Modifier = EscapedChar;
283      EscapedChar = *CurPtr++;
284    }
285
286    if (isdigit(EscapedChar)) {
287      // %n - Assembler operand n
288      unsigned N = 0;
289
290      --CurPtr;
291      while (CurPtr != StrEnd && isdigit(*CurPtr))
292        N = N*10 + ((*CurPtr++)-'0');
293
294      unsigned NumOperands =
295        getNumOutputs() + getNumPlusOperands() + getNumInputs();
296      if (N >= NumOperands) {
297        DiagOffs = CurPtr-StrStart-1;
298        return diag::err_asm_invalid_operand_number;
299      }
300
301      Pieces.push_back(AsmStringPiece(N, Modifier));
302      continue;
303    }
304
305    // Handle %[foo], a symbolic operand reference.
306    if (EscapedChar == '[') {
307      DiagOffs = CurPtr-StrStart-1;
308
309      // Find the ']'.
310      const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
311      if (NameEnd == 0)
312        return diag::err_asm_unterminated_symbolic_operand_name;
313      if (NameEnd == CurPtr)
314        return diag::err_asm_empty_symbolic_operand_name;
315
316      std::string SymbolicName(CurPtr, NameEnd);
317
318      int N = getNamedOperand(SymbolicName);
319      if (N == -1) {
320        // Verify that an operand with that name exists.
321        DiagOffs = CurPtr-StrStart;
322        return diag::err_asm_unknown_symbolic_operand_name;
323      }
324      Pieces.push_back(AsmStringPiece(N, Modifier));
325
326      CurPtr = NameEnd+1;
327      continue;
328    }
329
330    DiagOffs = CurPtr-StrStart-1;
331    return diag::err_asm_invalid_escape;
332  }
333}
334
335//===----------------------------------------------------------------------===//
336// Constructors
337//===----------------------------------------------------------------------===//
338
339AsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
340                 bool msasm, unsigned numoutputs, unsigned numinputs,
341                 std::string *names, StringLiteral **constraints,
342                 Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
343                 StringLiteral **clobbers, SourceLocation rparenloc)
344  : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
345  , IsSimple(issimple), IsVolatile(isvolatile), MSAsm(msasm)
346  , NumOutputs(numoutputs), NumInputs(numinputs) {
347  for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) {
348    Names.push_back(names[i]);
349    Exprs.push_back(exprs[i]);
350    Constraints.push_back(constraints[i]);
351  }
352
353  for (unsigned i = 0; i != numclobbers; i++)
354    Clobbers.push_back(clobbers[i]);
355}
356
357ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
358                                             Stmt *Body,  SourceLocation FCL,
359                                             SourceLocation RPL)
360: Stmt(ObjCForCollectionStmtClass) {
361  SubExprs[ELEM] = Elem;
362  SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect);
363  SubExprs[BODY] = Body;
364  ForLoc = FCL;
365  RParenLoc = RPL;
366}
367
368
369ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc,
370                                 SourceLocation rparenloc,
371                                 ParmVarDecl *catchVarDecl, Stmt *atCatchStmt,
372                                 Stmt *atCatchList)
373: Stmt(ObjCAtCatchStmtClass) {
374  ExceptionDecl = catchVarDecl;
375  SubExprs[BODY] = atCatchStmt;
376  SubExprs[NEXT_CATCH] = NULL;
377  // FIXME: O(N^2) in number of catch blocks.
378  if (atCatchList) {
379    ObjCAtCatchStmt *AtCatchList = static_cast<ObjCAtCatchStmt*>(atCatchList);
380
381    while (ObjCAtCatchStmt* NextCatch = AtCatchList->getNextCatchStmt())
382      AtCatchList = NextCatch;
383
384    AtCatchList->SubExprs[NEXT_CATCH] = this;
385  }
386  AtCatchLoc = atCatchLoc;
387  RParenLoc = rparenloc;
388}
389
390//===----------------------------------------------------------------------===//
391// AST Destruction.
392//===----------------------------------------------------------------------===//
393
394void Stmt::DestroyChildren(ASTContext &C) {
395  for (child_iterator I = child_begin(), E = child_end(); I !=E; )
396    if (Stmt* Child = *I++) Child->Destroy(C);
397}
398
399static void BranchDestroy(ASTContext &C, Stmt *S, Stmt **SubExprs,
400                          unsigned NumExprs) {
401  // We do not use child_iterator here because that will include
402  // the expressions referenced by the condition variable.
403  for (Stmt **I = SubExprs, **E = SubExprs + NumExprs; I != E; ++I)
404    if (Stmt *Child = *I) Child->Destroy(C);
405
406  S->~Stmt();
407  C.Deallocate((void *) S);
408}
409
410void Stmt::DoDestroy(ASTContext &C) {
411  DestroyChildren(C);
412  this->~Stmt();
413  C.Deallocate((void *)this);
414}
415
416void CXXCatchStmt::DoDestroy(ASTContext& C) {
417  if (ExceptionDecl)
418    ExceptionDecl->Destroy(C);
419  Stmt::DoDestroy(C);
420}
421
422void DeclStmt::DoDestroy(ASTContext &C) {
423  // Don't use StmtIterator to iterate over the Decls, as that can recurse
424  // into VLA size expressions (which are owned by the VLA).  Further, Decls
425  // are owned by the DeclContext, and will be destroyed with them.
426  if (DG.isDeclGroup())
427    DG.getDeclGroup().Destroy(C);
428}
429
430void IfStmt::DoDestroy(ASTContext &C) {
431  BranchDestroy(C, this, SubExprs, END_EXPR);
432}
433
434void ForStmt::DoDestroy(ASTContext &C) {
435  BranchDestroy(C, this, SubExprs, END_EXPR);
436}
437
438void SwitchStmt::DoDestroy(ASTContext &C) {
439  // Destroy the SwitchCase statements in this switch. In the normal
440  // case, this loop will merely decrement the reference counts from
441  // the Retain() calls in addSwitchCase();
442  SwitchCase *SC = FirstCase;
443  while (SC) {
444    SwitchCase *Next = SC->getNextSwitchCase();
445    SC->Destroy(C);
446    SC = Next;
447  }
448
449  BranchDestroy(C, this, SubExprs, END_EXPR);
450}
451
452void WhileStmt::DoDestroy(ASTContext &C) {
453  BranchDestroy(C, this, SubExprs, END_EXPR);
454}
455
456//===----------------------------------------------------------------------===//
457//  Child Iterators for iterating over subexpressions/substatements
458//===----------------------------------------------------------------------===//
459
460// DeclStmt
461Stmt::child_iterator DeclStmt::child_begin() {
462  return StmtIterator(DG.begin(), DG.end());
463}
464
465Stmt::child_iterator DeclStmt::child_end() {
466  return StmtIterator(DG.end(), DG.end());
467}
468
469// NullStmt
470Stmt::child_iterator NullStmt::child_begin() { return child_iterator(); }
471Stmt::child_iterator NullStmt::child_end() { return child_iterator(); }
472
473// CompoundStmt
474Stmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; }
475Stmt::child_iterator CompoundStmt::child_end() { return &Body[0]+NumStmts; }
476
477// CaseStmt
478Stmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; }
479Stmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; }
480
481// DefaultStmt
482Stmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; }
483Stmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; }
484
485// LabelStmt
486Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; }
487Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; }
488
489// IfStmt
490Stmt::child_iterator IfStmt::child_begin() {
491  return child_iterator(Var, &SubExprs[0]);
492}
493Stmt::child_iterator IfStmt::child_end() {
494  return child_iterator(0, &SubExprs[0]+END_EXPR);
495}
496
497// SwitchStmt
498Stmt::child_iterator SwitchStmt::child_begin() {
499  return child_iterator(Var, &SubExprs[0]);
500}
501Stmt::child_iterator SwitchStmt::child_end() {
502  return child_iterator(0, &SubExprs[0]+END_EXPR);
503}
504
505// WhileStmt
506Stmt::child_iterator WhileStmt::child_begin() {
507  return child_iterator(Var, &SubExprs[0]);
508}
509Stmt::child_iterator WhileStmt::child_end() {
510  return child_iterator(0, &SubExprs[0]+END_EXPR);
511}
512
513// DoStmt
514Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; }
515Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; }
516
517// ForStmt
518Stmt::child_iterator ForStmt::child_begin() {
519  return child_iterator(CondVar, &SubExprs[0]);
520}
521Stmt::child_iterator ForStmt::child_end() {
522  return child_iterator(0, &SubExprs[0]+END_EXPR);
523}
524
525// ObjCForCollectionStmt
526Stmt::child_iterator ObjCForCollectionStmt::child_begin() {
527  return &SubExprs[0];
528}
529Stmt::child_iterator ObjCForCollectionStmt::child_end() {
530  return &SubExprs[0]+END_EXPR;
531}
532
533// GotoStmt
534Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); }
535Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); }
536
537// IndirectGotoStmt
538Expr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); }
539const Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); }
540
541Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; }
542Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; }
543
544// ContinueStmt
545Stmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); }
546Stmt::child_iterator ContinueStmt::child_end() { return child_iterator(); }
547
548// BreakStmt
549Stmt::child_iterator BreakStmt::child_begin() { return child_iterator(); }
550Stmt::child_iterator BreakStmt::child_end() { return child_iterator(); }
551
552// ReturnStmt
553const Expr* ReturnStmt::getRetValue() const {
554  return cast_or_null<Expr>(RetExpr);
555}
556Expr* ReturnStmt::getRetValue() {
557  return cast_or_null<Expr>(RetExpr);
558}
559
560Stmt::child_iterator ReturnStmt::child_begin() {
561  return &RetExpr;
562}
563Stmt::child_iterator ReturnStmt::child_end() {
564  return RetExpr ? &RetExpr+1 : &RetExpr;
565}
566
567// AsmStmt
568Stmt::child_iterator AsmStmt::child_begin() {
569  return Exprs.empty() ? 0 : &Exprs[0];
570}
571Stmt::child_iterator AsmStmt::child_end() {
572  return Exprs.empty() ? 0 : &Exprs[0] + Exprs.size();
573}
574
575// ObjCAtCatchStmt
576Stmt::child_iterator ObjCAtCatchStmt::child_begin() { return &SubExprs[0]; }
577Stmt::child_iterator ObjCAtCatchStmt::child_end() {
578  return &SubExprs[0]+END_EXPR;
579}
580
581// ObjCAtFinallyStmt
582Stmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; }
583Stmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; }
584
585// ObjCAtTryStmt
586Stmt::child_iterator ObjCAtTryStmt::child_begin() { return &SubStmts[0]; }
587Stmt::child_iterator ObjCAtTryStmt::child_end()   {
588  return &SubStmts[0]+END_EXPR;
589}
590
591// ObjCAtThrowStmt
592Stmt::child_iterator ObjCAtThrowStmt::child_begin() {
593  return &Throw;
594}
595
596Stmt::child_iterator ObjCAtThrowStmt::child_end() {
597  return &Throw+1;
598}
599
600// ObjCAtSynchronizedStmt
601Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() {
602  return &SubStmts[0];
603}
604
605Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() {
606  return &SubStmts[0]+END_EXPR;
607}
608
609// CXXCatchStmt
610Stmt::child_iterator CXXCatchStmt::child_begin() {
611  return &HandlerBlock;
612}
613
614Stmt::child_iterator CXXCatchStmt::child_end() {
615  return &HandlerBlock + 1;
616}
617
618QualType CXXCatchStmt::getCaughtType() const {
619  if (ExceptionDecl)
620    return ExceptionDecl->getType();
621  return QualType();
622}
623
624// CXXTryStmt
625Stmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; }
626Stmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); }
627
628CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
629                       Stmt **handlers, unsigned numHandlers)
630  : Stmt(CXXTryStmtClass), TryLoc(tryLoc) {
631  Stmts.push_back(tryBlock);
632  Stmts.insert(Stmts.end(), handlers, handlers + numHandlers);
633}
634