-
Notifications
You must be signed in to change notification settings - Fork 15.1k
[libcxx] improves diagnostics for containers with bad value types #106296
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 16 commits
5529499
1e6b81b
6c1e1e3
938299d
65346a3
472ffcf
7596a2e
25e999f
5a1b902
99a4509
45c85d6
dbf872a
e596964
e2d65c0
0487281
6d9ce9e
c49b7e8
eb2fd68
55a2e7a
d9043c4
ab41024
7bd03b3
ef9d9c3
f0f88d7
bb82c95
33a452d
6981a2a
9fe3f4a
b97942e
02ffa16
f75d1ae
20e0996
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| //===----------------------------------------------------------------------===// | ||
| // | ||
| // 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 | ||
| // | ||
| //===----------------------------------------------------------------------===// | ||
|
|
||
| #ifndef _LIBCPP___TYPE_TRAITS_DIAGNOSTIC_UTILITIES_H | ||
| #define _LIBCPP___TYPE_TRAITS_DIAGNOSTIC_UTILITIES_H | ||
|
|
||
| #include <__config> | ||
| #include <__type_traits/is_bounded_array.h> | ||
| #include <__type_traits/is_const.h> | ||
| #include <__type_traits/is_function.h> | ||
| #include <__type_traits/is_reference.h> | ||
| #include <__type_traits/is_unbounded_array.h> | ||
| #include <__type_traits/is_void.h> | ||
| #include <__type_traits/is_volatile.h> | ||
|
|
||
| #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) | ||
| # pragma GCC system_header | ||
| #endif | ||
|
|
||
| #if _LIBCPP_STD_VER >= 20 | ||
| # define _LIBCPP_CHECK_CONTAINER_VALUE_TYPE_IS_NOT_ARRAY_BEFORE_CXX20(_Template, _Tp, _Verb) | ||
| #else | ||
| # define _LIBCPP_CHECK_CONTAINER_VALUE_TYPE_IS_NOT_ARRAY_BEFORE_CXX20(_Template, _Tp, _Verb) \ | ||
| ; \ | ||
| static_assert(!__libcpp_is_bounded_array<_Tp>::value, "'std::" _Template "' cannot " _Verb " C arrays before C++20") | ||
| #endif | ||
|
|
||
| // Per https://eel.is/c++draft/containers#container.reqmts-64, allocator-aware containers must have an | ||
| // allocator that meets the Cpp17Allocator requirements (https://eel.is/c++draft/allocator.requirements). | ||
| // In particular, this means that containers should only accept non-cv-qualified object types, and | ||
| // types that are Cpp17Erasable. | ||
| #define _LIBCPP_CHECK_ALLOCATOR_VALUE_TYPE_REQUIREMENTS(_Template, _Tp, _Verb) \ | ||
| static_assert(!is_const<_Tp>::value, "'std::" _Template "' cannot " _Verb " const types"); \ | ||
| static_assert(!is_volatile<_Tp>::value, "'std::" _Template "' cannot " _Verb " volatile types"); \ | ||
| static_assert(!is_reference<_Tp>::value, "'std::" _Template "' cannot " _Verb " references"); \ | ||
| static_assert(!is_function<_Tp>::value, "'std::" _Template "' cannot " _Verb " functions") \ | ||
| _LIBCPP_CHECK_CONTAINER_VALUE_TYPE_IS_NOT_ARRAY_BEFORE_CXX20(_Template, _Tp, _Verb) | ||
|
|
||
| #define _LIBCPP_CHECK_CONTAINER_VALUE_TYPE_REQUIREMENTS(_Container, _Tp) \ | ||
| static_assert( \ | ||
| !__libcpp_is_unbounded_array<_Tp>::value, "'std::" _Container "' cannot hold C arrays of an unknown size"); \ | ||
|
||
| _LIBCPP_CHECK_ALLOCATOR_VALUE_TYPE_REQUIREMENTS(_Container, _Tp, "hold"); \ | ||
| static_assert(!is_void<_Tp>::value, "'std::" _Container "' cannot hold 'void'") | ||
|
|
||
| #endif // _LIBCPP___TYPE_TRAITS_DIAGNOSTIC_UTILITIES_H | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1505,7 +1505,17 @@ module std_private_memory_align [system] { header "__m | |
| module std_private_memory_aligned_alloc [system] { header "__memory/aligned_alloc.h" } | ||
| module std_private_memory_allocate_at_least [system] { header "__memory/allocate_at_least.h" } | ||
| module std_private_memory_allocation_guard [system] { header "__memory/allocation_guard.h" } | ||
| module std_private_memory_allocator [system] { header "__memory/allocator.h" } | ||
| module std_private_memory_allocator [system] { | ||
| header "__memory/allocator.h" | ||
| export std_private_type_traits_diagnostic_utilities | ||
| export std_private_type_traits_is_bounded_array | ||
| export std_private_type_traits_is_const | ||
| export std_private_type_traits_is_function | ||
| export std_private_type_traits_is_reference | ||
| export std_private_type_traits_is_unbounded_array | ||
| export std_private_type_traits_is_void | ||
| export std_private_type_traits_is_volatile | ||
|
||
| } | ||
| module std_private_memory_allocator_arg_t [system] { header "__memory/allocator_arg_t.h" } | ||
| module std_private_memory_allocator_destructor [system] { header "__memory/allocator_destructor.h" } | ||
| module std_private_memory_allocator_traits [system] { header "__memory/allocator_traits.h" } | ||
|
|
@@ -1897,6 +1907,10 @@ module std_private_type_traits_decay [system | |
| } | ||
| module std_private_type_traits_dependent_type [system] { header "__type_traits/dependent_type.h" } | ||
| module std_private_type_traits_desugars_to [system] { header "__type_traits/desugars_to.h" } | ||
| module std_private_type_traits_diagnostic_utilities [system] { | ||
| textual header "__type_traits/diagnostic_utilities.h" | ||
| export * | ||
| } | ||
| module std_private_type_traits_disjunction [system] { header "__type_traits/disjunction.h" } | ||
| module std_private_type_traits_enable_if [system] { header "__type_traits/enable_if.h" } | ||
| module std_private_type_traits_extent [system] { header "__type_traits/extent.h" } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -600,7 +600,12 @@ template <class Key, class T, class Hash, class Pred, class Alloc> | |
| #include <__ranges/concepts.h> | ||
| #include <__ranges/container_compatible_range.h> | ||
| #include <__ranges/from_range.h> | ||
| #include <__type_traits/diagnostic_utilities.h> | ||
| #include <__type_traits/is_allocator.h> | ||
| #include <__type_traits/is_array.h> | ||
| #include <__type_traits/is_function.h> | ||
| #include <__type_traits/is_reference.h> | ||
| #include <__type_traits/is_void.h> | ||
| #include <__type_traits/type_identity.h> | ||
| #include <__utility/forward.h> | ||
| #include <stdexcept> | ||
|
|
@@ -1024,6 +1029,15 @@ template <class _Key, | |
| class _Pred = equal_to<_Key>, | ||
| class _Alloc = allocator<pair<const _Key, _Tp> > > | ||
| class _LIBCPP_TEMPLATE_VIS unordered_map { | ||
| // TODO(#106635): replace with _LIBCPP_CHECK_CONTAINER_VALUE_TYPE_REQUIREMENTS | ||
| // Remember to remove relevant headers when this is completed. | ||
|
||
| static_assert(!is_reference<_Key>::value, "'std::unordered_map' cannot hold references"); | ||
| static_assert(!is_function<_Key>::value && !is_function<_Tp>::value, "'std::unordered_map' cannot hold functions"); | ||
| static_assert(!is_void<_Key>::value && !is_void<_Tp>::value, "'std::unordered_map' cannot hold 'void'"); | ||
| static_assert(!__libcpp_is_unbounded_array<_Key>::value, | ||
| "'std::unordered_map' cannot hold C arrays of an unknown size"); | ||
| static_assert(!is_array<_Key>::value, "'std::unordered_map' cannot hold C arrays before C++20"); | ||
|
|
||
| public: | ||
| // types | ||
| typedef _Key key_type; | ||
|
|
@@ -1827,6 +1841,16 @@ template <class _Key, | |
| class _Pred = equal_to<_Key>, | ||
| class _Alloc = allocator<pair<const _Key, _Tp> > > | ||
| class _LIBCPP_TEMPLATE_VIS unordered_multimap { | ||
| // TODO(#106635): replace with _LIBCPP_CHECK_CONTAINER_VALUE_TYPE_REQUIREMENTS | ||
| // Remember to remove relevant headers when this is completed. | ||
| static_assert(!is_reference<_Key>::value, "'std::unordered_multimap' cannot hold references"); | ||
| static_assert(!is_function<_Key>::value && !is_function<_Tp>::value, | ||
| "'std::unordered_multimap' cannot hold functions"); | ||
| static_assert(!is_void<_Key>::value && !is_void<_Tp>::value, "'std::unordered_multimap' cannot hold 'void'"); | ||
| static_assert(!__libcpp_is_unbounded_array<_Key>::value, | ||
| "'std::unordered_multimap' cannot hold C arrays of an unknown size"); | ||
| static_assert(!is_array<_Key>::value, "'std::unordered_multimap' cannot hold C arrays before C++20"); | ||
|
|
||
| public: | ||
| // types | ||
| typedef _Key key_type; | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.