Files
llvm-project/clang/lib/AST/Stmt.cpp
Chris Lattner 7a51313d8a Make a major restructuring of the clang tree: introduce a top-level
lib dir and move all the libraries into it.  This follows the main
llvm tree, and allows the libraries to be built in parallel.  The
top level now enforces that all the libs are built before Driver,
but we don't care what order the libs are built in.  This speeds
up parallel builds, particularly incremental ones.

llvm-svn: 48402
2008-03-15 23:59:48 +00:00

294 lines
9.2 KiB
C++

//===--- 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;
}