gsl::at behavior change regarding gsl::span (#985)

* move span specialization of 'at' to <gsl/span> and update the parameter to be taken by reference

* undid previous changes and acted upon decisions made in maintainer sync. Fixed tests failing in /kernel mode

* ran clang-format on the include folder

* ran clang-format on the test folder

Co-authored-by: Jordan Maples <jordan.maples@microsoft.com>
This commit is contained in:
Jordan Maples [MSFT] 2021-05-20 18:18:08 -07:00 committed by GitHub
parent c1cbb41b42
commit b26f6d5ec7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 1304 additions and 1175 deletions

View File

@ -22,6 +22,7 @@
// Currently terminate is a no-op in this mode, so we add termination behavior back
//
#if defined(_MSC_VER) && (defined(_KERNEL_MODE) || (defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS))
#define GSL_KERNEL_MODE
#define GSL_MSVC_USE_STL_NOEXCEPTION_WORKAROUND
#include <intrin.h>

View File

@ -1,3 +1,4 @@
#pragma once
#pragma message("This header will soon be removed. Use <gsl/algorithm> instead of <gsl/gsl_algorithm>")
#pragma message( \
"This header will soon be removed. Use <gsl/algorithm> instead of <gsl/gsl_algorithm>")
#include <gsl/algorithm>

View File

@ -35,10 +35,17 @@ namespace gsl
namespace details
{
template <typename T, typename = void>
struct is_comparable_to_nullptr : std::false_type {};
struct is_comparable_to_nullptr : std::false_type
{
};
template <typename T>
struct is_comparable_to_nullptr<T, std::enable_if_t<std::is_convertible<decltype(std::declval<T>() != nullptr), bool>::value>> : std::true_type {};
struct is_comparable_to_nullptr<
T,
std::enable_if_t<std::is_convertible<decltype(std::declval<T>() != nullptr), bool>::value>>
: std::true_type
{
};
} // namespace details
//

View File

@ -23,6 +23,7 @@
#include <array> // for array
#include <cstddef> // for ptrdiff_t, size_t, nullptr_t
#include <gsl/span_ext> // for span specialization of gsl::at and other span-related extensions
#include <iterator> // for reverse_iterator, distance, random_access_...
#include <type_traits> // for enable_if_t, declval, is_convertible, inte...
@ -60,12 +61,6 @@
namespace gsl
{
// [views.constants], constants
constexpr const std::size_t dynamic_extent = narrow_cast<std::size_t>(-1);
template <class ElementType, std::size_t Extent = dynamic_extent>
class span;
// implementation details
namespace details
{

View File

@ -27,16 +27,29 @@
//
///////////////////////////////////////////////////////////////////////////////
#include <gsl/span> // for span
#include <gsl/assert> // GSL_KERNEL_MODE
#include <gsl/util> // for narrow_cast, narrow
#include <algorithm> // for lexicographical_compare
#include <cstddef> // for ptrdiff_t, size_t
#include <utility>
#ifndef GSL_KERNEL_MODE
#include <algorithm> // for lexicographical_compare
#endif // GSL_KERNEL_MODE
namespace gsl
{
// [span.views.constants], constants
constexpr const std::size_t dynamic_extent = narrow_cast<std::size_t>(-1);
template <class ElementType, std::size_t Extent = dynamic_extent>
class span;
// std::equal and std::lexicographical_compare are not /kernel compatible
// so all comparison operators must be removed for kernel mode.
#ifndef GSL_KERNEL_MODE
// [span.comparison], span comparison operators
template <class ElementType, std::size_t FirstExtent, std::size_t SecondExtent>
constexpr bool operator==(span<ElementType, FirstExtent> l, span<ElementType, SecondExtent> r)
@ -74,6 +87,8 @@ constexpr bool operator>=(span<ElementType, Extent> l, span<ElementType, Extent>
return !(l < r);
}
#endif // GSL_KERNEL_MODE
//
// make_span() - Utility functions for creating spans
//

View File

@ -25,6 +25,10 @@
#include <type_traits> // for is_signed, integral_constant
#include <utility> // for exchange, forward
#if defined(__cplusplus) && __cplusplus >= 202002L
#include <span>
#endif // __cplusplus >= 202002L
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
@ -134,6 +138,14 @@ constexpr T at(const std::initializer_list<T> cont, const index i)
return *(cont.begin() + i);
}
#if defined(__cplusplus) && __cplusplus >= 202002L
template <class T, size_t extent = std::dynamic_extent>
constexpr auto at(std::span<T, extent> sp, const index i)
{
Expects(i >= 0 && i < narrow_cast<i>(sp.size()));
return sp[i];
}
#endif // __cplusplus >= 202002L
} // namespace gsl
#if defined(_MSC_VER) && !defined(__clang__)

View File

@ -14,16 +14,13 @@
//
///////////////////////////////////////////////////////////////////////////////
#include <gtest/gtest.h>
#include <gsl/algorithm> // for copy
#include <gsl/span> // for span
#include <array> // for array
#include <cstddef> // for size_t
#include <gsl/algorithm> // for copy
#include <gsl/span> // for span
#include <gtest/gtest.h>
namespace
{
static constexpr char deathstring[] = "Expected Death";
}
#include "deathTestCommon.h"
namespace gsl
{
@ -204,10 +201,11 @@ TEST(algorithm_tests, incompatible_type)
TEST(algorithm_tests, small_destination_span)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. small_destination_span";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
std::array<int, 12> src{1, 2, 3, 4};
std::array<int, 4> dst{};
@ -217,9 +215,9 @@ TEST(algorithm_tests, small_destination_span)
const span<int> dst_span_dyn(dst);
const span<int, 4> dst_span_static(dst);
EXPECT_DEATH(copy(src_span_dyn, dst_span_dyn), deathstring);
EXPECT_DEATH(copy(src_span_dyn, dst_span_static), deathstring);
EXPECT_DEATH(copy(src_span_static, dst_span_dyn), deathstring);
EXPECT_DEATH(copy(src_span_dyn, dst_span_dyn), expected);
EXPECT_DEATH(copy(src_span_dyn, dst_span_static), expected);
EXPECT_DEATH(copy(src_span_static, dst_span_dyn), expected);
#ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static);

View File

@ -14,14 +14,14 @@
//
///////////////////////////////////////////////////////////////////////////////
#include <gtest/gtest.h>
#include "deathTestCommon.h"
#include <gsl/assert> // for fail_fast (ptr only), Ensures, Expects
#include <gtest/gtest.h>
using namespace gsl;
namespace
{
static constexpr char deathstring[] = "Expected Death";
int f(int i)
{
@ -39,23 +39,22 @@ int g(int i)
TEST(assertion_tests, expects)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. expects";
std::abort();
});
EXPECT_TRUE(f(2) == 2);
EXPECT_DEATH(f(10), deathstring);
EXPECT_DEATH(f(10), GetExpectedDeathString(terminateHandler));
}
TEST(assertion_tests, ensures)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. ensures";
std::abort();
});
EXPECT_TRUE(g(2) == 3);
EXPECT_DEATH(g(9), deathstring);
EXPECT_DEATH(g(9), GetExpectedDeathString(terminateHandler));
}

