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
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index 6d6a6a1..9d9a290 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -871,11 +871,20 @@
 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 @@
     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 @@
 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);