diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h index 300c63af009..e97cb315b5d 100644 --- a/absl/hash/internal/hash.h +++ b/absl/hash/internal/hash.h @@ -409,9 +409,23 @@ AbslHashValue(H hash_state, LongDouble value) { return H::combine(std::move(hash_state), category); } +// Without this overload, an array decays to a pointer and we hash that, which +// is not likely to be what the caller intended. +template +H AbslHashValue(H hash_state, T (&)[N]) { + static_assert( + sizeof(T) == -1, + "Hashing C arrays is not allowed. For string literals, wrap the literal " + "in absl::string_view(). To hash the array contents, use " + "absl::MakeSpan() or make the array an std::array. To hash the array " + "address, use &array[0]."); + return hash_state; +} + // AbslHashValue() for hashing pointers template -H AbslHashValue(H hash_state, T* ptr) { +std::enable_if_t::value, H> AbslHashValue(H hash_state, + T ptr) { auto v = reinterpret_cast(ptr); // Due to alignment, pointers tend to have low bits as zero, and the next few // bits follow a pattern since they are also multiples of some base value.