summaryrefslogtreecommitdiffstats
path: root/include/__hash_table
diff options
context:
space:
mode:
authorEric Fiselier <eric@efcs.ca>2017-01-13 22:42:53 +0000
committerEric Fiselier <eric@efcs.ca>2017-01-13 22:42:53 +0000
commiteaf292013defd65d96984e12733f67cb35e05561 (patch)
treea9f7c6d2edf5fef3c8482c51aa58759159aeb2b3 /include/__hash_table
parentebaf7dab14c3bf1c4f995d9ad1199b6c2784a8ca (diff)
downloadexternal_libcxx-eaf292013defd65d96984e12733f67cb35e05561.tar.gz
external_libcxx-eaf292013defd65d96984e12733f67cb35e05561.tar.bz2
external_libcxx-eaf292013defd65d96984e12733f67cb35e05561.zip
Diagnose non-const-callable hash functions and comparators
git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@291969 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'include/__hash_table')
-rw-r--r--include/__hash_table36
1 files changed, 36 insertions, 0 deletions
diff --git a/include/__hash_table b/include/__hash_table
index e082e6c81..6d6a6a1aa 100644
--- a/include/__hash_table
+++ b/include/__hash_table
@@ -18,6 +18,7 @@
#include <algorithm>
#include <cmath>
#include <utility>
+#include <type_traits>
#include <__undef_min_max>
@@ -38,6 +39,15 @@ template <class _Key, class _Tp>
struct __hash_value_type;
#endif
+template <class _Key, class _Cp, class _Hash,
+ bool = is_empty<_Hash>::value && !__libcpp_is_final<_Hash>::value>
+class __unordered_map_hasher;
+
+template <class _Key, class _Cp, class _Pred,
+ bool = is_empty<_Pred>::value && !__libcpp_is_final<_Pred>::value
+ >
+class __unordered_map_equal;
+
#ifndef _LIBCPP_CXX03_LANG
template <class _Tp>
struct __is_hash_value_type_imp : false_type {};
@@ -856,6 +866,29 @@ public:
template <class> friend class __hash_map_node_destructor;
};
+
+#ifndef _LIBCPP_CXX03_LANG
+template <class _Key, class _Hash, class _Equal, class _Alloc>
+struct __diagnose_hash_table_helper {
+ static constexpr bool __trigger_diagnostics()
+ _LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value,
+ "the specified hash functor does not provide a const call operator")
+ _LIBCPP_DIAGNOSE_WARNING(!__invokable<_Equal const&, _Key const&, _Key const&>::value,
+ "the specified comparator type does not provide a const call operator")
+ { return true; }
+};
+
+template <class _Key, class _Value, class _Hash, class _Equal, class _Alloc>
+struct __diagnose_hash_table_helper<
+ __hash_value_type<_Key, _Value>,
+ __unordered_map_hasher<_Key, __hash_value_type<_Key, _Value>, _Hash>,
+ __unordered_map_equal<_Key, __hash_value_type<_Key, _Value>, _Equal>,
+ _Alloc>
+: __diagnose_hash_table_helper<_Key, _Hash, _Equal, _Alloc>
+{
+};
+#endif // _LIBCPP_CXX03_LANG
+
template <class _Tp, class _Hash, class _Equal, class _Alloc>
class __hash_table
{
@@ -1453,6 +1486,9 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table()
"Predicate must be copy-constructible.");
static_assert((is_copy_constructible<hasher>::value),
"Hasher must be copy-constructible.");
+#ifndef _LIBCPP_CXX03_LANG
+ static_assert(__diagnose_hash_table_helper<_Tp, _Hash, _Equal, _Alloc>::__trigger_diagnostics(), "");
+#endif
__deallocate_node(__p1_.first().__next_);
#if _LIBCPP_DEBUG_LEVEL >= 2
__get_db()->__erase_c(this);