View File

@ -22,31 +22,33 @@
#include <cstddef> // for size_t
#include <initializer_list> // for initializer_list
#include <vector> // for vector
#if defined(__cplusplus) && __cplusplus >= 202002L
#include <span>
#endif // __cplusplus >= 202002L
namespace
{
static constexpr char deathstring[] = "Expected Death";
}
#include "deathTestCommon.h"
TEST(at_tests, static_array)
{
int a[4] = {1, 2, 3, 4};
const int(&c_a)[4] = a;
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
EXPECT_TRUE(&gsl::at(a, i) == &a[i]);
EXPECT_TRUE(&gsl::at(c_a, i) == &a[i]);
}
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. static_array";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
EXPECT_DEATH(gsl::at(a, -1), deathstring);
EXPECT_DEATH(gsl::at(a, 4), deathstring);
EXPECT_DEATH(gsl::at(c_a, -1), deathstring);
EXPECT_DEATH(gsl::at(c_a, 4), deathstring);
EXPECT_DEATH(gsl::at(a, -1), expected);
EXPECT_DEATH(gsl::at(a, 4), expected);
EXPECT_DEATH(gsl::at(c_a, -1), expected);
EXPECT_DEATH(gsl::at(c_a, 4), expected);
}
TEST(at_tests, std_array)
@ -54,20 +56,22 @@ TEST(at_tests, std_array)
std::array<int, 4> a = {1, 2, 3, 4};
const std::array<int, 4>& c_a = a;
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast<std::size_t>(i)]);
EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast<std::size_t>(i)]);
}
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. std_array";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
EXPECT_DEATH(gsl::at(a, -1), deathstring);
EXPECT_DEATH(gsl::at(a, 4), deathstring);
EXPECT_DEATH(gsl::at(c_a, -1), deathstring);
EXPECT_DEATH(gsl::at(c_a, 4), deathstring);
EXPECT_DEATH(gsl::at(a, -1), expected);
EXPECT_DEATH(gsl::at(a, 4), expected);
EXPECT_DEATH(gsl::at(c_a, -1), expected);
EXPECT_DEATH(gsl::at(c_a, 4), expected);
}
TEST(at_tests, std_vector)
@ -75,42 +79,68 @@ TEST(at_tests, std_vector)
std::vector<int> a = {1, 2, 3, 4};
const std::vector<int>& c_a = a;
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
EXPECT_TRUE(&gsl::at(a, i) == &a[static_cast<std::size_t>(i)]);
EXPECT_TRUE(&gsl::at(c_a, i) == &a[static_cast<std::size_t>(i)]);
}
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. std_vector";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
EXPECT_DEATH(gsl::at(a, -1), deathstring);
EXPECT_DEATH(gsl::at(a, 4), deathstring);
EXPECT_DEATH(gsl::at(c_a, -1), deathstring);
EXPECT_DEATH(gsl::at(c_a, 4), deathstring);
EXPECT_DEATH(gsl::at(a, -1), expected);
EXPECT_DEATH(gsl::at(a, 4), expected);
EXPECT_DEATH(gsl::at(c_a, -1), expected);
EXPECT_DEATH(gsl::at(c_a, 4), expected);
}
TEST(at_tests, InitializerList)
{
const std::initializer_list<int> a = {1, 2, 3, 4};
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
EXPECT_TRUE(gsl::at(a, i) == i + 1);
EXPECT_TRUE(gsl::at({1, 2, 3, 4}, i) == i + 1);
}
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. InitializerList";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
EXPECT_DEATH(gsl::at(a, -1), deathstring);
EXPECT_DEATH(gsl::at(a, 4), deathstring);
EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), deathstring);
EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), deathstring);
EXPECT_DEATH(gsl::at(a, -1), expected);
EXPECT_DEATH(gsl::at(a, 4), expected);
EXPECT_DEATH(gsl::at({1, 2, 3, 4}, -1), expected);
EXPECT_DEATH(gsl::at({1, 2, 3, 4}, 4), expected);
}
#if defined(__cplusplus) && __cplusplus >= 202002L
TEST(at_tests, std_span)
{
std::vector<int> vec{1, 2, 3, 4, 5};
std::span sp{vec};
std::vector<int> cvec{1, 2, 3, 4, 5};
std::span csp{cvec};
for (size_t i = 0, i < vec.size(); ++i)
{
EXPECT_TRUE(&gsl::at(sp, i) == &vec[i]);
EXPECT_TRUE(&gsl::at(csp, i) == &cvec[i]);
}
EXPECT_DEATH(gsl::at(sp, -1), expected);
EXPECT_DEATH(gsl::at(sp, sp.size()), expected);
EXPECT_DEATH(gsl::at(csp, -1), expected);
EXPECT_DEATH(gsl::at(csp, sp.size()), expected);
}
#endif // __cplusplus >= 202002L
#if !defined(_MSC_VER) || defined(__clang__) || _MSC_VER >= 1910
static constexpr bool test_constexpr()
{
@ -119,7 +149,8 @@ static constexpr bool test_constexpr()
std::array<int, 4> a2 = {1, 2, 3, 4};
const std::array<int, 4>& c_a2 = a2;
for (int i = 0; i < 4; ++i) {
for (int i = 0; i < 4; ++i)
{
if (&gsl::at(a1, i) != &a1[i]) return false;
if (&gsl::at(c_a1, i) != &a1[i]) return false;
// requires C++17:

View File

@ -37,7 +37,9 @@ TEST(byte_tests, construction)
EXPECT_TRUE(static_cast<unsigned char>(b) == 4);
}
// clang-format off
GSL_SUPPRESS(es.49)
// clang-format on
{
const byte b = byte(12);
EXPECT_TRUE(static_cast<unsigned char>(b) == 12);
@ -122,7 +124,7 @@ TEST(byte_tests, aliasing)
EXPECT_TRUE(res == i);
}
}
} // namespace
#ifdef CONFIRM_COMPILATION_ERRORS
copy(src_span_static, dst_span_static);

