Skip to content

Commit

Permalink
[Support] Rename HashBuilderImpl to HashBuilder (NFC) (#68173)
Browse files Browse the repository at this point in the history
Commit 9370271 made HashBuilder an
alias for HashBuilderImpl:

  template <class HasherT, support::endianness Endianness>
  using HashBuilder = HashBuilderImpl<HasherT, Endianness>;

This patch renames HashBuilderImpl to HashBuilder while removing the
alias above.
  • Loading branch information
kazutakahirata committed Oct 5, 2023
1 parent 6f44f87 commit f37028c
Show file tree
Hide file tree
Showing 8 changed files with 86 additions and 96 deletions.
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/ObjCRuntime.h
Original file line number Diff line number Diff line change
Expand Up @@ -483,7 +483,7 @@ class ObjCRuntime {
}

template <typename HasherT, llvm::support::endianness Endianness>
friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
const ObjCRuntime &OCR) {
HBuilder.add(OCR.getKind(), OCR.getVersion());
}
Expand Down
2 changes: 1 addition & 1 deletion clang/include/clang/Basic/Sanitizers.h
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class SanitizerMask {
llvm::hash_code hash_value() const;

template <typename HasherT, llvm::support::endianness Endianness>
friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
const SanitizerMask &SM) {
HBuilder.addRange(&SM.maskLoToHigh[0], &SM.maskLoToHigh[kNumElem]);
}
Expand Down
4 changes: 2 additions & 2 deletions clang/include/clang/Lex/HeaderSearchOptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ inline llvm::hash_code hash_value(const HeaderSearchOptions::Entry &E) {
}

template <typename HasherT, llvm::support::endianness Endianness>
inline void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
inline void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
const HeaderSearchOptions::Entry &E) {
HBuilder.add(E.Path, E.Group, E.IsFramework, E.IgnoreSysRoot);
}
Expand All @@ -279,7 +279,7 @@ hash_value(const HeaderSearchOptions::SystemHeaderPrefix &SHP) {
}

template <typename HasherT, llvm::support::endianness Endianness>
inline void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
inline void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
const HeaderSearchOptions::SystemHeaderPrefix &SHP) {
HBuilder.add(SHP.Prefix, SHP.IsSystemHeader);
}
Expand Down
3 changes: 1 addition & 2 deletions clang/include/clang/Serialization/ModuleFileExtension.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,7 @@ class ModuleFileExtension
/// The default implementation of this function simply does nothing, so the
/// presence/absence of this extension does not distinguish module files.
using ExtensionHashBuilder =
llvm::HashBuilderImpl<llvm::MD5,
llvm::support::endian::system_endianness()>;
llvm::HashBuilder<llvm::MD5, llvm::support::endian::system_endianness()>;
virtual void hashExtension(ExtensionHashBuilder &HBuilder) const;

/// Create a new module file extension writer, which will be
Expand Down
154 changes: 73 additions & 81 deletions llvm/include/llvm/Support/HashBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -85,20 +85,67 @@ template <typename HasherT> class HashBuilderBase {
HasherT &Hasher;
};

