diff options
author | JF Bastien <jfb@google.com> | 2016-04-09 20:04:34 +0000 |
---|---|---|
committer | JF Bastien <jfb@google.com> | 2016-04-09 20:04:34 +0000 |
commit | 6e94b16739fac1a7ed5bb27cb56c643cb7ab01e9 (patch) | |
tree | 1c2836b631aa2fb68bfab80ed6bbac635b04ae73 /llvm | |
parent | e86dd022c6084e3a12616fc594fb2d6584fcc9c2 (diff) | |
download | bcm5719-llvm-6e94b16739fac1a7ed5bb27cb56c643cb7ab01e9.tar.gz bcm5719-llvm-6e94b16739fac1a7ed5bb27cb56c643cb7ab01e9.zip |
is_integral_or_enum ❥ enum class ⇒ hashable enum class
Summary:
As discussed in D18775 making AtomicOrdering an enum class makes it non-hashable, which shouldn't be the case. Hashing.h defines hash_value for all is_integral_or_enum, but type_traits.h's definition of is_integral_or_enum only checks for *inplicit* conversion to integral types which leaves enum classes out and is very confusing because is_enum is true for enum classes.
This patch:
- Adds a check for is_enum when determining is_integral_or_enum.
- Explicitly converts the value parameter in hash_value to handle enum class hashing.
Note that the warning at the top of Hashing.h still applies: each execution of the program has a high probability of producing a different hash_code for a given input. Thus their values are not stable to save or persist, and should only be used during the execution for the construction of hashing datastructures.
Reviewers: dberlin, chandlerc
Subscribers: llvm-commits
Differential Revision: http://reviews.llvm.org/D18938
llvm-svn: 265879
Diffstat (limited to 'llvm')
-rw-r--r-- | llvm/include/llvm/ADT/Hashing.h | 3 | ||||
-rw-r--r-- | llvm/include/llvm/Support/type_traits.h | 10 |
2 files changed, 8 insertions, 5 deletions
diff --git a/llvm/include/llvm/ADT/Hashing.h b/llvm/include/llvm/ADT/Hashing.h index de56f91eddb..6c01b15d7f0 100644 --- a/llvm/include/llvm/ADT/Hashing.h +++ b/llvm/include/llvm/ADT/Hashing.h @@ -632,7 +632,8 @@ inline hash_code hash_integer_value(uint64_t value) { template <typename T> typename std::enable_if<is_integral_or_enum<T>::value, hash_code>::type hash_value(T value) { - return ::llvm::hashing::detail::hash_integer_value(value); + return ::llvm::hashing::detail::hash_integer_value( + static_cast<typename std::underlying_type<T>::type>(value)); } // Declared and documented above, but defined here so that any of the hashing diff --git a/llvm/include/llvm/Support/type_traits.h b/llvm/include/llvm/Support/type_traits.h index 88385c3fae1..2a429585201 100644 --- a/llvm/include/llvm/Support/type_traits.h +++ b/llvm/include/llvm/Support/type_traits.h @@ -54,11 +54,12 @@ struct isPodLike<std::pair<T, U> > { }; /// \brief Metafunction that determines whether the given type is either an -/// integral type or an enumeration type. +/// integral type or an enumeration type, including enum classes. /// /// Note that this accepts potentially more integral types than is_integral -/// because it is based on merely being convertible implicitly to an integral -/// type. +/// because it is based on being implicitly convertible to an integral type. +/// Also note that enum classes aren't implicitly convertible to integral types, +/// the value may therefore need to be explicitly converted before being used. template <typename T> class is_integral_or_enum { typedef typename std::remove_reference<T>::type UnderlyingT; @@ -67,7 +68,8 @@ public: !std::is_class<UnderlyingT>::value && // Filter conversion operators. !std::is_pointer<UnderlyingT>::value && !std::is_floating_point<UnderlyingT>::value && - std::is_convertible<UnderlyingT, unsigned long long>::value; + (std::is_enum<UnderlyingT>::value || + std::is_convertible<UnderlyingT, unsigned long long>::value); }; /// \brief If T is a pointer, just return it. If it is not, return T&. |