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
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 747f786..6280d63 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -30,8 +30,6 @@
#include <algorithm>
using namespace clang;
-void Expr::ANCHOR() {} // key function for Expr class.
-
/// isKnownToHaveBooleanValue - Return true if this is an integer expression
/// that is known to return 0 or 1. This happens for _Bool/bool expressions
/// but also int expressions which are produced by things like comparisons in
@@ -93,6 +91,42 @@
return false;
}
+// Amusing macro metaprogramming hack: check whether a class provides
+// a more specific implementation of getExprLoc().
+namespace {
+ /// This implementation is used when a class provides a custom
+ /// implementation of getExprLoc.
+ template <class E, class T>
+ SourceLocation getExprLocImpl(const Expr *expr,
+ SourceLocation (T::*v)() const) {
+ return static_cast<const E*>(expr)->getExprLoc();
+ }
+
+ /// This implementation is used when a class doesn't provide
+ /// a custom implementation of getExprLoc. Overload resolution
+ /// should pick it over the implementation above because it's
+ /// more specialized according to function template partial ordering.
+ template <class E>
+ SourceLocation getExprLocImpl(const Expr *expr,
+ SourceLocation (Expr::*v)() const) {
+ return static_cast<const E*>(expr)->getSourceRange().getBegin();
+ }
+}
+
+SourceLocation Expr::getExprLoc() const {
+ switch (getStmtClass()) {
+ case Stmt::NoStmtClass: llvm_unreachable("statement without class");
+#define ABSTRACT_STMT(type)
+#define STMT(type, base) \
+ case Stmt::type##Class: llvm_unreachable(#type " is not an Expr"); break;
+#define EXPR(type, base) \
+ case Stmt::type##Class: return getExprLocImpl<type>(this, &type::getExprLoc);
+#include "clang/AST/StmtNodes.inc"
+ }
+ llvm_unreachable("unknown statement kind");
+ return SourceLocation();
+}
+
//===----------------------------------------------------------------------===//
// Primary Expressions.
//===----------------------------------------------------------------------===//
@@ -1560,7 +1594,8 @@
static Expr::CanThrowResult CanSubExprsThrow(ASTContext &C, const Expr *CE) {
Expr *E = const_cast<Expr*>(CE);
Expr::CanThrowResult R = Expr::CT_Cannot;
- for (Expr::child_iterator I = E->child_begin(), IE = E->child_end();
+ Expr::child_iterator I, IE;
+ for (llvm::tie(I, IE) = E->children();
I != IE && R != Expr::CT_Can; ++I) {
R = MergeCanThrow(R, cast<Expr>(*I)->CanThrow(C));
}
@@ -2735,242 +2770,29 @@
// Child Iterators for iterating over subexpressions/substatements
//===----------------------------------------------------------------------===//
-// DeclRefExpr
-Stmt::child_iterator DeclRefExpr::child_begin() { return child_iterator(); }
-Stmt::child_iterator DeclRefExpr::child_end() { return child_iterator(); }
-
-// ObjCIvarRefExpr
-Stmt::child_iterator ObjCIvarRefExpr::child_begin() { return &Base; }
-Stmt::child_iterator ObjCIvarRefExpr::child_end() { return &Base+1; }
-
-// ObjCPropertyRefExpr
-Stmt::child_iterator ObjCPropertyRefExpr::child_begin()
-{
- if (Receiver.is<Stmt*>()) {
- // Hack alert!
- return reinterpret_cast<Stmt**> (&Receiver);
- }
- return child_iterator();
-}
-
-Stmt::child_iterator ObjCPropertyRefExpr::child_end()
-{ return Receiver.is<Stmt*>() ?
- reinterpret_cast<Stmt**> (&Receiver)+1 :
- child_iterator();
-}
-
-// ObjCIsaExpr
-Stmt::child_iterator ObjCIsaExpr::child_begin() { return &Base; }
-Stmt::child_iterator ObjCIsaExpr::child_end() { return &Base+1; }
-
-// PredefinedExpr
-Stmt::child_iterator PredefinedExpr::child_begin() { return child_iterator(); }
-Stmt::child_iterator PredefinedExpr::child_end() { return child_iterator(); }
-
-// IntegerLiteral
-Stmt::child_iterator IntegerLiteral::child_begin() { return child_iterator(); }
-Stmt::child_iterator IntegerLiteral::child_end() { return child_iterator(); }
-
-// CharacterLiteral
-Stmt::child_iterator CharacterLiteral::child_begin() { return child_iterator();}
-Stmt::child_iterator CharacterLiteral::child_end() { return child_iterator(); }
-
-// FloatingLiteral
-Stmt::child_iterator FloatingLiteral::child_begin() { return child_iterator(); }
-Stmt::child_iterator FloatingLiteral::child_end() { return child_iterator(); }
-
-// ImaginaryLiteral
-Stmt::child_iterator ImaginaryLiteral::child_begin() { return &Val; }
-Stmt::child_iterator ImaginaryLiteral::child_end() { return &Val+1; }
-
-// StringLiteral
-Stmt::child_iterator StringLiteral::child_begin() { return child_iterator(); }
-Stmt::child_iterator StringLiteral::child_end() { return child_iterator(); }
-
-// ParenExpr
-Stmt::child_iterator ParenExpr::child_begin() { return &Val; }
-Stmt::child_iterator ParenExpr::child_end() { return &Val+1; }
-
-// UnaryOperator
-Stmt::child_iterator UnaryOperator::child_begin() { return &Val; }
-Stmt::child_iterator UnaryOperator::child_end() { return &Val+1; }
-
-// OffsetOfExpr
-Stmt::child_iterator OffsetOfExpr::child_begin() {
- return reinterpret_cast<Stmt **> (reinterpret_cast<OffsetOfNode *> (this + 1)
- + NumComps);
-}
-Stmt::child_iterator OffsetOfExpr::child_end() {
- return child_iterator(&*child_begin() + NumExprs);
-}
-
// SizeOfAlignOfExpr
-Stmt::child_iterator SizeOfAlignOfExpr::child_begin() {
+Stmt::child_range SizeOfAlignOfExpr::children() {
// If this is of a type and the type is a VLA type (and not a typedef), the
// size expression of the VLA needs to be treated as an executable expression.
// Why isn't this weirdness documented better in StmtIterator?
if (isArgumentType()) {
if (const VariableArrayType* T = dyn_cast<VariableArrayType>(
getArgumentType().getTypePtr()))
- return child_iterator(T);
- return child_iterator();
+ return child_range(child_iterator(T), child_iterator());
+ return child_range();
}
- return child_iterator(&Argument.Ex);
-}
-Stmt::child_iterator SizeOfAlignOfExpr::child_end() {
- if (isArgumentType())
- return child_iterator();
- return child_iterator(&Argument.Ex + 1);
-}
-
-// ArraySubscriptExpr
-Stmt::child_iterator ArraySubscriptExpr::child_begin() {
- return &SubExprs[0];
-}
-Stmt::child_iterator ArraySubscriptExpr::child_end() {
- return &SubExprs[0]+END_EXPR;
-}
-
-// CallExpr
-Stmt::child_iterator CallExpr::child_begin() {
- return &SubExprs[0];
-}
-Stmt::child_iterator CallExpr::child_end() {
- return &SubExprs[0]+NumArgs+getNumPreArgs()+PREARGS_START;
-}
-
-// MemberExpr
-Stmt::child_iterator MemberExpr::child_begin() { return &Base; }
-Stmt::child_iterator MemberExpr::child_end() { return &Base+1; }
-
-// ExtVectorElementExpr
-Stmt::child_iterator ExtVectorElementExpr::child_begin() { return &Base; }
-Stmt::child_iterator ExtVectorElementExpr::child_end() { return &Base+1; }
-
-// CompoundLiteralExpr
-Stmt::child_iterator CompoundLiteralExpr::child_begin() { return &Init; }
-Stmt::child_iterator CompoundLiteralExpr::child_end() { return &Init+1; }
-
-// CastExpr
-Stmt::child_iterator CastExpr::child_begin() { return &Op; }
-Stmt::child_iterator CastExpr::child_end() { return &Op+1; }
-
-// BinaryOperator
-Stmt::child_iterator BinaryOperator::child_begin() {
- return &SubExprs[0];
-}
-Stmt::child_iterator BinaryOperator::child_end() {
- return &SubExprs[0]+END_EXPR;
-}
-
-// ConditionalOperator
-Stmt::child_iterator ConditionalOperator::child_begin() {
- return &SubExprs[0];
-}
-Stmt::child_iterator ConditionalOperator::child_end() {
- return &SubExprs[0]+END_EXPR;
-}
-
-// AddrLabelExpr
-Stmt::child_iterator AddrLabelExpr::child_begin() { return child_iterator(); }
-Stmt::child_iterator AddrLabelExpr::child_end() { return child_iterator(); }
-
-// StmtExpr
-Stmt::child_iterator StmtExpr::child_begin() { return &SubStmt; }
-Stmt::child_iterator StmtExpr::child_end() { return &SubStmt+1; }
-
-
-// ChooseExpr
-Stmt::child_iterator ChooseExpr::child_begin() { return &SubExprs[0]; }
-Stmt::child_iterator ChooseExpr::child_end() { return &SubExprs[0]+END_EXPR; }
-
-// GNUNullExpr
-Stmt::child_iterator GNUNullExpr::child_begin() { return child_iterator(); }
-Stmt::child_iterator GNUNullExpr::child_end() { return child_iterator(); }
-
-// ShuffleVectorExpr
-Stmt::child_iterator ShuffleVectorExpr::child_begin() {
- return &SubExprs[0];
-}
-Stmt::child_iterator ShuffleVectorExpr::child_end() {
- return &SubExprs[0]+NumExprs;
-}
-
-// VAArgExpr
-Stmt::child_iterator VAArgExpr::child_begin() { return &Val; }
-Stmt::child_iterator VAArgExpr::child_end() { return &Val+1; }
-
-// InitListExpr
-Stmt::child_iterator InitListExpr::child_begin() {
- return InitExprs.size() ? &InitExprs[0] : 0;
-}
-Stmt::child_iterator InitListExpr::child_end() {
- return InitExprs.size() ? &InitExprs[0] + InitExprs.size() : 0;
-}
-
-// DesignatedInitExpr
-Stmt::child_iterator DesignatedInitExpr::child_begin() {
- char* Ptr = static_cast<char*>(static_cast<void *>(this));
- Ptr += sizeof(DesignatedInitExpr);
- return reinterpret_cast<Stmt**>(reinterpret_cast<void**>(Ptr));
-}
-Stmt::child_iterator DesignatedInitExpr::child_end() {
- return child_iterator(&*child_begin() + NumSubExprs);
-}
-
-// ImplicitValueInitExpr
-Stmt::child_iterator ImplicitValueInitExpr::child_begin() {
- return child_iterator();
-}
-
-Stmt::child_iterator ImplicitValueInitExpr::child_end() {
- return child_iterator();
-}
-
-// ParenListExpr
-Stmt::child_iterator ParenListExpr::child_begin() {
- return &Exprs[0];
-}
-Stmt::child_iterator ParenListExpr::child_end() {
- return &Exprs[0]+NumExprs;
-}
-
-// ObjCStringLiteral
-Stmt::child_iterator ObjCStringLiteral::child_begin() {
- return &String;
-}
-Stmt::child_iterator ObjCStringLiteral::child_end() {
- return &String+1;
-}
-
-// ObjCEncodeExpr
-Stmt::child_iterator ObjCEncodeExpr::child_begin() { return child_iterator(); }
-Stmt::child_iterator ObjCEncodeExpr::child_end() { return child_iterator(); }
-
-// ObjCSelectorExpr
-Stmt::child_iterator ObjCSelectorExpr::child_begin() {
- return child_iterator();
-}
-Stmt::child_iterator ObjCSelectorExpr::child_end() {
- return child_iterator();
-}
-
-// ObjCProtocolExpr
-Stmt::child_iterator ObjCProtocolExpr::child_begin() {
- return child_iterator();
-}
-Stmt::child_iterator ObjCProtocolExpr::child_end() {
- return child_iterator();
+ return child_range(&Argument.Ex, &Argument.Ex + 1);
}
// ObjCMessageExpr
-Stmt::child_iterator ObjCMessageExpr::child_begin() {
+Stmt::child_range ObjCMessageExpr::children() {
+ Stmt **begin;
if (getReceiverKind() == Instance)
- return reinterpret_cast<Stmt **>(this + 1);
- return reinterpret_cast<Stmt **>(getArgs());
-}
-Stmt::child_iterator ObjCMessageExpr::child_end() {
- return reinterpret_cast<Stmt **>(getArgs() + getNumArgs());
+ begin = reinterpret_cast<Stmt **>(this + 1);
+ else
+ begin = reinterpret_cast<Stmt **>(getArgs());
+ return child_range(begin,
+ reinterpret_cast<Stmt **>(getArgs() + getNumArgs()));
}
// Blocks
@@ -2988,14 +2810,3 @@
ExprBits.ValueDependent = ValueDependent;
}
-Stmt::child_iterator BlockExpr::child_begin() { return child_iterator(); }
-Stmt::child_iterator BlockExpr::child_end() { return child_iterator(); }
-
-Stmt::child_iterator BlockDeclRefExpr::child_begin() { return child_iterator();}
-Stmt::child_iterator BlockDeclRefExpr::child_end() { return child_iterator(); }
-
-// OpaqueValueExpr
-SourceRange OpaqueValueExpr::getSourceRange() const { return Loc; }
-Stmt::child_iterator OpaqueValueExpr::child_begin() { return child_iterator(); }
-Stmt::child_iterator OpaqueValueExpr::child_end() { return child_iterator(); }
-
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index a11d05a..28ff9fb 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -29,67 +29,12 @@
.getUnqualifiedType();
}
-// CXXTypeidExpr - has child iterators if the operand is an expression
-Stmt::child_iterator CXXTypeidExpr::child_begin() {
- return isTypeOperand() ? child_iterator()
- : reinterpret_cast<Stmt **>(&Operand);
-}
-Stmt::child_iterator CXXTypeidExpr::child_end() {
- return isTypeOperand() ? child_iterator()
- : reinterpret_cast<Stmt **>(&Operand) + 1;
-}
-
QualType CXXUuidofExpr::getTypeOperand() const {
assert(isTypeOperand() && "Cannot call getTypeOperand for __uuidof(expr)");
return Operand.get<TypeSourceInfo *>()->getType().getNonReferenceType()
.getUnqualifiedType();
}
-// CXXUuidofExpr - has child iterators if the operand is an expression
-Stmt::child_iterator CXXUuidofExpr::child_begin() {
- return isTypeOperand() ? child_iterator()
- : reinterpret_cast<Stmt **>(&Operand);
-}
-Stmt::child_iterator CXXUuidofExpr::child_end() {
- return isTypeOperand() ? child_iterator()
- : reinterpret_cast<Stmt **>(&Operand) + 1;
-}
-
-// CXXBoolLiteralExpr
-Stmt::child_iterator CXXBoolLiteralExpr::child_begin() {
- return child_iterator();
-}
-Stmt::child_iterator CXXBoolLiteralExpr::child_end() {
- return child_iterator();
-}
-
-// CXXNullPtrLiteralExpr
-Stmt::child_iterator CXXNullPtrLiteralExpr::child_begin() {
- return child_iterator();
-}
-Stmt::child_iterator CXXNullPtrLiteralExpr::child_end() {
- return child_iterator();
-}
-
-// CXXThisExpr
-Stmt::child_iterator CXXThisExpr::child_begin() { return child_iterator(); }
-Stmt::child_iterator CXXThisExpr::child_end() { return child_iterator(); }
-
-// CXXThrowExpr
-Stmt::child_iterator CXXThrowExpr::child_begin() { return &Op; }
-Stmt::child_iterator CXXThrowExpr::child_end() {
- // If Op is 0, we are processing throw; which has no children.
- return Op ? &Op+1 : &Op;
-}
-
-// CXXDefaultArgExpr
-Stmt::child_iterator CXXDefaultArgExpr::child_begin() {
- return child_iterator();
-}
-Stmt::child_iterator CXXDefaultArgExpr::child_end() {
- return child_iterator();
-}
-
// CXXScalarValueInitExpr
SourceRange CXXScalarValueInitExpr::getSourceRange() const {
SourceLocation Start = RParenLoc;
@@ -98,13 +43,6 @@
return SourceRange(Start, RParenLoc);
}
-Stmt::child_iterator CXXScalarValueInitExpr::child_begin() {
- return child_iterator();
-}
-Stmt::child_iterator CXXScalarValueInitExpr::child_end() {
- return child_iterator();
-}
-
// CXXNewExpr
CXXNewExpr::CXXNewExpr(ASTContext &C, bool globalNew, FunctionDecl *operatorNew,
Expr **placementArgs, unsigned numPlaceArgs,
@@ -163,11 +101,6 @@
}
-Stmt::child_iterator CXXNewExpr::child_begin() { return &SubExprs[0]; }
-Stmt::child_iterator CXXNewExpr::child_end() {
- return &SubExprs[0] + Array + getNumPlacementArgs() + getNumConstructorArgs();
-}
-
// CXXDeleteExpr
QualType CXXDeleteExpr::getDestroyedType() const {
const Expr *Arg = getArgument();
@@ -187,15 +120,7 @@
return ArgType->getAs<PointerType>()->getPointeeType();
}
-Stmt::child_iterator CXXDeleteExpr::child_begin() { return &Argument; }
-Stmt::child_iterator CXXDeleteExpr::child_end() { return &Argument+1; }
-
// CXXPseudoDestructorExpr
-Stmt::child_iterator CXXPseudoDestructorExpr::child_begin() { return &Base; }
-Stmt::child_iterator CXXPseudoDestructorExpr::child_end() {
- return &Base + 1;
-}
-
PseudoDestructorTypeStorage::PseudoDestructorTypeStorage(TypeSourceInfo *Info)
: Type(Info)
{
@@ -355,28 +280,6 @@
return cast<UnresolvedMemberExpr>(this)->getNamingClass();
}
-Stmt::child_iterator UnresolvedLookupExpr::child_begin() {
- return child_iterator();
-}
-Stmt::child_iterator UnresolvedLookupExpr::child_end() {
- return child_iterator();
-}
-// UnaryTypeTraitExpr
-Stmt::child_iterator UnaryTypeTraitExpr::child_begin() {
- return child_iterator();
-}
-Stmt::child_iterator UnaryTypeTraitExpr::child_end() {
- return child_iterator();
-}
-
-//BinaryTypeTraitExpr
-Stmt::child_iterator BinaryTypeTraitExpr::child_begin() {
- return child_iterator();
-}
-Stmt::child_iterator BinaryTypeTraitExpr::child_end() {
- return child_iterator();
-}
-
// DependentScopeDeclRefExpr
DependentScopeDeclRefExpr::DependentScopeDeclRefExpr(QualType T,
NestedNameSpecifier *Qualifier,
@@ -431,14 +334,6 @@
return E;
}
-StmtIterator DependentScopeDeclRefExpr::child_begin() {
- return child_iterator();
-}
-
-StmtIterator DependentScopeDeclRefExpr::child_end() {
- return child_iterator();
-}
-
SourceRange CXXConstructExpr::getSourceRange() const {
if (ParenRange.isValid())
return SourceRange(Loc, ParenRange.getEnd());
@@ -746,32 +641,6 @@
return new (C) ExprWithCleanups(C, SubExpr, Temps, NumTemps);
}
-// CXXBindTemporaryExpr
-Stmt::child_iterator CXXBindTemporaryExpr::child_begin() {
- return &SubExpr;
-}
-
-Stmt::child_iterator CXXBindTemporaryExpr::child_end() {
- return &SubExpr + 1;
-}
-
-// CXXConstructExpr
-Stmt::child_iterator CXXConstructExpr::child_begin() {
- return &Args[0];
-}
-Stmt::child_iterator CXXConstructExpr::child_end() {
- return &Args[0]+NumArgs;
-}
-
-// ExprWithCleanups
-Stmt::child_iterator ExprWithCleanups::child_begin() {
- return &SubExpr;
-}
-
-Stmt::child_iterator ExprWithCleanups::child_end() {
- return &SubExpr + 1;
-}
-
CXXUnresolvedConstructExpr::CXXUnresolvedConstructExpr(TypeSourceInfo *Type,
SourceLocation LParenLoc,
Expr **Args,
@@ -820,14 +689,6 @@
return SourceRange(Type->getTypeLoc().getBeginLoc(), RParenLoc);
}
-Stmt::child_iterator CXXUnresolvedConstructExpr::child_begin() {
- return child_iterator(reinterpret_cast<Stmt **>(this + 1));
-}
-
-Stmt::child_iterator CXXUnresolvedConstructExpr::child_end() {
- return child_iterator(reinterpret_cast<Stmt **>(this + 1) + NumArgs);
-}
-
CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
Expr *Base, QualType BaseType,
bool IsArrow,
@@ -927,16 +788,6 @@
return E;
}
-Stmt::child_iterator CXXDependentScopeMemberExpr::child_begin() {
- return child_iterator(&Base);
-}
-
-Stmt::child_iterator CXXDependentScopeMemberExpr::child_end() {
- if (isImplicitAccess())
- return child_iterator(&Base);
- return child_iterator(&Base + 1);
-}
-
UnresolvedMemberExpr::UnresolvedMemberExpr(ASTContext &C,
bool HasUnresolvedUsing,
Expr *Base, QualType BaseType,
@@ -1025,47 +876,6 @@
return Record;
}
-Stmt::child_iterator UnresolvedMemberExpr::child_begin() {
- return child_iterator(&Base);
-}
-
-Stmt::child_iterator UnresolvedMemberExpr::child_end() {
- if (isImplicitAccess())
- return child_iterator(&Base);
- return child_iterator(&Base + 1);
-}
-
-Stmt::child_iterator CXXNoexceptExpr::child_begin() {
- return child_iterator(&Operand);
-}
-Stmt::child_iterator CXXNoexceptExpr::child_end() {
- return child_iterator(&Operand + 1);
-}
-
-SourceRange PackExpansionExpr::getSourceRange() const {
- return SourceRange(Pattern->getLocStart(), EllipsisLoc);
-}
-
-Stmt::child_iterator PackExpansionExpr::child_begin() {
- return child_iterator(&Pattern);
-}
-
-Stmt::child_iterator PackExpansionExpr::child_end() {
- return child_iterator(&Pattern + 1);
-}
-
-SourceRange SizeOfPackExpr::getSourceRange() const {
- return SourceRange(OperatorLoc, RParenLoc);
-}
-
-Stmt::child_iterator SizeOfPackExpr::child_begin() {
- return child_iterator();
-}
-
-Stmt::child_iterator SizeOfPackExpr::child_end() {
- return child_iterator();
-}
-
SubstNonTypeTemplateParmPackExpr::
SubstNonTypeTemplateParmPackExpr(QualType T,
NonTypeTemplateParmDecl *Param,
@@ -1080,16 +890,4 @@
return TemplateArgument(Arguments, NumArguments);
}
-SourceRange SubstNonTypeTemplateParmPackExpr::getSourceRange() const {
- return NameLoc;
-}
-
-Stmt::child_iterator SubstNonTypeTemplateParmPackExpr::child_begin() {
- return child_iterator();
-}
-
-Stmt::child_iterator SubstNonTypeTemplateParmPackExpr::child_end() {
- return child_iterator();
-}
-
diff --git a/lib/AST/ExprClassification.cpp b/lib/AST/ExprClassification.cpp
index c9f4fa8..ba3b88b 100644
--- a/lib/AST/ExprClassification.cpp
+++ b/lib/AST/ExprClassification.cpp
@@ -90,6 +90,7 @@
switch (E->getStmtClass()) {
// First come the expressions that are always lvalues, unconditionally.
case Stmt::NoStmtClass:
+#define ABSTRACT_STMT(Kind)
#define STMT(Kind, Base) case Expr::Kind##Class:
#define EXPR(Kind, Base)
#include "clang/AST/StmtNodes.inc"
diff --git a/lib/AST/ExprConstant.cpp b/lib/AST/ExprConstant.cpp
index 0a7a9d2..227c60e 100644
--- a/lib/AST/ExprConstant.cpp
+++ b/lib/AST/ExprConstant.cpp
@@ -2578,6 +2578,7 @@
}
switch (E->getStmtClass()) {
+#define ABSTRACT_STMT(Node)
#define STMT(Node, Base) case Expr::Node##Class:
#define EXPR(Node, Base)
#include "clang/AST/StmtNodes.inc"
diff --git a/lib/AST/ItaniumMangle.cpp b/lib/AST/ItaniumMangle.cpp
index a84df12..0e05041 100644
--- a/lib/AST/ItaniumMangle.cpp
+++ b/lib/AST/ItaniumMangle.cpp
@@ -1690,6 +1690,7 @@
// ::= L <mangled-name> E # external name
switch (E->getStmtClass()) {
case Expr::NoStmtClass:
+#define ABSTRACT_STMT(Type)
#define EXPR(Type, Base)
#define STMT(Type, Base) \
case Expr::Type##Class:
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index acd77be..b4abd05 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -84,6 +84,61 @@
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 @@
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 @@
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 @@
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 @@
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;
-}
diff --git a/lib/AST/StmtPrinter.cpp b/lib/AST/StmtPrinter.cpp
index 2ed2c92..5d31fd6 100644
--- a/lib/AST/StmtPrinter.cpp
+++ b/lib/AST/StmtPrinter.cpp
@@ -220,10 +220,6 @@
}
}
-void StmtPrinter::VisitSwitchCase(SwitchCase*) {
- assert(0 && "SwitchCase is an abstract class");
-}
-
void StmtPrinter::VisitWhileStmt(WhileStmt *Node) {
Indent() << "while (";
PrintExpr(Node->getCond());