11
tests/deathTestCommon.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include <gsl/assert>
constexpr char deathstring[] = "Expected Death";
constexpr char failed_set_terminate_deathstring[] = ".*";
// This prevents a failed call to set_terminate from failing the test suite.
constexpr const char* GetExpectedDeathString(std::terminate_handler handle)
{
return handle ? deathstring : failed_set_terminate_deathstring;
}

View File

@ -25,13 +25,9 @@
#include <string> // for basic_string, operator==, string, operator<<
#include <typeinfo> // for type_info
#include "deathTestCommon.h"
using namespace gsl;
namespace
{
constexpr char deathstring[] = "Expected Death";
} // namespace
struct MyBase
{
};
@ -64,7 +60,9 @@ struct CustomPtr
template <typename T, typename U>
std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
return reinterpret_cast<const void*>(lhs.p_) == reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@ -72,7 +70,9 @@ std::string operator==(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U>
std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
return reinterpret_cast<const void*>(lhs.p_) != reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@ -80,7 +80,9 @@ std::string operator!=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U>
std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
return reinterpret_cast<const void*>(lhs.p_) < reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@ -88,7 +90,9 @@ std::string operator<(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U>
std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
return reinterpret_cast<const void*>(lhs.p_) > reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@ -96,7 +100,9 @@ std::string operator>(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U>
std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
return reinterpret_cast<const void*>(lhs.p_) <= reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@ -104,7 +110,9 @@ std::string operator<=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
template <typename T, typename U>
std::string operator>=(CustomPtr<T> const& lhs, CustomPtr<U> const& rhs)
{
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
return reinterpret_cast<const void*>(lhs.p_) >= reinterpret_cast<const void*>(rhs.p_) ? "true"
: "false";
}
@ -120,9 +128,13 @@ struct NonCopyableNonMovable
namespace
{
// clang-format off
GSL_SUPPRESS(f .4) // NO-FORMAT: attribute
// clang-format on
bool helper(not_null<int*> p) { return *p == 12; }
// clang-format off
GSL_SUPPRESS(f .4) // NO-FORMAT: attribute
// clang-format on
bool helper_const(not_null<const int*> p) { return *p == 12; }
int* return_pointer() { return nullptr; }
@ -145,10 +157,12 @@ TEST(notnull_tests, TestNotNullConstructors)
#endif
}
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. TestNotNullConstructors";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
{
// from shared pointer
int i = 12;
@ -160,7 +174,7 @@ TEST(notnull_tests, TestNotNullConstructors)
std::make_shared<int>(10)); // shared_ptr<int> is nullptr assignable
int* pi = nullptr;
EXPECT_DEATH((not_null<decltype(pi)>(pi)), deathstring);
EXPECT_DEATH((not_null<decltype(pi)>(pi)), expected);
}
{
@ -217,8 +231,8 @@ TEST(notnull_tests, TestNotNullConstructors)
{
// from returned pointer
EXPECT_DEATH(helper(return_pointer()), deathstring);
EXPECT_DEATH(helper_const(return_pointer()), deathstring);
EXPECT_DEATH(helper(return_pointer()), expected);
EXPECT_DEATH(helper_const(return_pointer()), expected);
}
}
@ -278,17 +292,18 @@ TEST(notnull_tests, TestNotNullCasting)
TEST(notnull_tests, TestNotNullAssignment)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. TestNotNullAssignmentd";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
int i = 12;
not_null<int*> p(&i);
EXPECT_TRUE(helper(p));
int* q = nullptr;
EXPECT_DEATH(p = not_null<int*>(q), deathstring);
EXPECT_DEATH(p = not_null<int*>(q), expected);
}
TEST(notnull_tests, TestNotNullRawPointerComparison)
@ -437,17 +452,18 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction)
EXPECT_TRUE(*x == 42);
}
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. TestNotNullConstructorTypeDeduction";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
{
auto workaround_macro = []() {
int* p1 = nullptr;
const not_null x{p1};
};
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
{
@ -455,14 +471,14 @@ TEST(notnull_tests, TestNotNullConstructorTypeDeduction)
const int* p1 = nullptr;
const not_null x{p1};
};
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
{
int* p = nullptr;
EXPECT_DEATH(helper(not_null{p}), deathstring);
EXPECT_DEATH(helper_const(not_null{p}), deathstring);
EXPECT_DEATH(helper(not_null{p}), expected);
EXPECT_DEATH(helper_const(not_null{p}), expected);
}
#ifdef CONFIRM_COMPILATION_ERRORS
@ -498,10 +514,11 @@ TEST(notnull_tests, TestMakeNotNull)
EXPECT_TRUE(*x == 42);
}
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. TestMakeNotNull";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
{
const auto workaround_macro = []() {
@ -509,7 +526,7 @@ TEST(notnull_tests, TestMakeNotNull)
const auto x = make_not_null(p1);
EXPECT_TRUE(*x == 42);
};
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
{
@ -518,21 +535,21 @@ TEST(notnull_tests, TestMakeNotNull)
const auto x = make_not_null(p1);
EXPECT_TRUE(*x == 42);
};
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
{
int* p = nullptr;
EXPECT_DEATH(helper(make_not_null(p)), deathstring);
EXPECT_DEATH(helper_const(make_not_null(p)), deathstring);
EXPECT_DEATH(helper(make_not_null(p)), expected);
EXPECT_DEATH(helper_const(make_not_null(p)), expected);
}
#ifdef CONFIRM_COMPILATION_ERRORS
{
EXPECT_DEATH(make_not_null(nullptr), deathstring);
EXPECT_DEATH(helper(make_not_null(nullptr)), deathstring);
EXPECT_DEATH(helper_const(make_not_null(nullptr)), deathstring);
EXPECT_DEATH(make_not_null(nullptr), expected);
EXPECT_DEATH(helper(make_not_null(nullptr)), expected);
EXPECT_DEATH(helper_const(make_not_null(nullptr)), expected);
}
#endif
}

