Index: libcxx/trunk/include/__hash_table =================================================================== --- libcxx/trunk/include/__hash_table +++ libcxx/trunk/include/__hash_table @@ -875,9 +875,9 @@ template #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); Index: libcxx/trunk/include/__tree =================================================================== --- libcxx/trunk/include/__tree +++ libcxx/trunk/include/__tree @@ -971,7 +971,7 @@ template #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(); Index: libcxx/trunk/include/map =================================================================== --- libcxx/trunk/include/map +++ libcxx/trunk/include/map @@ -907,7 +907,6 @@ typedef value_type& reference; typedef const value_type& const_reference; - static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), ""); static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); @@ -1086,6 +1085,11 @@ } _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 @@ typedef value_type& reference; typedef const value_type& const_reference; - static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), ""); static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); @@ -1818,6 +1821,11 @@ } _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();} Index: libcxx/trunk/include/set =================================================================== --- libcxx/trunk/include/set +++ libcxx/trunk/include/set @@ -450,7 +450,6 @@ typedef value_type& reference; typedef const value_type& const_reference; - static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), ""); static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); @@ -597,6 +596,11 @@ #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 @@ typedef value_type& reference; typedef const value_type& const_reference; - static_assert(sizeof(__diagnose_non_const_comparator<_Key, _Compare>()), ""); static_assert((is_same::value), "Allocator::value_type must be same type as value_type"); @@ -1084,6 +1087,11 @@ #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();} Index: libcxx/trunk/include/unordered_map =================================================================== --- libcxx/trunk/include/unordered_map +++ libcxx/trunk/include/unordered_map @@ -852,7 +852,6 @@ typedef const value_type& const_reference; static_assert((is_same::value), "Invalid allocator::value_type"); - static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), ""); private: typedef __hash_value_type __value_type; @@ -963,7 +962,11 @@ 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 @@ typedef const value_type& const_reference; static_assert((is_same::value), "Invalid allocator::value_type"); - static_assert(sizeof(__diagnose_unordered_container_requirements<_Key, _Hash, _Pred>(0)), ""); private: typedef __hash_value_type __value_type; @@ -1787,7 +1789,11 @@ 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) { Index: libcxx/trunk/include/unordered_set =================================================================== --- libcxx/trunk/include/unordered_set +++ libcxx/trunk/include/unordered_set @@ -390,7 +390,6 @@ typedef const value_type& const_reference; static_assert((is_same::value), "Invalid allocator::value_type"); - static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), ""); private: typedef __hash_table __table; @@ -486,7 +485,11 @@ : 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 @@ typedef const value_type& const_reference; static_assert((is_same::value), "Invalid allocator::value_type"); - static_assert(sizeof(__diagnose_unordered_container_requirements<_Value, _Hash, _Pred>(0)), ""); private: typedef __hash_table __table; @@ -1084,7 +1086,11 @@ : 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) { Index: libcxx/trunk/test/libcxx/containers/associative/non_const_comparator.fail.cpp =================================================================== --- libcxx/trunk/test/libcxx/containers/associative/non_const_comparator.fail.cpp +++ libcxx/trunk/test/libcxx/containers/associative/non_const_comparator.fail.cpp @@ -26,8 +26,8 @@ static_assert(!std::__invokable::value, ""); static_assert(std::__invokable::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; C s; Index: libcxx/trunk/test/libcxx/containers/associative/non_const_comparator.pass.cpp =================================================================== --- libcxx/trunk/test/libcxx/containers/associative/non_const_comparator.pass.cpp +++ libcxx/trunk/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 +#include +#include + + +template