diff options
author | Erik Verbruggen <erikjv@me.com> | 2012-12-25 14:51:39 +0000 |
---|---|---|
committer | Erik Verbruggen <erikjv@me.com> | 2012-12-25 14:51:39 +0000 |
commit | 65d78312ce026092cb6e7b1d4d06f05e18d02aa0 (patch) | |
tree | 165233da9770e9d2bf6b5d46af36b1303d7db11d /lib/AST/Stmt.cpp | |
parent | 38980086c0f791e8c23cc882574f18e5b4a87db6 (diff) |
Fix for PR12222.
Changed getLocStart() and getLocEnd() to be required for Stmts, and make
getSourceRange() optional. The default implementation for getSourceRange()
is build the range by calling getLocStart() and getLocEnd().
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@171067 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/AST/Stmt.cpp')
-rw-r--r-- | lib/AST/Stmt.cpp | 107 |
1 files changed, 45 insertions, 62 deletions
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp index ddb1560723..1ef80c95c4 100644 --- a/lib/AST/Stmt.cpp +++ b/lib/AST/Stmt.cpp @@ -142,18 +142,28 @@ namespace { return bad(); } - typedef SourceRange getSourceRange_t() const; - template <class T> good implements_getSourceRange(getSourceRange_t T::*) { + typedef SourceLocation getLocStart_t() const; + template <class T> good implements_getLocStart(getLocStart_t T::*) { return good(); } - static inline bad implements_getSourceRange(getSourceRange_t Stmt::*) { + static inline bad implements_getLocStart(getLocStart_t Stmt::*) { + return bad(); + } + + typedef SourceLocation getLocEnd_t() const; + template <class T> good implements_getLocEnd(getLocEnd_t T::*) { + return good(); + } + static inline bad implements_getLocEnd(getLocEnd_t Stmt::*) { return bad(); } #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))) +#define ASSERT_IMPLEMENTS_getLocStart(type) \ + (void) sizeof(is_good(implements_getLocStart(&type::getLocStart))) +#define ASSERT_IMPLEMENTS_getLocEnd(type) \ + (void) sizeof(is_good(implements_getLocEnd(&type::getLocEnd))) } /// Check whether the various Stmt classes implement their member @@ -162,7 +172,8 @@ static inline void check_implementations() { #define ABSTRACT_STMT(type) #define STMT(type, base) \ ASSERT_IMPLEMENTS_children(type); \ - ASSERT_IMPLEMENTS_getSourceRange(type); + ASSERT_IMPLEMENTS_getLocStart(type); \ + ASSERT_IMPLEMENTS_getLocEnd(type); #include "clang/AST/StmtNodes.inc" } @@ -178,67 +189,51 @@ Stmt::child_range Stmt::children() { llvm_unreachable("unknown statement kind!"); } -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!"); -} - // Amusing macro metaprogramming hack: check whether a class provides -// a more specific implementation of getLocStart() and getLocEnd(). +// a more specific implementation of getSourceRange. // // See also Expr.cpp:getExprLoc(). namespace { /// This implementation is used when a class provides a custom - /// implementation of getLocStart. + /// implementation of getSourceRange. template <class S, class T> - SourceLocation getLocStartImpl(const Stmt *stmt, - SourceLocation (T::*v)() const) { - return static_cast<const S*>(stmt)->getLocStart(); + SourceRange getSourceRangeImpl(const Stmt *stmt, + SourceRange (T::*v)() const) { + return static_cast<const S*>(stmt)->getSourceRange(); } /// This implementation is used when a class doesn't provide a custom - /// implementation of getLocStart. Overload resolution should pick it over + /// implementation of getSourceRange. 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(); + SourceRange getSourceRangeImpl(const Stmt *stmt, + SourceRange (Stmt::*v)() const) { + return SourceRange(static_cast<const S*>(stmt)->getLocStart(), + 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(); +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 getSourceRangeImpl<type>(this, &type::getSourceRange); +#include "clang/AST/StmtNodes.inc" } + llvm_unreachable("unknown statement kind!"); } SourceLocation Stmt::getLocStart() const { +// llvm::errs() << "getLocStart() for " << getStmtClassName() << "\n"; 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); + return static_cast<const type*>(this)->getLocStart(); #include "clang/AST/StmtNodes.inc" } llvm_unreachable("unknown statement kind"); @@ -250,7 +245,7 @@ SourceLocation Stmt::getLocEnd() const { #define ABSTRACT_STMT(type) #define STMT(type, base) \ case Stmt::type##Class: \ - return getLocEndImpl<type>(this, &type::getLocEnd); + return static_cast<const type*>(this)->getLocEnd(); #include "clang/AST/StmtNodes.inc" } llvm_unreachable("unknown statement kind"); @@ -302,14 +297,6 @@ AttributedStmt *AttributedStmt::CreateEmpty(ASTContext &C, unsigned NumAttrs) { return new (Mem) AttributedStmt(EmptyShell(), NumAttrs); } -// 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 (StmtBits.sClass) { default: @@ -773,16 +760,12 @@ ObjCAtTryStmt *ObjCAtTryStmt::CreateEmpty(ASTContext &Context, return new (Mem) ObjCAtTryStmt(EmptyShell(), NumCatchStmts, HasFinally); } -SourceRange ObjCAtTryStmt::getSourceRange() const { - SourceLocation EndLoc; +SourceLocation ObjCAtTryStmt::getLocEnd() const { if (HasFinally) - EndLoc = getFinallyStmt()->getLocEnd(); - else if (NumCatchStmts) - EndLoc = getCatchStmt(NumCatchStmts - 1)->getLocEnd(); - else - EndLoc = getTryBody()->getLocEnd(); - - return SourceRange(AtTryLoc, EndLoc); + return getFinallyStmt()->getLocEnd(); + if (NumCatchStmts) + return getCatchStmt(NumCatchStmts - 1)->getLocEnd(); + return getTryBody()->getLocEnd(); } CXXTryStmt *CXXTryStmt::Create(ASTContext &C, SourceLocation tryLoc, |