diff options
Diffstat (limited to 'clang/lib/AST/Stmt.cpp')
-rw-r--r-- | clang/lib/AST/Stmt.cpp | 293 |
1 files changed, 293 insertions, 0 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp new file mode 100644 index 00000000000..572280bc054 --- /dev/null +++ b/clang/lib/AST/Stmt.cpp @@ -0,0 +1,293 @@ +//===--- Stmt.cpp - Statement AST Node Implementation ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file 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; + } + } +} + +//===----------------------------------------------------------------------===// +// Constructors +//===----------------------------------------------------------------------===// + +AsmStmt::AsmStmt(SourceLocation asmloc, bool issimple, 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) + , IsSimple(issimple), 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]); +} + +ObjCForCollectionStmt::ObjCForCollectionStmt(Stmt *Elem, Expr *Collect, + Stmt *Body, SourceLocation FCL, + SourceLocation RPL) +: Stmt(ObjCForCollectionStmtClass) { + SubExprs[ELEM] = Elem; + SubExprs[COLLECTION] = reinterpret_cast<Stmt*>(Collect); + SubExprs[BODY] = Body; + ForLoc = FCL; + RParenLoc = RPL; +} + + +ObjCAtCatchStmt::ObjCAtCatchStmt(SourceLocation atCatchLoc, + SourceLocation rparenloc, + Stmt *catchVarStmtDecl, Stmt *atCatchStmt, + Stmt *atCatchList) +: Stmt(ObjCAtCatchStmtClass) { + SubExprs[SELECTOR] = catchVarStmtDecl; + SubExprs[BODY] = atCatchStmt; + if (!atCatchList) + SubExprs[NEXT_CATCH] = NULL; + else { + ObjCAtCatchStmt *AtCatchList = static_cast<ObjCAtCatchStmt*>(atCatchList); + + while (ObjCAtCatchStmt* NextCatch = AtCatchList->getNextCatchStmt()) + AtCatchList = NextCatch; + + AtCatchList->SubExprs[NEXT_CATCH] = this; + } + AtCatchLoc = atCatchLoc; + RParenLoc = rparenloc; +} + + +//===----------------------------------------------------------------------===// +// 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; } + +// ObjCForCollectionStmt +Stmt::child_iterator ObjCForCollectionStmt::child_begin() { + return &SubExprs[0]; +} +Stmt::child_iterator ObjCForCollectionStmt::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; +} + +// ObjCAtSynchronizedStmt +Stmt::child_iterator ObjCAtSynchronizedStmt::child_begin() { + return &SubStmts[0]; +} + +Stmt::child_iterator ObjCAtSynchronizedStmt::child_end() { + return &SubStmts[0]+END_EXPR; +} + |