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
diff --git a/lib/AST/Expr.cpp b/lib/AST/Expr.cpp
index d3f8ac0..5fd38bb 100644
--- a/lib/AST/Expr.cpp
+++ b/lib/AST/Expr.cpp
@@ -445,14 +445,6 @@
   return new (Mem) DeclRefExpr(EmptyShell());
 }
 
-SourceRange DeclRefExpr::getSourceRange() const {
-  SourceRange R = getNameInfo().getSourceRange();
-  if (hasQualifier())
-    R.setBegin(getQualifierLoc().getBeginLoc());
-  if (hasExplicitTemplateArgs())
-    R.setEnd(getRAngleLoc());
-  return R;
-}
 SourceLocation DeclRefExpr::getLocStart() const {
   if (hasQualifier())
     return getQualifierLoc().getBeginLoc();
@@ -1159,21 +1151,9 @@
   return FnType->getResultType();
 }
 
-SourceRange CallExpr::getSourceRange() const {
-  if (isa<CXXOperatorCallExpr>(this))
-    return cast<CXXOperatorCallExpr>(this)->getSourceRange();
-
-  SourceLocation begin = getCallee()->getLocStart();
-  if (begin.isInvalid() && getNumArgs() > 0)
-    begin = getArg(0)->getLocStart();
-  SourceLocation end = getRParenLoc();
-  if (end.isInvalid() && getNumArgs() > 0)
-    end = getArg(getNumArgs() - 1)->getLocEnd();
-  return SourceRange(begin, end);
-}
 SourceLocation CallExpr::getLocStart() const {
   if (isa<CXXOperatorCallExpr>(this))
-    return cast<CXXOperatorCallExpr>(this)->getSourceRange().getBegin();
+    return cast<CXXOperatorCallExpr>(this)->getLocStart();
 
   SourceLocation begin = getCallee()->getLocStart();
   if (begin.isInvalid() && getNumArgs() > 0)
@@ -1182,7 +1162,7 @@
 }
 SourceLocation CallExpr::getLocEnd() const {
   if (isa<CXXOperatorCallExpr>(this))
-    return cast<CXXOperatorCallExpr>(this)->getSourceRange().getEnd();
+    return cast<CXXOperatorCallExpr>(this)->getLocEnd();
 
   SourceLocation end = getRParenLoc();
   if (end.isInvalid() && getNumArgs() > 0)
@@ -1310,9 +1290,6 @@
   return E;
 }
 
-SourceRange MemberExpr::getSourceRange() const {
-  return SourceRange(getLocStart(), getLocEnd());
-}
 SourceLocation MemberExpr::getLocStart() const {
   if (isImplicitAccess()) {
     if (hasQualifier())
@@ -1808,10 +1785,10 @@
   return isa<StringLiteral>(Init) || isa<ObjCEncodeExpr>(Init);
 }
 
-SourceRange InitListExpr::getSourceRange() const {
+SourceLocation InitListExpr::getLocStart() const {
   if (InitListExpr *SyntacticForm = getSyntacticForm())
-    return SyntacticForm->getSourceRange();
-  SourceLocation Beg = LBraceLoc, End = RBraceLoc;
+    return SyntacticForm->getLocStart();
+  SourceLocation Beg = LBraceLoc;
   if (Beg.isInvalid()) {
     // Find the first non-null initializer.
     for (InitExprsTy::const_iterator I = InitExprs.begin(),
@@ -1823,18 +1800,25 @@
       }  
     }
   }
+  return Beg;
+}
+
+SourceLocation InitListExpr::getLocEnd() const {
+  if (InitListExpr *SyntacticForm = getSyntacticForm())
+    return SyntacticForm->getLocEnd();
+  SourceLocation End = RBraceLoc;
   if (End.isInvalid()) {
     // Find the first non-null initializer from the end.
     for (InitExprsTy::const_reverse_iterator I = InitExprs.rbegin(),
-                                             E = InitExprs.rend();
-      I != E; ++I) {
+         E = InitExprs.rend();
+         I != E; ++I) {
       if (Stmt *S = *I) {
-        End = S->getSourceRange().getEnd();
+        End = S->getLocEnd();
         break;
-      }  
+      }
     }
   }
-  return SourceRange(Beg, End);
+  return End;
 }
 
 /// getFunctionType - Return the underlying function type for this block.
@@ -3684,11 +3668,11 @@
   DesignatedInitExpr *DIE = const_cast<DesignatedInitExpr*>(this);
   if (size() == 1)
     return DIE->getDesignator(0)->getSourceRange();
-  return SourceRange(DIE->getDesignator(0)->getStartLocation(),
-                     DIE->getDesignator(size()-1)->getEndLocation());
+  return SourceRange(DIE->getDesignator(0)->getLocStart(),
+                     DIE->getDesignator(size()-1)->getLocEnd());
 }
 
