1075 Wrong Expects in gsl::at? (#1076)

https://github.com/microsoft/GSL/issues/1075
- Add `static_assert` because we only support C style array `at` for up to half of the address space.
- Add `std::` before `size_t`.
- tests:
  - Add `#include <exception>`
  - Implement `span_tests` `interop_with_gsl_at` like `at_tests` `std_span`
This commit is contained in:
Werner Henze 2023-01-18 22:33:20 +01:00 committed by GitHub
parent 0822838a7c
commit a381a3759f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 9 deletions

View File

@ -21,6 +21,7 @@
#include <array> #include <array>
#include <cstddef> // for ptrdiff_t, size_t #include <cstddef> // for ptrdiff_t, size_t
#include <limits> // for numeric_limits
#include <initializer_list> // for initializer_list #include <initializer_list> // for initializer_list
#include <type_traits> // for is_signed, integral_constant #include <type_traits> // for is_signed, integral_constant
#include <utility> // for exchange, forward #include <utility> // for exchange, forward
@ -110,6 +111,7 @@ GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on // clang-format on
constexpr T& at(T (&arr)[N], const index i) constexpr T& at(T (&arr)[N], const index i)
{ {
static_assert(N <= static_cast<std::size_t>(std::numeric_limits<std::ptrdiff_t>::max()), "We only support arrays up to PTRDIFF_MAX bytes.");
Expects(i >= 0 && i < narrow_cast<index>(N)); Expects(i >= 0 && i < narrow_cast<index>(N));
return arr[narrow_cast<std::size_t>(i)]; return arr[narrow_cast<std::size_t>(i)];
} }
@ -137,11 +139,11 @@ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
} }
#if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L #if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L
template <class T, size_t extent = std::dynamic_extent> template <class T, std::size_t extent = std::dynamic_extent>
constexpr auto at(std::span<T, extent> sp, const index i) -> decltype(sp[sp.size()]) constexpr auto at(std::span<T, extent> sp, const index i) -> decltype(sp[sp.size()])
{ {
Expects(i >= 0 && i < narrow_cast<index>(sp.size())); Expects(i >= 0 && i < narrow_cast<index>(sp.size()));
return sp[gsl::narrow_cast<size_t>(i)]; return sp[gsl::narrow_cast<std::size_t>(i)];
} }
#endif // __cpp_lib_span >= 202002L #endif // __cpp_lib_span >= 202002L
} // namespace gsl } // namespace gsl

View File

@ -20,6 +20,7 @@
#include <array> // for array #include <array> // for array
#include <cstddef> // for size_t #include <cstddef> // for size_t
#include <exception> // for terminate
#include <initializer_list> // for initializer_list #include <initializer_list> // for initializer_list
#include <vector> // for vector #include <vector> // for vector
#if defined(__cplusplus) && __cplusplus >= 202002L #if defined(__cplusplus) && __cplusplus >= 202002L

View File

@ -19,9 +19,10 @@
#include <gsl/span> // for span and span_ext #include <gsl/span> // for span and span_ext
#include <gsl/util> // for narrow_cast, at #include <gsl/util> // for narrow_cast, at
#include <array> // for array #include <array> // for array
#include <iostream> // for cerr #include <exception> // for terminate
#include <vector> // for vector #include <iostream> // for cerr
#include <vector> // for vector
using namespace std; using namespace std;
using namespace gsl; using namespace gsl;
@ -193,10 +194,28 @@ TEST(span_ext_test, make_span_from_container_constructor)
TEST(span_test, interop_with_gsl_at) TEST(span_test, interop_with_gsl_at)
{ {
int arr[5] = {1, 2, 3, 4, 5}; std::vector<int> vec{1, 2, 3, 4, 5};
gsl::span<int> s{arr}; gsl::span<int> sp{vec};
EXPECT_TRUE(at(s, 0) == 1);
EXPECT_TRUE(at(s, 1) == 2); std::vector<int> cvec{1, 2, 3, 4, 5};
gsl::span<int> csp{cvec};
for (gsl::index i = 0; i < gsl::narrow_cast<gsl::index>(vec.size()); ++i)
{
EXPECT_TRUE(&gsl::at(sp, i) == &vec[gsl::narrow_cast<size_t>(i)]);
EXPECT_TRUE(&gsl::at(csp, i) == &cvec[gsl::narrow_cast<size_t>(i)]);
}
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. interop_with_gsl_at";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
EXPECT_DEATH(gsl::at(sp, -1), expected);
EXPECT_DEATH(gsl::at(sp, gsl::narrow_cast<gsl::index>(sp.size())), expected);
EXPECT_DEATH(gsl::at(csp, -1), expected);
EXPECT_DEATH(gsl::at(csp, gsl::narrow_cast<gsl::index>(sp.size())), expected);
} }
TEST(span_ext_test, iterator_free_functions) TEST(span_ext_test, iterator_free_functions)