From 1dd1320c8b29099fe5bba591d1b0dba367fa68d7 Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Tue, 17 Mar 2020 13:53:13 -0700 Subject: [PATCH 01/14] test commit to get extra eyes on the problem --- include/gsl/span | 18 ++++++++++++++++++ tests/span_compatibility_tests.cpp | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/gsl/span b/include/gsl/span index 23c58c9..7c15eb4 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -441,6 +441,8 @@ public: : storage_(KnownNotNull{arr + 0}, details::extent_type<N>()) {} +// #define useold +#if defined(useold) template <std::size_t N, std::enable_if_t<details::is_allowed_extent_conversion<N, Extent>::value, int> = 0> constexpr span(std::array<element_type, N>& arr) noexcept @@ -455,7 +457,23 @@ public: constexpr span(const std::array<value_type, N>& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type<N>()) {} +#else + template <class T, std::size_t N, + std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value && + details::is_allowed_element_type_conversion<T, element_type>::value), int> = 0> + constexpr span(std::array<T, N>& arr) noexcept + : storage_(KnownNotNull{arr.data()}, details::extent_type<N>()) + {} + template <class T, std::size_t N, + std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value && + details::is_allowed_element_type_conversion<const T, + element_type>::value), + int> = 0> + constexpr span(const std::array<T, N>& arr) noexcept + : storage_(KnownNotNull{arr.data()}, details::extent_type<N>()) + {} +#endif // NB: the SFINAE here uses .data() as an incomplete/imperfect proxy for the requirement // on Container to be a contiguous sequence container. template <class Container, diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index 8733e72..1985f6f 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -46,6 +46,22 @@ TEST(span_compatibility_tests, assertion_tests) { int arr[3]{10, 20, 30}; std::array<int, 3> stl{{100, 200, 300}}; + std::array<int*, 3> stl_nullptr{{nullptr,nullptr,nullptr}}; + + { + gsl::span<const int* const> sp_const_nullptr_1{stl_nullptr}; + EXPECT_TRUE(sp_const_nullptr_1.data() == stl_nullptr.data()); + EXPECT_TRUE(sp_const_nullptr_1.size() == 3); + +#if __cplusplus >= 201703l + span<const int* const> sp_const_nullptr_2{std::as_const(stl_nullptr)}; + EXPECT_TRUE(sp_const_nullptr_2.data() == stl_nullptr.data()); + EXPECT_TRUE(sp_const_nullptr_2.size() == 3); + + static_assert(std::is_same<decltype(span{stl_nullptr}), span<int*, 3>); + static_assert(std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<int* const, 3>); +#endif + } { gsl::span<int> sp_dyn; From 9b3ac8d681222a082231de712a4bd4299b658f11 Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Tue, 17 Mar 2020 15:02:00 -0700 Subject: [PATCH 02/14] discussed the issue with Casey Carter, the span ctor changes are accurate but the tests are not. The test require work that was done in C++17 regarding qualifier conversions to work correctly. Scoping tests for 17. --- include/gsl/span | 19 +------------------ tests/span_compatibility_tests.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 20 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 7c15eb4..469a2db 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -441,23 +441,6 @@ public: : storage_(KnownNotNull{arr + 0}, details::extent_type<N>()) {} -// #define useold -#if defined(useold) - template <std::size_t N, - std::enable_if_t<details::is_allowed_extent_conversion<N, Extent>::value, int> = 0> - constexpr span(std::array<element_type, N>& arr) noexcept - : storage_(KnownNotNull{arr.data()}, details::extent_type<N>()) - {} - - template <std::size_t N, - std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value && - details::is_allowed_element_type_conversion<const value_type, - element_type>::value), - int> = 0> - constexpr span(const std::array<value_type, N>& arr) noexcept - : storage_(KnownNotNull{arr.data()}, details::extent_type<N>()) - {} -#else template <class T, std::size_t N, std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value && details::is_allowed_element_type_conversion<T, element_type>::value), int> = 0> @@ -473,7 +456,7 @@ public: constexpr span(const std::array<T, N>& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type<N>()) {} -#endif + // NB: the SFINAE here uses .data() as an incomplete/imperfect proxy for the requirement // on Container to be a contiguous sequence container. template <class Container, diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index 1985f6f..acd85c5 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -48,20 +48,22 @@ TEST(span_compatibility_tests, assertion_tests) std::array<int, 3> stl{{100, 200, 300}}; std::array<int*, 3> stl_nullptr{{nullptr,nullptr,nullptr}}; +#if __cplusplus >= 201703l + // This std::is_convertible_v<int*(*)[], int const* const(*)[]> fails for C++14 + // so these conversions aren't valid in C++14 { gsl::span<const int* const> sp_const_nullptr_1{stl_nullptr}; EXPECT_TRUE(sp_const_nullptr_1.data() == stl_nullptr.data()); EXPECT_TRUE(sp_const_nullptr_1.size() == 3); -#if __cplusplus >= 201703l span<const int* const> sp_const_nullptr_2{std::as_const(stl_nullptr)}; EXPECT_TRUE(sp_const_nullptr_2.data() == stl_nullptr.data()); EXPECT_TRUE(sp_const_nullptr_2.size() == 3); static_assert(std::is_same<decltype(span{stl_nullptr}), span<int*, 3>); static_assert(std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<int* const, 3>); -#endif } +#endif { gsl::span<int> sp_dyn; From f8bcb7d9eb44be91a04882eb972fbef328c24cae Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Tue, 17 Mar 2020 15:04:58 -0700 Subject: [PATCH 03/14] applied clang-format --- include/gsl/span | 43 +++++++++++++++++------------- tests/span_compatibility_tests.cpp | 22 +++++++-------- 2 files changed, 36 insertions(+), 29 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 469a2db..566f731 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -21,9 +21,9 @@ #include <gsl/gsl_byte> // for byte #include <gsl/gsl_util> // for narrow_cast, narrow -#include <array> // for array -#include <cstddef> // for ptrdiff_t, size_t, nullptr_t -#include <iterator> // for reverse_iterator, distance, random_access_... +#include <array> // for array +#include <cstddef> // for ptrdiff_t, size_t, nullptr_t +#include <iterator> // for reverse_iterator, distance, random_access_... #include <type_traits> // for enable_if_t, declval, is_convertible, inte... #if defined(_MSC_VER) && !defined(__clang__) @@ -441,18 +441,20 @@ public: : storage_(KnownNotNull{arr + 0}, details::extent_type<N>()) {} - template <class T, std::size_t N, - std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value && - details::is_allowed_element_type_conversion<T, element_type>::value), int> = 0> + template < + class T, std::size_t N, + std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value && + details::is_allowed_element_type_conversion<T, element_type>::value), + int> = 0> constexpr span(std::array<T, N>& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type<N>()) {} template <class T, std::size_t N, - std::enable_if_t<(details::is_allowed_extent_conversion<N, Extent>::value && - details::is_allowed_element_type_conversion<const T, - element_type>::value), - int> = 0> + std::enable_if_t< + (details::is_allowed_extent_conversion<N, Extent>::value && + details::is_allowed_element_type_conversion<const T, element_type>::value), + int> = 0> constexpr span(const std::array<T, N>& arr) noexcept : storage_(KnownNotNull{arr.data()}, details::extent_type<N>()) {} @@ -463,7 +465,9 @@ public: class = std::enable_if_t< !details::is_span<Container>::value && !details::is_std_array<Container>::value && std::is_pointer<decltype(std::declval<Container&>().data())>::value && - std::is_convertible<std::remove_pointer_t<decltype(std::declval<Container&>().data())>(*)[], element_type(*)[]>::value>> + std::is_convertible< + std::remove_pointer_t<decltype(std::declval<Container&>().data())> (*)[], + element_type (*)[]>::value>> constexpr span(Container& cont) noexcept : span(cont.data(), cont.size()) {} @@ -472,7 +476,9 @@ public: std::is_const<element_type>::value && !details::is_span<Container>::value && !details::is_std_array<Container>::value && std::is_pointer<decltype(std::declval<const Container&>().data())>::value && - std::is_convertible<std::remove_pointer_t<decltype(std::declval<const Container&>().data())>(*)[], element_type(*)[]>::value>> + std::is_convertible<std::remove_pointer_t< + decltype(std::declval<const Container&>().data())> (*)[], + element_type (*)[]>::value>> constexpr span(const Container& cont) noexcept : span(cont.data(), cont.size()) {} @@ -501,8 +507,8 @@ public: template <std::size_t Count> // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on - constexpr span<element_type, Count> last() const noexcept + // clang-format on + constexpr span<element_type, Count> last() const noexcept { Expects(Count <= size()); return {data() + (size() - Count), Count}; @@ -511,9 +517,9 @@ public: template <std::size_t Offset, std::size_t Count = dynamic_extent> // clang-format off GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute - // clang-format on - constexpr auto subspan() const noexcept -> - typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type + // clang-format on + constexpr auto subspan() const noexcept -> + typename details::calculate_subspan_type<ElementType, Extent, Offset, Count>::type { Expects((size() >= Offset) && (Count == dynamic_extent || (Count <= size() - Offset))); @@ -674,7 +680,8 @@ private: template <std::size_t CallerExtent> constexpr span<element_type, dynamic_extent> make_subspan(size_type offset, size_type count, - subspan_selector<CallerExtent>) const noexcept + subspan_selector<CallerExtent>) const + noexcept { const span<element_type, dynamic_extent> tmp(*this); return tmp.subspan(offset, count); diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index acd85c5..d8226ec 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -24,7 +24,7 @@ #include <iterator> // for reverse_iterator, operator-, operator== #include <type_traits> // for integral_constant<>::value, is_default_co... #include <utility> -#include <vector> // for vector +#include <vector> // for vector using namespace std; using namespace gsl; @@ -46,7 +46,7 @@ TEST(span_compatibility_tests, assertion_tests) { int arr[3]{10, 20, 30}; std::array<int, 3> stl{{100, 200, 300}}; - std::array<int*, 3> stl_nullptr{{nullptr,nullptr,nullptr}}; + std::array<int*, 3> stl_nullptr{{nullptr, nullptr, nullptr}}; #if __cplusplus >= 201703l // This std::is_convertible_v<int*(*)[], int const* const(*)[]> fails for C++14 @@ -60,8 +60,9 @@ TEST(span_compatibility_tests, assertion_tests) EXPECT_TRUE(sp_const_nullptr_2.data() == stl_nullptr.data()); EXPECT_TRUE(sp_const_nullptr_2.size() == 3); - static_assert(std::is_same<decltype(span{stl_nullptr}), span<int*, 3>); - static_assert(std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<int* const, 3>); + static_assert(std::is_same < decltype(span{stl_nullptr}), span<int*, 3>); + static_assert(std::is_same < decltype(span{std::as_const(stl_nullptr)}), + span<int* const, 3>); } #endif @@ -1070,21 +1071,20 @@ static_assert(std::is_convertible<std::array<int, 3>&, gsl::span<const int>>::va static_assert(std::is_convertible<const std::array<int, 3>&, gsl::span<const int>>::value, "std::is_convertible<const std::array<int, 3>&, gsl::span<const int>>"); - #if __cplusplus >= 201703l template <typename U, typename = void> static constexpr bool AsWritableBytesCompilesFor = false; template <typename U> -static constexpr bool AsWritableBytesCompilesFor<U, void_t<decltype(as_writable_bytes(declval<U>()))>> = - true; +static constexpr bool + AsWritableBytesCompilesFor<U, void_t<decltype(as_writable_bytes(declval<U>()))>> = true; static_assert(AsWritableBytesCompilesFor<gsl::span<int>>, - "AsWritableBytesCompilesFor<gsl::span<int>>"); + "AsWritableBytesCompilesFor<gsl::span<int>>"); static_assert(AsWritableBytesCompilesFor<gsl::span<int, 9>>, - "AsWritableBytesCompilesFor<gsl::span<int, 9>>"); + "AsWritableBytesCompilesFor<gsl::span<int, 9>>"); static_assert(!AsWritableBytesCompilesFor<gsl::span<const int>>, - "!AsWritableBytesCompilesFor<gsl::span<const int>>"); + "!AsWritableBytesCompilesFor<gsl::span<const int>>"); static_assert(!AsWritableBytesCompilesFor<gsl::span<const int, 9>>, - "!AsWritableBytesCompilesFor<gsl::span<const int, 9>>"); + "!AsWritableBytesCompilesFor<gsl::span<const int, 9>>"); #endif // __cplusplus >= 201703l From 6eab19d3c145911cd34f00644e041512cda6e717 Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Tue, 17 Mar 2020 15:13:26 -0700 Subject: [PATCH 04/14] moving decl so we dont get the stl_nullptr is not used warning --- tests/span_compatibility_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index d8226ec..4be3c4d 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -46,12 +46,12 @@ TEST(span_compatibility_tests, assertion_tests) { int arr[3]{10, 20, 30}; std::array<int, 3> stl{{100, 200, 300}}; - std::array<int*, 3> stl_nullptr{{nullptr, nullptr, nullptr}}; #if __cplusplus >= 201703l // This std::is_convertible_v<int*(*)[], int const* const(*)[]> fails for C++14 // so these conversions aren't valid in C++14 { + std::array<int*, 3> stl_nullptr{{nullptr, nullptr, nullptr}}; gsl::span<const int* const> sp_const_nullptr_1{stl_nullptr}; EXPECT_TRUE(sp_const_nullptr_1.data() == stl_nullptr.data()); EXPECT_TRUE(sp_const_nullptr_1.size() == 3); From ddde9e153d150ba5b635825898a2bde45512b635 Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Thu, 19 Mar 2020 14:08:04 -0700 Subject: [PATCH 05/14] update convertibility test --- tests/span_compatibility_tests.cpp | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index 4be3c4d..e344e88 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -42,14 +42,11 @@ static_assert(std::is_convertible<Derived*, Base*>::value, "std::is_convertible< static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value, "!std::is_convertible<Derived(*)[], Base(*)[]>"); -TEST(span_compatibility_tests, assertion_tests) +template <class = void> +void ArrayConvertibilityCheck() { - int arr[3]{10, 20, 30}; - std::array<int, 3> stl{{100, 200, 300}}; - #if __cplusplus >= 201703l - // This std::is_convertible_v<int*(*)[], int const* const(*)[]> fails for C++14 - // so these conversions aren't valid in C++14 + if constexpr (std::is_convertible<int*(*) [], int const* const(*)[]>::value) { std::array<int*, 3> stl_nullptr{{nullptr, nullptr, nullptr}}; gsl::span<const int* const> sp_const_nullptr_1{stl_nullptr}; @@ -60,11 +57,22 @@ TEST(span_compatibility_tests, assertion_tests) EXPECT_TRUE(sp_const_nullptr_2.data() == stl_nullptr.data()); EXPECT_TRUE(sp_const_nullptr_2.size() == 3); - static_assert(std::is_same < decltype(span{stl_nullptr}), span<int*, 3>); - static_assert(std::is_same < decltype(span{std::as_const(stl_nullptr)}), - span<int* const, 3>); + static_assert(std::is_same<decltype(span{stl_nullptr}), span<int*, 3>>::value, + "std::is_same< decltype(span{stl_nullptr}), span<int*, 3>>::value"); + static_assert( + std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<int* const, 3>>::value, + "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span<int* const, " + "3>>::value"); } #endif +} + +TEST(span_compatibility_tests, assertion_tests) +{ + int arr[3]{10, 20, 30}; + std::array<int, 3> stl{{100, 200, 300}}; + + ArrayConvertibilityCheck(); { gsl::span<int> sp_dyn; From 01d206f4d8997a01741ffe8f6ba719a747b7e014 Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Wed, 8 Apr 2020 14:38:01 -0700 Subject: [PATCH 06/14] adding additional filtering --- tests/span_compatibility_tests.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index e344e88..fa327f7 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -42,6 +42,7 @@ static_assert(std::is_convertible<Derived*, Base*>::value, "std::is_convertible< static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value, "!std::is_convertible<Derived(*)[], Base(*)[]>"); +#if (defined(_MSC_VER)) || (defined(__GNUC__) && __GNUC__ > 7) || (defined(__clang__) && __clang_major__ > 6) template <class = void> void ArrayConvertibilityCheck() { @@ -57,15 +58,19 @@ void ArrayConvertibilityCheck() EXPECT_TRUE(sp_const_nullptr_2.data() == stl_nullptr.data()); EXPECT_TRUE(sp_const_nullptr_2.size() == 3); - static_assert(std::is_same<decltype(span{stl_nullptr}), span<int*, 3>>::value, - "std::is_same< decltype(span{stl_nullptr}), span<int*, 3>>::value"); - static_assert( - std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<int* const, 3>>::value, - "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span<int* const, " - "3>>::value"); + static_assert(std::is_same<decltype(span{stl_nullptr}), span<int*, 3>>::value, + "std::is_same< decltype(span{stl_nullptr}), span<int*, 3>>::value"); + static_assert( + std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<int* const, 3>>::value, + "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span<int* const, " + "3>>::value"); } #endif } +#else +template <class = void> +void ArrayConvertibilityCheck(){} +#endif TEST(span_compatibility_tests, assertion_tests) { From 2f9d8730439ba0cc1998c6f3239498af79e352fe Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Thu, 9 Apr 2020 10:34:58 -0700 Subject: [PATCH 07/14] added additional filtering to Apple clang versions 9.4 and 10.1 for the ArrayConvertibilityCheck --- tests/span_compatibility_tests.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index fa327f7..db9efba 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -42,7 +42,14 @@ static_assert(std::is_convertible<Derived*, Base*>::value, "std::is_convertible< static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value, "!std::is_convertible<Derived(*)[], Base(*)[]>"); -#if (defined(_MSC_VER)) || (defined(__GNUC__) && __GNUC__ > 7) || (defined(__clang__) && __clang_major__ > 6) +// int*(*) [], int const* const(*)[] was identified as an issue in CWG330 and the resolution was provided with N4261 +// The changes were not backported to all versions of the compilers that GSL supports. +// The `if constexpr` should prevent codegen from happening if it is not supported however a few compilers continue to complain about the logic within. +// Filtering g++ version < 8, clang version < 7, and Apple clang versions 9.4 and 10.1. +#if (defined(_MSC_VER)) || \ +(defined(__GNUC__) && __GNUC__ > 7) || \ +(defined(__APPLE__) && defined(__clang__) && (!(__clang_major__ == 9 && __clang_minor == 4) && !(__clang_major__ == 10 && __clang_minro__ == 1))) || \ +(defined(__clang__) && __clang_major__ > 6) template <class = void> void ArrayConvertibilityCheck() { From 6ef56d73daae558bde2f02a436474c26b35587d7 Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Thu, 9 Apr 2020 10:35:44 -0700 Subject: [PATCH 08/14] fixed a couple typos --- tests/span_compatibility_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index db9efba..e32a507 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -48,7 +48,7 @@ static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value, // Filtering g++ version < 8, clang version < 7, and Apple clang versions 9.4 and 10.1. #if (defined(_MSC_VER)) || \ (defined(__GNUC__) && __GNUC__ > 7) || \ -(defined(__APPLE__) && defined(__clang__) && (!(__clang_major__ == 9 && __clang_minor == 4) && !(__clang_major__ == 10 && __clang_minro__ == 1))) || \ +(defined(__APPLE__) && defined(__clang__) && (!(__clang_major__ == 9 && __clang_minor__ == 4) && !(__clang_major__ == 10 && __clang_minor__ == 1))) || \ (defined(__clang__) && __clang_major__ > 6) template <class = void> void ArrayConvertibilityCheck() From 809aee231519d939c151fc355ded2b4e1b1085c2 Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Thu, 9 Apr 2020 11:51:59 -0700 Subject: [PATCH 09/14] testing different major/minor for Apple suppression --- tests/span_compatibility_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index e32a507..4012839 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -45,10 +45,10 @@ static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value, // int*(*) [], int const* const(*)[] was identified as an issue in CWG330 and the resolution was provided with N4261 // The changes were not backported to all versions of the compilers that GSL supports. // The `if constexpr` should prevent codegen from happening if it is not supported however a few compilers continue to complain about the logic within. -// Filtering g++ version < 8, clang version < 7, and Apple clang versions 9.4 and 10.1. +// Filtering g++ version < 8, clang version < 7, and XCode 9.4 and 10.1 which looks to be Apple clang versions 9.1 and 10.0. #if (defined(_MSC_VER)) || \ (defined(__GNUC__) && __GNUC__ > 7) || \ -(defined(__APPLE__) && defined(__clang__) && (!(__clang_major__ == 9 && __clang_minor__ == 4) && !(__clang_major__ == 10 && __clang_minor__ == 1))) || \ +(defined(__APPLE__) && defined(__clang__) && (!(__clang_major__ == 9 && __clang_minor__ == 1) && !(__clang_major__ == 10 && __clang_minor__ == 0))) || \ (defined(__clang__) && __clang_major__ > 6) template <class = void> void ArrayConvertibilityCheck() From b7d9d754aca05d248ef17688c94186d9016e551a Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Thu, 9 Apr 2020 14:17:52 -0700 Subject: [PATCH 10/14] another attempt at apple clang version filtering --- tests/span_compatibility_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index 4012839..ef9e50c 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -48,7 +48,7 @@ static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value, // Filtering g++ version < 8, clang version < 7, and XCode 9.4 and 10.1 which looks to be Apple clang versions 9.1 and 10.0. #if (defined(_MSC_VER)) || \ (defined(__GNUC__) && __GNUC__ > 7) || \ -(defined(__APPLE__) && defined(__clang__) && (!(__clang_major__ == 9 && __clang_minor__ == 1) && !(__clang_major__ == 10 && __clang_minor__ == 0))) || \ +(defined(__apple_build_version__) && __apple_build_version__ != 10001145 && __apple_build_version__ != 9020039 ) || \ (defined(__clang__) && __clang_major__ > 6) template <class = void> void ArrayConvertibilityCheck() From 8d907dadfbe9d605185b968bc8a9aa73fd196f5b Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Thu, 9 Apr 2020 14:35:44 -0700 Subject: [PATCH 11/14] prevent comparison for apple clang versions older than 11 --- tests/span_compatibility_tests.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index ef9e50c..d8e9e99 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -48,7 +48,7 @@ static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value, // Filtering g++ version < 8, clang version < 7, and XCode 9.4 and 10.1 which looks to be Apple clang versions 9.1 and 10.0. #if (defined(_MSC_VER)) || \ (defined(__GNUC__) && __GNUC__ > 7) || \ -(defined(__apple_build_version__) && __apple_build_version__ != 10001145 && __apple_build_version__ != 9020039 ) || \ +(defined(__apple_build_version__) && defined(__clang__) && __clang_major__ > 10 ) || \ (defined(__clang__) && __clang_major__ > 6) template <class = void> void ArrayConvertibilityCheck() From 5ca02327c4ca3d67f66094c7b5c92f3eb86d4d11 Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Thu, 9 Apr 2020 15:56:26 -0700 Subject: [PATCH 12/14] another test --- tests/span_compatibility_tests.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index d8e9e99..b1be4cb 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -48,8 +48,8 @@ static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value, // Filtering g++ version < 8, clang version < 7, and XCode 9.4 and 10.1 which looks to be Apple clang versions 9.1 and 10.0. #if (defined(_MSC_VER)) || \ (defined(__GNUC__) && __GNUC__ > 7) || \ -(defined(__apple_build_version__) && defined(__clang__) && __clang_major__ > 10 ) || \ -(defined(__clang__) && __clang_major__ > 6) +(defined(__APPLE__) && defined(__clang_major__) && __clang_major__ > 10 ) || \ +(!defined(__APPLE__) && defined(__clang__) && __clang_major__ > 6) template <class = void> void ArrayConvertibilityCheck() { From ffbfcc0a9fecd7740440bfc8ab3dec7a0108ed87 Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Thu, 9 Apr 2020 16:15:08 -0700 Subject: [PATCH 13/14] apply clang-format to the span_compatibility_tests. --- tests/span_compatibility_tests.cpp | 31 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index b1be4cb..e8981d1 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -42,14 +42,14 @@ static_assert(std::is_convertible<Derived*, Base*>::value, "std::is_convertible< static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value, "!std::is_convertible<Derived(*)[], Base(*)[]>"); -// int*(*) [], int const* const(*)[] was identified as an issue in CWG330 and the resolution was provided with N4261 -// The changes were not backported to all versions of the compilers that GSL supports. -// The `if constexpr` should prevent codegen from happening if it is not supported however a few compilers continue to complain about the logic within. -// Filtering g++ version < 8, clang version < 7, and XCode 9.4 and 10.1 which looks to be Apple clang versions 9.1 and 10.0. -#if (defined(_MSC_VER)) || \ -(defined(__GNUC__) && __GNUC__ > 7) || \ -(defined(__APPLE__) && defined(__clang_major__) && __clang_major__ > 10 ) || \ -(!defined(__APPLE__) && defined(__clang__) && __clang_major__ > 6) +// int*(*) [], int const* const(*)[] was identified as an issue in CWG330 and the resolution was +// provided with N4261. The changes were not backported to all versions of the compilers that GSL +// supports. The `if constexpr` should prevent codegen from happening if it is not supported however +// a few compilers continue to complain about the logic within. Filtering g++ version < 8, clang +// version < 7, and XCode 9.4 and 10.1 which looks to be Apple clang versions 9.1 and 10.0. +#if (defined(_MSC_VER)) || (defined(__GNUC__) && __GNUC__ > 7) || \ + (defined(__APPLE__) && defined(__clang_major__) && __clang_major__ > 10) || \ + (!defined(__APPLE__) && defined(__clang__) && __clang_major__ > 6) template <class = void> void ArrayConvertibilityCheck() { @@ -65,18 +65,19 @@ void ArrayConvertibilityCheck() EXPECT_TRUE(sp_const_nullptr_2.data() == stl_nullptr.data()); EXPECT_TRUE(sp_const_nullptr_2.size() == 3); - static_assert(std::is_same<decltype(span{stl_nullptr}), span<int*, 3>>::value, - "std::is_same< decltype(span{stl_nullptr}), span<int*, 3>>::value"); - static_assert( - std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<int* const, 3>>::value, - "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span<int* const, " - "3>>::value"); + static_assert(std::is_same<decltype(span{stl_nullptr}), span<int*, 3>>::value, + "std::is_same< decltype(span{stl_nullptr}), span<int*, 3>>::value"); + static_assert( + std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<int* const, 3>>::value, + "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span<int* const, " + "3>>::value"); } #endif } #else template <class = void> -void ArrayConvertibilityCheck(){} +void ArrayConvertibilityCheck() +{} #endif TEST(span_compatibility_tests, assertion_tests) From efbce17ca498bbdf7bb1694f6323ecfa126b74cc Mon Sep 17 00:00:00 2001 From: Jordan Maples <jomaples@microsoft.com> Date: Thu, 9 Apr 2020 17:33:33 -0700 Subject: [PATCH 14/14] testing one of CaseyCarter's comments --- tests/span_compatibility_tests.cpp | 31 ++++++++++-------------------- 1 file changed, 10 insertions(+), 21 deletions(-) diff --git a/tests/span_compatibility_tests.cpp b/tests/span_compatibility_tests.cpp index e8981d1..ab29748 100644 --- a/tests/span_compatibility_tests.cpp +++ b/tests/span_compatibility_tests.cpp @@ -43,42 +43,31 @@ static_assert(!std::is_convertible<Derived (*)[], Base (*)[]>::value, "!std::is_convertible<Derived(*)[], Base(*)[]>"); // int*(*) [], int const* const(*)[] was identified as an issue in CWG330 and the resolution was -// provided with N4261. The changes were not backported to all versions of the compilers that GSL -// supports. The `if constexpr` should prevent codegen from happening if it is not supported however -// a few compilers continue to complain about the logic within. Filtering g++ version < 8, clang -// version < 7, and XCode 9.4 and 10.1 which looks to be Apple clang versions 9.1 and 10.0. -#if (defined(_MSC_VER)) || (defined(__GNUC__) && __GNUC__ > 7) || \ - (defined(__APPLE__) && defined(__clang_major__) && __clang_major__ > 10) || \ - (!defined(__APPLE__) && defined(__clang__) && __clang_major__ > 6) -template <class = void> +// provided with N4261. +template <class T = int> void ArrayConvertibilityCheck() { #if __cplusplus >= 201703l - if constexpr (std::is_convertible<int*(*) [], int const* const(*)[]>::value) + if constexpr (std::is_convertible<T*(*) [], T const* const(*)[]>::value) { - std::array<int*, 3> stl_nullptr{{nullptr, nullptr, nullptr}}; - gsl::span<const int* const> sp_const_nullptr_1{stl_nullptr}; + std::array<T*, 3> stl_nullptr{{nullptr, nullptr, nullptr}}; + gsl::span<const T* const> sp_const_nullptr_1{stl_nullptr}; EXPECT_TRUE(sp_const_nullptr_1.data() == stl_nullptr.data()); EXPECT_TRUE(sp_const_nullptr_1.size() == 3); - span<const int* const> sp_const_nullptr_2{std::as_const(stl_nullptr)}; + span<const T* const> sp_const_nullptr_2{std::as_const(stl_nullptr)}; EXPECT_TRUE(sp_const_nullptr_2.data() == stl_nullptr.data()); EXPECT_TRUE(sp_const_nullptr_2.size() == 3); - static_assert(std::is_same<decltype(span{stl_nullptr}), span<int*, 3>>::value, - "std::is_same< decltype(span{stl_nullptr}), span<int*, 3>>::value"); + static_assert(std::is_same<decltype(span{stl_nullptr}), span<T*, 3>>::value, + "std::is_same< decltype(span{stl_nullptr}), span<T*, 3>>::value"); static_assert( - std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<int* const, 3>>::value, - "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span<int* const, " + std::is_same<decltype(span{std::as_const(stl_nullptr)}), span<T* const, 3>>::value, + "std::is_same< decltype(span{std::as_const(stl_nullptr)}), span<T* const, " "3>>::value"); } #endif } -#else -template <class = void> -void ArrayConvertibilityCheck() -{} -#endif TEST(span_compatibility_tests, assertion_tests) {