summaryrefslogtreecommitdiff
path: root/libstdc++-v3/include
diff options
context:
space:
mode:
authorJonathan Wakely <jwakely@redhat.com>2019-03-26 15:28:48 +0000
committerJonathan Wakely <redi@gcc.gnu.org>2019-03-26 15:28:48 +0000
commit7ac205673caade367552a567a98e27940f17cf35 (patch)
treeb21f5b213dae138df7639a8dd1f8820504c7d73f /libstdc++-v3/include
parent0da83a168fdca32fec2d6bf8280670d05514c4c4 (diff)
downloadgcc-7ac205673caade367552a567a98e27940f17cf35.tar.gz
PR libstdc++/85965 delay static assertions until types are complete
The static assertions added for PR libstdc++/48101 were at class scope and so were evaluated too eagerly, when it might not be possible to determine whether the function objects are invocable with the key types. The problematic cases are where the key type is not known to be convertible to the argument type(s) of the function object until later, after a type has been completed. Specifically, if the key type is a pointer to a derived class and the function object's argument type is a pointer to a base class, then the derived-to-base conversion is only valid once the derived type is complete. By moving the static assertions to the destructor they will only be evaluated when the destructor is instantiated, at which point whether the key type can be passed to the function object should be knowable. The ideal place to do the checks would be only when the function objects are actually invoked, but that would mean adding the checks in numerous places, so the destructor is used instead. The tests need to be adjusted because the "required from here" line is now the location of the destructor, not the point of instantiation in the test file. For the map and multimap tests which check two specializations, the dg-error matching the assertion text matches both cases. Also check the diagnostic output for the template arguments, to ensure both specializations trigger the assertion. PR libstdc++/85965 * include/bits/hashtable.h (_Hashtable): Move static assertions to destructor so they are not evaluated until the _Key type is complete. * include/bits/stl_tree.h (_Rb_tree): Likewise. * testsuite/23_containers/set/85965.cc: New test. * testsuite/23_containers/unordered_set/85965.cc: New test. * testsuite/23_containers/map/48101_neg.cc: Replace "here" errors with regexp matching the corresponding _Rb_tree specialization. * testsuite/23_containers/multimap/48101_neg.cc: Likewise. * testsuite/23_containers/multiset/48101_neg.cc: Remove "here" error. * testsuite/23_containers/set/48101_neg.cc: Likewise. * testsuite/23_containers/unordered_map/48101_neg.cc: Likewise. * testsuite/23_containers/unordered_multimap/48101_neg.cc: Likewise. * testsuite/23_containers/unordered_multiset/48101_neg.cc: Likewise. * testsuite/23_containers/unordered_set/48101_neg.cc: Likewise. From-SVN: r269949
Diffstat (limited to 'libstdc++-v3/include')
-rw-r--r--libstdc++-v3/include/bits/hashtable.h11
-rw-r--r--libstdc++-v3/include/bits/stl_tree.h27
2 files changed, 21 insertions, 17 deletions
diff --git a/libstdc++-v3/include/bits/hashtable.h b/libstdc++-v3/include/bits/hashtable.h
index 4737247994a..da78c68434f 100644
--- a/libstdc++-v3/include/bits/hashtable.h
+++ b/libstdc++-v3/include/bits/hashtable.h
@@ -192,11 +192,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
static_assert(is_same<typename _Alloc::value_type, _Value>{},
"unordered container must have the same value_type as its allocator");
#endif
- static_assert(__is_invocable<const _H1&, const _Key&>{},
- "hash function must be invocable with an argument of key type");
- static_assert(__is_invocable<const _Equal&, const _Key&, const _Key&>{},
- "key equality predicate must be invocable with two arguments of "
- "key type");
using __traits_type = _Traits;
using __hash_cached = typename __traits_type::__hash_cached;
@@ -1356,6 +1351,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
clear();
_M_deallocate_buckets();
+
+ static_assert(__is_invocable<const _H1&, const _Key&>{},
+ "hash function must be invocable with an argument of key type");
+ static_assert(__is_invocable<const _Equal&, const _Key&, const _Key&>{},
+ "key equality predicate must be invocable with two arguments of "
+ "key type");
}
template<typename _Key, typename _Value,
diff --git a/libstdc++-v3/include/bits/stl_tree.h b/libstdc++-v3/include/bits/stl_tree.h
index 47ae0ae9531..7545ade3f7b 100644
--- a/libstdc++-v3/include/bits/stl_tree.h
+++ b/libstdc++-v3/include/bits/stl_tree.h
@@ -440,17 +440,6 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
typedef __gnu_cxx::__alloc_traits<_Node_allocator> _Alloc_traits;
-#if __cplusplus >= 201103L
- static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},
- "comparison object must be invocable with two arguments of key type");
-# if __cplusplus >= 201703L
- // _GLIBCXX_RESOLVE_LIB_DEFECTS
- // 2542. Missing const requirements for associative containers
- static_assert(is_invocable_v<const _Compare&, const _Key&, const _Key&>,
- "comparison object must be invocable as const");
-# endif // C++17
-#endif // C++11
-
protected:
typedef _Rb_tree_node_base* _Base_ptr;
typedef const _Rb_tree_node_base* _Const_Base_ptr;
@@ -985,7 +974,21 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
~_Rb_tree() _GLIBCXX_NOEXCEPT
- { _M_erase(_M_begin()); }
+ {
+ _M_erase(_M_begin());
+
+#if __cplusplus >= 201103L
+ static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{},
+ "comparison object must be invocable "
+ "with two arguments of key type");
+# if __cplusplus >= 201703L
+ // _GLIBCXX_RESOLVE_LIB_DEFECTS
+ // 2542. Missing const requirements for associative containers
+ static_assert(is_invocable_v<const _Compare&, const _Key&, const _Key&>,
+ "comparison object must be invocable as const");
+# endif // C++17
+#endif // C++11
+ }
_Rb_tree&
operator=(const _Rb_tree& __x);