From 1995e86d1ad70519465374fb4876c6ef7c9f8c61 Mon Sep 17 00:00:00 2001 From: Anna Gringauze Date: Sun, 19 Aug 2018 17:10:53 -0700 Subject: [PATCH] span constructor no address (#723) * Changed &arr[0] to std::array::data and std::address_of to protect against overloaded operator&. * Removed the usage of `std::addressof` because it is a C++ 17 feature. Using decay for C arrays instead. * Add unit tests for #662. * Added c++17 test configurations for clang5.0 and clang6.0 * fixed CppCoreCheck pointer decay warning --- include/gsl/span | 7 +++--- tests/span_tests.cpp | 52 ++++++++++++++++++++++++++++++++------------ 2 files changed, 42 insertions(+), 17 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index a4f9256..8cb3dbe 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -29,6 +29,7 @@ #include #include // for enable_if_t, declval, is_convertible, inte... #include +#include // for std::addressof #ifdef _MSC_VER #pragma warning(push) @@ -390,19 +391,19 @@ public: template constexpr span(element_type (&arr)[N]) noexcept - : storage_(KnownNotNull{&arr[0]}, details::extent_type()) + : storage_(KnownNotNull{std::addressof(arr[0])}, details::extent_type()) {} template > // GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug constexpr span(std::array& arr) noexcept - : storage_(&arr[0], details::extent_type()) + : storage_(arr.data(), details::extent_type()) {} template // GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute // TODO: parser bug constexpr span(const std::array, N>& arr) noexcept - : storage_(&arr[0], details::extent_type()) + : storage_(arr.data(), details::extent_type()) {} // NB: the SFINAE here uses .data() as a incomplete/imperfect proxy for the requirement diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index 081221b..07a59c8 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -52,6 +52,10 @@ struct BaseClass struct DerivedClass : BaseClass { }; +struct AddressOverloaded +{ + AddressOverloaded operator&() const { return {}; } +}; } GSL_SUPPRESS(con.4) // NO-FORMAT: attribute @@ -306,19 +310,17 @@ TEST_CASE("from_pointer_pointer_constructor") } } -GSL_SUPPRESS(con.4) // NO-FORMAT: attribute -GSL_SUPPRESS(bounds.3) // NO-FORMAT: attribute // TODO: false positive? TEST_CASE("from_array_constructor") { int arr[5] = {1, 2, 3, 4, 5}; { - span s{arr}; + const span s{arr}; CHECK((s.size() == 5 && s.data() == &arr[0])); } { - span s{arr}; + const span s{arr}; CHECK((s.size() == 5 && s.data() == &arr[0])); } @@ -350,8 +352,8 @@ TEST_CASE("from_array_constructor") } #endif { - span s{&arr2d[0], 1}; - CHECK((s.size() == 1 && s.data() == &arr2d[0])); + const span s{std::addressof(arr2d[0]), 1}; + CHECK((s.size() == 1 && s.data() == std::addressof(arr2d[0]))); } int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12}; @@ -379,24 +381,32 @@ TEST_CASE("from_array_constructor") } #endif { - span s{&arr3d[0], 1}; - CHECK((s.size() == 1 && s.data() == &arr3d[0])); + const span s{std::addressof(arr3d[0]), 1}; + CHECK((s.size() == 1 && s.data() == std::addressof(arr3d[0]))); } { - auto s = make_span(arr); - CHECK((s.size() == 5 && s.data() == &arr[0])); + const auto s = make_span(arr); + CHECK((s.size() == 5 && s.data() == std::addressof(arr[0]))); } { - auto s = make_span(&(arr2d[0]), 1); - CHECK((s.size() == 1 && s.data() == &arr2d[0])); + const auto s = make_span(std::addressof(arr2d[0]), 1); + CHECK((s.size() == 1 && s.data() == std::addressof(arr2d[0]))); } { - auto s = make_span(&arr3d[0], 1); - CHECK((s.size() == 1 && s.data() == &arr3d[0])); + const auto s = make_span(std::addressof(arr3d[0]), 1); + CHECK((s.size() == 1 && s.data() == std::addressof(arr3d[0]))); } + + AddressOverloaded ao_arr[5] = {}; + + { + const span s{ao_arr}; + CHECK((s.size() == 5 && s.data() == std::addressof(ao_arr[0]))); + } + } GSL_SUPPRESS(con.4) // NO-FORMAT: attribute @@ -442,6 +452,13 @@ TEST_CASE("from_std_array_constructor") CHECK((cs.size() == narrow_cast(arr.size()) && cs.data() == arr.data())); } + std::array ao_arr{}; + + { + span fs{ao_arr}; + CHECK((fs.size() == narrow_cast(ao_arr.size()) && ao_arr.data() == fs.data())); + } + #ifdef CONFIRM_COMPILATION_ERRORS { span s{arr}; @@ -516,6 +533,13 @@ TEST_CASE("from_const_std_array_constructor") CHECK((s.size() == narrow_cast(arr.size()) && s.data() == arr.data())); } + const std::array ao_arr{}; + + { + span s{ao_arr}; + CHECK((s.size() == narrow_cast(ao_arr.size()) && s.data() == ao_arr.data())); + } + #ifdef CONFIRM_COMPILATION_ERRORS { span s{arr};