[ODRHash] Support hashing enums.

llvm-svn: 337978
diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp
index a23499f..3b9b85a 100644
--- a/clang/lib/AST/Decl.cpp
+++ b/clang/lib/AST/Decl.cpp
@@ -3973,6 +3973,17 @@
   SpecializationInfo = new (C) MemberSpecializationInfo(ED, TSK);
 }
 
+unsigned EnumDecl::getODRHash() {
+  if (HasODRHash)
+    return ODRHash;
+
+  class ODRHash Hash;
+  Hash.AddEnumDecl(this);
+  HasODRHash = true;
+  ODRHash = Hash.CalculateHash();
+  return ODRHash;
+}
+
 //===----------------------------------------------------------------------===//
 // RecordDecl Implementation
 //===----------------------------------------------------------------------===//
diff --git a/clang/lib/AST/ODRHash.cpp b/clang/lib/AST/ODRHash.cpp
index 45b8ee6..e710d37 100644
--- a/clang/lib/AST/ODRHash.cpp
+++ b/clang/lib/AST/ODRHash.cpp
@@ -407,12 +407,17 @@
     AddDecl(D->getTemplatedDecl());
     Inherited::VisitFunctionTemplateDecl(D);
   }
+
+  void VisitEnumConstantDecl(const EnumConstantDecl *D) {
+    AddStmt(D->getInitExpr());
+    Inherited::VisitEnumConstantDecl(D);
+  }
 };
 } // namespace
 
 // Only allow a small portion of Decl's to be processed.  Remove this once
 // all Decl's can be handled.
-bool ODRHash::isWhitelistedDecl(const Decl *D, const CXXRecordDecl *Parent) {
+bool ODRHash::isWhitelistedDecl(const Decl *D, const DeclContext *Parent) {
   if (D->isImplicit()) return false;
   if (D->getDeclContext() != Parent) return false;
 
@@ -423,6 +428,7 @@
     case Decl::CXXConstructor:
     case Decl::CXXDestructor:
     case Decl::CXXMethod:
+    case Decl::EnumConstant: // Only found in EnumDecl's.
     case Decl::Field:
     case Decl::Friend:
     case Decl::FunctionTemplate:
@@ -554,6 +560,34 @@
   }
 }
 
+void ODRHash::AddEnumDecl(const EnumDecl *Enum) {
+  assert(Enum);
+  AddDeclarationName(Enum->getDeclName());
+
+  AddBoolean(Enum->isScoped());
+  if (Enum->isScoped())
+    AddBoolean(Enum->isScopedUsingClassTag());
+
+  if (Enum->getIntegerTypeSourceInfo())
+    AddQualType(Enum->getIntegerType());
+
+  // 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 (Decl *SubDecl : Enum->decls()) {
+    if (isWhitelistedDecl(SubDecl, Enum)) {
+      assert(isa<EnumConstantDecl>(SubDecl) && "Unexpected Decl");
+      Decls.push_back(SubDecl);
+    }
+  }
+
+  ID.AddInteger(Decls.size());
+  for (auto SubDecl : Decls) {
+    AddSubDecl(SubDecl);
+  }
+
+}
+
 void ODRHash::AddDecl(const Decl *D) {
   assert(D && "Expecting non-null pointer.");
   D = D->getCanonicalDecl();