View File

@ -16,8 +16,8 @@
#include <gtest/gtest.h>
#include <gsl/span> // for span and span_ext
#include <gsl/util> // for narrow_cast, at
#include <gsl/span_ext> // for operator==, operator!=, make_span
#include <array> // for array
#include <iostream> // for cerr
@ -26,17 +26,16 @@
using namespace std;
using namespace gsl;
namespace
{
static constexpr char deathstring[] = "Expected Death";
} // namespace
#include "deathTestCommon.h"
TEST(span_ext_test, make_span_from_pointer_length_constructor)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. from_pointer_length_constructor";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
int arr[4] = {1, 2, 3, 4};
{
@ -57,7 +56,7 @@ TEST(span_ext_test, make_span_from_pointer_length_constructor)
{
int* p = nullptr;
auto workaround_macro = [=]() { make_span(p, 2); };
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
}
@ -239,6 +238,7 @@ TEST(span_ext_test, make_span_from_array_constructor)
EXPECT_TRUE(s.size() == static_cast<std::size_t>(ssize(s)));
}
#ifndef GSL_KERNEL_MODE
TEST(span_ext_test, comparison_operators)
{
{
@ -358,3 +358,4 @@ TEST(span_ext_test, make_span_from_array_constructor)
EXPECT_FALSE(s1 >= s2);
}
}
#endif // GSL_KERNEL_MODE

View File

