summaryrefslogtreecommitdiffstats
path: root/clang/lib/AST/Stmt.cpp
diff options
context:
space:
mode:
authorDaniel Dunbar <daniel@zuster.org>2012-03-09 15:39:19 +0000
committerDaniel Dunbar <daniel@zuster.org>2012-03-09 15:39:19 +0000
commitb0ab5e9f5c49e5146b917b7916aa71dd12b40c0c (patch)
tree2d753df13c303b1f292f21f4546f7769a01b9f06 /clang/lib/AST/Stmt.cpp
parentb507f2718575a55a936372ed946feeac643be95b (diff)
downloadbcm5719-llvm-b0ab5e9f5c49e5146b917b7916aa71dd12b40c0c.tar.gz
bcm5719-llvm-b0ab5e9f5c49e5146b917b7916aa71dd12b40c0c.zip
[AST] Reimplement Stmt::getLoc{Start,End} to dispatch to subclass overloads.
- getSourceRange() can be very expensive, we should try to avoid it if at all possible. In conjunction with the previous commit I measured a ~2% speedup on 403.gcc/combine.c and a 3% speedup on OmniGroupFrameworks/NSBezierPath-OAExtensions.m. llvm-svn: 152411
Diffstat (limited to 'clang/lib/AST/Stmt.cpp')
-rw-r--r--clang/lib/AST/Stmt.cpp66
1 files changed, 66 insertions, 0 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp
index 0deaaa83bad..7907e565dde 100644
--- a/clang/lib/AST/Stmt.cpp
+++ b/clang/lib/AST/Stmt.cpp
@@ -176,6 +176,72 @@ SourceRange Stmt::getSourceRange() const {
llvm_unreachable("unknown statement kind!");
}
+// Amusing macro metaprogramming hack: check whether a class provides
+// a more specific implementation of getLocStart() and getLocEnd().
+//
+// See also Expr.cpp:getExprLoc().
+namespace {
+ /// This implementation is used when a class provides a custom
+ /// implementation of getLocStart.
+ template <class S, class T>
+ SourceLocation getLocStartImpl(const Stmt *stmt,
+ SourceLocation (T::*v)() const) {
+ return static_cast<const S*>(stmt)->getLocStart();
+ }
+
+ /// This implementation is used when a class doesn't provide a custom
+ /// implementation of getLocStart. Overload resolution should pick it over
+ /// the implementation above because it's more specialized according to
+ /// function template partial ordering.
+ template <class S>
+ SourceLocation getLocStartImpl(const Stmt *stmt,
+ SourceLocation (Stmt::*v)() const) {
+ return static_cast<const S*>(stmt)->getSourceRange().getBegin();
+ }
+
+ /// This implementation is used when a class provides a custom
+ /// implementation of getLocEnd.
+ template <class S, class T>
+ SourceLocation getLocEndImpl(const Stmt *stmt,
+ SourceLocation (T::*v)() const) {
+ return static_cast<const S*>(stmt)->getLocEnd();
+ }
+
+ /// This implementation is used when a class doesn't provide a custom
+ /// implementation of getLocEnd. Overload resolution should pick it over
+ /// the implementation above because it's more specialized according to
+ /// function template partial ordering.
+ template <class S>
+ SourceLocation getLocEndImpl(const Stmt *stmt,
+ SourceLocation (Stmt::*v)() const) {
+ return static_cast<const S*>(stmt)->getSourceRange().getEnd();
+ }
+}
+
+SourceLocation Stmt::getLocStart() const {
+ switch (getStmtClass()) {
+ case Stmt::NoStmtClass: llvm_unreachable("statement without class");
+#define ABSTRACT_STMT(type)
+#define STMT(type, base) \
+ case Stmt::type##Class: \
+ return getLocStartImpl<type>(this, &type::getLocStart);
+#include "clang/AST/StmtNodes.inc"
+ }
+ llvm_unreachable("unknown statement kind");
+}
+
+SourceLocation Stmt::getLocEnd() const {
+ switch (getStmtClass()) {
+ case Stmt::NoStmtClass: llvm_unreachable("statement without class");
+#define ABSTRACT_STMT(type)
+#define STMT(type, base) \
+ case Stmt::type##Class: \
+ return getLocEndImpl<type>(this, &type::getLocEnd);
+#include "clang/AST/StmtNodes.inc"
+ }
+ llvm_unreachable("unknown statement kind");
+}
+
void CompoundStmt::setStmts(ASTContext &C, Stmt **Stmts, unsigned NumStmts) {
if (this->Body)
C.Deallocate(Body);
OpenPOWER on IntegriCloud