From 36fcea21f4e422e914e721f6fcd5e119c503fca6 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Wed, 3 Aug 2022 13:57:51 -0700 Subject: [PATCH 01/12] make _Get_unwrapped noexcept when possible additionally, add conditional noexcepts to a lot of `_Unwrapped()`s --- stl/inc/iterator | 13 ++++++++++--- stl/inc/ranges | 10 ++++++++-- stl/inc/xutility | 17 +++++++++++++---- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/stl/inc/iterator b/stl/inc/iterator index f719511760a..38b3ebc8d28 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -1371,12 +1371,19 @@ public: using _Prevent_inheriting_unwrap = counted_iterator; - _NODISCARD constexpr counted_iterator<_Unwrapped_t> - _Unwrapped() const& requires _Unwrappable_v { + // clang-format off + _NODISCARD constexpr counted_iterator<_Unwrapped_t> _Unwrapped() const& + noexcept(noexcept(counted_iterator<_Unwrapped_t>{_Current._Unwrapped(), _Length}) + requires _Unwrappable_v { + // clang-format on return counted_iterator<_Unwrapped_t>{_Current._Unwrapped(), _Length}; } - _NODISCARD constexpr counted_iterator<_Unwrapped_t<_Iter>> _Unwrapped() && requires _Unwrappable_v<_Iter> { + // clang-format off + _NODISCARD constexpr counted_iterator<_Unwrapped_t<_Iter>> _Unwrapped() && + noexcept(noexcept(counted_iterator<_Unwrapped_t<_Iter>>{_STD move(_Current)._Unwrapped(), _Length}) + requires _Unwrappable_v<_Iter> { + // clang-format on return counted_iterator<_Unwrapped_t<_Iter>>{_STD move(_Current)._Unwrapped(), _Length}; } diff --git a/stl/inc/ranges b/stl/inc/ranges index eda6d3e0b15..c6fefc7d056 100644 --- a/stl/inc/ranges +++ b/stl/inc/ranges @@ -2388,12 +2388,15 @@ namespace ranges { // clang-format off _NODISCARD constexpr auto _Unwrapped() const& + noexcept(noexcept(_Sentinel<_Const, false>{_Get_unwrapped(_Last)})) requires _Wrapped && _Unwrappable_v&> { // clang-format on return _Sentinel<_Const, false>{_Get_unwrapped(_Last)}; } // clang-format off - _NODISCARD constexpr auto _Unwrapped() && requires _Wrapped && _Unwrappable_v> { + _NODISCARD constexpr auto _Unwrapped() && + noexcept(noexcept(_Sentinel<_Const, false>{_Get_unwrapped(_STD move(_Last))})) + requires _Wrapped && _Unwrappable_v> { // clang-format on return _Sentinel<_Const, false>{_Get_unwrapped(_STD move(_Last))}; } @@ -2644,12 +2647,15 @@ namespace ranges { // clang-format off _NODISCARD constexpr auto _Unwrapped() const& + noexcept(noexcept(_Sentinel<_Const, false>{_Get_unwrapped(_Last), _Pred})) requires _Wrapped && _Unwrappable_v&> { // clang-format on return _Sentinel<_Const, false>{_Get_unwrapped(_Last), _Pred}; } // clang-format off - _NODISCARD constexpr auto _Unwrapped() && requires _Wrapped && _Unwrappable_v> { + _NODISCARD constexpr auto _Unwrapped() && + noexcept(noexcept(_Sentinel<_Const, false>{_Get_unwrapped(_STD move(_Last)), _Pred})) + requires _Wrapped && _Unwrappable_v> { // clang-format on return _Sentinel<_Const, false>{_Get_unwrapped(_STD move(_Last)), _Pred}; } diff --git a/stl/inc/xutility b/stl/inc/xutility index 30bcfb7b623..ac1f6aa2248 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -896,8 +896,14 @@ _INLINE_VAR constexpr bool _Unwrappable_v<_Iter, void_t&>()._Seek_to(_STD declval<_Iter>()._Unwrapped()))>> = _Allow_inheriting_unwrap_v<_Remove_cvref_t<_Iter>>; +template > +_INLINE_VAR constexpr bool _Is_nothrow_unwrappable_v = true; + +template +_INLINE_VAR constexpr bool _Is_nothrow_unwrappable_v<_Iter, true> = noexcept(declval<_Iter>()._Unwrapped()); + template -_NODISCARD constexpr decltype(auto) _Get_unwrapped(_Iter&& _It) { +_NODISCARD constexpr decltype(auto) _Get_unwrapped(_Iter&& _It) noexcept(_Is_nothrow_unwrappable_v<_Iter>) { // unwrap an iterator previously subjected to _Adl_verify_range or otherwise validated if constexpr (is_pointer_v>) { // special-case pointers and arrays return _It + 0; @@ -1347,7 +1353,8 @@ public: } template , int> = 0> - _NODISCARD constexpr reverse_iterator<_Unwrapped_t> _Unwrapped() const { + _NODISCARD constexpr reverse_iterator<_Unwrapped_t> _Unwrapped() const + noexcept(noexcept(static_cast>>(current._Unwrapped()))) { return static_cast>>(current._Unwrapped()); } @@ -3404,11 +3411,13 @@ public: } template , int> = 0> - _NODISCARD constexpr move_iterator<_Unwrapped_t> _Unwrapped() const& { + _NODISCARD constexpr move_iterator<_Unwrapped_t> _Unwrapped() const& noexcept( + noexcept(static_cast>>(_Current._Unwrapped()))) { return static_cast>>(_Current._Unwrapped()); } template , int> = 0> - _NODISCARD constexpr move_iterator<_Unwrapped_t<_Iter2>> _Unwrapped() && { + _NODISCARD constexpr move_iterator<_Unwrapped_t<_Iter2>> _Unwrapped() && noexcept( + noexcept(static_cast>>(_STD move(_Current)._Unwrapped()))) { return static_cast>>(_STD move(_Current)._Unwrapped()); } From 21962a40a6d2a392909ce93478d06e99d6b7344e Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Wed, 3 Aug 2022 15:38:30 -0700 Subject: [PATCH 02/12] fix build --- stl/inc/iterator | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/inc/iterator b/stl/inc/iterator index 38b3ebc8d28..8486fbee1d0 100644 --- a/stl/inc/iterator +++ b/stl/inc/iterator @@ -1373,7 +1373,7 @@ public: // clang-format off _NODISCARD constexpr counted_iterator<_Unwrapped_t> _Unwrapped() const& - noexcept(noexcept(counted_iterator<_Unwrapped_t>{_Current._Unwrapped(), _Length}) + noexcept(noexcept(counted_iterator<_Unwrapped_t>{_Current._Unwrapped(), _Length})) requires _Unwrappable_v { // clang-format on return counted_iterator<_Unwrapped_t>{_Current._Unwrapped(), _Length}; @@ -1381,7 +1381,7 @@ public: // clang-format off _NODISCARD constexpr counted_iterator<_Unwrapped_t<_Iter>> _Unwrapped() && - noexcept(noexcept(counted_iterator<_Unwrapped_t<_Iter>>{_STD move(_Current)._Unwrapped(), _Length}) + noexcept(noexcept(counted_iterator<_Unwrapped_t<_Iter>>{_STD move(_Current)._Unwrapped(), _Length})) requires _Unwrappable_v<_Iter> { // clang-format on return counted_iterator<_Unwrapped_t<_Iter>>{_STD move(_Current)._Unwrapped(), _Length}; From 10f28224359ec7056a804ea10e7c399a0591a134 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Fri, 5 Aug 2022 11:27:06 -0700 Subject: [PATCH 03/12] add _Unwrapped() && noexcept for path::iterator --- stl/inc/filesystem | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/stl/inc/filesystem b/stl/inc/filesystem index 0130975f0ef..8c8e04aa636 100644 --- a/stl/inc/filesystem +++ b/stl/inc/filesystem @@ -1455,8 +1455,10 @@ namespace filesystem { _Path_iterator(const _Base_iter& _Position_, const path* _Mypath_) noexcept : _Position(_Position_), _Element(), _Mypath(_Mypath_) {} - _Path_iterator(const _Base_iter& _Position_, wstring_view _Element_text, const path* _Mypath_) - : _Position(_Position_), _Element(_Element_text), _Mypath(_Mypath_) {} + _Path_iterator(const _Base_iter& _Position_, const path& _Element_, const path* _Mypath_) + : _Position(_Position_), _Element(_Element_), _Mypath(_Mypath_) {} + _Path_iterator(const _Base_iter& _Position_, path&& _Element_, const path* _Mypath_) + : _Position(_Position_), _Element(_STD move(_Element_)), _Mypath(_Mypath_) {} _Path_iterator(const _Path_iterator&) = default; _Path_iterator(_Path_iterator&&) = default; @@ -1600,8 +1602,13 @@ namespace filesystem { using _Prevent_inheriting_unwrap = _Path_iterator; template , int> = 0> - _NODISCARD _Path_iterator<_Unwrapped_t> _Unwrapped() const { - return {_Position._Unwrapped(), _Element.native(), _Mypath}; + _NODISCARD _Path_iterator<_Unwrapped_t> _Unwrapped() const& noexcept(false) { + return {_Position._Unwrapped(), _Element, _Mypath}; + } + template , int> = 0> + _NODISCARD _Path_iterator<_Unwrapped_t<_Iter2>> _Unwrapped() && noexcept { + _STL_INTERNAL_STATIC_ASSERT(noexcept(_Is_nothrow_unwrappable_v<_Iter2>)); + return {_Position._Unwrapped(), _STD move(_Element), _Mypath}; } static constexpr bool _Unwrap_when_unverified = _Do_unwrap_when_unverified_v<_Base_iter>; From 3e9c4749c56e827646f802364ef5bbcc02d5431e Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Fri, 5 Aug 2022 11:48:32 -0700 Subject: [PATCH 04/12] add tests --- tests/std/test.lst | 1 + .../GH_002989_nothrow_unwrappable/env.lst | 4 ++ .../GH_002989_nothrow_unwrappable/test.cpp | 37 +++++++++++++++++++ 3 files changed, 42 insertions(+) create mode 100644 tests/std/tests/GH_002989_nothrow_unwrappable/env.lst create mode 100644 tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp diff --git a/tests/std/test.lst b/tests/std/test.lst index 15b0eb8f766..4512b1ac36f 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -209,6 +209,7 @@ tests\GH_002711_Zc_alignedNew- tests\GH_002760_syncstream_memory_leak tests\GH_002769_handle_deque_block_pointers tests\GH_002789_Hash_vec_Tidy +tests\GH_002989_nothrow_unwrappable tests\LWG2597_complex_branch_cut tests\LWG3018_shared_ptr_function tests\LWG3121_constrained_tuple_forwarding_ctor diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/env.lst b/tests/std/tests/GH_002989_nothrow_unwrappable/env.lst new file mode 100644 index 00000000000..2de7aab2959 --- /dev/null +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_17_matrix.lst diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp new file mode 100644 index 00000000000..e49347806b0 --- /dev/null +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +using namespace std; + +#define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) + +template +void do_test() { + STATIC_ASSERT(_Is_nothrow_unwrappable_v); + STATIC_ASSERT(_Is_nothrow_unwrappable_v); + STATIC_ASSERT(noexcept(_Get_unwrapped(declval()))); + + STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); + STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); + STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); + STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); +} + +int main() { + do_test(); + do_test(); + do_test(); + + do_test::iterator>(); + do_test::const_iterator>(); + do_test::iterator>(); + do_test::const_iterator>(); + + do_test(); +} From e53cbba6fade16d15ab929c810a47208a8a2b4ef Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Fri, 5 Aug 2022 13:40:54 -0700 Subject: [PATCH 05/12] moar testing plus, fix reverse_iterator up with an `_Unwrapped() &&` --- stl/inc/xutility | 9 ++- .../GH_002989_nothrow_unwrappable/test.cpp | 68 ++++++++++++++----- 2 files changed, 58 insertions(+), 19 deletions(-) diff --git a/stl/inc/xutility b/stl/inc/xutility index ac1f6aa2248..70a5162ec2e 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -1353,10 +1353,15 @@ public: } template , int> = 0> - _NODISCARD constexpr reverse_iterator<_Unwrapped_t> _Unwrapped() const - noexcept(noexcept(static_cast>>(current._Unwrapped()))) { + _NODISCARD constexpr reverse_iterator<_Unwrapped_t> _Unwrapped() const& noexcept( + noexcept(static_cast>>(current._Unwrapped()))) { return static_cast>>(current._Unwrapped()); } + template , int> = 0> + _NODISCARD constexpr reverse_iterator<_Unwrapped_t<_BidIt2>> _Unwrapped() && noexcept( + noexcept(static_cast>>(_STD move(current)._Unwrapped()))) { + return static_cast>>(_STD move(current)._Unwrapped()); + } static constexpr bool _Unwrap_when_unverified = _Do_unwrap_when_unverified_v<_BidIt>; diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp index e49347806b0..fb2b68623f6 100644 --- a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp @@ -7,31 +7,65 @@ #include #include +#if _HAS_CXX20 +#include +#endif + using namespace std; +using filesystem::path; #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) -template -void do_test() { - STATIC_ASSERT(_Is_nothrow_unwrappable_v); - STATIC_ASSERT(_Is_nothrow_unwrappable_v); - STATIC_ASSERT(noexcept(_Get_unwrapped(declval()))); +struct Predicate { + template + bool operator()(const T&) const { + return true; + } +}; + +template +void do_single_test() { + STATIC_ASSERT(_Is_nothrow_unwrappable_v); + STATIC_ASSERT(_Is_nothrow_unwrappable_v); + STATIC_ASSERT(noexcept(_Get_unwrapped(declval()))); + + STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); + STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); + STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); + STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); +} + +template +void do_full_test() { + do_single_test(); + do_single_test, CopyUnwrapNothrow>(); + do_single_test, CopyUnwrapNothrow>(); + +#ifdef __cpp_lib_concepts // TRANSITION, GH-395 + using R = ranges::subrange; + + do_single_test, CopyUnwrapNothrow>(); - STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); - STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); - STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); - STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); + // iterator_t does not define _Unwrapped + do_single_test>, true>(); + // iterator_t does not define _Unwrapped + do_single_test>, true>(); + if constexpr (ranges::bidirectional_range) { + // iterator_t does not define _Unwrapped + do_single_test>, true>(); + } +#endif // __cpp_lib_concepts } int main() { - do_test(); - do_test(); - do_test(); + do_single_test(); + do_full_test(); + do_single_test(); - do_test::iterator>(); - do_test::const_iterator>(); - do_test::iterator>(); - do_test::const_iterator>(); + do_full_test::iterator>(); + do_full_test::const_iterator>(); + do_full_test::iterator>(); + do_full_test::const_iterator>(); - do_test(); + do_full_test(); } From 8b48dc4f2735d1f4730e132610ec165e9cb16714 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Fri, 5 Aug 2022 14:10:55 -0700 Subject: [PATCH 06/12] add more tests, use TRANSITION comments --- .../GH_002989_nothrow_unwrappable/test.cpp | 62 +++++++++++++++++-- 1 file changed, 58 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp index fb2b68623f6..e83fcb6387c 100644 --- a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp @@ -46,17 +46,70 @@ void do_full_test() { do_single_test, CopyUnwrapNothrow>(); - // iterator_t does not define _Unwrapped + // TRANSITION, GH-2997 do_single_test>, true>(); - // iterator_t does not define _Unwrapped + // TRANSITION, GH-2997 do_single_test>, true>(); if constexpr (ranges::bidirectional_range) { - // iterator_t does not define _Unwrapped - do_single_test>, true>(); + do_single_test>, CopyUnwrapNothrow>(); } #endif // __cpp_lib_concepts } +struct BidiIterUnwrapThrowing : vector::iterator { + using _Base = vector::iterator; + + using _Base::_Base; + using _Base::iterator_category; + +#ifdef __cpp_lib_concepts // TRANSITION, GH-395 + using _Base::iterator_concept; +#endif + + using _Base::pointer; + using _Base::reference; + using _Base::value_type; + + friend bool operator==(const BidiIterUnwrapThrowing& lhs, const BidiIterUnwrapThrowing& rhs) noexcept { + return static_cast(lhs) == static_cast(rhs); + } + friend bool operator!=(const BidiIterUnwrapThrowing& lhs, const BidiIterUnwrapThrowing& rhs) noexcept { + return static_cast(lhs) != static_cast(rhs); + } + + BidiIterUnwrapThrowing& operator++() { + _Base::operator++(); + return *this; + } + BidiIterUnwrapThrowing operator++(int) { + auto res = *this; + _Base::operator++(); + return res; + } + BidiIterUnwrapThrowing& operator--() { + _Base::operator--(); + return *this; + } + BidiIterUnwrapThrowing operator--(int) { + auto res = *this; + _Base::operator--(); + return res; + } + + using _Prevent_inheriting_unwrap = BidiIterUnwrapThrowing; + + int* _Unwrapped() const& noexcept(false) { + return _Base::_Unwrapped(); + } + int* _Unwrapped() && noexcept { + return std::move(*this)._Base::_Unwrapped(); + } + + void _Seek_to(int* p) & noexcept { + _Base::_Seek_to(p); + } +}; + int main() { do_single_test(); do_full_test(); @@ -68,4 +121,5 @@ int main() { do_full_test::const_iterator>(); do_full_test(); + do_full_test(); } From 349c0610f67d674a3327df509551993f93da9f4a Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Mon, 8 Aug 2022 15:39:28 -0700 Subject: [PATCH 07/12] review comments, make _Is_nothrow_unwrappable more normal --- stl/inc/filesystem | 4 +- stl/inc/xutility | 7 +-- .../GH_002989_nothrow_unwrappable/env.lst | 2 +- .../GH_002989_nothrow_unwrappable/test.cpp | 46 +++++++++---------- 4 files changed, 30 insertions(+), 29 deletions(-) diff --git a/stl/inc/filesystem b/stl/inc/filesystem index 8c8e04aa636..250e3443168 100644 --- a/stl/inc/filesystem +++ b/stl/inc/filesystem @@ -1602,12 +1602,12 @@ namespace filesystem { using _Prevent_inheriting_unwrap = _Path_iterator; template , int> = 0> - _NODISCARD _Path_iterator<_Unwrapped_t> _Unwrapped() const& noexcept(false) { + _NODISCARD _Path_iterator<_Unwrapped_t> _Unwrapped() const& { return {_Position._Unwrapped(), _Element, _Mypath}; } template , int> = 0> _NODISCARD _Path_iterator<_Unwrapped_t<_Iter2>> _Unwrapped() && noexcept { - _STL_INTERNAL_STATIC_ASSERT(noexcept(_Is_nothrow_unwrappable_v<_Iter2>)); + _STL_INTERNAL_STATIC_ASSERT(_Is_nothrow_unwrappable_v<_Iter2>); return {_Position._Unwrapped(), _STD move(_Element), _Mypath}; } diff --git a/stl/inc/xutility b/stl/inc/xutility index 70a5162ec2e..160f6d9255b 100644 --- a/stl/inc/xutility +++ b/stl/inc/xutility @@ -897,13 +897,14 @@ _INLINE_VAR constexpr bool _Unwrappable_v<_Iter, _Allow_inheriting_unwrap_v<_Remove_cvref_t<_Iter>>; template > -_INLINE_VAR constexpr bool _Is_nothrow_unwrappable_v = true; +_INLINE_VAR constexpr bool _Is_nothrow_unwrappable_v = noexcept(_STD declval<_Iter>()._Unwrapped()); template -_INLINE_VAR constexpr bool _Is_nothrow_unwrappable_v<_Iter, true> = noexcept(declval<_Iter>()._Unwrapped()); +_INLINE_VAR constexpr bool _Is_nothrow_unwrappable_v<_Iter, false> = false; template -_NODISCARD constexpr decltype(auto) _Get_unwrapped(_Iter&& _It) noexcept(_Is_nothrow_unwrappable_v<_Iter>) { +_NODISCARD constexpr decltype(auto) _Get_unwrapped(_Iter&& _It) noexcept( + !_Unwrappable_v<_Iter> || _Is_nothrow_unwrappable_v<_Iter>) { // unwrap an iterator previously subjected to _Adl_verify_range or otherwise validated if constexpr (is_pointer_v>) { // special-case pointers and arrays return _It + 0; diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/env.lst b/tests/std/tests/GH_002989_nothrow_unwrappable/env.lst index 2de7aab2959..19f025bd0e6 100644 --- a/tests/std/tests/GH_002989_nothrow_unwrappable/env.lst +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/env.lst @@ -1,4 +1,4 @@ # Copyright (c) Microsoft Corporation. # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -RUNALL_INCLUDE ..\usual_17_matrix.lst +RUNALL_INCLUDE ..\usual_matrix.lst diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp index e83fcb6387c..ecb292803f2 100644 --- a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp @@ -12,7 +12,10 @@ #endif using namespace std; + +#if _HAS_CXX17 using filesystem::path; +#endif #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) @@ -23,15 +26,24 @@ struct Predicate { } }; +#pragma warning(disable : 4984) // 'if constexpr' is a C++17 language extension +#ifdef __clang__ +#pragma clang diagnostic ignored "-Wc++17-extensions" // constexpr if is a C++17 extension +#endif + template void do_single_test() { - STATIC_ASSERT(_Is_nothrow_unwrappable_v); - STATIC_ASSERT(_Is_nothrow_unwrappable_v); + if constexpr (_Unwrappable_v) { + STATIC_ASSERT(_Is_nothrow_unwrappable_v); + STATIC_ASSERT(_Is_nothrow_unwrappable_v); + } STATIC_ASSERT(noexcept(_Get_unwrapped(declval()))); - STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); + if constexpr (_Unwrappable_v) { + STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); + STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); + } STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); - STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); } @@ -44,13 +56,11 @@ void do_full_test() { #ifdef __cpp_lib_concepts // TRANSITION, GH-395 using R = ranges::subrange; - do_single_test, CopyUnwrapNothrow>(); - // TRANSITION, GH-2997 do_single_test>, true>(); // TRANSITION, GH-2997 do_single_test>, true>(); - if constexpr (ranges::bidirectional_range) { + if constexpr (bidirectional_iterator) { do_single_test>, CopyUnwrapNothrow>(); } #endif // __cpp_lib_concepts @@ -60,22 +70,10 @@ struct BidiIterUnwrapThrowing : vector::iterator { using _Base = vector::iterator; using _Base::_Base; - using _Base::iterator_category; -#ifdef __cpp_lib_concepts // TRANSITION, GH-395 - using _Base::iterator_concept; -#endif - - using _Base::pointer; - using _Base::reference; - using _Base::value_type; + using iterator_concept = bidirectional_iterator_tag; + using iterator_category = bidirectional_iterator_tag; - friend bool operator==(const BidiIterUnwrapThrowing& lhs, const BidiIterUnwrapThrowing& rhs) noexcept { - return static_cast(lhs) == static_cast(rhs); - } - friend bool operator!=(const BidiIterUnwrapThrowing& lhs, const BidiIterUnwrapThrowing& rhs) noexcept { - return static_cast(lhs) != static_cast(rhs); - } BidiIterUnwrapThrowing& operator++() { _Base::operator++(); @@ -102,7 +100,7 @@ struct BidiIterUnwrapThrowing : vector::iterator { return _Base::_Unwrapped(); } int* _Unwrapped() && noexcept { - return std::move(*this)._Base::_Unwrapped(); + return move(*this)._Base::_Unwrapped(); } void _Seek_to(int* p) & noexcept { @@ -120,6 +118,8 @@ int main() { do_full_test::iterator>(); do_full_test::const_iterator>(); - do_full_test(); do_full_test(); +#if _HAS_CXX17 + do_full_test(); +#endif } From 31bca24d1e019a73febc806ecaece5e047445561 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Tue, 9 Aug 2022 07:53:08 -0700 Subject: [PATCH 08/12] switch to \implies to avoid extensions in test --- .../GH_002989_nothrow_unwrappable/test.cpp | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp index ecb292803f2..681b47a3565 100644 --- a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp @@ -26,23 +26,16 @@ struct Predicate { } }; -#pragma warning(disable : 4984) // 'if constexpr' is a C++17 language extension -#ifdef __clang__ -#pragma clang diagnostic ignored "-Wc++17-extensions" // constexpr if is a C++17 extension -#endif - template void do_single_test() { - if constexpr (_Unwrappable_v) { - STATIC_ASSERT(_Is_nothrow_unwrappable_v); - STATIC_ASSERT(_Is_nothrow_unwrappable_v); - } + // !a || b is equivalent to a => b (a implies b) + // This is written this way to avoid `if constexpr` in C++14 mode. + STATIC_ASSERT(!_Unwrappable_v || _Is_nothrow_unwrappable_v); + STATIC_ASSERT(!_Unwrappable_v || _Is_nothrow_unwrappable_v); STATIC_ASSERT(noexcept(_Get_unwrapped(declval()))); - if constexpr (_Unwrappable_v) { - STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); - STATIC_ASSERT(_Is_nothrow_unwrappable_v == CopyUnwrapNothrow); - } + STATIC_ASSERT(!_Unwrappable_v || _Is_nothrow_unwrappable_v == CopyUnwrapNothrow); + STATIC_ASSERT(!_Unwrappable_v || _Is_nothrow_unwrappable_v == CopyUnwrapNothrow); STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); } @@ -74,7 +67,6 @@ struct BidiIterUnwrapThrowing : vector::iterator { using iterator_concept = bidirectional_iterator_tag; using iterator_category = bidirectional_iterator_tag; - BidiIterUnwrapThrowing& operator++() { _Base::operator++(); return *this; From 8af9046d9c965febdf34c5e48ef6f15dd498d5c8 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Thu, 11 Aug 2022 12:58:43 -0700 Subject: [PATCH 09/12] Casey's CRs --- tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp index 681b47a3565..0d070eb4e02 100644 --- a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp @@ -30,12 +30,12 @@ template void do_single_test() { // !a || b is equivalent to a => b (a implies b) // This is written this way to avoid `if constexpr` in C++14 mode. - STATIC_ASSERT(!_Unwrappable_v || _Is_nothrow_unwrappable_v); - STATIC_ASSERT(!_Unwrappable_v || _Is_nothrow_unwrappable_v); + STATIC_ASSERT(!_Unwrappable_v == _Is_nothrow_unwrappable_v); + STATIC_ASSERT(!_Unwrappable_v == _Is_nothrow_unwrappable_v); STATIC_ASSERT(noexcept(_Get_unwrapped(declval()))); - STATIC_ASSERT(!_Unwrappable_v || _Is_nothrow_unwrappable_v == CopyUnwrapNothrow); - STATIC_ASSERT(!_Unwrappable_v || _Is_nothrow_unwrappable_v == CopyUnwrapNothrow); + STATIC_ASSERT(!_Unwrappable_v || (_Is_nothrow_unwrappable_v == CopyUnwrapNothrow)); + STATIC_ASSERT(!_Unwrappable_v || (_Is_nothrow_unwrappable_v == CopyUnwrapNothrow)); STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); } From c2ad1ea5a7754194023732db11ce7a8599ee9f82 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Thu, 11 Aug 2022 16:07:05 -0700 Subject: [PATCH 10/12] ups --- tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp index 0d070eb4e02..6462b8fe92f 100644 --- a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp @@ -30,8 +30,8 @@ template void do_single_test() { // !a || b is equivalent to a => b (a implies b) // This is written this way to avoid `if constexpr` in C++14 mode. - STATIC_ASSERT(!_Unwrappable_v == _Is_nothrow_unwrappable_v); - STATIC_ASSERT(!_Unwrappable_v == _Is_nothrow_unwrappable_v); + STATIC_ASSERT(_Unwrappable_v == _Is_nothrow_unwrappable_v); + STATIC_ASSERT(_Unwrappable_v == _Is_nothrow_unwrappable_v); STATIC_ASSERT(noexcept(_Get_unwrapped(declval()))); STATIC_ASSERT(!_Unwrappable_v || (_Is_nothrow_unwrappable_v == CopyUnwrapNothrow)); From 20e999418dbe97cd9e1c2a5033a1583e28f66091 Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Thu, 11 Aug 2022 18:54:58 -0700 Subject: [PATCH 11/12] Remove extraneous `()` of unknown origin --- tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp index 6462b8fe92f..27d41ed158b 100644 --- a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp @@ -34,8 +34,8 @@ void do_single_test() { STATIC_ASSERT(_Unwrappable_v == _Is_nothrow_unwrappable_v); STATIC_ASSERT(noexcept(_Get_unwrapped(declval()))); - STATIC_ASSERT(!_Unwrappable_v || (_Is_nothrow_unwrappable_v == CopyUnwrapNothrow)); - STATIC_ASSERT(!_Unwrappable_v || (_Is_nothrow_unwrappable_v == CopyUnwrapNothrow)); + STATIC_ASSERT(!_Unwrappable_v || _Is_nothrow_unwrappable_v == CopyUnwrapNothrow); + STATIC_ASSERT(!_Unwrappable_v || _Is_nothrow_unwrappable_v == CopyUnwrapNothrow); STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); STATIC_ASSERT(noexcept(_Get_unwrapped(declval())) == CopyUnwrapNothrow); } From 29faf88f17478a970a899f2f1c8b6038e1fec877 Mon Sep 17 00:00:00 2001 From: Nicole Mazzuca Date: Fri, 12 Aug 2022 07:59:31 -0700 Subject: [PATCH 12/12] STL CRs --- .../GH_002989_nothrow_unwrappable/test.cpp | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp index 27d41ed158b..a92bc561ce4 100644 --- a/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp +++ b/tests/std/tests/GH_002989_nothrow_unwrappable/test.cpp @@ -1,12 +1,15 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#include #include #include #include #include +#if _HAS_CXX17 +#include +#endif + #if _HAS_CXX20 #include #endif @@ -60,43 +63,43 @@ void do_full_test() { } struct BidiIterUnwrapThrowing : vector::iterator { - using _Base = vector::iterator; + using Base = vector::iterator; - using _Base::_Base; + using Base::Base; using iterator_concept = bidirectional_iterator_tag; using iterator_category = bidirectional_iterator_tag; BidiIterUnwrapThrowing& operator++() { - _Base::operator++(); + Base::operator++(); return *this; } BidiIterUnwrapThrowing operator++(int) { auto res = *this; - _Base::operator++(); + Base::operator++(); return res; } BidiIterUnwrapThrowing& operator--() { - _Base::operator--(); + Base::operator--(); return *this; } BidiIterUnwrapThrowing operator--(int) { auto res = *this; - _Base::operator--(); + Base::operator--(); return res; } using _Prevent_inheriting_unwrap = BidiIterUnwrapThrowing; int* _Unwrapped() const& noexcept(false) { - return _Base::_Unwrapped(); + return Base::_Unwrapped(); } int* _Unwrapped() && noexcept { - return move(*this)._Base::_Unwrapped(); + return move(*this).Base::_Unwrapped(); } void _Seek_to(int* p) & noexcept { - _Base::_Seek_to(p); + Base::_Seek_to(p); } };