summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libcxx/include/__hash_table4
-rw-r--r--libcxx/include/__tree2
-rw-r--r--libcxx/include/map12
-rw-r--r--libcxx/include/set12
-rw-r--r--libcxx/include/unordered_map14
-rw-r--r--libcxx/include/unordered_set14
-rw-r--r--libcxx/test/libcxx/containers/associative/non_const_comparator.fail.cpp4
-rw-r--r--libcxx/test/libcxx/containers/associative/non_const_comparator.pass.cpp58
-rw-r--r--libcxx/test/libcxx/containers/unord/non_const_comparator.fail.cpp8
-rw-r--r--libcxx/test/libcxx/containers/unord/non_const_comparator.pass.cpp58
10 files changed, 165 insertions, 21 deletions
diff --git a/libcxx/include/__hash_table b/libcxx/include/__hash_table
index c5a9db1dc41..4b04dd62dbb 100644
--- a/libcxx/include/__hash_table
+++ b/libcxx/include/__hash_table
@@ -875,9 +875,9 @@ struct __enforce_unordered_container_requirements {
template <class _Key, class _Hash, class _Equal>
#ifndef _LIBCPP_CXX03_LANG
_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Equal const&, _Key const&, _Key const&>::value,
- "the specified comparator type does not provide a const call operator")
+ "the specified comparator type does not provide a viable const call operator")
_LIBCPP_DIAGNOSE_WARNING(!__invokable<_Hash const&, _Key const&>::value,
- "the specified hash functor does not provide a const call operator")
+ "the specified hash functor does not provide a viable const call operator")
#endif
typename __enforce_unordered_container_requirements<_Key, _Hash, _Equal>::type
__diagnose_unordered_container_requirements(int);
diff --git a/libcxx/include/__tree b/libcxx/include/__tree
index 9f0931ee940..0aa9bff6151 100644
--- a/libcxx/include/__tree
+++ b/libcxx/include/__tree
@@ -971,7 +971,7 @@ private:
template<class _Tp, class _Compare>
#ifndef _LIBCPP_CXX03_LANG
_LIBCPP_DIAGNOSE_WARNING(!std::__invokable<_Compare const&, _Tp const&, _Tp const&>::value,
- "the specified comparator type does not provide a const call operator")
+ "the specified comparator type does not provide a viable const call operator")
#endif
int __diagnose_non_const_comparator();
diff --git a/libcxx/include/map b/libcxx/include/map
index e21dd5a8454..a8bf448dd57 100644
--- a/libcxx/include/map
+++ b/libcxx/include/map
@@ -907,7 +907,6 @@ public:
typedef value_type& reference;
typedef const value_type& const_reference;
- static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
"Allocator::value_type must be same type as value_type");
@@ -1086,6 +1085,11 @@ public:
}
_LIBCPP_INLINE_VISIBILITY
+ ~map() {
+ static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
iterator begin() _NOEXCEPT {return __tree_.begin();}
_LIBCPP_INLINE_VISIBILITY
const_iterator begin() const _NOEXCEPT {return __tree_.begin();}
@@ -1638,7 +1642,6 @@ public:
typedef value_type& reference;
typedef const value_type& const_reference;
- static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
"Allocator::value_type must be same type as value_type");
@@ -1818,6 +1821,11 @@ public:
}
_LIBCPP_INLINE_VISIBILITY
+ ~multimap() {
+ static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
iterator begin() _NOEXCEPT {return __tree_.begin();}
_LIBCPP_INLINE_VISIBILITY
const_iterator begin() const _NOEXCEPT {return __tree_.begin();}
diff --git a/libcxx/include/set b/libcxx/include/set
index 17837228f26..4574f69fa8a 100644
--- a/libcxx/include/set
+++ b/libcxx/include/set
@@ -450,7 +450,6 @@ public:
typedef value_type& reference;
typedef const value_type& const_reference;
- static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
"Allocator::value_type must be same type as value_type");
@@ -597,6 +596,11 @@ public:
#endif // _LIBCPP_CXX03_LANG
_LIBCPP_INLINE_VISIBILITY
+ ~set() {
+ static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
iterator begin() _NOEXCEPT {return __tree_.begin();}
_LIBCPP_INLINE_VISIBILITY
const_iterator begin() const _NOEXCEPT {return __tree_.begin();}
@@ -938,7 +942,6 @@ public:
typedef value_type& reference;
typedef const value_type& const_reference;
- static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
static_assert((is_same<typename allocator_type::value_type, value_type>::value),
"Allocator::value_type must be same type as value_type");
@@ -1084,6 +1087,11 @@ public:
#endif // _LIBCPP_CXX03_LANG
_LIBCPP_INLINE_VISIBILITY
+ ~multiset() {
+ static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), "");
+ }
+
+ _LIBCPP_INLINE_VISIBILITY
iterator begin() _NOEXCEPT {return __tree_.begin();}
_LIBCPP_INLINE_VISIBILITY
const_iterator begin() const _NOEXCEPT {return __tree_.begin();}
diff --git a/libcxx/include/unordered_map b/libcxx/include/unordered_map
index 7ae9805d81d..42057c5d3fd 100644
--- a/libcxx/include/unordered_map
+++ b/libcxx/include/unordered_map
@@ -852,7 +852,6 @@ public:
typedef const value_type& const_reference;
static_assert((is_same<value_type, typename allocator_type::value_type>::value),
"Invalid allocator::value_type");
- static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), "");
private:
typedef __hash_value_type<key_type, mapped_type> __value_type;
@@ -963,7 +962,11 @@ public:
const allocator_type& __a)
: unordered_map(__il, __n, __hf, key_equal(), __a) {}
#endif
- // ~unordered_map() = default;
+ _LIBCPP_INLINE_VISIBILITY
+ ~unordered_map() {
+ static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), "");
+ }
+
_LIBCPP_INLINE_VISIBILITY
unordered_map& operator=(const unordered_map& __u)
{
@@ -1678,7 +1681,6 @@ public:
typedef const value_type& const_reference;
static_assert((is_same<value_type, typename allocator_type::value_type>::value),
"Invalid allocator::value_type");
- static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), "");
private:
typedef __hash_value_type<key_type, mapped_type> __value_type;
@@ -1787,7 +1789,11 @@ public:
const allocator_type& __a)
: unordered_multimap(__il, __n, __hf, key_equal(), __a) {}
#endif
- // ~unordered_multimap() = default;
+ _LIBCPP_INLINE_VISIBILITY
+ ~unordered_multimap() {
+ static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), "");
+ }
+
_LIBCPP_INLINE_VISIBILITY
unordered_multimap& operator=(const unordered_multimap& __u)
{
diff --git a/libcxx/include/unordered_set b/libcxx/include/unordered_set
index 4cfaa86b883..b32e4cae2cd 100644
--- a/libcxx/include/unordered_set
+++ b/libcxx/include/unordered_set
@@ -390,7 +390,6 @@ public:
typedef const value_type& const_reference;
static_assert((is_same<value_type, typename allocator_type::value_type>::value),
"Invalid allocator::value_type");
- static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), "");
private:
typedef __hash_table<value_type, hasher, key_equal, allocator_type> __table;
@@ -486,7 +485,11 @@ public:
: unordered_set(__il, __n, __hf, key_equal(), __a) {}
#endif
#endif // _LIBCPP_CXX03_LANG
- // ~unordered_set() = default;
+ _LIBCPP_INLINE_VISIBILITY
+ ~unordered_set() {
+ static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), "");
+ }
+
_LIBCPP_INLINE_VISIBILITY
unordered_set& operator=(const unordered_set& __u)
{
@@ -990,7 +993,6 @@ public:
typedef const value_type& const_reference;
static_assert((is_same<value_type, typename allocator_type::value_type>::value),
"Invalid allocator::value_type");
- static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), "");
private:
typedef __hash_table<value_type, hasher, key_equal, allocator_type> __table;
@@ -1084,7 +1086,11 @@ public:
: unordered_multiset(__il, __n, __hf, key_equal(), __a) {}
#endif
#endif // _LIBCPP_CXX03_LANG
- // ~unordered_multiset() = default;
+ _LIBCPP_INLINE_VISIBILITY
+ ~unordered_multiset() {
+ static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), "");
+ }
+
_LIBCPP_INLINE_VISIBILITY
unordered_multiset& operator=(const unordered_multiset& __u)
{
diff --git a/libcxx/test/libcxx/containers/associative/non_const_comparator.fail.cpp b/libcxx/test/libcxx/containers/associative/non_const_comparator.fail.cpp
index 432e7c08d14..9a9a1c6d6d1 100644
--- a/libcxx/test/libcxx/containers/associative/non_const_comparator.fail.cpp
+++ b/libcxx/test/libcxx/containers/associative/non_const_comparator.fail.cpp
@@ -26,8 +26,8 @@ int main(int, char**) {
static_assert(!std::__invokable<BadCompare const&, int const&, int const&>::value, "");
static_assert(std::__invokable<BadCompare&, int const&, int const&>::value, "");
- // expected-warning@set:* 2 {{the specified comparator type does not provide a const call operator}}
- // expected-warning@map:* 2 {{the specified comparator type does not provide a const call operator}}
+ // expected-warning@set:* 2 {{the specified comparator type does not provide a viable const call operator}}
+ // expected-warning@map:* 2 {{the specified comparator type does not provide a viable const call operator}}
{
using C = std::set<int, BadCompare>;
C s;
diff --git a/libcxx/test/libcxx/containers/associative/non_const_comparator.pass.cpp b/libcxx/test/libcxx/containers/associative/non_const_comparator.pass.cpp
new file mode 100644
index 00000000000..83a1cee1127
--- /dev/null
+++ b/libcxx/test/libcxx/containers/associative/non_const_comparator.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+// REQUIRES: verify-support
+
+// Test that libc++ does not generate a warning diagnostic about the comparator
+// too early for containers of incomplete types.
+//
+// See PR41360.
+
+#include <set>
+#include <map>
+#include <functional>
+
+
+template <template <typename ...> class Container>
+void test_set() {
+ struct KeyBase { };
+ struct KeyDerived; // derives from KeyBase, but incomplete at this point
+
+ // Name the type but don't instantiate it.
+ using C = Container<KeyDerived*, std::less<KeyBase*>>;
+
+ // Instantiate it but don't ODR use any members.
+ typename C::value_type dummy; (void)dummy;
+
+ // Complete the types.
+ struct KeyDerived : KeyBase { };
+
+ C c; // ODR use it, which should be OK
+}
+
+template <template <typename ...> class Container>
+void test_map() {
+ struct Value { };
+ struct KeyBase { };
+ struct KeyDerived;
+ using C = Container<KeyDerived*, Value, std::less<KeyBase*>>;
+ typename C::value_type dummy; (void)dummy;
+ struct KeyDerived : KeyBase { };
+ C c;
+}
+
+int main(int, char**) {
+ // expected-no-diagnostics
+ test_set<std::set>();
+ test_set<std::multiset>();
+ test_map<std::map>();
+ test_map<std::multimap>();
+
+ return 0;
+}
diff --git a/libcxx/test/libcxx/containers/unord/non_const_comparator.fail.cpp b/libcxx/test/libcxx/containers/unord/non_const_comparator.fail.cpp
index 8fa500e45e4..c1027adbc8e 100644
--- a/libcxx/test/libcxx/containers/unord/non_const_comparator.fail.cpp
+++ b/libcxx/test/libcxx/containers/unord/non_const_comparator.fail.cpp
@@ -33,10 +33,10 @@ int main(int, char**) {
static_assert(!std::__invokable<BadEqual const&, int const&, int const&>::value, "");
static_assert(std::__invokable<BadEqual&, int const&, int const&>::value, "");
- // expected-warning@unordered_set:* 2 {{the specified comparator type does not provide a const call operator}}
- // expected-warning@unordered_map:* 2 {{the specified comparator type does not provide a const call operator}}
- // expected-warning@unordered_set:* 2 {{the specified hash functor does not provide a const call operator}}
- // expected-warning@unordered_map:* 2 {{the specified hash functor does not provide a const call operator}}
+ // expected-warning@unordered_set:* 2 {{the specified comparator type does not provide a viable const call operator}}
+ // expected-warning@unordered_map:* 2 {{the specified comparator type does not provide a viable const call operator}}
+ // expected-warning@unordered_set:* 2 {{the specified hash functor does not provide a viable const call operator}}
+ // expected-warning@unordered_map:* 2 {{the specified hash functor does not provide a viable const call operator}}
{
using C = std::unordered_set<int, BadHash, BadEqual>;
diff --git a/libcxx/test/libcxx/containers/unord/non_const_comparator.pass.cpp b/libcxx/test/libcxx/containers/unord/non_const_comparator.pass.cpp
new file mode 100644
index 00000000000..e2eeda53964
--- /dev/null
+++ b/libcxx/test/libcxx/containers/unord/non_const_comparator.pass.cpp
@@ -0,0 +1,58 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++98, c++03
+// REQUIRES: verify-support
+
+// Test that libc++ does not generate a warning diagnostic about the comparator
+// or the hasher too early for containers of incomplete types.
+//
+// See PR41360.
+
+#include <unordered_set>
+#include <unordered_map>
+#include <functional>
+
+
+template <template <typename ...> class Container>
+void test_set() {
+ struct KeyBase { };
+ struct KeyDerived; // derives from KeyBase, but incomplete at this point
+
+ // Name the type but don't instantiate it.
+ using C = Container<KeyDerived*, std::hash<KeyBase*>, std::equal_to<KeyBase*>>;
+
+ // Instantiate it but don't ODR use any members.
+ typename C::value_type dummy; (void)dummy;
+
+ // Complete the types.
+ struct KeyDerived : KeyBase { };
+
+ C c; // ODR use it, which should be OK
+}
+
+template <template <typename ...> class Container>
+void test_map() {
+ struct Value { };
+ struct KeyBase { };
+ struct KeyDerived;
+ using C = Container<KeyDerived*, Value, std::hash<KeyBase*>, std::equal_to<KeyBase*>>;
+ typename C::value_type dummy; (void)dummy;
+ struct KeyDerived : KeyBase { };
+ C c;
+}
+
+int main(int, char**) {
+ // expected-no-disagnostics
+ test_set<std::unordered_set>();
+ test_set<std::unordered_multiset>();
+ test_map<std::unordered_map>();
+ test_map<std::unordered_multimap>();
+
+ return 0;
+}
OpenPOWER on IntegriCloud