summaryrefslogtreecommitdiff
path: root/AST/Stmt.cpp
blob: 6663d6f88b0dbfe1cdc7bc6be730c97d0102b9ac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file was developed by Chris Lattner and is distributed under
// the University of Illinois Open Source License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
//
// This file implements the Stmt class and statement subclasses.
//
//===----------------------------------------------------------------------===//

#include "clang/AST/Stmt.h"
#include "clang/AST/ExprCXX.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/IdentifierTable.h"
using namespace clang;

static struct StmtClassNameTable {
  const char *Name;
  unsigned Counter;
  unsigned Size;
} StmtClassInfo[Stmt::lastExprConstant+1];

static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
  static bool Initialized = false;
  if (Initialized)
    return StmtClassInfo[E];

  // Intialize the table on the first use.
  Initialized = true;
#define STMT(N, CLASS, PARENT) \
  StmtClassInfo[N].Name = #CLASS; \
  StmtClassInfo[N].Size = sizeof(CLASS);
#include "clang/AST/StmtNodes.def"
  
  return StmtClassInfo[E];
}

const char *Stmt::getStmtClassName() const {
  return getStmtInfoTableEntry(sClass).Name;
}

void Stmt::PrintStats() {
  // Ensure the table is primed.
  getStmtInfoTableEntry(Stmt::NullStmtClass);
  
  unsigned sum = 0;
  fprintf(stderr, "*** Stmt/Expr Stats:\n");
  for (int i = 0; i != Stmt::lastExprConstant+1; i++) {
    if (StmtClassInfo[i].Name == 0) continue;
    sum += StmtClassInfo[i].Counter;
  }
  fprintf(stderr, "  %d stmts/exprs total.\n", sum);
  sum = 0;
  for (int i = 0; i != Stmt::lastExprConstant+1; i++) {
    if (StmtClassInfo[i].Name == 0) continue;
    fprintf(stderr, "    %d %s, %d each (%d bytes)\n", 
            StmtClassInfo[i].Counter, StmtClassInfo[i].Name,
            StmtClassInfo[i].Size,
            StmtClassInfo[i].Counter*StmtClassInfo[i].Size);
    sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
  }
  fprintf(stderr, "Total bytes = %d\n", sum);
}

void Stmt::addStmtClass(StmtClass s) {
  ++getStmtInfoTableEntry(s).Counter;
}

static bool StatSwitch = false;

bool Stmt::CollectingStats(bool enable) {
  if (enable) StatSwitch = true;
  return StatSwitch;
}


const char *LabelStmt::getName() const {
  return getID()->getName();
}

// This is defined here to avoid polluting Stmt.h with importing Expr.h
SourceRange ReturnStmt::getSourceRange() const { 
  if (RetExpr)
    return SourceRange(RetLoc, RetExpr->getLocEnd());
  else
    return SourceRange(RetLoc);
}

bool Stmt::hasImplicitControlFlow() const {
  switch (sClass) {
    default:
      return false;
      
    case CallExprClass:
    case ConditionalOperatorClass:
    case ChooseExprClass:
    case StmtExprClass:
    case DeclStmtClass:
      return true;    
      
    case Stmt::BinaryOperatorClass: {
      const BinaryOperator* B = cast<BinaryOperator>(this);
      if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma)
        return true;
      else
        return false;
    }
  }
}

AsmStmt::AsmStmt(SourceLocation asmloc, 
                 bool isvolatile,
                 unsigned numoutputs,
                 unsigned numinputs,
                 std::string *names,
                 StringLiteral **constraints,
                 Expr **exprs,
                 StringLiteral *asmstr,
                 unsigned numclobbers,
                 StringLiteral **clobbers,                 
                 SourceLocation rparenloc)
  : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
  , IsVolatile(isvolatile), NumOutputs(numoutputs), NumInputs(numinputs)
{
  for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) {
    Names.push_back(names[i]);
    Exprs.push_back(exprs[i]);
    Constraints.push_back(constraints[i]);    
  }
  
  for (unsigned i = 0; i != numclobbers; i++)
    Clobbers.push_back(clobbers[i]);
}

//===----------------------------------------------------------------------===//
//  Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//

// DeclStmt
Stmt::child_iterator DeclStmt::child_begin() { return getDecl(); }
Stmt::child_iterator DeclStmt::child_end() { return child_iterator(); }

// NullStmt
Stmt::child_iterator NullStmt::child_begin() { return child_iterator(); }
Stmt::child_iterator NullStmt::child_end() { return child_iterator(); }

// CompoundStmt
Stmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; }
Stmt::child_iterator CompoundStmt::child_end() { return &Body[0]+Body.size(); }

// CaseStmt
Stmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; }

// DefaultStmt
Stmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; }
Stmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; }

// LabelStmt
Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; }
Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; }

// IfStmt
Stmt::child_iterator IfStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator IfStmt::child_end() { return &SubExprs[0]+END_EXPR; }

// SwitchStmt
Stmt::child_iterator SwitchStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator SwitchStmt::child_end() { return &SubExprs[0]+END_EXPR; }

// WhileStmt
Stmt::child_iterator WhileStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator WhileStmt::child_end() { return &SubExprs[0]+END_EXPR; }

// DoStmt
Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; }

// ForStmt
Stmt::child_iterator ForStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator ForStmt::child_end() { return &SubExprs[0]+END_EXPR; }

// GotoStmt
Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); }
Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); }

// IndirectGotoStmt
Stmt::child_iterator IndirectGotoStmt::child_begin() { 
  return reinterpret_cast<Stmt**>(&Target); 
}

Stmt::child_iterator IndirectGotoStmt::child_end() { return ++child_begin(); }

// ContinueStmt
Stmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); }
Stmt::child_iterator ContinueStmt::child_end() { return child_iterator(); }

// BreakStmt
Stmt::child_iterator BreakStmt::child_begin() { return child_iterator(); }
Stmt::child_iterator BreakStmt::child_end() { return child_iterator(); }

// ReturnStmt
Stmt::child_iterator ReturnStmt::child_begin() {
  if (RetExpr) return reinterpret_cast<Stmt**>(&RetExpr);
  else return child_iterator();
}

Stmt::child_iterator ReturnStmt::child_end() { 
  if (RetExpr) return reinterpret_cast<Stmt**>(&RetExpr)+1;
  else return child_iterator();
}

// AsmStmt
Stmt::child_iterator AsmStmt::child_begin() { return child_iterator(); }
Stmt::child_iterator AsmStmt::child_end() { return child_iterator(); }

// ObjcAtCatchStmt
Stmt::child_iterator ObjcAtCatchStmt::child_begin() { return &SubExprs[0]; }
Stmt::child_iterator ObjcAtCatchStmt::child_end() { 
  return &SubExprs[0]+END_EXPR; 
}

// ObjcAtFinallyStmt
Stmt::child_iterator ObjcAtFinallyStmt::child_begin() { return &AtFinallyStmt; }
Stmt::child_iterator ObjcAtFinallyStmt::child_end() { return &AtFinallyStmt+1; }

// ObjcAtTryStmt
Stmt::child_iterator ObjcAtTryStmt::child_begin() { return &SubStmts[0]; }
Stmt::child_iterator ObjcAtTryStmt::child_end()   { 
  return &SubStmts[0]+END_EXPR; 
}

// ObjcAtThrowStmt
Stmt::child_iterator ObjcAtThrowStmt::child_begin() {
  return &Throw;
}

Stmt::child_iterator ObjcAtThrowStmt::child_end() {
  return &Throw+1;
}