From 1bf66d8a5deca8981462f50679030655d5361ff8 Mon Sep 17 00:00:00 2001 From: Dmitry Kobets Date: Thu, 17 Feb 2022 11:37:55 -0800 Subject: [PATCH 01/11] Make gsl::span's iterators use the contiguous_iterator concept The only missing part to satisfy this concept was to use the contiguous_iterator_tag --- include/gsl/span | 3 +++ tests/span_tests.cpp | 13 +++++++++++++ 2 files changed, 16 insertions(+) diff --git a/include/gsl/span b/include/gsl/span index 5488f5282..4bbfc7d77 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -110,6 +110,9 @@ namespace details class span_iterator { public: +#ifdef __cpp_lib_concepts + using iterator_concept = std::contiguous_iterator_tag; +#endif // __cpp_lib_concepts using iterator_category = std::random_access_iterator_tag; using value_type = std::remove_cv_t; using difference_type = std::ptrdiff_t; diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 33ccf560c..a1c073db0 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -40,6 +40,9 @@ #endif // __has_include() #endif // __has_include #endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L)) +#if defined(__cplusplus) && __cplusplus >= 202002L +#include +#endif // __cplusplus >= 202002L #include "deathTestCommon.h" @@ -1297,3 +1300,13 @@ TEST(span_test, front_back) EXPECT_DEATH(s2.front(), expected); EXPECT_DEATH(s2.back(), expected); } + +#if defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L +TEST(span_test, std_span) +{ + // make sure std::span can be constructed from gsl::span + gsl::span gsl_span; + std::span std_span = gsl_span; + (void)std_span; // suppress unused variable warning +} +#endif // defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L From 1569507e225317271adad16d10e9203ed9e3f76b Mon Sep 17 00:00:00 2001 From: Casey Carter Date: Wed, 23 Feb 2022 17:09:49 -0800 Subject: [PATCH 02/11] Casey's review feedback --- include/gsl/span | 24 ++++++++++++++++++++++-- tests/span_tests.cpp | 11 +++++++++-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 4bbfc7d77..9415332a4 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -25,8 +25,15 @@ #include // for array #include // for ptrdiff_t, size_t, nullptr_t #include // for reverse_iterator, distance, random_access_... +#include // for pointer_traits #include // for enable_if_t, declval, is_convertible, inte... +#ifdef __has_include +#if __has_include() +#include +#endif +#endif + #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) @@ -110,9 +117,9 @@ namespace details class span_iterator { public: -#ifdef __cpp_lib_concepts +#ifdef __cpp_lib_ranges using iterator_concept = std::contiguous_iterator_tag; -#endif // __cpp_lib_concepts +#endif // __cpp_lib_ranges using iterator_category = std::random_access_iterator_tag; using value_type = std::remove_cv_t; using difference_type = std::ptrdiff_t; @@ -333,7 +340,20 @@ namespace details pointer end_ = nullptr; pointer current_ = nullptr; }; +}} // namespace gsl::details + +template +struct std::pointer_traits<::gsl::details::span_iterator> { + using pointer = ::gsl::details::span_iterator; + using element_type = Type; + using difference_type = ptrdiff_t; + + static constexpr element_type* to_address(const pointer i) noexcept { + return i._Unwrapped(); + } +}; +namespace gsl { namespace details { template class extent_type { diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index a1c073db0..875211147 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1305,8 +1305,15 @@ TEST(span_test, front_back) TEST(span_test, std_span) { // make sure std::span can be constructed from gsl::span - gsl::span gsl_span; + int arr[5] = {1, 2, 3, 4, 5}; + gsl::span gsl_span{arr}; +#ifdef __cpp_lib_ranges + EXPECT_TRUE(std::to_address(gsl_span.begin()) == gsl_span.data()); + EXPECT_TRUE(std::to_address(gsl_span.end()) == gsl_span.data() + gsl_span.size()); +#endif // __cpp_lib_ranges + std::span std_span = gsl_span; - (void)std_span; // suppress unused variable warning + EXPECT_TRUE(std_span.data() == gsl_span.data()); + EXPECT_TRUE(std_span.size() == gsl_span.size()); } #endif // defined(FORCE_STD_SPAN_TESTS) || defined(__cpp_lib_span) && __cpp_lib_span >= 202002L From df1cbd3613bb717053916027bcdea6da44d714e9 Mon Sep 17 00:00:00 2001 From: Dmitry Kobets Date: Tue, 8 Mar 2022 14:34:16 -0800 Subject: [PATCH 03/11] Enable pointer_traits to use unwrapped iterator contents _Unwrapped is only available for MSVC. Instead, make the pointer_traits class a friend --- include/gsl/span | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 9415332a4..6304d98b0 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -339,6 +339,9 @@ namespace details pointer begin_ = nullptr; pointer end_ = nullptr; pointer current_ = nullptr; + + template + friend struct std::pointer_traits; }; }} // namespace gsl::details @@ -349,7 +352,7 @@ struct std::pointer_traits<::gsl::details::span_iterator> { using difference_type = ptrdiff_t; static constexpr element_type* to_address(const pointer i) noexcept { - return i._Unwrapped(); + return i.current_; } }; From d340867c4e1f642491647ddb258741e53a0a8e3f Mon Sep 17 00:00:00 2001 From: Dmitry Kobets Date: Tue, 8 Mar 2022 14:38:13 -0800 Subject: [PATCH 04/11] Make define conditions on one line --- include/gsl/span | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 6304d98b0..48d5625a9 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -28,11 +28,9 @@ #include // for pointer_traits #include // for enable_if_t, declval, is_convertible, inte... -#ifdef __has_include -#if __has_include() +#if defined(__has_include) && __has_include() #include #endif -#endif #if defined(_MSC_VER) && !defined(__clang__) #pragma warning(push) From c8f8d0358f771bbd0f2e4937e8ec28bb49fb5417 Mon Sep 17 00:00:00 2001 From: Dmitry Kobets Date: Thu, 17 Mar 2022 13:50:40 -0700 Subject: [PATCH 05/11] Add workaround for __cpp_lib_ranges for VS2019 --- include/gsl/span | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/gsl/span b/include/gsl/span index 48d5625a9..4413a4d65 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -115,7 +115,7 @@ namespace details class span_iterator { public: -#ifdef __cpp_lib_ranges +#if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts)) using iterator_concept = std::contiguous_iterator_tag; #endif // __cpp_lib_ranges using iterator_category = std::random_access_iterator_tag; From b8b60c512d0095cc2b52974333270f036ec88fc3 Mon Sep 17 00:00:00 2001 From: Dmitry Kobets Date: Thu, 17 Mar 2022 14:54:40 -0700 Subject: [PATCH 06/11] Suppress clang warnings for reserved identifiers --- include/gsl/span | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/include/gsl/span b/include/gsl/span index 4413a4d65..3e3af6615 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -125,6 +125,7 @@ namespace details using reference = Type&; #ifdef _MSC_VER +#pragma clang diagnostic ignored "-Wreserved-identifier" using _Unchecked_type = pointer; #endif // _MSC_VER constexpr span_iterator() = default; @@ -293,6 +294,7 @@ namespace details // MSVC++ iterator debugging support; allows STL algorithms in 15.8+ // to unwrap span_iterator to a pointer type after a range check in STL // algorithm calls +#pragma clang diagnostic ignored "-Wreserved-identifier" friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept { // test that [lhs, rhs) forms a valid range inside an STL algorithm Expects(lhs.begin_ == rhs.begin_ // range spans have to match @@ -300,6 +302,7 @@ namespace details lhs.current_ <= rhs.current_); // range must not be transposed } +#pragma clang diagnostic ignored "-Wreserved-identifier" constexpr void _Verify_offset(const difference_type n) const noexcept { // test that *this + n is within the range of this call if (n != 0) Expects(begin_ && current_ && end_); @@ -310,6 +313,7 @@ namespace details // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on +#pragma clang diagnostic ignored "-Wreserved-identifier" constexpr pointer _Unwrapped() const noexcept { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw @@ -320,13 +324,16 @@ namespace details // Tell the STL that span_iterator should not be unwrapped if it can't // validate in advance, even in release / optimized builds: #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) +#pragma clang diagnostic ignored "-Wreserved-identifier" static constexpr const bool _Unwrap_when_unverified = false; #else +#pragma clang diagnostic ignored "-Wreserved-identifier" static constexpr bool _Unwrap_when_unverified = false; #endif // clang-format off GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive // clang-format on +#pragma clang diagnostic ignored "-Wreserved-identifier" constexpr void _Seek_to(const pointer p) noexcept { // adjust the position of *this to previously verified location p // after _Unwrapped @@ -677,7 +684,9 @@ public: #ifdef _MSC_VER // Tell MSVC how to unwrap spans in range-based-for +#pragma clang diagnostic ignored "-Wreserved-identifier" constexpr pointer _Unchecked_begin() const noexcept { return data(); } +#pragma clang diagnostic ignored "-Wreserved-identifier" constexpr pointer _Unchecked_end() const noexcept { // clang-format off From 5e79e544e8dafce6f696d9f23a825646db41a84d Mon Sep 17 00:00:00 2001 From: Dmitry Kobets Date: Thu, 17 Mar 2022 15:15:07 -0700 Subject: [PATCH 07/11] Revert "Suppress clang warnings for reserved identifiers" This reverts commit ddd5b12e120f87346bb290de7388475d18b0b4bc. Apparently trying to suppress clang warnings is hard to do inline in the library headers. Instead, will simply suppress in the cmake config --- include/gsl/span | 9 --------- 1 file changed, 9 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 3e3af6615..4413a4d65 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -125,7 +125,6 @@ namespace details using reference = Type&; #ifdef _MSC_VER -#pragma clang diagnostic ignored "-Wreserved-identifier" using _Unchecked_type = pointer; #endif // _MSC_VER constexpr span_iterator() = default; @@ -294,7 +293,6 @@ namespace details // MSVC++ iterator debugging support; allows STL algorithms in 15.8+ // to unwrap span_iterator to a pointer type after a range check in STL // algorithm calls -#pragma clang diagnostic ignored "-Wreserved-identifier" friend constexpr void _Verify_range(span_iterator lhs, span_iterator rhs) noexcept { // test that [lhs, rhs) forms a valid range inside an STL algorithm Expects(lhs.begin_ == rhs.begin_ // range spans have to match @@ -302,7 +300,6 @@ namespace details lhs.current_ <= rhs.current_); // range must not be transposed } -#pragma clang diagnostic ignored "-Wreserved-identifier" constexpr void _Verify_offset(const difference_type n) const noexcept { // test that *this + n is within the range of this call if (n != 0) Expects(begin_ && current_ && end_); @@ -313,7 +310,6 @@ namespace details // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute // clang-format on -#pragma clang diagnostic ignored "-Wreserved-identifier" constexpr pointer _Unwrapped() const noexcept { // after seeking *this to a high water mark, or using one of the // _Verify_xxx functions above, unwrap this span_iterator to a raw @@ -324,16 +320,13 @@ namespace details // Tell the STL that span_iterator should not be unwrapped if it can't // validate in advance, even in release / optimized builds: #if defined(GSL_USE_STATIC_CONSTEXPR_WORKAROUND) -#pragma clang diagnostic ignored "-Wreserved-identifier" static constexpr const bool _Unwrap_when_unverified = false; #else -#pragma clang diagnostic ignored "-Wreserved-identifier" static constexpr bool _Unwrap_when_unverified = false; #endif // clang-format off GSL_SUPPRESS(con.3) // NO-FORMAT: attribute // TODO: false positive // clang-format on -#pragma clang diagnostic ignored "-Wreserved-identifier" constexpr void _Seek_to(const pointer p) noexcept { // adjust the position of *this to previously verified location p // after _Unwrapped @@ -684,9 +677,7 @@ public: #ifdef _MSC_VER // Tell MSVC how to unwrap spans in range-based-for -#pragma clang diagnostic ignored "-Wreserved-identifier" constexpr pointer _Unchecked_begin() const noexcept { return data(); } -#pragma clang diagnostic ignored "-Wreserved-identifier" constexpr pointer _Unchecked_end() const noexcept { // clang-format off From cd619433df671a79a884cef90126b4bcc966498c Mon Sep 17 00:00:00 2001 From: Dmitry Kobets Date: Thu, 17 Mar 2022 15:30:25 -0700 Subject: [PATCH 08/11] Disable reserved identifier warnings for MSVC with llvm --- tests/CMakeLists.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 891569bea..7f8b96641 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -100,6 +100,7 @@ if(MSVC) # MSVC or simulating MSVC -Wno-shift-sign-overflow # GTest gtest-port.h -Wno-undef # GTest -Wno-used-but-marked-unused # GTest EXPECT_DEATH + -Wreserved-identifier # required by span implementation $<$: # no support for [[maybe_unused]] -Wno-unused-member-function -Wno-unused-variable @@ -231,6 +232,7 @@ if(MSVC) # MSVC or simulating MSVC -Wno-c++98-compat-pedantic -Wno-missing-prototypes -Wno-unknown-attributes + -Wreserved-identifier # required by span implementation > ) check_cxx_compiler_flag("-Wno-reserved-identifier" WARN_RESERVED_ID) From 4e2b9058d1ca6b7054df7efd3954abf1551a788b Mon Sep 17 00:00:00 2001 From: Dmitry Kobets Date: Thu, 17 Mar 2022 16:02:45 -0700 Subject: [PATCH 09/11] Suppress instead of enabling the warning --- tests/CMakeLists.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 7f8b96641..9a549459e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -100,7 +100,7 @@ if(MSVC) # MSVC or simulating MSVC -Wno-shift-sign-overflow # GTest gtest-port.h -Wno-undef # GTest -Wno-used-but-marked-unused # GTest EXPECT_DEATH - -Wreserved-identifier # required by span implementation + -Wno-reserved-identifier # required by span implementation $<$: # no support for [[maybe_unused]] -Wno-unused-member-function -Wno-unused-variable @@ -232,7 +232,7 @@ if(MSVC) # MSVC or simulating MSVC -Wno-c++98-compat-pedantic -Wno-missing-prototypes -Wno-unknown-attributes - -Wreserved-identifier # required by span implementation + -Wno-reserved-identifier # required by span implementation > ) check_cxx_compiler_flag("-Wno-reserved-identifier" WARN_RESERVED_ID) From 6675b97cb7b8076bff699ab5a32fb345e178eef6 Mon Sep 17 00:00:00 2001 From: Dmitry Kobets Date: Tue, 22 Mar 2022 12:27:25 -0700 Subject: [PATCH 10/11] Remove incorrect suppression strategy (warns on old VS) --- tests/CMakeLists.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 9a549459e..891569bea 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -100,7 +100,6 @@ if(MSVC) # MSVC or simulating MSVC -Wno-shift-sign-overflow # GTest gtest-port.h -Wno-undef # GTest -Wno-used-but-marked-unused # GTest EXPECT_DEATH - -Wno-reserved-identifier # required by span implementation $<$: # no support for [[maybe_unused]] -Wno-unused-member-function -Wno-unused-variable @@ -232,7 +231,6 @@ if(MSVC) # MSVC or simulating MSVC -Wno-c++98-compat-pedantic -Wno-missing-prototypes -Wno-unknown-attributes - -Wno-reserved-identifier # required by span implementation > ) check_cxx_compiler_flag("-Wno-reserved-identifier" WARN_RESERVED_ID) From d1cfb612476c587ff5d71e0b68120996698f51a8 Mon Sep 17 00:00:00 2001 From: Dmitry Kobets Date: Tue, 22 Mar 2022 12:58:04 -0700 Subject: [PATCH 11/11] Make sure tests have the same condition as the feature being tested --- tests/span_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 875211147..41ac3aee5 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1307,7 +1307,7 @@ TEST(span_test, std_span) // make sure std::span can be constructed from gsl::span int arr[5] = {1, 2, 3, 4, 5}; gsl::span gsl_span{arr}; -#ifdef __cpp_lib_ranges +#if defined(__cpp_lib_ranges) || (defined(_MSVC_STL_VERSION) && defined(__cpp_lib_concepts)) EXPECT_TRUE(std::to_address(gsl_span.begin()) == gsl_span.data()); EXPECT_TRUE(std::to_address(gsl_span.end()) == gsl_span.data() + gsl_span.size()); #endif // __cpp_lib_ranges