[llvm] c3c9312 - [Support] Automatically support `hash_value` when `HashBuilder` support is available.

Alexandre Rames via llvm-commits llvm-commits at lists.llvm.org
Tue Sep 7 09:56:16 PDT 2021


Author: Alexandre Rames
Date: 2021-09-07T09:56:11-07:00
New Revision: c3c9312f7049e8a9b1bf05db877b4b39df897416

URL: https://github.com/llvm/llvm-project/commit/c3c9312f7049e8a9b1bf05db877b4b39df897416
DIFF: https://github.com/llvm/llvm-project/commit/c3c9312f7049e8a9b1bf05db877b4b39df897416.diff

LOG: [Support] Automatically support `hash_value` when `HashBuilder` support is available.

Use the `HBuilder` interface to provide default implementations of `llvm::hash_value`.

Reviewed By: dexonsmith

Differential Revision: https://reviews.llvm.org/D109024

Added: 
    

Modified: 
    llvm/include/llvm/Support/HashBuilder.h
    llvm/unittests/ADT/HashingTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/HashBuilder.h b/llvm/include/llvm/Support/HashBuilder.h
index 9ff5acf167298..bf93a0d22da73 100644
--- a/llvm/include/llvm/Support/HashBuilder.h
+++ b/llvm/include/llvm/Support/HashBuilder.h
@@ -16,6 +16,7 @@
 #define LLVM_SUPPORT_HASHBUILDER_H
 
 #include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/Hashing.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Endian.h"
@@ -405,6 +406,33 @@ using HashBuilder =
     HashBuilderImpl<HasherT, (Endianness == support::endianness::native
                                   ? support::endian::system_endianness()
                                   : Endianness)>;
+
+namespace hashbuilder_detail {
+class HashCodeHasher {
+public:
+  HashCodeHasher() : Code(0) {}
+  void update(ArrayRef<uint8_t> Data) {
+    hash_code DataCode = hash_value(Data);
+    Code = hash_combine(Code, DataCode);
+  }
+  hash_code Code;
+};
+
+using HashCodeHashBuilder = HashBuilder<hashbuilder_detail::HashCodeHasher,
+                                        support::endianness::native>;
+} // namespace hashbuilder_detail
+
+/// Provide a default implementation of `hash_value` when `addHash(const T &)`
+/// is supported.
+template <typename T>
+std::enable_if_t<
+    is_detected<hashbuilder_detail::HashCodeHashBuilder::HasAddHashT, T>::value,
+    hash_code>
+hash_value(const T &Value) {
+  hashbuilder_detail::HashCodeHashBuilder HBuilder;
+  HBuilder.add(Value);
+  return HBuilder.getHasher().Code;
+}
 } // end namespace llvm
 
 #endif // LLVM_SUPPORT_HASHBUILDER_H

diff  --git a/llvm/unittests/ADT/HashingTest.cpp b/llvm/unittests/ADT/HashingTest.cpp
index d2cda3afdda0f..bb19a569999f2 100644
--- a/llvm/unittests/ADT/HashingTest.cpp
+++ b/llvm/unittests/ADT/HashingTest.cpp
@@ -12,6 +12,7 @@
 
 #include "llvm/ADT/Hashing.h"
 #include "llvm/Support/DataTypes.h"
+#include "llvm/Support/HashBuilder.h"
 #include "gtest/gtest.h"
 #include <deque>
 #include <list>
@@ -402,4 +403,36 @@ TEST(HashingTest, HashCombineArgs18) {
 #undef CHECK_SAME
 }
 
+struct StructWithHashBuilderSupport {
+  char C;
+  int I;
+  template <typename HasherT, llvm::support::endianness Endianness>
+  friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
+                      const StructWithHashBuilderSupport &Value) {
+    HBuilder.add(Value.C, Value.I);
+  }
+};
+
+TEST(HashingTest, HashWithHashBuilder) {
+  StructWithHashBuilderSupport S{'c', 1};
+  EXPECT_NE(static_cast<size_t>(llvm::hash_value(S)), static_cast<size_t>(0));
 }
+
+struct StructWithHashBuilderAndHashValueSupport {
+  char C;
+  int I;
+  template <typename HasherT, llvm::support::endianness Endianness>
+  friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
+                      const StructWithHashBuilderAndHashValueSupport &Value) {}
+  friend hash_code
+  hash_value(const StructWithHashBuilderAndHashValueSupport &Value) {
+    return 0xbeef;
+  }
+};
+
+TEST(HashingTest, HashBuilderAndHashValue) {
+  StructWithHashBuilderAndHashValueSupport S{'c', 1};
+  EXPECT_EQ(static_cast<size_t>(hash_value(S)), static_cast<size_t>(0xbeef));
+}
+
+} // namespace


        


More information about the llvm-commits mailing list