@ -17,19 +17,19 @@
#include <gtest/gtest.h>
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast, at
#include <gsl/span> // for span, span_iterator, operator==, operator!=
#include <gsl/util> // for narrow_cast, at
#include <array> // for array
#include <cstddef> // for ptrdiff_t
#include <iostream> // for ptrdiff_t
#include <iterator> // for reverse_iterator, operator-, operator==
#include <memory> // for unique_ptr, shared_ptr, make_unique, allo...
#include <regex> // for match_results, sub_match, match_results<>...
#include <cstddef> // for ptrdiff_t
#include <string> // for string
#include <type_traits> // for integral_constant<>::value, is_default_co...
#include <vector> // for vector
#include <utility>
#include <vector> // for vector
// the string_view include and macro are used in the deduction guide verification
#if (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
@ -41,12 +41,13 @@
#endif // __has_include
#endif // (defined(__cpp_deduction_guides) && (__cpp_deduction_guides >= 201611L))
#include "deathTestCommon.h"
using namespace std;
using namespace gsl;
namespace
{
static constexpr char deathstring[] = "Expected Death";
struct BaseClass
{
@ -111,10 +112,12 @@ TEST(span_test, size_optimization)
TEST(span_test, from_nullptr_size_constructor)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. from_nullptr_size_constructor";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
{
span<int> s{nullptr, narrow_cast<span<int>::size_type>(0)};
EXPECT_TRUE(s.size() == 0);
@ -128,21 +131,21 @@ TEST(span_test, from_nullptr_size_constructor)
auto workaround_macro = []() {
const span<int, 1> s{nullptr, narrow_cast<span<int>::size_type>(0)};
};
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
{
auto workaround_macro = []() { const span<int> s{nullptr, 1}; };
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
auto const_workaround_macro = []() { const span<const int> s{nullptr, 1}; };
EXPECT_DEATH(const_workaround_macro(), deathstring);
EXPECT_DEATH(const_workaround_macro(), expected);
}
{
auto workaround_macro = []() { const span<int, 0> s{nullptr, 1}; };
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
auto const_workaround_macro = []() { const span<const int, 0> s{nullptr, 1}; };
EXPECT_DEATH(const_workaround_macro(), deathstring);
EXPECT_DEATH(const_workaround_macro(), expected);
}
{
span<int*> s{nullptr, narrow_cast<span<int>::size_type>(0)};
@ -157,10 +160,12 @@ TEST(span_test, from_nullptr_size_constructor)
TEST(span_test, from_pointer_length_constructor)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. from_pointer_length_constructor";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
int arr[4] = {1, 2, 3, 4};
{
@ -171,8 +176,7 @@ TEST(span_test, from_pointer_length_constructor)
EXPECT_TRUE(s.size() == narrow_cast<std::size_t>(i));
EXPECT_TRUE(s.data() == &arr[0]);
EXPECT_TRUE(s.empty() == (i == 0));
for (int j = 0; j < i; ++j)
EXPECT_TRUE(arr[j] == s[narrow_cast<std::size_t>(j)]);
for (int j = 0; j < i; ++j) EXPECT_TRUE(arr[j] == s[narrow_cast<std::size_t>(j)]);
}
{
span<int> s = {&arr[i], 4 - narrow_cast<std::size_t>(i)};
@ -204,7 +208,7 @@ TEST(span_test, from_pointer_length_constructor)
{
int* p = nullptr;
auto workaround_macro = [=]() { const span<int> s{p, 2}; };
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
}
@ -242,14 +246,14 @@ TEST(span_test, from_pointer_pointer_construction)
// this will fail the std::distance() precondition, which asserts on MSVC debug builds
//{
// auto workaround_macro = [&]() { span<int> s{&arr[1], &arr[0]}; };
// EXPECT_DEATH(workaround_macro(), deathstring);
// EXPECT_DEATH(workaround_macro(), expected);
//}
// this will fail the std::distance() precondition, which asserts on MSVC debug builds
//{
// int* p = nullptr;
// auto workaround_macro = [&]() { span<int> s{&arr[0], p}; };
// EXPECT_DEATH(workaround_macro(), deathstring);
// EXPECT_DEATH(workaround_macro(), expected);
//}
{
@ -270,7 +274,7 @@ TEST(span_test, from_pointer_pointer_construction)
//{
// int* p = nullptr;
// auto workaround_macro = [&]() { span<int> s{&arr[0], p}; };
// EXPECT_DEATH(workaround_macro(), deathstring);
// EXPECT_DEATH(workaround_macro(), expected);
//}
}
@ -692,7 +696,8 @@ TEST(span_test, from_array_constructor)
auto use_span = [&](span<const int> s) {
EXPECT_TRUE(s.size() == 2);
EXPECT_TRUE(s.data() == &arr[1]);
}; use_span(get_temp_span());
};
use_span(get_temp_span());
s1 = get_temp_span();
EXPECT_TRUE(s1.size() == 2);
@ -701,10 +706,12 @@ TEST(span_test, from_array_constructor)
TEST(span_test, first)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. first";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
int arr[5] = {1, 2, 3, 4, 5};
{
@ -731,7 +738,7 @@ TEST(span_test, from_array_constructor)
EXPECT_TRUE(av.first<6>().size() == 6);
EXPECT_TRUE(av.first<-1>().size() == -1);
#endif
EXPECT_DEATH(av.first(6).size(), deathstring);
EXPECT_DEATH(av.first(6).size(), expected);
}
{
@ -743,10 +750,12 @@ TEST(span_test, from_array_constructor)
TEST(span_test, last)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. last";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
int arr[5] = {1, 2, 3, 4, 5};
{
@ -772,7 +781,7 @@ TEST(span_test, from_array_constructor)
#ifdef CONFIRM_COMPILATION_ERRORS
EXPECT_TRUE(av.last<6>().size() == 6);
#endif
EXPECT_DEATH(av.last(6).size(), deathstring);
EXPECT_DEATH(av.last(6).size(), expected);
}
{
@ -784,10 +793,12 @@ TEST(span_test, from_array_constructor)
TEST(span_test, subspan)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. subspan";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
int arr[5] = {1, 2, 3, 4, 5};
{
@ -811,8 +822,8 @@ TEST(span_test, from_array_constructor)
EXPECT_TRUE(decltype(av.subspan<0, 5>())::extent == 5);
EXPECT_TRUE(av.subspan(0, 5).size() == 5);
EXPECT_DEATH(av.subspan(0, 6).size(), deathstring);
EXPECT_DEATH(av.subspan(1, 5).size(), deathstring);
EXPECT_DEATH(av.subspan(0, 6).size(), expected);
EXPECT_DEATH(av.subspan(1, 5).size(), expected);
}
{
@ -821,7 +832,7 @@ TEST(span_test, from_array_constructor)
EXPECT_TRUE(decltype(av.subspan<4, 0>())::extent == 0);
EXPECT_TRUE(av.subspan(4, 0).size() == 0);
EXPECT_TRUE(av.subspan(5, 0).size() == 0);
EXPECT_DEATH(av.subspan(6, 0).size(), deathstring);
EXPECT_DEATH(av.subspan(6, 0).size(), expected);
}
{
@ -835,13 +846,13 @@ TEST(span_test, from_array_constructor)
EXPECT_TRUE((av.subspan<0, 0>().size()) == 0);
EXPECT_TRUE(decltype(av.subspan<0, 0>())::extent == 0);
EXPECT_TRUE(av.subspan(0, 0).size() == 0);
EXPECT_DEATH((av.subspan<1, 0>().size()), deathstring);
EXPECT_DEATH((av.subspan<1, 0>().size()), expected);
}
{
span<int> av;
EXPECT_TRUE(av.subspan(0).size() == 0);
EXPECT_DEATH(av.subspan(1).size(), deathstring);
EXPECT_DEATH(av.subspan(1).size(), expected);
}
{
@ -850,7 +861,7 @@ TEST(span_test, from_array_constructor)
EXPECT_TRUE(av.subspan(1).size() == 4);
EXPECT_TRUE(av.subspan(4).size() == 1);
EXPECT_TRUE(av.subspan(5).size() == 0);
EXPECT_DEATH(av.subspan(6).size(), deathstring);
EXPECT_DEATH(av.subspan(6).size(), expected);
const auto av2 = av.subspan(1);
for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast<int>(i) + 2);
}
@ -861,7 +872,7 @@ TEST(span_test, from_array_constructor)
EXPECT_TRUE(av.subspan(1).size() == 4);
EXPECT_TRUE(av.subspan(4).size() == 1);
EXPECT_TRUE(av.subspan(5).size() == 0);
EXPECT_DEATH(av.subspan(6).size(), deathstring);
EXPECT_DEATH(av.subspan(6).size(), expected);
const auto av2 = av.subspan(1);
for (std::size_t i = 0; i < 4; ++i) EXPECT_TRUE(av2[i] == static_cast<int>(i) + 2);
}
@ -906,10 +917,11 @@ TEST(span_test, from_array_constructor)
TEST(span_test, incomparable_iterators)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. incomparable_iterators";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
int a[] = {1, 2, 3, 4};
int b[] = {1, 2, 3, 4};
@ -917,21 +929,23 @@ TEST(span_test, from_array_constructor)
span<int> s = a;
span<int> s2 = b;
#if (__cplusplus > 201402L)
EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() == s2.begin()), deathstring);
EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() <= s2.begin()), deathstring);
EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() == s2.begin()), expected);
EXPECT_DEATH([[maybe_unused]] bool _ = (s.begin() <= s2.begin()), expected);
#else
EXPECT_DEATH(bool _ = (s.begin() == s2.begin()), deathstring);
EXPECT_DEATH(bool _ = (s.begin() <= s2.begin()), deathstring);
EXPECT_DEATH(bool _ = (s.begin() == s2.begin()), expected);
EXPECT_DEATH(bool _ = (s.begin() <= s2.begin()), expected);
#endif
}
}
TEST(span_test, begin_end)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. begin_end";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
{
int a[] = {1, 2, 3, 4};
span<int> s = a;
@ -956,7 +970,7 @@ TEST(span_test, from_array_constructor)
auto beyond = s.end();
EXPECT_TRUE(it != beyond);
EXPECT_DEATH(*beyond, deathstring);
EXPECT_DEATH(*beyond, expected);
EXPECT_TRUE(beyond - first == 4);
EXPECT_TRUE(first - first == 0);
@ -986,10 +1000,12 @@ TEST(span_test, from_array_constructor)
TEST(span_test, rbegin_rend)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. rbegin_rend";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
{
int a[] = {1, 2, 3, 4};
span<int> s = a;
@ -1002,9 +1018,9 @@ TEST(span_test, from_array_constructor)
auto beyond = s.rend();
EXPECT_TRUE(it != beyond);
#if (__cplusplus > 201402L)
EXPECT_DEATH([[maybe_unused]] auto _ = *beyond , deathstring);
EXPECT_DEATH([[maybe_unused]] auto _ = *beyond, expected);
#else
EXPECT_DEATH(auto _ = *beyond , deathstring);
EXPECT_DEATH(auto _ = *beyond, expected);
#endif
EXPECT_TRUE(beyond - first == 4);
@ -1035,10 +1051,11 @@ TEST(span_test, from_array_constructor)
TEST(span_test, as_bytes)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. as_bytes";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
int a[] = {1, 2, 3, 4};
{
@ -1069,7 +1086,7 @@ TEST(span_test, from_array_constructor)
int b[5] = {1, 2, 3, 4, 5};
{
span<int> sp(begin(b), static_cast<size_t>(-2));
EXPECT_DEATH((void) sp.size_bytes(), deathstring);
EXPECT_DEATH((void) sp.size_bytes(), expected);
}
}
@ -1108,10 +1125,12 @@ TEST(span_test, from_array_constructor)
TEST(span_test, fixed_size_conversions)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. fixed_size_conversions";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
int arr[] = {1, 2, 3, 4};
// converting to an span from an equal size array is ok
@ -1146,7 +1165,7 @@ TEST(span_test, from_array_constructor)
const span<int, 2> s2 = s;
static_cast<void>(s2);
};
EXPECT_DEATH(f(), deathstring);
EXPECT_DEATH(f(), expected);
*/
}
@ -1193,17 +1212,18 @@ TEST(span_test, from_array_constructor)
const span<int, 4> _s4{arr2, 2};
static_cast<void>(_s4);
};
EXPECT_DEATH(f(), deathstring);
EXPECT_DEATH(f(), expected);
}
/*
// This no longer compiles. There is no suitable conversion from dynamic span to a fixed size span.
// This no longer compiles. There is no suitable conversion from dynamic span to a fixed size
span.
// this should fail - we are trying to assign a small dynamic span to a fixed_size larger one
span<int> av = arr2; auto f = [&]() {
const span<int, 4> _s4 = av;
static_cast<void>(_s4);
};
EXPECT_DEATH(f(), deathstring);
EXPECT_DEATH(f(), expected);
*/
}
@ -1268,11 +1288,13 @@ TEST(span_test, from_array_constructor)
EXPECT_TRUE(s.front() == 1);
EXPECT_TRUE(s.back() == 5);
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. front_back";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
span<int> s2;
EXPECT_DEATH(s2.front(), deathstring);
EXPECT_DEATH(s2.back(), deathstring);
EXPECT_DEATH(s2.front(), expected);
EXPECT_DEATH(s2.back(), expected);
}