/// Implementation of the `HashBuilder` interface.
/// Interface to help hash various types through a hasher type.
///
/// Via provided specializations of `add`, `addRange`, and `addRangeElements`
/// functions, various types (e.g. `ArrayRef`, `StringRef`, etc.) can be hashed
/// without requiring any knowledge of hashed types from the hasher type.
///
/// The only method expected from the templated hasher type `HasherT` is:
/// * void update(ArrayRef<uint8_t> Data)
///
/// Additionally, the following methods will be forwarded to the hasher type:
/// * decltype(std::declval<HasherT &>().final()) final()
/// * decltype(std::declval<HasherT &>().result()) result()
///
/// From a user point of view, the interface provides the following:
/// * `template<typename T> add(const T &Value)`
/// The `add` function implements hashing of various types.
/// * `template <typename ItT> void addRange(ItT First, ItT Last)`
/// The `addRange` function is designed to aid hashing a range of values.
/// It explicitly adds the size of the range in the hash.
/// * `template <typename ItT> void addRangeElements(ItT First, ItT Last)`
/// The `addRangeElements` function is also designed to aid hashing a range of
/// values. In contrast to `addRange`, it **ignores** the size of the range,
/// behaving as if elements were added one at a time with `add`.
///
/// User-defined `struct` types can participate in this interface by providing
/// an `addHash` templated function. See the associated template specialization
/// for details.
///
/// This interface does not impose requirements on the hasher
/// `update(ArrayRef<uint8_t> Data)` method. We want to avoid collisions for
/// variable-size types; for example for
/// ```
/// builder.add({1});
/// builder.add({2, 3});
/// ```
/// and
/// ```
/// builder.add({1, 2});
/// builder.add({3});
/// ```
/// . Thus, specializations of `add` and `addHash` for variable-size types must
/// not assume that the hasher type considers the size as part of the hash; they
/// must explicitly add the size to the hash. See for example specializations
/// for `ArrayRef` and `StringRef`.
///
/// Additionally, since types are eventually forwarded to the hasher's
/// `void update(ArrayRef<uint8_t>)` method, endianness plays a role in the hash
/// computation (for example when computing `add((int)123)`).
/// Specifiying a non-`native` `Endianness` template parameter allows to compute
/// stable hash across platforms with different endianness.
template <typename HasherT, support::endianness Endianness>
class HashBuilderImpl : public HashBuilderBase<HasherT> {
class HashBuilder : public HashBuilderBase<HasherT> {
public:
explicit HashBuilderImpl(HasherT &Hasher)
: HashBuilderBase<HasherT>(Hasher) {}
explicit HashBuilder(HasherT &Hasher) : HashBuilderBase<HasherT>(Hasher) {}
template <typename... ArgTypes>
explicit HashBuilderImpl(ArgTypes &&...Args)
explicit HashBuilder(ArgTypes &&...Args)
: HashBuilderBase<HasherT>(Args...) {}

/// Implement hashing for hashable data types, e.g. integral or enum values.
template <typename T>
std::enable_if_t<hashbuilder_detail::IsHashableData<T>::value,
HashBuilderImpl &>
std::enable_if_t<hashbuilder_detail::IsHashableData<T>::value, HashBuilder &>
add(T Value) {
return adjustForEndiannessAndAdd(Value);
}
Expand All @@ -116,7 +163,7 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {
/// builder.add({3});
/// ```
/// do not collide.
template <typename T> HashBuilderImpl &add(ArrayRef<T> Value) {
template <typename T> HashBuilder &add(ArrayRef<T> Value) {
// As of implementation time, simply calling `addRange(Value)` would also go
// through the `update` fast path. But that would rely on the implementation
// details of `ArrayRef::begin()` and `ArrayRef::end()`. Explicitly call
Expand Down Expand Up @@ -146,7 +193,7 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {
/// builder.add("c");
/// ```
/// do not collide.
HashBuilderImpl &add(StringRef Value) {
HashBuilder &add(StringRef Value) {
// As of implementation time, simply calling `addRange(Value)` would also go
// through `update`. But that would rely on the implementation of
// `StringRef::begin()` and `StringRef::end()`. Explicitly call `update` to
Expand All @@ -159,7 +206,7 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {

template <typename T>
using HasAddHashT =
decltype(addHash(std::declval<HashBuilderImpl &>(), std::declval<T &>()));
decltype(addHash(std::declval<HashBuilder &>(), std::declval<T &>()));
/// Implement hashing for user-defined `struct`s.
///
/// Any user-define `struct` can participate in hashing via `HashBuilder` by
Expand All @@ -179,7 +226,7 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {
/// };
///
/// template <typename HasherT, support::endianness Endianness>
/// void addHash(HashBuilderImpl<HasherT, Endianness> &HBuilder,
/// void addHash(HashBuilder<HasherT, Endianness> &HBuilder,
/// const SimpleStruct &Value) {
/// HBuilder.add(Value.c);
/// HBuilder.add(Value.i);
Expand All @@ -199,7 +246,7 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {
/// // If possible, we want to hash both `I` and `C` in a single
/// // `update` call for performance concerns.
/// template <typename HasherT, support::endianness Endianness>
/// friend void addHash(HashBuilderImpl<HasherT, Endianness> &HBuilder,
/// friend void addHash(HashBuilder<HasherT, Endianness> &HBuilder,
/// const StructWithFastHash &Value) {
/// if (Endianness == support::endian::system_endianness()) {
/// HBuilder.update(ArrayRef(
Expand Down Expand Up @@ -229,7 +276,7 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {
/// Elements[I] = I;
/// }
/// template <typename HasherT, support::endianness Endianness>
/// friend void addHash(HashBuilderImpl<HasherT, Endianness> &HBuilder,
/// friend void addHash(HashBuilder<HasherT, Endianness> &HBuilder,
/// const CustomContainer &Value) {
/// if (Endianness == support::endian::system_endianness()) {
/// HBuilder.update(ArrayRef(
Expand All @@ -246,18 +293,18 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {
template <typename T>
std::enable_if_t<is_detected<HasAddHashT, T>::value &&
!hashbuilder_detail::IsHashableData<T>::value,
HashBuilderImpl &>
HashBuilder &>
add(const T &Value) {
addHash(*this, Value);
return *this;
}

template <typename T1, typename T2>
HashBuilderImpl &add(const std::pair<T1, T2> &Value) {
HashBuilder &add(const std::pair<T1, T2> &Value) {
return add(Value.first, Value.second);
}

template <typename... Ts> HashBuilderImpl &add(const std::tuple<Ts...> &Arg) {
template <typename... Ts> HashBuilder &add(const std::tuple<Ts...> &Arg) {
std::apply([this](const auto &...Args) { this->add(Args...); }, Arg);
return *this;
}
Expand All @@ -273,31 +320,29 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {
/// add(Arg2)
/// ```
template <typename... Ts>
std::enable_if_t<(sizeof...(Ts) > 1), HashBuilderImpl &>
add(const Ts &...Args) {
std::enable_if_t<(sizeof...(Ts) > 1), HashBuilder &> add(const Ts &...Args) {
return (add(Args), ...);
}

template <typename ForwardIteratorT>
HashBuilderImpl &addRange(ForwardIteratorT First, ForwardIteratorT Last) {
HashBuilder &addRange(ForwardIteratorT First, ForwardIteratorT Last) {
add(std::distance(First, Last));
return addRangeElements(First, Last);
}

template <typename RangeT> HashBuilderImpl &addRange(const RangeT &Range) {
template <typename RangeT> HashBuilder &addRange(const RangeT &Range) {
return addRange(adl_begin(Range), adl_end(Range));
}

template <typename ForwardIteratorT>
HashBuilderImpl &addRangeElements(ForwardIteratorT First,
ForwardIteratorT Last) {
HashBuilder &addRangeElements(ForwardIteratorT First, ForwardIteratorT Last) {
return addRangeElementsImpl(
First, Last,
typename std::iterator_traits<ForwardIteratorT>::iterator_category());
}

template <typename RangeT>
HashBuilderImpl &addRangeElements(const RangeT &Range) {
HashBuilder &addRangeElements(const RangeT &Range) {
return addRangeElements(adl_begin(Range), adl_end(Range));
}

Expand All @@ -306,7 +351,7 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {
std::declval<T &>(), support::endianness::little));
/// Adjust `Value` for the target endianness and add it to the hash.
template <typename T>
std::enable_if_t<is_detected<HasByteSwapT, T>::value, HashBuilderImpl &>
std::enable_if_t<is_detected<HasByteSwapT, T>::value, HashBuilder &>
adjustForEndiannessAndAdd(const T &Value) {
T SwappedValue = support::endian::byte_swap(Value, Endianness);
this->update(ArrayRef(reinterpret_cast<const uint8_t *>(&SwappedValue),
Expand All @@ -318,9 +363,9 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {
// FIXME: Once available, specialize this function for `contiguous_iterator`s,
// and use it for `ArrayRef` and `StringRef`.
template <typename ForwardIteratorT>
HashBuilderImpl &addRangeElementsImpl(ForwardIteratorT First,
ForwardIteratorT Last,
std::forward_iterator_tag) {
HashBuilder &addRangeElementsImpl(ForwardIteratorT First,
ForwardIteratorT Last,
std::forward_iterator_tag) {
for (auto It = First; It != Last; ++It)
add(*It);
return *this;
Expand All @@ -329,67 +374,14 @@ class HashBuilderImpl : public HashBuilderBase<HasherT> {
template <typename T>
std::enable_if_t<hashbuilder_detail::IsHashableData<T>::value &&
Endianness == support::endian::system_endianness(),
HashBuilderImpl &>
HashBuilder &>
addRangeElementsImpl(T *First, T *Last, std::forward_iterator_tag) {
this->update(ArrayRef(reinterpret_cast<const uint8_t *>(First),
(Last - First) * sizeof(T)));
return *this;
}
};

/// Interface to help hash various types through a hasher type.
///
/// Via provided specializations of `add`, `addRange`, and `addRangeElements`
/// functions, various types (e.g. `ArrayRef`, `StringRef`, etc.) can be hashed
/// without requiring any knowledge of hashed types from the hasher type.
///
/// The only method expected from the templated hasher type `HasherT` is:
/// * void update(ArrayRef<uint8_t> Data)
///
/// Additionally, the following methods will be forwarded to the hasher type:
/// * decltype(std::declval<HasherT &>().final()) final()
/// * decltype(std::declval<HasherT &>().result()) result()
///
/// From a user point of view, the interface provides the following:
/// * `template<typename T> add(const T &Value)`
/// The `add` function implements hashing of various types.
/// * `template <typename ItT> void addRange(ItT First, ItT Last)`
/// The `addRange` function is designed to aid hashing a range of values.
/// It explicitly adds the size of the range in the hash.
/// * `template <typename ItT> void addRangeElements(ItT First, ItT Last)`
/// The `addRangeElements` function is also designed to aid hashing a range of
/// values. In contrast to `addRange`, it **ignores** the size of the range,
/// behaving as if elements were added one at a time with `add`.
///
/// User-defined `struct` types can participate in this interface by providing
/// an `addHash` templated function. See the associated template specialization
/// for details.
///
/// This interface does not impose requirements on the hasher
/// `update(ArrayRef<uint8_t> Data)` method. We want to avoid collisions for
/// variable-size types; for example for
/// ```
/// builder.add({1});
/// builder.add({2, 3});
/// ```
/// and
/// ```
/// builder.add({1, 2});
/// builder.add({3});
/// ```
/// . Thus, specializations of `add` and `addHash` for variable-size types must
/// not assume that the hasher type considers the size as part of the hash; they
/// must explicitly add the size to the hash. See for example specializations
/// for `ArrayRef` and `StringRef`.
///
/// Additionally, since types are eventually forwarded to the hasher's
/// `void update(ArrayRef<uint8_t>)` method, endianness plays a role in the hash
/// computation (for example when computing `add((int)123)`).
/// Specifiying a non-`native` `Endianness` template parameter allows to compute
/// stable hash across platforms with different endianness.
template <class HasherT, support::endianness Endianness>
using HashBuilder = HashBuilderImpl<HasherT, Endianness>;

namespace hashbuilder_detail {
class HashCodeHasher {
public:
Expand Down
5 changes: 2 additions & 3 deletions llvm/include/llvm/Support/VersionTuple.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,7 @@
#include <tuple>

namespace llvm {
template <typename HasherT, support::endianness Endianness>
class HashBuilderImpl;
template <typename HasherT, support::endianness Endianness> class HashBuilder;
class raw_ostream;
class StringRef;

Expand Down Expand Up @@ -175,7 +174,7 @@ class VersionTuple {
}

template <typename HasherT, llvm::support::endianness Endianness>
friend void addHash(HashBuilderImpl<HasherT, Endianness> &HBuilder,
friend void addHash(HashBuilder<HasherT, Endianness> &HBuilder,
const VersionTuple &VT) {
HBuilder.add(VT.Major, VT.Minor, VT.Subminor, VT.Build);
}
Expand Down
4 changes: 2 additions & 2 deletions llvm/unittests/ADT/HashingTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -425,7 +425,7 @@ struct StructWithHashBuilderSupport {
char C;
int I;
template <typename HasherT, llvm::support::endianness Endianness>
friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
const StructWithHashBuilderSupport &Value) {
HBuilder.add(Value.C, Value.I);
}
Expand All @@ -440,7 +440,7 @@ struct StructWithHashBuilderAndHashValueSupport {
char C;
int I;
template <typename HasherT, llvm::support::endianness Endianness>
friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
const StructWithHashBuilderAndHashValueSupport &Value) {}
friend hash_code
hash_value(const StructWithHashBuilderAndHashValueSupport &Value) {
Expand Down
8 changes: 4 additions & 4 deletions llvm/unittests/Support/HashBuilderTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ struct SimpleStruct {
};

template <typename HasherT, llvm::support::endianness Endianness>
void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
const SimpleStruct &Value) {
HBuilder.add(Value.C);
HBuilder.add(Value.I);
Expand All @@ -139,7 +139,7 @@ struct StructWithoutCopyOrMove {
StructWithoutCopyOrMove &operator=(const StructWithoutCopyOrMove &) = delete;

template <typename HasherT, llvm::support::endianness Endianness>
friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
const StructWithoutCopyOrMove &Value) {
HBuilder.add(Value.I);
}
Expand All @@ -154,7 +154,7 @@ struct /* __attribute__((packed)) */ StructWithFastHash {
// If possible, we want to hash both `I` and `C` in a single `update`
// call for performance concerns.
template <typename HasherT, llvm::support::endianness Endianness>
friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
const StructWithFastHash &Value) {
if (Endianness == llvm::support::endian::system_endianness()) {
HBuilder.update(llvm::ArrayRef(reinterpret_cast<const uint8_t *>(&Value),
Expand All @@ -178,7 +178,7 @@ struct CustomContainer {
Elements[I] = I;
}
template <typename HasherT, llvm::support::endianness Endianness>
friend void addHash(llvm::HashBuilderImpl<HasherT, Endianness> &HBuilder,
friend void addHash(llvm::HashBuilder<HasherT, Endianness> &HBuilder,
const CustomContainer &Value) {
if (Endianness == llvm::support::endian::system_endianness()) {
HBuilder.update(llvm::ArrayRef(
Expand Down

0 comments on commit f37028c

Please sign in to comment.