[ODRHash] Merge the two function hashes into one.

Functions that are a sub-Decl of a record were hashed differently than other
functions.  This change keeps the AddFunctionDecl function and the hash of
records now calls this function.  In addition, AddFunctionDecl has an option
to perform a hash as if the body was absent, which is required for some
checks after loading modules.  Additional logic prevents multiple error
message from being printed.

llvm-svn: 336632
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index ef1235e..45b8ee6 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -317,35 +317,14 @@
   }
 
   void VisitFunctionDecl(const FunctionDecl *D) {
-    ID.AddInteger(D->getStorageClass());
-    Hash.AddBoolean(D->isInlineSpecified());
-    Hash.AddBoolean(D->isVirtualAsWritten());
-    Hash.AddBoolean(D->isPure());
-    Hash.AddBoolean(D->isDeletedAsWritten());
-
-    ID.AddInteger(D->param_size());
-
-    for (auto *Param : D->parameters()) {
-      Hash.AddSubDecl(Param);
-    }
-
-    AddQualType(D->getReturnType());
-
-    const auto* SpecializationArgs = D->getTemplateSpecializationArgs();
-    Hash.AddBoolean(SpecializationArgs);
-    if (SpecializationArgs) {
-      ID.AddInteger(SpecializationArgs->size());
-      for (const TemplateArgument &TA : SpecializationArgs->asArray()) {
-        Hash.AddTemplateArgument(TA);
-      }
-    }
+    // Handled by the ODRHash for FunctionDecl
+    ID.AddInteger(D->getODRHash());
 
     Inherited::VisitFunctionDecl(D);
   }
 
   void VisitCXXMethodDecl(const CXXMethodDecl *D) {
-    Hash.AddBoolean(D->isConst());
-    Hash.AddBoolean(D->isVolatile());
+    // Handled by the ODRHash for FunctionDecl
 
     Inherited::VisitCXXMethodDecl(D);
   }
@@ -425,7 +404,6 @@
   }
 
   void VisitFunctionTemplateDecl(const FunctionTemplateDecl *D) {
-    Visit(D->getTemplatedDecl());
     AddDecl(D->getTemplatedDecl());
     Inherited::VisitFunctionTemplateDecl(D);
   }
@@ -479,9 +457,13 @@
   // Filter out sub-Decls which will not be processed in order to get an
   // accurate count of Decl's.
   llvm::SmallVector<const Decl *, 16> Decls;
-  for (const Decl *SubDecl : Record->decls()) {
+  for (Decl *SubDecl : Record->decls()) {
     if (isWhitelistedDecl(SubDecl, Record)) {
       Decls.push_back(SubDecl);
+      if (auto *Function = dyn_cast<FunctionDecl>(SubDecl)) {
+        // Compute/Preload ODRHash into FunctionDecl.
+        Function->getODRHash();
+      }
     }
   }
 
@@ -505,25 +487,48 @@
   }
 }
 
-void ODRHash::AddFunctionDecl(const FunctionDecl *Function) {
+void ODRHash::AddFunctionDecl(const FunctionDecl *Function,
+                              bool SkipBody) {
   assert(Function && "Expecting non-null pointer.");
 
-  // Skip hashing these kinds of function.
-  if (Function->isImplicit()) return;
-  if (Function->isDefaulted()) return;
-  if (Function->isDeleted()) return;
-  if (!Function->hasBody()) return;
-  if (!Function->getBody()) return;
-
   // Skip functions that are specializations or in specialization context.
   const DeclContext *DC = Function;
   while (DC) {
     if (isa<ClassTemplateSpecializationDecl>(DC)) return;
-    if (auto *F = dyn_cast<FunctionDecl>(DC))
-      if (F->isFunctionTemplateSpecialization()) return;
+    if (auto *F = dyn_cast<FunctionDecl>(DC)) {
+      if (F->isFunctionTemplateSpecialization()) {
+        if (!isa<CXXMethodDecl>(DC)) return;
+        if (DC->getLexicalParent()->isFileContext()) return;
+        // Inline method specializations are the only supported
+        // specialization for now.
+      }
+    }
     DC = DC->getParent();
   }
 
+  ID.AddInteger(Function->getDeclKind());
+
+  const auto *SpecializationArgs = Function->getTemplateSpecializationArgs();
+  AddBoolean(SpecializationArgs);
+  if (SpecializationArgs) {
+    ID.AddInteger(SpecializationArgs->size());
+    for (const TemplateArgument &TA : SpecializationArgs->asArray()) {
+      AddTemplateArgument(TA);
+    }
+  }
+
+  if (const auto *Method = dyn_cast<CXXMethodDecl>(Function)) {
+    AddBoolean(Method->isConst());
+    AddBoolean(Method->isVolatile());
+  }
+
+  ID.AddInteger(Function->getStorageClass());
+  AddBoolean(Function->isInlineSpecified());
+  AddBoolean(Function->isVirtualAsWritten());
+  AddBoolean(Function->isPure());
+  AddBoolean(Function->isDeletedAsWritten());
+  AddBoolean(Function->isExplicitlyDefaulted());
+
   AddDecl(Function);
 
   AddQualType(Function->getReturnType());
@@ -532,7 +537,21 @@
   for (auto Param : Function->parameters())
     AddSubDecl(Param);
 
-  AddStmt(Function->getBody());
+  if (SkipBody) {
+    AddBoolean(false);
+    return;
+  }
+
+  const bool HasBody = Function->isThisDeclarationADefinition() &&
+                       !Function->isDefaulted() && !Function->isDeleted() &&
+                       !Function->isLateTemplateParsed();
+  AddBoolean(HasBody);
+  if (HasBody) {
+    auto *Body = Function->getBody();
+    AddBoolean(Body);
+    if (Body)
+      AddStmt(Body);
+  }
 }
 
 void ODRHash::AddDecl(const Decl *D) {