diff --git a/libcxx/include/CMakeLists.txt b/libcxx/include/CMakeLists.txt index f2f1ec50d5b75..db918a16e9a61 100644 --- a/libcxx/include/CMakeLists.txt +++ b/libcxx/include/CMakeLists.txt @@ -911,6 +911,7 @@ set(files __utility/cmp.h __utility/convert_to_integral.h __utility/declval.h + __utility/default_three_way_comparator.h __utility/element_count.h __utility/empty.h __utility/exception_guard.h @@ -921,6 +922,7 @@ set(files __utility/integer_sequence.h __utility/is_pointer_in_range.h __utility/is_valid_range.h + __utility/lazy_synth_three_way_comparator.h __utility/move.h __utility/no_destroy.h __utility/pair.h diff --git a/libcxx/include/__config b/libcxx/include/__config index c197851f1c8fe..23b9123fa6917 100644 --- a/libcxx/include/__config +++ b/libcxx/include/__config @@ -1156,6 +1156,13 @@ typedef __char32_t char32_t; # define _LIBCPP_LIFETIMEBOUND # endif +// This is to work around https://llvm.org/PR156809 +# ifndef _LIBCPP_CXX03_LANG +# define _LIBCPP_CTOR_LIFETIMEBOUND _LIBCPP_LIFETIMEBOUND +# else +# define _LIBCPP_CTOR_LIFETIMEBOUND +# endif + # if __has_cpp_attribute(_Clang::__noescape__) # define _LIBCPP_NOESCAPE [[_Clang::__noescape__]] # else diff --git a/libcxx/include/__tree b/libcxx/include/__tree index c5f52f404eff3..8b4bda8c7a3ee 100644 --- a/libcxx/include/__tree +++ b/libcxx/include/__tree @@ -34,6 +34,7 @@ #include <__type_traits/is_swappable.h> #include <__type_traits/remove_const.h> #include <__utility/forward.h> +#include <__utility/lazy_synth_three_way_comparator.h> #include <__utility/move.h> #include <__utility/pair.h> #include <__utility/swap.h> @@ -1749,14 +1750,18 @@ __tree<_Tp, _Compare, _Allocator>::__find_equal(const _Key& __v) { } __node_base_pointer* __node_ptr = __root_ptr(); + auto __comp = __lazy_synth_three_way_comparator<_Compare, _Key, value_type>(value_comp()); + while (true) { - if (value_comp()(__v, __nd->__get_value())) { + auto __comp_res = __comp(__v, __nd->__get_value()); + + if (__comp_res.__less()) { if (__nd->__left_ == nullptr) return _Pair(static_cast<__end_node_pointer>(__nd), __nd->__left_); __node_ptr = std::addressof(__nd->__left_); __nd = static_cast<__node_pointer>(__nd->__left_); - } else if (value_comp()(__nd->__get_value(), __v)) { + } else if (__comp_res.__greater()) { if (__nd->__right_ == nullptr) return _Pair(static_cast<__end_node_pointer>(__nd), __nd->__right_); @@ -2065,10 +2070,12 @@ template typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__count_unique(const _Key& __k) const { __node_pointer __rt = __root(); + auto __comp = __lazy_synth_three_way_comparator(value_comp()); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__get_value())) { + auto __comp_res = __comp(__k, __rt->__get_value()); + if (__comp_res.__less()) { __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__get_value(), __k)) + } else if (__comp_res.__greater()) __rt = static_cast<__node_pointer>(__rt->__right_); else return 1; @@ -2082,11 +2089,13 @@ typename __tree<_Tp, _Compare, _Allocator>::size_type __tree<_Tp, _Compare, _Allocator>::__count_multi(const _Key& __k) const { __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); + auto __comp = __lazy_synth_three_way_comparator(value_comp()); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__get_value())) { + auto __comp_res = __comp(__k, __rt->__get_value()); + if (__comp_res.__less()) { __result = static_cast<__end_node_pointer>(__rt); __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__get_value(), __k)) + } else if (__comp_res.__greater()) __rt = static_cast<__node_pointer>(__rt->__right_); else return std::distance( @@ -2159,11 +2168,13 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) { using _Pp = pair; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); + auto __comp = __lazy_synth_three_way_comparator(value_comp()); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__get_value())) { + auto __comp_res = __comp(__k, __rt->__get_value()); + if (__comp_res.__less()) { __result = static_cast<__end_node_pointer>(__rt); __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__get_value(), __k)) + } else if (__comp_res.__greater()) __rt = static_cast<__node_pointer>(__rt->__right_); else return _Pp(iterator(__rt), @@ -2181,11 +2192,13 @@ __tree<_Tp, _Compare, _Allocator>::__equal_range_unique(const _Key& __k) const { using _Pp = pair; __end_node_pointer __result = __end_node(); __node_pointer __rt = __root(); + auto __comp = __lazy_synth_three_way_comparator(value_comp()); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__get_value())) { + auto __comp_res = __comp(__k, __rt->__get_value()); + if (__comp_res.__less()) { __result = static_cast<__end_node_pointer>(__rt); __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__get_value(), __k)) + } else if (__comp_res.__greater()) __rt = static_cast<__node_pointer>(__rt->__right_); else return _Pp( @@ -2202,12 +2215,14 @@ pair::iterator, typename __tree<_Tp, __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) { using _Pp = pair; __end_node_pointer __result = __end_node(); - __node_pointer __rt = __root(); + __node_pointer __rt = __root(); + auto __comp = __lazy_synth_three_way_comparator(value_comp()); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__get_value())) { + auto __comp_res = __comp(__k, __rt->__get_value()); + if (__comp_res.__less()) { __result = static_cast<__end_node_pointer>(__rt); __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__get_value(), __k)) + } else if (__comp_res.__greater()) __rt = static_cast<__node_pointer>(__rt->__right_); else return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)), @@ -2223,12 +2238,14 @@ pair::const_iterator, __tree<_Tp, _Compare, _Allocator>::__equal_range_multi(const _Key& __k) const { using _Pp = pair; __end_node_pointer __result = __end_node(); - __node_pointer __rt = __root(); + __node_pointer __rt = __root(); + auto __comp = __lazy_synth_three_way_comparator(value_comp()); while (__rt != nullptr) { - if (value_comp()(__k, __rt->__get_value())) { + auto __comp_res = __comp(__k, __rt->__get_value()); + if (__comp_res.__less()) { __result = static_cast<__end_node_pointer>(__rt); __rt = static_cast<__node_pointer>(__rt->__left_); - } else if (value_comp()(__rt->__get_value(), __k)) + } else if (__comp_res.__greater()) __rt = static_cast<__node_pointer>(__rt->__right_); else return _Pp(__lower_bound(__k, static_cast<__node_pointer>(__rt->__left_), static_cast<__end_node_pointer>(__rt)), diff --git a/libcxx/include/__utility/default_three_way_comparator.h b/libcxx/include/__utility/default_three_way_comparator.h new file mode 100644 index 0000000000000..ce423c6ce98e4 --- /dev/null +++ b/libcxx/include/__utility/default_three_way_comparator.h @@ -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___UTILITY_DEFAULT_THREE_WAY_COMPARATOR_H +#define _LIBCPP___UTILITY_DEFAULT_THREE_WAY_COMPARATOR_H + +#include <__config> +#include <__type_traits/enable_if.h> +#include <__type_traits/is_arithmetic.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +// This struct can be specialized to provide a three way comparator between _LHS and _RHS. +// The return value should be +// - less than zero if (lhs_val < rhs_val) +// - greater than zero if (rhs_val < lhs_val) +// - zero otherwise +template +struct __default_three_way_comparator; + +template +struct __default_three_way_comparator<_Tp, _Tp, __enable_if_t::value> > { + _LIBCPP_HIDE_FROM_ABI static int operator()(_Tp __lhs, _Tp __rhs) { + if (__lhs < __rhs) + return -1; + if (__lhs > __rhs) + return 1; + return 0; + } +}; + +template +inline const bool __has_default_three_way_comparator_v = false; + +template +inline const bool + __has_default_three_way_comparator_v< _LHS, _RHS, sizeof(__default_three_way_comparator<_LHS, _RHS>) >= 0> = true; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___UTILITY_DEFAULT_THREE_WAY_COMPARATOR_H diff --git a/libcxx/include/__utility/lazy_synth_three_way_comparator.h b/libcxx/include/__utility/lazy_synth_three_way_comparator.h new file mode 100644 index 0000000000000..ca98845f04191 --- /dev/null +++ b/libcxx/include/__utility/lazy_synth_three_way_comparator.h @@ -0,0 +1,90 @@ +//===----------------------------------------------------------------------===// +// +// 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___UTILITY_LAZY_SYNTH_THREE_WAY_COMPARATOR_H +#define _LIBCPP___UTILITY_LAZY_SYNTH_THREE_WAY_COMPARATOR_H + +#include <__config> +#include <__type_traits/desugars_to.h> +#include <__type_traits/enable_if.h> +#include <__utility/default_three_way_comparator.h> + +#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) +# pragma GCC system_header +#endif + +// This file implements a __lazy_synth_three_way_comparator, which tries to build an efficient three way comparison from +// a binary comparator. That is done in multiple steps: +// 1) Check whether the comparator desugars to a less-than operator +// If that is the case, check whether there exists a specialization of `__default_three_way_comparator`, which +// can be specialized to implement a three way comparator for the specific types. +// 2) Fall back to doing a lazy less than/greater than comparison + +_LIBCPP_BEGIN_NAMESPACE_STD + +template +struct __lazy_compare_result { + const _Comparator& __comp_; + const _LHS& __lhs_; + const _RHS& __rhs_; + + _LIBCPP_HIDE_FROM_ABI + __lazy_compare_result(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp, + _LIBCPP_CTOR_LIFETIMEBOUND const _LHS& __lhs, + _LIBCPP_CTOR_LIFETIMEBOUND const _RHS& __rhs) + : __comp_(__comp), __lhs_(__lhs), __rhs_(__rhs) {} + + _LIBCPP_HIDE_FROM_ABI bool __less() const { return __comp_(__lhs_, __rhs_); } + _LIBCPP_HIDE_FROM_ABI bool __greater() const { return __comp_(__rhs_, __lhs_); } +}; + +// This class provides three way comparison between _LHS and _RHS as efficiently as possible. This can be specialized if +// a comparator only compares part of the object, potentially allowing an efficient three way comparison between the +// subobjects. The specialization should use the __lazy_synth_three_way_comparator for the subobjects to achieve this. +template +struct __lazy_synth_three_way_comparator { + const _Comparator& __comp_; + + _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator& __comp) + : __comp_(__comp) {} + + _LIBCPP_HIDE_FROM_ABI __lazy_compare_result<_Comparator, _LHS, _RHS> + operator()(_LIBCPP_LIFETIMEBOUND const _LHS& __lhs, _LIBCPP_LIFETIMEBOUND const _RHS& __rhs) const { + return __lazy_compare_result<_Comparator, _LHS, _RHS>(__comp_, __lhs, __rhs); + } +}; + +struct __eager_compare_result { + int __res_; + + _LIBCPP_HIDE_FROM_ABI explicit __eager_compare_result(int __res) : __res_(__res) {} + + _LIBCPP_HIDE_FROM_ABI bool __less() const { return __res_ < 0; } + _LIBCPP_HIDE_FROM_ABI bool __greater() const { return __res_ > 0; } +}; + +template +struct __lazy_synth_three_way_comparator<_Comparator, + _LHS, + _RHS, + __enable_if_t<__desugars_to_v<__less_tag, _Comparator, _LHS, _RHS> && + __has_default_three_way_comparator_v<_LHS, _RHS> > > { + // This lifetimebound annotation is technically incorrect, but other specializations actually capture the lifetime of + // the comparator. + _LIBCPP_HIDE_FROM_ABI __lazy_synth_three_way_comparator(_LIBCPP_CTOR_LIFETIMEBOUND const _Comparator&) {} + + // Same comment as above. + _LIBCPP_HIDE_FROM_ABI static __eager_compare_result + operator()(_LIBCPP_LIFETIMEBOUND const _LHS& __lhs, _LIBCPP_LIFETIMEBOUND const _RHS& __rhs) { + return __eager_compare_result(__default_three_way_comparator<_LHS, _RHS>()(__lhs, __rhs)); + } +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif // _LIBCPP___UTILITY_LAZY_SYNTH_THREE_WAY_COMPARATOR_H diff --git a/libcxx/include/map b/libcxx/include/map index a734df671fd6f..f428c781e5036 100644 --- a/libcxx/include/map +++ b/libcxx/include/map @@ -603,6 +603,7 @@ erase_if(multimap& c, Predicate pred); // C++20 # include <__type_traits/remove_const.h> # include <__type_traits/type_identity.h> # include <__utility/forward.h> +# include <__utility/lazy_synth_three_way_comparator.h> # include <__utility/pair.h> # include <__utility/piecewise_construct.h> # include <__utility/swap.h> @@ -702,6 +703,50 @@ public: # endif }; +# if _LIBCPP_STD_VER >= 14 +template +struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _Compare>, _MapValueT, _MapValueT> { + __lazy_synth_three_way_comparator<_Compare, _Key, _Key> __comp_; + + __lazy_synth_three_way_comparator( + _LIBCPP_CTOR_LIFETIMEBOUND const __map_value_compare<_Key, _MapValueT, _Compare>& __comp) + : __comp_(__comp.key_comp()) {} + + _LIBCPP_HIDE_FROM_ABI auto + operator()(_LIBCPP_LIFETIMEBOUND const _MapValueT& __lhs, _LIBCPP_LIFETIMEBOUND const _MapValueT& __rhs) const { + return __comp_(__lhs.first, __rhs.first); + } +}; + +template +struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _Compare>, _TransparentKey, _MapValueT> { + __lazy_synth_three_way_comparator<_Compare, _TransparentKey, _Key> __comp_; + + __lazy_synth_three_way_comparator( + _LIBCPP_CTOR_LIFETIMEBOUND const __map_value_compare<_Key, _MapValueT, _Compare>& __comp) + : __comp_(__comp.key_comp()) {} + + _LIBCPP_HIDE_FROM_ABI auto + operator()(_LIBCPP_LIFETIMEBOUND const _TransparentKey& __lhs, _LIBCPP_LIFETIMEBOUND const _MapValueT& __rhs) const { + return __comp_(__lhs, __rhs.first); + } +}; + +template +struct __lazy_synth_three_way_comparator<__map_value_compare<_Key, _MapValueT, _Compare>, _MapValueT, _TransparentKey> { + __lazy_synth_three_way_comparator<_Compare, _Key, _TransparentKey> __comp_; + + __lazy_synth_three_way_comparator( + _LIBCPP_CTOR_LIFETIMEBOUND const __map_value_compare<_Key, _MapValueT, _Compare>& __comp) + : __comp_(__comp.key_comp()) {} + + _LIBCPP_HIDE_FROM_ABI auto + operator()(_LIBCPP_LIFETIMEBOUND const _MapValueT& __lhs, _LIBCPP_LIFETIMEBOUND const _TransparentKey& __rhs) const { + return __comp_(__lhs.first, __rhs); + } +}; +# endif // _LIBCPP_STD_VER >= 14 + template inline _LIBCPP_HIDE_FROM_ABI void swap(__map_value_compare<_Key, _CP, _Compare, __b>& __x, __map_value_compare<_Key, _CP, _Compare, __b>& __y) diff --git a/libcxx/include/module.modulemap.in b/libcxx/include/module.modulemap.in index 7ac7b510f826a..63cf8e847751f 100644 --- a/libcxx/include/module.modulemap.in +++ b/libcxx/include/module.modulemap.in @@ -2144,41 +2144,43 @@ module std [system] { } module utility { - module as_const { header "__utility/as_const.h" } - module as_lvalue { header "__utility/as_lvalue.h" } - module auto_cast { + module as_const { header "__utility/as_const.h" } + module as_lvalue { header "__utility/as_lvalue.h" } + module auto_cast { header "__utility/auto_cast.h" export std_core.type_traits.decay // the macro expansion uses that trait } - module cmp { header "__utility/cmp.h" } - module convert_to_integral { header "__utility/convert_to_integral.h" } - module element_count { header "__utility/element_count.h" } - module exception_guard { header "__utility/exception_guard.h" } - module exchange { header "__utility/exchange.h" } - module forward_like { header "__utility/forward_like.h" } - module in_place { + module cmp { header "__utility/cmp.h" } + module convert_to_integral { header "__utility/convert_to_integral.h" } + module default_three_way_comparator { header "__utility/default_three_way_comparator.h" } + module element_count { header "__utility/element_count.h" } + module exception_guard { header "__utility/exception_guard.h" } + module exchange { header "__utility/exchange.h" } + module forward_like { header "__utility/forward_like.h" } + module in_place { header "__utility/in_place.h" export std_core.type_traits.integral_constant } - module integer_sequence { header "__utility/integer_sequence.h" } - module is_pointer_in_range { header "__utility/is_pointer_in_range.h" } - module is_valid_range { header "__utility/is_valid_range.h" } - module move { header "__utility/move.h" } - module no_destroy { header "__utility/no_destroy.h" } - module pair { + module integer_sequence { header "__utility/integer_sequence.h" } + module is_pointer_in_range { header "__utility/is_pointer_in_range.h" } + module is_valid_range { header "__utility/is_valid_range.h" } + module lazy_synth_three_way_comparator { header "__utility/lazy_synth_three_way_comparator.h" } + module move { header "__utility/move.h" } + module no_destroy { header "__utility/no_destroy.h" } + module pair { header "__utility/pair.h" export std.utility.piecewise_construct } - module piecewise_construct { header "__utility/piecewise_construct.h" } - module priority_tag { header "__utility/priority_tag.h" } - module private_constructor_tag { header "__utility/private_constructor_tag.h" } - module rel_ops { header "__utility/rel_ops.h" } - module scope_guard { header "__utility/scope_guard.h" } - module small_buffer { header "__utility/small_buffer.h" } - module swap { header "__utility/swap.h" } - module to_underlying { header "__utility/to_underlying.h" } - module try_key_extraction { header "__utility/try_key_extraction.h" } - module unreachable { header "__utility/unreachable.h" } + module piecewise_construct { header "__utility/piecewise_construct.h" } + module priority_tag { header "__utility/priority_tag.h" } + module private_constructor_tag { header "__utility/private_constructor_tag.h" } + module rel_ops { header "__utility/rel_ops.h" } + module scope_guard { header "__utility/scope_guard.h" } + module small_buffer { header "__utility/small_buffer.h" } + module swap { header "__utility/swap.h" } + module to_underlying { header "__utility/to_underlying.h" } + module try_key_extraction { header "__utility/try_key_extraction.h" } + module unreachable { header "__utility/unreachable.h" } header "utility" export * diff --git a/libcxx/include/string b/libcxx/include/string index 19a538d96e85c..0abdfebcb863f 100644 --- a/libcxx/include/string +++ b/libcxx/include/string @@ -639,13 +639,12 @@ basic_string operator""s( const char32_t *str, size_t len ); # include <__type_traits/remove_cvref.h> # include <__type_traits/void_t.h> # include <__utility/auto_cast.h> -# include <__utility/declval.h> +# include <__utility/default_three_way_comparator.h> # include <__utility/forward.h> # include <__utility/is_pointer_in_range.h> # include <__utility/move.h> # include <__utility/scope_guard.h> # include <__utility/swap.h> -# include <__utility/unreachable.h> # include # include // EOF # include @@ -966,7 +965,7 @@ private: std::__wrap_iter(__get_pointer() + size())); # else return const_iterator(__p); -# endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING +# endif // _LIBCPP_ABI_BOUNDED_ITERATORS_IN_STRING } public: @@ -2522,6 +2521,19 @@ _LIBCPP_STRING_V1_EXTERN_TEMPLATE_LIST(_LIBCPP_DECLARE, wchar_t) # endif # undef _LIBCPP_DECLARE +template +struct __default_three_way_comparator, basic_string<_CharT, _Traits, _Alloc> > { + using __string_t _LIBCPP_NODEBUG = basic_string<_CharT, _Traits, _Alloc>; + + _LIBCPP_HIDE_FROM_ABI static int operator()(const __string_t& __lhs, const __string_t& __rhs) { + auto __min_len = std::min(__lhs.size(), __rhs.size()); + auto __ret = _Traits::compare(__lhs.data(), __rhs.data(), __min_len); + if (__ret == 0) + return __lhs.size() == __rhs.size() ? 0 : __lhs.size() < __rhs.size() ? -1 : 1; + return __ret; + } +}; + # if _LIBCPP_STD_VER >= 17 template , diff --git a/libcxx/test/std/experimental/utilities/meta/meta.detect/detected_t.pass.cpp b/libcxx/test/std/experimental/utilities/meta/meta.detect/detected_t.pass.cpp index b64b86f1b05ea..4f9f26cb4587b 100644 --- a/libcxx/test/std/experimental/utilities/meta/meta.detect/detected_t.pass.cpp +++ b/libcxx/test/std/experimental/utilities/meta/meta.detect/detected_t.pass.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "test_macros.h" diff --git a/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected.pass.cpp b/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected.pass.cpp index 4a977917f1ec6..6960c71abb33e 100644 --- a/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected.pass.cpp +++ b/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected.pass.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "test_macros.h" diff --git a/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected_convertible.pass.cpp b/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected_convertible.pass.cpp index 6906461f1edcc..de1d223b91897 100644 --- a/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected_convertible.pass.cpp +++ b/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected_convertible.pass.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "test_macros.h" diff --git a/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected_exact.pass.cpp b/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected_exact.pass.cpp index 500187e86dd08..2161c11e7d2c2 100644 --- a/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected_exact.pass.cpp +++ b/libcxx/test/std/experimental/utilities/meta/meta.detect/is_detected_exact.pass.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "test_macros.h" diff --git a/libcxx/test/std/input.output/iostreams.base/fpos/fpos.operations/fpos.pass.cpp b/libcxx/test/std/input.output/iostreams.base/fpos/fpos.operations/fpos.pass.cpp index c3d3e0cfc411b..8e2f84fba0def 100644 --- a/libcxx/test/std/input.output/iostreams.base/fpos/fpos.operations/fpos.pass.cpp +++ b/libcxx/test/std/input.output/iostreams.base/fpos/fpos.operations/fpos.pass.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "test_macros.h" diff --git a/libcxx/test/support/any_helpers.h b/libcxx/test/support/any_helpers.h index 0e5563142d58a..66f393b108cc5 100644 --- a/libcxx/test/support/any_helpers.h +++ b/libcxx/test/support/any_helpers.h @@ -9,9 +9,10 @@ #ifndef ANY_HELPERS_H #define ANY_HELPERS_H +#include #include #include -#include +#include namespace std { namespace experimental {} }