aboutsummaryrefslogtreecommitdiff
path: root/lib/AST/Expr.cpp
diff options
context:
space:
mode:
authorJohn McCall <rjmccall@apple.com>2011-02-09 08:16:59 +0000
committerJohn McCall <rjmccall@apple.com>2011-02-09 08:16:59 +0000
commit63c00d7f35fa060c0a446c9df3a4402d9c7757fe (patch)
tree64f68effbaf44e33590151cab184481c9313db35 /lib/AST/Expr.cpp
parentf0ed580ea5cdc171973c1ac259a9ee21badb80d8 (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/Expr.cpp')
-rw-r--r--lib/AST/Expr.cpp287
1 files changed, 49 insertions, 238 deletions
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index 747f786542..6280d633aa 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 @@ bool Expr::isKnownToHaveBooleanValue() const {
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 MergeCanThrow(Expr::CanThrowResult CT1,
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 @@ const Expr* ConstExprIterator::operator->() const { return cast<Expr>(*I); }
// 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 @@ BlockDeclRefExpr::BlockDeclRefExpr(VarDecl *d, QualType t, ExprValueKind VK,
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(); }
-