View File

@ -14,23 +14,33 @@
//
///////////////////////////////////////////////////////////////////////////////
#include <gtest/gtest.h>
#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
#include <gtest/gtest.h>
#include "deathTestCommon.h"
using namespace gsl;
namespace
{
// clang-format off
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
// clang-format on
bool helper(not_null<int*> p) { return *p == 12; }
// clang-format off
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
// clang-format on
bool helper_const(not_null<const int*> p) { return *p == 12; }
// clang-format off
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
// clang-format on
bool strict_helper(strict_not_null<int*> p) { return *p == 12; }
// clang-format off
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
// clang-format on
bool strict_helper_const(strict_not_null<const int*> p) { return *p == 12; }
#ifdef CONFIRM_COMPILATION_ERRORS
@ -123,17 +133,14 @@ TEST(strict_notnull_tests, TestStrictNotNull)
}
#if defined(__cplusplus) && (__cplusplus >= 201703L)
namespace
{
static constexpr char deathstring[] = "Expected Death";
}
TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. TestStrictNotNullConstructorTypeDeduction";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
{
int i = 42;
@ -161,7 +168,7 @@ TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction)
int* p1 = nullptr;
const strict_not_null x{p1};
};
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
{
@ -169,14 +176,14 @@ TEST(strict_notnull_tests, TestStrictNotNullConstructorTypeDeduction)
const int* p1 = nullptr;
const strict_not_null x{p1};
};
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
{
int* p = nullptr;
EXPECT_DEATH(helper(strict_not_null{p}), deathstring);
EXPECT_DEATH(helper_const(strict_not_null{p}), deathstring);
EXPECT_DEATH(helper(strict_not_null{p}), expected);
EXPECT_DEATH(helper_const(strict_not_null{p}), expected);
}
#ifdef CONFIRM_COMPILATION_ERRORS

