Introduce Decl::hasBody() and FunctionDecl::hasBody() and use them instead of getBody() when we are just checking the existence of a body, to avoid de-serialization of the body from PCH.

Makes de-serialization of the function body even more "lazier".

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@107768 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/lib/AST/Decl.cpp b/lib/AST/Decl.cpp
index 6b52a17..149938f 100644
--- a/lib/AST/Decl.cpp
+++ b/lib/AST/Decl.cpp
@@ -953,6 +953,17 @@
   return false;
 }
 
+bool FunctionDecl::hasBody(const FunctionDecl *&Definition) const {
+  for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
+    if (I->Body) {
+      Definition = *I;
+      return true;
+    }
+  }
+
+  return false;
+}
+
 Stmt *FunctionDecl::getBody(const FunctionDecl *&Definition) const {
   for (redecl_iterator I = redecls_begin(), E = redecls_end(); I != E; ++I) {
     if (I->Body) {
@@ -1153,11 +1164,11 @@
   }
 
   const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
-  Stmt *Pattern = 0;
+  bool HasPattern = false;
   if (PatternDecl)
-    Pattern = PatternDecl->getBody(PatternDecl);
+    HasPattern = PatternDecl->hasBody(PatternDecl);
   
-  if (Pattern && PatternDecl)
+  if (HasPattern && PatternDecl)
     return PatternDecl->isInlined();
   
   return false;
@@ -1302,15 +1313,15 @@
 
   // Find the actual template from which we will instantiate.
   const FunctionDecl *PatternDecl = getTemplateInstantiationPattern();
-  Stmt *Pattern = 0;
+  bool HasPattern = false;
   if (PatternDecl)
-    Pattern = PatternDecl->getBody(PatternDecl);
+    HasPattern = PatternDecl->hasBody(PatternDecl);
   
   // C++0x [temp.explicit]p9:
   //   Except for inline functions, other explicit instantiation declarations
   //   have the effect of suppressing the implicit instantiation of the entity
   //   to which they refer. 
-  if (!Pattern || !PatternDecl)
+  if (!HasPattern || !PatternDecl) 
     return true;
 
   return PatternDecl->isInlined();
@@ -1514,7 +1525,7 @@
   // class template, check whether that member function was defined out-of-line.
   if (FunctionDecl *FD = getInstantiatedFromMemberFunction()) {
     const FunctionDecl *Definition;
-    if (FD->getBody(Definition))
+    if (FD->hasBody(Definition))
       return Definition->isOutOfLine();
   }
   
@@ -1522,7 +1533,7 @@
   // check whether that function template was defined out-of-line.
   if (FunctionTemplateDecl *FunTmpl = getPrimaryTemplate()) {
     const FunctionDecl *Definition;
-    if (FunTmpl->getTemplatedDecl()->getBody(Definition))
+    if (FunTmpl->getTemplatedDecl()->hasBody(Definition))
       return Definition->isOutOfLine();
   }
   
diff --git a/lib/AST/DeclBase.cpp b/lib/AST/DeclBase.cpp
index 7a104f4..0821da3 100644
--- a/lib/AST/DeclBase.cpp
+++ b/lib/AST/DeclBase.cpp
@@ -452,6 +452,15 @@
 }
 
 SourceLocation Decl::getBodyRBrace() const {
+  // Special handling of FunctionDecl to avoid de-serializing the body from PCH.
+  // FunctionDecl stores EndRangeLoc for this purpose.
+  if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(this)) {
+    const FunctionDecl *Definition;
+    if (FD->hasBody(Definition))
+      return Definition->getSourceRange().getEnd();
+    return SourceLocation();
+  }
+
   Stmt *Body = getBody();
   if (!Body)
     return SourceLocation();
diff --git a/lib/AST/DeclCXX.cpp b/lib/AST/DeclCXX.cpp
index 19c3ac1..dd0fe08 100644
--- a/lib/AST/DeclCXX.cpp
+++ b/lib/AST/DeclCXX.cpp
@@ -743,7 +743,7 @@
     CheckFn = this;
   
   const FunctionDecl *fn;
-  return CheckFn->getBody(fn) && !fn->isOutOfLine();
+  return CheckFn->hasBody(fn) && !fn->isOutOfLine();
 }
 
 CXXBaseOrMemberInitializer::