1 //===--- Stmt.cpp - Statement AST Node Implementation ---------------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the Stmt class and statement subclasses.
12 //===----------------------------------------------------------------------===//
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 using namespace clang;
24 static struct StmtClassNameTable {
28 } StmtClassInfo[Stmt::lastExprConstant+1];
30 static StmtClassNameTable &getStmtInfoTableEntry(Stmt::StmtClass E) {
31 static bool Initialized = false;
33 return StmtClassInfo[E];
35 // Intialize the table on the first use.
37 #define STMT(CLASS, PARENT) \
38 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Name = #CLASS; \
39 StmtClassInfo[(unsigned)Stmt::CLASS##Class].Size = sizeof(CLASS);
40 #include "clang/AST/StmtNodes.def"
42 return StmtClassInfo[E];
45 const char *Stmt::getStmtClassName() const {
46 return getStmtInfoTableEntry(sClass).Name;
49 void Stmt::DestroyChildren(ASTContext &C) {
50 for (child_iterator I = child_begin(), E = child_end(); I !=E; )
51 if (Stmt* Child = *I++) Child->Destroy(C);
54 void Stmt::Destroy(ASTContext &C) {
56 // FIXME: Eventually all Stmts should be allocated with the allocator
57 // in ASTContext, just like with Decls.
59 C.Deallocate((void *)this);
62 void DeclStmt::Destroy(ASTContext &C) {
64 C.Deallocate((void *)this);
67 void Stmt::PrintStats() {
68 // Ensure the table is primed.
69 getStmtInfoTableEntry(Stmt::NullStmtClass);
72 fprintf(stderr, "*** Stmt/Expr Stats:\n");
73 for (int i = 0; i != Stmt::lastExprConstant+1; i++) {
74 if (StmtClassInfo[i].Name == 0) continue;
75 sum += StmtClassInfo[i].Counter;
77 fprintf(stderr, " %d stmts/exprs total.\n", sum);
79 for (int i = 0; i != Stmt::lastExprConstant+1; i++) {
80 if (StmtClassInfo[i].Name == 0) continue;
81 if (StmtClassInfo[i].Counter == 0) continue;
82 fprintf(stderr, " %d %s, %d each (%d bytes)\n",
83 StmtClassInfo[i].Counter, StmtClassInfo[i].Name,
84 StmtClassInfo[i].Size,
85 StmtClassInfo[i].Counter*StmtClassInfo[i].Size);
86 sum += StmtClassInfo[i].Counter*StmtClassInfo[i].Size;
88 fprintf(stderr, "Total bytes = %d\n", sum);
91 void Stmt::addStmtClass(StmtClass s) {
92 ++getStmtInfoTableEntry(s).Counter;
95 static bool StatSwitch = false;
97 bool Stmt::CollectingStats(bool enable) {
98 if (enable) StatSwitch = true;
102 NullStmt* NullStmt::Clone(ASTContext &C) const {
103 return new (C) NullStmt(SemiLoc);
106 ContinueStmt* ContinueStmt::Clone(ASTContext &C) const {
107 return new (C) ContinueStmt(ContinueLoc);
110 BreakStmt* BreakStmt::Clone(ASTContext &C) const {
111 return new (C) BreakStmt(BreakLoc);
114 void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
117 this->NumStmts = NumStmts;
119 Body = new (C) Stmt*[NumStmts];
120 memcpy(Body, Stmts, sizeof(Stmt *) * NumStmts);
123 const char *LabelStmt::getName() const {
124 return getID()->getName();
127 // This is defined here to avoid polluting Stmt.h with importing Expr.h
128 SourceRange ReturnStmt::getSourceRange() const {
130 return SourceRange(RetLoc, RetExpr->getLocEnd());
132 return SourceRange(RetLoc);
135 bool Stmt::hasImplicitControlFlow() const {
141 case ConditionalOperatorClass:
142 case ChooseExprClass:
147 case Stmt::BinaryOperatorClass: {
148 const BinaryOperator* B = cast<BinaryOperator>(this);
149 if (B->isLogicalOp() || B->getOpcode() == BinaryOperator::Comma)
157 Expr *AsmStmt::getOutputExpr(unsigned i) {
158 return cast<Expr>(Exprs[i]);
161 /// getOutputConstraint - Return the constraint string for the specified
162 /// output operand. All output constraints are known to be non-empty (either
164 std::string AsmStmt::getOutputConstraint(unsigned i) const {
165 return std::string(Constraints[i]->getStrData(),
166 Constraints[i]->getByteLength());
169 /// getNumPlusOperands - Return the number of output operands that have a "+"
171 unsigned AsmStmt::getNumPlusOperands() const {
173 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i)
174 if (isOutputPlusConstraint(i))
181 Expr *AsmStmt::getInputExpr(unsigned i) {
182 return cast<Expr>(Exprs[i + NumOutputs]);
185 /// getInputConstraint - Return the specified input constraint. Unlike output
186 /// constraints, these can be empty.
187 std::string AsmStmt::getInputConstraint(unsigned i) const {
188 return std::string(Constraints[i + NumOutputs]->getStrData(),
189 Constraints[i + NumOutputs]->getByteLength());
193 void AsmStmt::setOutputsAndInputs(unsigned NumOutputs,
195 const std::string *Names,
196 StringLiteral **Constraints,
198 this->NumOutputs = NumOutputs;
199 this->NumInputs = NumInputs;
201 this->Names.insert(this->Names.end(), Names, Names + NumOutputs + NumInputs);
202 this->Constraints.clear();
203 this->Constraints.insert(this->Constraints.end(),
204 Constraints, Constraints + NumOutputs + NumInputs);
206 this->Exprs.insert(this->Exprs.end(), Exprs, Exprs + NumOutputs + NumInputs);
209 /// getNamedOperand - Given a symbolic operand reference like %[foo],
210 /// translate this into a numeric value needed to reference the same operand.
211 /// This returns -1 if the operand name is invalid.
212 int AsmStmt::getNamedOperand(const std::string &SymbolicName) const {
213 unsigned NumPlusOperands = 0;
215 // Check if this is an output operand.
216 for (unsigned i = 0, e = getNumOutputs(); i != e; ++i) {
217 if (getOutputName(i) == SymbolicName)
221 for (unsigned i = 0, e = getNumInputs(); i != e; ++i)
222 if (getInputName(i) == SymbolicName)
223 return getNumOutputs() + NumPlusOperands + i;
229 void AsmStmt::setClobbers(StringLiteral **Clobbers, unsigned NumClobbers) {
230 this->Clobbers.clear();
231 this->Clobbers.insert(this->Clobbers.end(), Clobbers, Clobbers + NumClobbers);
234 /// AnalyzeAsmString - Analyze the asm string of the current asm, decomposing
235 /// it into pieces. If the asm string is erroneous, emit errors and return
236 /// true, otherwise return false.
237 unsigned AsmStmt::AnalyzeAsmString(llvm::SmallVectorImpl<AsmStringPiece>&Pieces,
238 ASTContext &C, unsigned &DiagOffs) const {
239 const char *StrStart = getAsmString()->getStrData();
240 const char *StrEnd = StrStart + getAsmString()->getByteLength();
241 const char *CurPtr = StrStart;
243 // "Simple" inline asms have no constraints or operands, just convert the asm
244 // string to escape $'s.
247 for (; CurPtr != StrEnd; ++CurPtr) {
257 Pieces.push_back(AsmStringPiece(Result));
261 // CurStringPiece - The current string that we are building up as we scan the
263 std::string CurStringPiece;
266 // Done with the string?
267 if (CurPtr == StrEnd) {
268 if (!CurStringPiece.empty())
269 Pieces.push_back(AsmStringPiece(CurStringPiece));
273 char CurChar = *CurPtr++;
274 if (CurChar == '$') {
275 CurStringPiece += "$$";
277 } else if (CurChar != '%') {
278 CurStringPiece += CurChar;
282 // Escaped "%" character in asm string.
283 if (CurPtr == StrEnd) {
284 // % at end of string is invalid (no escape).
285 DiagOffs = CurPtr-StrStart-1;
286 return diag::err_asm_invalid_escape;
289 char EscapedChar = *CurPtr++;
290 if (EscapedChar == '%') { // %% -> %
291 // Escaped percentage sign.
292 CurStringPiece += '%';
296 if (EscapedChar == '=') { // %= -> Generate an unique ID.
297 CurStringPiece += "${:uid}";
301 // Otherwise, we have an operand. If we have accumulated a string so far,
302 // add it to the Pieces list.
303 if (!CurStringPiece.empty()) {
304 Pieces.push_back(AsmStringPiece(CurStringPiece));
305 CurStringPiece.clear();
308 // Handle %x4 and %x[foo] by capturing x as the modifier character.
309 char Modifier = '\0';
310 if (isalpha(EscapedChar)) {
311 Modifier = EscapedChar;
312 EscapedChar = *CurPtr++;
315 if (isdigit(EscapedChar)) {
316 // %n - Assembler operand n
320 while (CurPtr != StrEnd && isdigit(*CurPtr))
321 N = N*10 + ((*CurPtr++)-'0');
323 unsigned NumOperands =
324 getNumOutputs() + getNumPlusOperands() + getNumInputs();
325 if (N >= NumOperands) {
326 DiagOffs = CurPtr-StrStart-1;
327 return diag::err_asm_invalid_operand_number;
330 Pieces.push_back(AsmStringPiece(N, Modifier));
334 // Handle %[foo], a symbolic operand reference.
335 if (EscapedChar == '[') {
336 DiagOffs = CurPtr-StrStart-1;
339 const char *NameEnd = (const char*)memchr(CurPtr, ']', StrEnd-CurPtr);
341 return diag::err_asm_unterminated_symbolic_operand_name;
342 if (NameEnd == CurPtr)
343 return diag::err_asm_empty_symbolic_operand_name;
345 std::string SymbolicName(CurPtr, NameEnd);
347 int N = getNamedOperand(SymbolicName);
349 // Verify that an operand with that name exists.
350 DiagOffs = CurPtr-StrStart;
351 return diag::err_asm_unknown_symbolic_operand_name;
353 Pieces.push_back(AsmStringPiece(N, Modifier));
359 DiagOffs = CurPtr-StrStart-1;
360 return diag::err_asm_invalid_escape;
364 //===----------------------------------------------------------------------===//
366 //===----------------------------------------------------------------------===//
368 AsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, bool isvolatile,
369 unsigned numoutputs, unsigned numinputs,
370 std::string *names, StringLiteral **constraints,
371 Expr **exprs, StringLiteral *asmstr, unsigned numclobbers,
372 StringLiteral **clobbers, SourceLocation rparenloc)
373 : Stmt(AsmStmtClass), AsmLoc(asmloc), RParenLoc(rparenloc), AsmStr(asmstr)
374 , IsSimple(issimple), IsVolatile(isvolatile)
375 , NumOutputs(numoutputs), NumInputs(numinputs) {
376 for (unsigned i = 0, e = numinputs + numoutputs; i != e; i++) {
377 Names.push_back(names[i]);
378 Exprs.push_back(exprs[i]);
379 Constraints.push_back(constraints[i]);
382 for (unsigned i = 0; i != numclobbers; i++)
383 Clobbers.push_back(clobbers[i]);
386 ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect,
387 Stmt *Body, SourceLocation FCL,
389 : Stmt(ObjCForCollectionStmtClass) {
390 SubExprs[ELEM] = Elem;
391 SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect);
392 SubExprs[BODY] = Body;
398 ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc,
399 SourceLocation rparenloc,
400 ParmVarDecl *catchVarDecl, Stmt *atCatchStmt,
402 : Stmt(ObjCAtCatchStmtClass) {
403 ExceptionDecl = catchVarDecl;
404 SubExprs[BODY] = atCatchStmt;
405 SubExprs[NEXT_CATCH] = NULL;
406 // FIXME: O(N^2) in number of catch blocks.
408 ObjCAtCatchStmt *AtCatchList = static_cast<ObjCAtCatchStmt*>(atCatchList);
410 while (ObjCAtCatchStmt* NextCatch = AtCatchList->getNextCatchStmt())
411 AtCatchList = NextCatch;
413 AtCatchList->SubExprs[NEXT_CATCH] = this;
415 AtCatchLoc = atCatchLoc;
416 RParenLoc = rparenloc;
420 //===----------------------------------------------------------------------===//
421 // Child Iterators for iterating over subexpressions/substatements
422 //===----------------------------------------------------------------------===//
425 Stmt::child_iterator DeclStmt::child_begin() {
426 return StmtIterator(DG.begin(), DG.end());
429 Stmt::child_iterator DeclStmt::child_end() {
430 return StmtIterator(DG.end(), DG.end());
434 Stmt::child_iterator NullStmt::child_begin() { return child_iterator(); }
435 Stmt::child_iterator NullStmt::child_end() { return child_iterator(); }
438 Stmt::child_iterator CompoundStmt::child_begin() { return &Body[0]; }
439 Stmt::child_iterator CompoundStmt::child_end() { return &Body[0]+NumStmts; }
442 Stmt::child_iterator CaseStmt::child_begin() { return &SubExprs[0]; }
443 Stmt::child_iterator CaseStmt::child_end() { return &SubExprs[END_EXPR]; }
446 Stmt::child_iterator DefaultStmt::child_begin() { return &SubStmt; }
447 Stmt::child_iterator DefaultStmt::child_end() { return &SubStmt+1; }
450 Stmt::child_iterator LabelStmt::child_begin() { return &SubStmt; }
451 Stmt::child_iterator LabelStmt::child_end() { return &SubStmt+1; }
454 Stmt::child_iterator IfStmt::child_begin() { return &SubExprs[0]; }
455 Stmt::child_iterator IfStmt::child_end() { return &SubExprs[0]+END_EXPR; }
458 Stmt::child_iterator SwitchStmt::child_begin() { return &SubExprs[0]; }
459 Stmt::child_iterator SwitchStmt::child_end() { return &SubExprs[0]+END_EXPR; }
462 Stmt::child_iterator WhileStmt::child_begin() { return &SubExprs[0]; }
463 Stmt::child_iterator WhileStmt::child_end() { return &SubExprs[0]+END_EXPR; }
466 Stmt::child_iterator DoStmt::child_begin() { return &SubExprs[0]; }
467 Stmt::child_iterator DoStmt::child_end() { return &SubExprs[0]+END_EXPR; }
470 Stmt::child_iterator ForStmt::child_begin() { return &SubExprs[0]; }
471 Stmt::child_iterator ForStmt::child_end() { return &SubExprs[0]+END_EXPR; }
473 // ObjCForCollectionStmt
474 Stmt::child_iterator ObjCForCollectionStmt::child_begin() {
477 Stmt::child_iterator ObjCForCollectionStmt::child_end() {
478 return &SubExprs[0]+END_EXPR;
482 Stmt::child_iterator GotoStmt::child_begin() { return child_iterator(); }
483 Stmt::child_iterator GotoStmt::child_end() { return child_iterator(); }
486 Expr* IndirectGotoStmt::getTarget() { return cast<Expr>(Target); }
487 const Expr* IndirectGotoStmt::getTarget() const { return cast<Expr>(Target); }
489 Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; }
490 Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; }
493 Stmt::child_iterator ContinueStmt::child_begin() { return child_iterator(); }
494 Stmt::child_iterator ContinueStmt::child_end() { return child_iterator(); }
497 Stmt::child_iterator BreakStmt::child_begin() { return child_iterator(); }
498 Stmt::child_iterator BreakStmt::child_end() { return child_iterator(); }
501 const Expr* ReturnStmt::getRetValue() const {
502 return cast_or_null<Expr>(RetExpr);
504 Expr* ReturnStmt::getRetValue() {
505 return cast_or_null<Expr>(RetExpr);
508 Stmt::child_iterator ReturnStmt::child_begin() {
511 Stmt::child_iterator ReturnStmt::child_end() {
512 return RetExpr ? &RetExpr+1 : &RetExpr;
516 Stmt::child_iterator AsmStmt::child_begin() {
517 return Exprs.empty() ? 0 : &Exprs[0];
519 Stmt::child_iterator AsmStmt::child_end() {
520 return Exprs.empty() ? 0 : &Exprs[0] + Exprs.size();
524 Stmt::child_iterator ObjCAtCatchStmt::child_begin() { return &SubExprs[0]; }
525 Stmt::child_iterator ObjCAtCatchStmt::child_end() {
526 return &SubExprs[0]+END_EXPR;
530 Stmt::child_iterator ObjCAtFinallyStmt::child_begin() { return &AtFinallyStmt; }
531 Stmt::child_iterator ObjCAtFinallyStmt::child_end() { return &AtFinallyStmt+1; }
534 Stmt::child_iterator ObjCAtTryStmt::child_begin() { return &SubStmts[0]; }
535 Stmt::child_iterator ObjCAtTryStmt::child_end() {
536 return &SubStmts[0]+END_EXPR;
540 Stmt::child_iterator ObjCAtThrowStmt::child_begin() {
544 Stmt::child_iterator ObjCAtThrowStmt::child_end() {
548 // ObjCAtSynchronizedStmt
549 Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() {
553 Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() {
554 return &SubStmts[0]+END_EXPR;
558 Stmt::child_iterator CXXCatchStmt::child_begin() {
559 return &HandlerBlock;
562 Stmt::child_iterator CXXCatchStmt::child_end() {
563 return &HandlerBlock + 1;
566 QualType CXXCatchStmt::getCaughtType() {
568 return ExceptionDecl->getType();
572 void CXXCatchStmt::Destroy(ASTContext& C) {
574 ExceptionDecl->Destroy(C);
579 Stmt::child_iterator CXXTryStmt::child_begin() { return &Stmts[0]; }
580 Stmt::child_iterator CXXTryStmt::child_end() { return &Stmts[0]+Stmts.size(); }
582 CXXTryStmt::CXXTryStmt(SourceLocation tryLoc, Stmt *tryBlock,
583 Stmt **handlers, unsigned numHandlers)
584 : Stmt(CXXTryStmtClass), TryLoc(tryLoc) {
585 Stmts.push_back(tryBlock);
586 Stmts.insert(Stmts.end(), handlers, handlers + numHandlers);