View File

@ -28,13 +28,11 @@
#include <type_traits> // for remove_reference<>::type
#include <vector> // for vector, allocator
#include "deathTestCommon.h"
using namespace std;
using namespace gsl;
namespace
{
static constexpr char deathstring[] = "Expected Death";
}
// Generic string functions
namespace generic
@ -76,8 +74,7 @@ T create()
template <class T>
void use(basic_string_span<T, gsl::dynamic_extent>)
{
}
{}
#endif
czstring_span<> CreateTempName(string_span<> span)
@ -85,7 +82,8 @@ czstring_span<> CreateTempName(string_span<> span)
Expects(span.size() > 1);
std::size_t last = 0;
if (span.size() > 4) {
if (span.size() > 4)
{
span[0] = 't';
span[1] = 'm';
span[2] = 'p';
@ -102,7 +100,8 @@ cwzstring_span<> CreateTempNameW(wstring_span<> span)
Expects(span.size() > 1);
std::size_t last = 0;
if (span.size() > 4) {
if (span.size() > 4)
{
span[0] = L't';
span[1] = L'm';
span[2] = L'p';
@ -119,7 +118,8 @@ cu16zstring_span<> CreateTempNameU16(u16string_span<> span)
Expects(span.size() > 1);
std::size_t last = 0;
if (span.size() > 4) {
if (span.size() > 4)
{
span[0] = u't';
span[1] = u'm';
span[2] = u'p';
@ -136,7 +136,8 @@ cu32zstring_span<> CreateTempNameU32(u32string_span<> span)
Expects(span.size() > 1);
std::size_t last = 0;
if (span.size() > 4) {
if (span.size() > 4)
{
span[0] = U't';
span[1] = U'm';
span[2] = U'p';
@ -950,10 +951,11 @@ TEST(string_span_tests, Conversion)
TEST(string_span_tests, zstring)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. zstring";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
// create zspan from zero terminated string
{
@ -973,7 +975,7 @@ TEST(string_span_tests, zstring)
buf[0] = 'a';
auto workaround_macro = [&]() { const zstring_span<> zspan({buf, 1}); };
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
// usage scenario: create zero-terminated temp file name and pass to a legacy API
@ -981,7 +983,8 @@ TEST(string_span_tests, zstring)
char buf[10];
auto name = CreateTempName({buf, 10});
if (!name.empty()) {
if (!name.empty())
{
czstring<> str = name.assume_z();
EXPECT_TRUE(generic::strlen(str) == 3);
EXPECT_TRUE(*(str + 3) == '\0');
@ -991,10 +994,11 @@ TEST(string_span_tests, zstring)
TEST(string_span_tests, wzstring)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. wzstring";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
// create zspan from zero terminated string
{
@ -1014,7 +1018,7 @@ TEST(string_span_tests, wzstring)
buf[0] = L'a';
const auto workaround_macro = [&]() { const wzstring_span<> zspan({buf, 1}); };
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
// usage scenario: create zero-terminated temp file name and pass to a legacy API
@ -1022,7 +1026,8 @@ TEST(string_span_tests, wzstring)
wchar_t buf[10];
const auto name = CreateTempNameW({buf, 10});
if (!name.empty()) {
if (!name.empty())
{
cwzstring<> str = name.assume_z();
EXPECT_TRUE(generic::strnlen(str, 10) == 3);
EXPECT_TRUE(*(str + 3) == L'\0');
@ -1032,10 +1037,11 @@ TEST(string_span_tests, wzstring)
TEST(string_span_tests, u16zstring)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. u16zstring";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
// create zspan from zero terminated string
{
@ -1055,7 +1061,7 @@ TEST(string_span_tests, u16zstring)
buf[0] = u'a';
const auto workaround_macro = [&]() { const u16zstring_span<> zspan({buf, 1}); };
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
// usage scenario: create zero-terminated temp file name and pass to a legacy API
@ -1063,7 +1069,8 @@ TEST(string_span_tests, u16zstring)
char16_t buf[10];
const auto name = CreateTempNameU16({buf, 10});
if (!name.empty()) {
if (!name.empty())
{
cu16zstring<> str = name.assume_z();
EXPECT_TRUE(generic::strnlen(str, 10) == 3);
EXPECT_TRUE(*(str + 3) == L'\0');
@ -1073,10 +1080,11 @@ TEST(string_span_tests, u16zstring)
TEST(string_span_tests, u32zstring)
{
std::set_terminate([] {
const auto terminateHandler = std::set_terminate([] {
std::cerr << "Expected Death. u31zstring";
std::abort();
});
const auto expected = GetExpectedDeathString(terminateHandler);
// create zspan from zero terminated string
{
@ -1096,7 +1104,7 @@ TEST(string_span_tests, u32zstring)
buf[0] = u'a';
const auto workaround_macro = [&]() { const u32zstring_span<> zspan({buf, 1}); };
EXPECT_DEATH(workaround_macro(), deathstring);
EXPECT_DEATH(workaround_macro(), expected);
}
// usage scenario: create zero-terminated temp file name and pass to a legacy API
@ -1104,7 +1112,8 @@ TEST(string_span_tests, u32zstring)
char32_t buf[10];
const auto name = CreateTempNameU32({buf, 10});
if (!name.empty()) {
if (!name.empty())
{
cu32zstring<> str = name.assume_z();
EXPECT_TRUE(generic::strnlen(str, 10) == 3);
EXPECT_TRUE(*(str + 3) == L'\0');

View File

@ -16,14 +16,14 @@
#include <gtest/gtest.h>
#include <gsl/util> // finally, narrow_cast
#include <gsl/narrow> // for narrow, narrowing_error
#include <algorithm> // for move
#include <cstddef> // for std::ptrdiff_t
#include <functional> // for reference_wrapper, _Bind_helper<>::type
#include <gsl/narrow> // for narrow, narrowing_error
#include <gsl/util> // finally, narrow_cast
#include <limits> // for numeric_limits
#include <stdint.h> // for uint32_t, int32_t
#include <type_traits> // for is_same
#include <cstddef> // for std::ptrdiff_t
using namespace gsl;
@ -32,8 +32,7 @@ namespace
void f(int& i) { i += 1; }
static int j = 0;
void g() { j += 1; }
}
} // namespace
TEST(utils_tests, sanity_check_for_gsl_index_typedef)
{
@ -123,6 +122,7 @@ TEST(utils_tests, narrow_cast)
EXPECT_TRUE(uc == 44);
}
#ifndef GSL_KERNEL_MODE
TEST(utils_tests, narrow)
{
int n = 120;
@ -145,3 +145,4 @@ TEST(utils_tests, narrow)
n = -42;
EXPECT_THROW(narrow<unsigned>(n), narrowing_error);
}
#endif // GSL_KERNEL_MODE