-SourceRange DesignatedInitExpr::getSourceRange() const {
+SourceLocation DesignatedInitExpr::getLocStart() const {
   SourceLocation StartLoc;
   Designator &First =
     *const_cast<DesignatedInitExpr*>(this)->designators_begin();
@@ -3700,7 +3684,11 @@
   } else
     StartLoc =
       SourceLocation::getFromRawEncoding(First.ArrayOrRange.LBracketLoc);
-  return SourceRange(StartLoc, getInit()->getSourceRange().getEnd());
+  return StartLoc;
+}
+
+SourceLocation DesignatedInitExpr::getLocEnd() const {
+  return getInit()->getLocEnd();
 }
 
 Expr *DesignatedInitExpr::getArrayIndex(const Designator& D) {
diff --git a/lib/AST/ExprCXX.cpp b/lib/AST/ExprCXX.cpp
index fcf34d9..e1977d8 100644
--- a/lib/AST/ExprCXX.cpp
+++ b/lib/AST/ExprCXX.cpp
@@ -73,11 +73,8 @@
 }
 
 // CXXScalarValueInitExpr
-SourceRange CXXScalarValueInitExpr::getSourceRange() const {
-  SourceLocation Start = RParenLoc;
-  if (TypeInfo)
-    Start = TypeInfo->getTypeLoc().getBeginLoc();
-  return SourceRange(Start, RParenLoc);
+SourceLocation CXXScalarValueInitExpr::getLocStart() const {
+  return TypeInfo ? TypeInfo->getTypeLoc().getBeginLoc() : RParenLoc;
 }
 
 // CXXNewExpr
@@ -218,11 +215,11 @@
   return QualType();
 }
 
-SourceRange CXXPseudoDestructorExpr::getSourceRange() const {
+SourceLocation CXXPseudoDestructorExpr::getLocEnd() const {
   SourceLocation End = DestroyedType.getLocation();
   if (TypeSourceInfo *TInfo = DestroyedType.getTypeSourceInfo())
     End = TInfo->getTypeLoc().getLocalSourceRange().getEnd();
-  return SourceRange(Base->getLocStart(), End);
+  return End;
 }
 
 // UnresolvedLookupExpr
@@ -420,12 +417,18 @@
   return E;
 }
 
-SourceRange CXXConstructExpr::getSourceRange() const {
+SourceLocation CXXConstructExpr::getLocStart() const {
   if (isa<CXXTemporaryObjectExpr>(this))
-    return cast<CXXTemporaryObjectExpr>(this)->getSourceRange();
+    return cast<CXXTemporaryObjectExpr>(this)->getLocStart();
+  return Loc;
+}
+
+SourceLocation CXXConstructExpr::getLocEnd() const {
+  if (isa<CXXTemporaryObjectExpr>(this))
+    return cast<CXXTemporaryObjectExpr>(this)->getLocEnd();
 
   if (ParenRange.isValid())
-    return SourceRange(Loc, ParenRange.getEnd());
+    return ParenRange.getEnd();
 
   SourceLocation End = Loc;
   for (unsigned I = getNumArgs(); I > 0; --I) {
@@ -439,7 +442,7 @@
     }
   }
 
-  return SourceRange(Loc, End);
+  return End;
 }
 
 SourceRange CXXOperatorCallExpr::getSourceRangeImpl() const {
@@ -729,9 +732,12 @@
     Type(Type) {
 }
 
-SourceRange CXXTemporaryObjectExpr::getSourceRange() const {
-  return SourceRange(Type->getTypeLoc().getBeginLoc(),
-                     getParenRange().getEnd());
+SourceLocation CXXTemporaryObjectExpr::getLocStart() const {
+  return Type->getTypeLoc().getBeginLoc();
+}
+
+SourceLocation CXXTemporaryObjectExpr::getLocEnd() const {
+  return getParenRange().getEnd();
 }
 
 CXXConstructExpr *CXXConstructExpr::Create(ASTContext &C, QualType T,
@@ -1060,8 +1066,8 @@
   return new (Mem) CXXUnresolvedConstructExpr(Empty, NumArgs);
 }
 
-SourceRange CXXUnresolvedConstructExpr::getSourceRange() const {
-  return SourceRange(Type->getTypeLoc().getBeginLoc(), RParenLoc);
+SourceLocation CXXUnresolvedConstructExpr::getLocStart() const {
+  return Type->getTypeLoc().getBeginLoc();
 }
 
 CXXDependentScopeMemberExpr::CXXDependentScopeMemberExpr(ASTContext &C,
diff --git a/lib/AST/Stmt.cpp b/lib/AST/Stmt.cpp
index ddb1560..1ef80c9 100644
--- a/lib/AST/Stmt.cpp
+++ b/lib/AST/Stmt.cpp
@@ -142,18 +142,28 @@
     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 @@
 #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 @@
   llvm_unreachable("unknown statement kind!");
 }
 
+// Amusing macro metaprogramming hack: check whether a class provides
+// a more specific implementation of getSourceRange.
+//
+// See also Expr.cpp:getExprLoc().
+namespace {
+  /// This implementation is used when a class provides a custom
+  /// implementation of getSourceRange.
+  template <class S, class T>
+  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 getSourceRange.  Overload resolution should pick it over
+  /// the implementation above because it's more specialized according to
+  /// function template partial ordering.
+  template <class S>
+  SourceRange getSourceRangeImpl(const Stmt *stmt,
+                                 SourceRange (Stmt::*v)() const) {
+    return SourceRange(static_cast<const S*>(stmt)->getLocStart(),
+                       static_cast<const S*>(stmt)->getLocEnd());
+  }
+}
+
 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();
+    return getSourceRangeImpl<type>(this, &type::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().
-//
-// 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 {
+//  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 @@
 #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 @@
   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 @@
   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,