diff options
| author | Eric Fiselier <eric@efcs.ca> | 2017-03-01 02:02:28 +0000 |
|---|---|---|
| committer | Eric Fiselier <eric@efcs.ca> | 2017-03-01 02:02:28 +0000 |
| commit | acb21581d7d0fa97e51c7b3f1a23525bf1cbbee7 (patch) | |
| tree | 65276004605bef83104af746ed00e5927b077be2 /libcxx/include | |
| parent | 65f8cf945dfacdd80a664022cde5cc4c15537fcb (diff) | |
| download | bcm5719-llvm-acb21581d7d0fa97e51c7b3f1a23525bf1cbbee7.tar.gz bcm5719-llvm-acb21581d7d0fa97e51c7b3f1a23525bf1cbbee7.zip | |
Improve diagnostics when an invalid hash is used in an unordered container.
This patch adds a static assertion that the specified hash meets
the requirements of an enabled hash, and it ensures that the static
assertion is evaluated before __compressed_pair is instantiated.
That way the static assertion diagnostic is emitted first.
llvm-svn: 296565
Diffstat (limited to 'libcxx/include')
| -rw-r--r-- | libcxx/include/__hash_table | 27 |
1 files changed, 20 insertions, 7 deletions
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table index 6d6a6a1aa33..9d9a2905532 100644 --- a/libcxx/include/__hash_table +++ b/libcxx/include/__hash_table @@ -871,11 +871,20 @@ public: 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; } + _LIBCPP_DIAGNOSE_WARNING(__has_enabled_hash<_Key, _Hash>::value + && !__invokable<_Hash const&, _Key const&>::value, + "the specified hash functor does not provide a const call operator") + _LIBCPP_DIAGNOSE_WARNING(is_copy_constructible<_Equal>::value + && !__invokable<_Equal const&, _Key const&, _Key const&>::value, + "the specified comparator type does not provide a const call operator") + { + static_assert(__has_enabled_hash<_Key, _Hash>::value, + "the specified hash functor does not meet the requirements for an " + "enabled hash"); + static_assert(is_copy_constructible<_Equal>::value, + "the specified comparator is required to be copy constructible"); + return true; + } }; template <class _Key, class _Value, class _Hash, class _Equal, class _Alloc> @@ -951,6 +960,10 @@ private: typedef allocator_traits<__pointer_allocator> __pointer_alloc_traits; typedef typename __bucket_list_deleter::pointer __node_pointer_pointer; +#ifndef _LIBCPP_CXX03_LANG + static_assert(__diagnose_hash_table_helper<_Tp, _Hash, _Equal, _Alloc>::__trigger_diagnostics(), ""); +#endif + // --- Member data begin --- __bucket_list __bucket_list_; __compressed_pair<__first_node, __node_allocator> __p1_; @@ -1482,13 +1495,13 @@ __hash_table<_Tp, _Hash, _Equal, _Alloc>::__hash_table(__hash_table&& __u, template <class _Tp, class _Hash, class _Equal, class _Alloc> __hash_table<_Tp, _Hash, _Equal, _Alloc>::~__hash_table() { +#if defined(_LIBCPP_CXX03_LANG) static_assert((is_copy_constructible<key_equal>::value), "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); |

