diff options
author | John McCall <rjmccall@apple.com> | 2011-02-09 08:16:59 +0000 |
---|---|---|
committer | John McCall <rjmccall@apple.com> | 2011-02-09 08:16:59 +0000 |
commit | 63c00d7f35fa060c0a446c9df3a4402d9c7757fe (patch) | |
tree | 64f68effbaf44e33590151cab184481c9313db35 /lib/AST/Stmt.cpp | |
parent | f0ed580ea5cdc171973c1ac259a9ee21badb80d8 (diff) |
Remove vtables from the Stmt hierarchy; this was pretty easy as
there were only three virtual methods of any significance.
The primary way to grab child iterators now is with
Stmt::child_range children();
Stmt::const_child_range children() const;
where a child_range is just a std::pair of iterators suitable for
being llvm::tie'd to some locals. I've left the old child_begin()
and child_end() accessors in place, but it's probably a substantial
penalty to grab the iterators individually now, since the
switch-based dispatch is kindof inherently slower than vtable
dispatch. Grabbing them together is probably a slight win over the
status quo, although of course we could've achieved that with vtables, too.
I also reclassified SwitchCase (correctly) as an abstract Stmt
class, which (as the first such class that wasn't an Expr subclass)
required some fiddling in a few places.
There are somewhat gross metaprogramming hooks in place to ensure
that new statements/expressions continue to implement
getSourceRange() and children(). I had to work around a recent clang
bug; dgregor actually fixed it already, but I didn't want to
introduce a selfhosting dependency on ToT.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@125183 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Stmt.cpp')
-rw-r--r-- | lib/AST/Stmt.cpp | 220 |
1 files changed, 60 insertions, 160 deletions
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index acd77beaca..b4abd05d68 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -84,6 +84,61 @@ bool Stmt::CollectingStats(bool Enable) { return StatSwitch; } +namespace { + struct good {}; + struct bad {}; + static inline good is_good(good); // static inline to suppress unused warning + + typedef Stmt::child_range children_t(); + template <class T> good implements_children(children_t T::*); + static inline bad implements_children(children_t Stmt::*); + + typedef SourceRange getSourceRange_t() const; + template <class T> good implements_getSourceRange(getSourceRange_t T::*); + static inline bad implements_getSourceRange(getSourceRange_t Stmt::*); + +#define ASSERT_IMPLEMENTS_children(type) \ + (void) sizeof(is_good(implements_children(&type::children))) +#define ASSERT_IMPLEMENTS_getSourceRange(type) \ + (void) sizeof(is_good(implements_getSourceRange(&type::getSourceRange))) +} + +/// Check whether the various Stmt classes implement their member +/// functions. +static inline void check_implementations() { +#define ABSTRACT_STMT(type) +#define STMT(type, base) \ + ASSERT_IMPLEMENTS_children(type); \ + ASSERT_IMPLEMENTS_getSourceRange(type); +#include "clang/AST/StmtNodes.inc" +} + +Stmt::child_range Stmt::children() { + switch (getStmtClass()) { + case Stmt::NoStmtClass: llvm_unreachable("statement without class"); +#define ABSTRACT_STMT(type) +#define STMT(type, base) \ + case Stmt::type##Class: \ + return static_cast<type*>(this)->children(); +#include "clang/AST/StmtNodes.inc" + } + llvm_unreachable("unknown statement kind!"); + return child_range(); +} + +SourceRange Stmt::getSourceRange() const { + switch (getStmtClass()) { + case Stmt::NoStmtClass: llvm_unreachable("statement without class"); +#define ABSTRACT_STMT(type) +#define STMT(type, base) \ + case Stmt::type##Class: \ + return static_cast<const type*>(this)->getSourceRange(); +#include "clang/AST/StmtNodes.inc" + } + llvm_unreachable("unknown statement kind!"); + return SourceRange(); +} + void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) { if (this->Body) C.Deallocate(Body); @@ -556,6 +611,11 @@ void SwitchStmt::setConditionVariable(ASTContext &C, VarDecl *V) { V->getSourceRange().getEnd()); } +Stmt *SwitchCase::getSubStmt() { + if (isa<CaseStmt>(this)) return cast<CaseStmt>(this)->getSubStmt(); + return cast<DefaultStmt>(this)->getSubStmt(); +} + WhileStmt::WhileStmt(ASTContext &C, VarDecl *Var, Expr *cond, Stmt *body, SourceLocation WL) : Stmt(WhileStmtClass) @@ -585,89 +645,6 @@ void WhileStmt::setConditionVariable(ASTContext &C, VarDecl *V) { V->getSourceRange().getEnd()); } -//===----------------------------------------------------------------------===// -// Child Iterators for iterating over subexpressions/substatements -//===----------------------------------------------------------------------===// - -// DeclStmt -Stmt::child_iterator DeclStmt::child_begin() { - return StmtIterator(DG.begin(), DG.end()); -} - -Stmt::child_iterator DeclStmt::child_end() { - return StmtIterator(DG.end(), DG.end()); -} - -// 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]+CompoundStmtBits.NumStmts; -} - -// 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 LabelStmt *IndirectGotoStmt::getConstantTarget() { if (AddrLabelExpr *E = @@ -676,17 +653,6 @@ LabelStmt *IndirectGotoStmt::getConstantTarget() { return 0; } -Stmt::child_iterator IndirectGotoStmt::child_begin() { return &Target; } -Stmt::child_iterator IndirectGotoStmt::child_end() { return &Target+1; } - -// 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 const Expr* ReturnStmt::getRetValue() const { return cast_or_null<Expr>(RetExpr); @@ -694,69 +660,3 @@ const Expr* ReturnStmt::getRetValue() const { Expr* ReturnStmt::getRetValue() { return cast_or_null<Expr>(RetExpr); } - -Stmt::child_iterator ReturnStmt::child_begin() { - return &RetExpr; -} -Stmt::child_iterator ReturnStmt::child_end() { - return RetExpr ? &RetExpr+1 : &RetExpr; -} - -// AsmStmt -Stmt::child_iterator AsmStmt::child_begin() { - return NumOutputs + NumInputs == 0 ? 0 : &Exprs[0]; -} -Stmt::child_iterator AsmStmt::child_end() { - return NumOutputs + NumInputs == 0 ? 0 : &Exprs[0] + NumOutputs + NumInputs; -} - -// ObjCAtCatchStmt -Stmt::child_iterator ObjCAtCatchStmt::child_begin() { return &Body; } -Stmt::child_iterator ObjCAtCatchStmt::child_end() { return &Body + 1; } - -// 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 getStmts(); } - -Stmt::child_iterator ObjCAtTryStmt::child_end() { - return getStmts() + 1 + NumCatchStmts + HasFinally; -} - -// 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; -} - -// CXXCatchStmt -Stmt::child_iterator CXXCatchStmt::child_begin() { - return &HandlerBlock; -} - -Stmt::child_iterator CXXCatchStmt::child_end() { - return &HandlerBlock + 1; -} - -// CXXTryStmt -Stmt::child_iterator CXXTryStmt::child_begin() { - return reinterpret_cast<Stmt **>(this + 1); -} - -Stmt::child_iterator CXXTryStmt::child_end() { - return reinterpret_cast<Stmt **>(this + 1) + NumHandlers + 1; -} |