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

@ -30,7 +30,7 @@ template <class T, class U>
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
GSL_SUPPRESS(f.6) // NO-FORMAT: attribute // TODO: MSVC /analyze does not recognise noexcept(false)
// clang-format on
// clang-format on
constexpr T narrow(U u) noexcept(false)
{
constexpr const bool is_different_signedness =

View File

@ -34,12 +34,19 @@ namespace gsl
namespace details
{
template<typename T, typename = void>
struct is_comparable_to_nullptr : std::false_type {};
template <typename T, typename = void>
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 {};
} // namespace details
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
{
};
} // namespace details
//
// GSL.owner: ownership pointers

View File

@ -21,10 +21,11 @@
#include <gsl/byte> // for byte
#include <gsl/util> // for narrow_cast
#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...
#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...
#if defined(_MSC_VER) && !defined(__clang__)
#pragma warning(push)
@ -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/util> // for narrow_cast, narrow
#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 <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)
@ -92,8 +96,8 @@ finally(F&& f) noexcept
template <class T, class U>
// clang-format off
GSL_SUPPRESS(type.1) // NO-FORMAT: attribute
// clang-format on
constexpr T narrow_cast(U&& u) noexcept
// clang-format on
constexpr T narrow_cast(U&& u) noexcept
{
return static_cast<T>(std::forward<U>(u));
}
@ -105,7 +109,7 @@ template <class T, std::size_t N>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on
// clang-format on
constexpr T& at(T (&arr)[N], const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(N));
@ -116,7 +120,7 @@ template <class Cont>
// clang-format off
GSL_SUPPRESS(bounds.4) // NO-FORMAT: attribute
GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
// clang-format on
// clang-format on
constexpr auto at(Cont& cont, const index i) -> decltype(cont[cont.size()])
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
@ -127,13 +131,21 @@ GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute
template <class T>
// clang-format off
GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute
// clang-format on
constexpr T at(const std::initializer_list<T> cont, const index i)
// clang-format on
constexpr T at(const std::initializer_list<T> cont, const index i)
{
Expects(i >= 0 && i < narrow_cast<index>(cont.size()));
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 <array> // for array
#include <cstddef> // for size_t
#include <gsl/algorithm> // for copy
#include <gsl/span> // for span
#include <array> // for array
#include <cstddef> // for size_t
#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);
@ -55,7 +57,7 @@ TEST(byte_tests, construction)
#if defined(__cplusplus) && (__cplusplus >= 201703L)
{
const byte b { 14 };
const byte b{14};
EXPECT_TRUE(static_cast<unsigned char>(b) == 14);
}
#endif
@ -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
{
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
// clang-format off
GSL_SUPPRESS(f .4) // NO-FORMAT: attribute
// clang-format on
bool helper(not_null<int*> p) { return *p == 12; }
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
// 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

@ -20,7 +20,7 @@
using namespace gsl;
GSL_SUPPRESS(f.23) // NO-FORMAT: attribute
GSL_SUPPRESS(f .23) // NO-FORMAT: attribute
void f(int* i) { *i += 1; }
TEST(owner_tests, basic_test)
@ -34,10 +34,10 @@ TEST(owner_tests, basic_test)
TEST(owner_tests, check_pointer_constraint)
{
#ifdef CONFIRM_COMPILATION_ERRORS
#ifdef CONFIRM_COMPILATION_ERRORS
{
owner<int> integerTest = 10;
owner<std::shared_ptr<int>> sharedPtrTest(new int(10));
}
#endif
#endif
}

View File

@ -17,7 +17,7 @@
#include <gtest/gtest.h>
#include <gsl/byte> // for byte
#include <gsl/span> // for span, span_iterator, operator==, operator!=
#include <gsl/span> // for span, span_iterator, operator==, operator!=
#include <array> // for array
#include <cstddef> // for ptrdiff_t

View File

@ -16,27 +16,26 @@
#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
#include <vector> // for vector
#include <array> // for array
#include <iostream> // for cerr
#include <vector> // for vector
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);
}
}
@ -88,273 +87,275 @@ TEST(span_ext_test, make_span_from_pointer_pointer_construction)
}
TEST(span_ext_test, make_span_from_array_constructor)
{
int arr[5] = {1, 2, 3, 4, 5};
int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
{
int arr[5] = {1, 2, 3, 4, 5};
int arr2d[2][3] = {1, 2, 3, 4, 5, 6};
int arr3d[2][3][2] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
{
const auto s = make_span(arr);
EXPECT_TRUE(s.size() == 5);
EXPECT_TRUE(s.data() == std::addressof(arr[0]));
}
{
const auto s = make_span(arr);
EXPECT_TRUE(s.size() == 5);
EXPECT_TRUE(s.data() == std::addressof(arr[0]));
}
{
const auto s = make_span(std::addressof(arr2d[0]), 1);
EXPECT_TRUE(s.size() == 1);
EXPECT_TRUE(s.data() == std::addressof(arr2d[0]));
}
{
const auto s = make_span(std::addressof(arr2d[0]), 1);
EXPECT_TRUE(s.size() == 1);
EXPECT_TRUE(s.data() == std::addressof(arr2d[0]));
}
{
const auto s = make_span(std::addressof(arr3d[0]), 1);
EXPECT_TRUE(s.size() == 1);
EXPECT_TRUE(s.data() == std::addressof(arr3d[0]));
}
}
{
const auto s = make_span(std::addressof(arr3d[0]), 1);
EXPECT_TRUE(s.size() == 1);
EXPECT_TRUE(s.data() == std::addressof(arr3d[0]));
}
}
TEST(span_ext_test, make_span_from_dynamic_array_constructor)
{
double(*arr)[3][4] = new double[100][3][4];
TEST(span_ext_test, make_span_from_dynamic_array_constructor)
{
double(*arr)[3][4] = new double[100][3][4];
{
auto s = make_span(&arr[0][0][0], 10);
EXPECT_TRUE(s.size() == 10);
EXPECT_TRUE(s.data() == &arr[0][0][0]);
}
{
auto s = make_span(&arr[0][0][0], 10);
EXPECT_TRUE(s.size() == 10);
EXPECT_TRUE(s.data() == &arr[0][0][0]);
}
delete[] arr;
}
delete[] arr;
}
TEST(span_ext_test, make_span_from_std_array_constructor)
{
std::array<int, 4> arr = {1, 2, 3, 4};
TEST(span_ext_test, make_span_from_std_array_constructor)
{
std::array<int, 4> arr = {1, 2, 3, 4};
{
auto s = make_span(arr);
EXPECT_TRUE(s.size() == arr.size());
EXPECT_TRUE(s.data() == arr.data());
}
{
auto s = make_span(arr);
EXPECT_TRUE(s.size() == arr.size());
EXPECT_TRUE(s.data() == arr.data());
}
// This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590
{
span<int> s1 = make_span(arr);
// This test checks for the bug found in gcc 6.1, 6.2, 6.3, 6.4, 6.5 7.1, 7.2, 7.3 - issue #590
{
span<int> s1 = make_span(arr);
static span<int> s2;
s2 = s1;
static span<int> s2;
s2 = s1;
#if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \
__GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__)
// Known to be broken in gcc 6.4 and 6.5 with optimizations
// Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116
EXPECT_TRUE(s1.size() == 4);
EXPECT_TRUE(s2.size() == 0);
#else
EXPECT_TRUE(s1.size() == s2.size());
#endif
}
}
#if defined(__GNUC__) && __GNUC__ == 6 && (__GNUC_MINOR__ == 4 || __GNUC_MINOR__ == 5) && \
__GNUC_PATCHLEVEL__ == 0 && defined(__OPTIMIZE__)
// Known to be broken in gcc 6.4 and 6.5 with optimizations
// Issue in gcc: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=83116
EXPECT_TRUE(s1.size() == 4);
EXPECT_TRUE(s2.size() == 0);
#else
EXPECT_TRUE(s1.size() == s2.size());
#endif
}
}
TEST(span_ext_test, make_span_from_const_std_array_constructor)
{
const std::array<int, 4> arr = {1, 2, 3, 4};
TEST(span_ext_test, make_span_from_const_std_array_constructor)
{
const std::array<int, 4> arr = {1, 2, 3, 4};
{
auto s = make_span(arr);
EXPECT_TRUE(s.size() == arr.size());
EXPECT_TRUE(s.data() == arr.data());
}
}
{
auto s = make_span(arr);
EXPECT_TRUE(s.size() == arr.size());
EXPECT_TRUE(s.data() == arr.data());
}
}
TEST(span_ext_test, make_span_from_std_array_const_constructor)
{
std::array<const int, 4> arr = {1, 2, 3, 4};
TEST(span_ext_test, make_span_from_std_array_const_constructor)
{
std::array<const int, 4> arr = {1, 2, 3, 4};
{
auto s = make_span(arr);
EXPECT_TRUE(s.size() == arr.size());
EXPECT_TRUE(s.data() == arr.data());
}
}
{
auto s = make_span(arr);
EXPECT_TRUE(s.size() == arr.size());
EXPECT_TRUE(s.data() == arr.data());
}
}
TEST(span_ext_test, make_span_from_container_constructor)
{
std::vector<int> v = {1, 2, 3};
const std::vector<int> cv = v;
TEST(span_ext_test, make_span_from_container_constructor)
{
std::vector<int> v = {1, 2, 3};
const std::vector<int> cv = v;
{
auto s = make_span(v);
EXPECT_TRUE(s.size() == v.size());
EXPECT_TRUE(s.data() == v.data());
{
auto s = make_span(v);
EXPECT_TRUE(s.size() == v.size());
EXPECT_TRUE(s.data() == v.data());
auto cs = make_span(cv);
EXPECT_TRUE(cs.size() == cv.size());
EXPECT_TRUE(cs.data() == cv.data());
}
}
auto cs = make_span(cv);
EXPECT_TRUE(cs.size() == cv.size());
EXPECT_TRUE(cs.data() == cv.data());
}
}
TEST(span_test, interop_with_gsl_at)
{
int arr[5] = {1, 2, 3, 4, 5};
span<int> s{arr};
EXPECT_TRUE(at(s, 0) == 1);
EXPECT_TRUE(at(s, 1) == 2);
}
TEST(span_test, interop_with_gsl_at)
{
int arr[5] = {1, 2, 3, 4, 5};
span<int> s{arr};
EXPECT_TRUE(at(s, 0) == 1);
EXPECT_TRUE(at(s, 1) == 2);
}
TEST(span_ext_test, iterator_free_functions)
{
int a[] = {1, 2, 3, 4};
span<int> s{a};
TEST(span_ext_test, iterator_free_functions)
{
int a[] = {1, 2, 3, 4};
span<int> s{a};
EXPECT_TRUE((std::is_same<decltype(s.begin()), decltype(begin(s))>::value));
EXPECT_TRUE((std::is_same<decltype(s.end()), decltype(end(s))>::value));
EXPECT_TRUE((std::is_same<decltype(s.begin()), decltype(begin(s))>::value));
EXPECT_TRUE((std::is_same<decltype(s.end()), decltype(end(s))>::value));
EXPECT_TRUE((std::is_same<decltype(std::cbegin(s)), decltype(cbegin(s))>::value));
EXPECT_TRUE((std::is_same<decltype(std::cend(s)), decltype(cend(s))>::value));
EXPECT_TRUE((std::is_same<decltype(std::cbegin(s)), decltype(cbegin(s))>::value));
EXPECT_TRUE((std::is_same<decltype(std::cend(s)), decltype(cend(s))>::value));
EXPECT_TRUE((std::is_same<decltype(s.rbegin()), decltype(rbegin(s))>::value));
EXPECT_TRUE((std::is_same<decltype(s.rend()), decltype(rend(s))>::value));
EXPECT_TRUE((std::is_same<decltype(s.rbegin()), decltype(rbegin(s))>::value));
EXPECT_TRUE((std::is_same<decltype(s.rend()), decltype(rend(s))>::value));
EXPECT_TRUE((std::is_same<decltype(std::crbegin(s)), decltype(crbegin(s))>::value));
EXPECT_TRUE((std::is_same<decltype(std::crend(s)), decltype(crend(s))>::value));
EXPECT_TRUE((std::is_same<decltype(std::crbegin(s)), decltype(crbegin(s))>::value));
EXPECT_TRUE((std::is_same<decltype(std::crend(s)), decltype(crend(s))>::value));
EXPECT_TRUE(s.begin() == begin(s));
EXPECT_TRUE(s.end() == end(s));
EXPECT_TRUE(s.begin() == begin(s));
EXPECT_TRUE(s.end() == end(s));
EXPECT_TRUE(s.rbegin() == rbegin(s));
EXPECT_TRUE(s.rend() == rend(s));
EXPECT_TRUE(s.rbegin() == rbegin(s));
EXPECT_TRUE(s.rend() == rend(s));
EXPECT_TRUE(s.begin() == cbegin(s));
EXPECT_TRUE(s.end() == cend(s));
EXPECT_TRUE(s.begin() == cbegin(s));
EXPECT_TRUE(s.end() == cend(s));
EXPECT_TRUE(s.rbegin() == crbegin(s));
EXPECT_TRUE(s.rend() == crend(s));
}
EXPECT_TRUE(s.rbegin() == crbegin(s));
EXPECT_TRUE(s.rend() == crend(s));
}
TEST(span_ext_test, ssize_free_function)
{
int a[] = {1, 2, 3, 4};
span<int> s{a};
TEST(span_ext_test, ssize_free_function)
{
int a[] = {1, 2, 3, 4};
span<int> s{a};
EXPECT_FALSE((std::is_same<decltype(s.size()), decltype(ssize(s))>::value));
EXPECT_TRUE(s.size() == static_cast<std::size_t>(ssize(s)));
}
EXPECT_FALSE((std::is_same<decltype(s.size()), decltype(ssize(s))>::value));
EXPECT_TRUE(s.size() == static_cast<std::size_t>(ssize(s)));
}
TEST(span_ext_test, comparison_operators)
{
{
span<int> s1;
span<int> s2;
EXPECT_TRUE(s1 == s2);
EXPECT_FALSE(s1 != s2);
EXPECT_FALSE(s1 < s2);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s1 >= s2);
EXPECT_TRUE(s2 == s1);
EXPECT_FALSE(s2 != s1);
EXPECT_FALSE(s2 != s1);
EXPECT_TRUE(s2 <= s1);
EXPECT_FALSE(s2 > s1);
EXPECT_TRUE(s2 >= s1);
}
#ifndef GSL_KERNEL_MODE
TEST(span_ext_test, comparison_operators)
{
{
span<int> s1;
span<int> s2;
EXPECT_TRUE(s1 == s2);
EXPECT_FALSE(s1 != s2);
EXPECT_FALSE(s1 < s2);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s1 >= s2);
EXPECT_TRUE(s2 == s1);
EXPECT_FALSE(s2 != s1);
EXPECT_FALSE(s2 != s1);
EXPECT_TRUE(s2 <= s1);
EXPECT_FALSE(s2 > s1);
EXPECT_TRUE(s2 >= s1);
}
{
int arr[] = {2, 1};
span<int> s1 = arr;
span<int> s2 = arr;
{
int arr[] = {2, 1};
span<int> s1 = arr;
span<int> s2 = arr;
EXPECT_TRUE(s1 == s2);
EXPECT_FALSE(s1 != s2);
EXPECT_FALSE(s1 < s2);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s1 >= s2);
EXPECT_TRUE(s2 == s1);
EXPECT_FALSE(s2 != s1);
EXPECT_FALSE(s2 < s1);
EXPECT_TRUE(s2 <= s1);
EXPECT_FALSE(s2 > s1);
EXPECT_TRUE(s2 >= s1);
}
EXPECT_TRUE(s1 == s2);
EXPECT_FALSE(s1 != s2);
EXPECT_FALSE(s1 < s2);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s1 >= s2);
EXPECT_TRUE(s2 == s1);
EXPECT_FALSE(s2 != s1);
EXPECT_FALSE(s2 < s1);
EXPECT_TRUE(s2 <= s1);
EXPECT_FALSE(s2 > s1);
EXPECT_TRUE(s2 >= s1);
}
{
int arr[] = {2, 1}; // bigger
{
int arr[] = {2, 1}; // bigger
span<int> s1;
span<int> s2 = arr;
span<int> s1;
span<int> s2 = arr;
EXPECT_TRUE(s1 != s2);
EXPECT_TRUE(s2 != s1);
EXPECT_FALSE(s1 == s2);
EXPECT_FALSE(s2 == s1);
EXPECT_TRUE(s1 < s2);
EXPECT_FALSE(s2 < s1);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s2 <= s1);
EXPECT_TRUE(s2 > s1);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s2 >= s1);
EXPECT_FALSE(s1 >= s2);
}
EXPECT_TRUE(s1 != s2);
EXPECT_TRUE(s2 != s1);
EXPECT_FALSE(s1 == s2);
EXPECT_FALSE(s2 == s1);
EXPECT_TRUE(s1 < s2);
EXPECT_FALSE(s2 < s1);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s2 <= s1);
EXPECT_TRUE(s2 > s1);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s2 >= s1);
EXPECT_FALSE(s1 >= s2);
}
{
int arr1[] = {1, 2};
int arr2[] = {1, 2};
span<int> s1 = arr1;
span<int> s2 = arr2;
{
int arr1[] = {1, 2};
int arr2[] = {1, 2};
span<int> s1 = arr1;
span<int> s2 = arr2;
EXPECT_TRUE(s1 == s2);
EXPECT_FALSE(s1 != s2);
EXPECT_FALSE(s1 < s2);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s1 >= s2);
EXPECT_TRUE(s2 == s1);
EXPECT_FALSE(s2 != s1);
EXPECT_FALSE(s2 < s1);
EXPECT_TRUE(s2 <= s1);
EXPECT_FALSE(s2 > s1);
EXPECT_TRUE(s2 >= s1);
}
EXPECT_TRUE(s1 == s2);
EXPECT_FALSE(s1 != s2);
EXPECT_FALSE(s1 < s2);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s1 >= s2);
EXPECT_TRUE(s2 == s1);
EXPECT_FALSE(s2 != s1);
EXPECT_FALSE(s2 < s1);
EXPECT_TRUE(s2 <= s1);
EXPECT_FALSE(s2 > s1);
EXPECT_TRUE(s2 >= s1);
}
{
int arr[] = {1, 2, 3};
{
int arr[] = {1, 2, 3};
span<int> s1 = {&arr[0], 2}; // shorter
span<int> s2 = arr; // longer
span<int> s1 = {&arr[0], 2}; // shorter
span<int> s2 = arr; // longer
EXPECT_TRUE(s1 != s2);
EXPECT_TRUE(s2 != s1);
EXPECT_FALSE(s1 == s2);
EXPECT_FALSE(s2 == s1);
EXPECT_TRUE(s1 < s2);
EXPECT_FALSE(s2 < s1);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s2 <= s1);
EXPECT_TRUE(s2 > s1);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s2 >= s1);
EXPECT_FALSE(s1 >= s2);
}
EXPECT_TRUE(s1 != s2);
EXPECT_TRUE(s2 != s1);
EXPECT_FALSE(s1 == s2);
EXPECT_FALSE(s2 == s1);
EXPECT_TRUE(s1 < s2);
EXPECT_FALSE(s2 < s1);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s2 <= s1);
EXPECT_TRUE(s2 > s1);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s2 >= s1);
EXPECT_FALSE(s1 >= s2);
}
{
int arr1[] = {1, 2}; // smaller
int arr2[] = {2, 1}; // bigger
{
int arr1[] = {1, 2}; // smaller
int arr2[] = {2, 1}; // bigger
span<int> s1 = arr1;
span<int> s2 = arr2;
span<int> s1 = arr1;
span<int> s2 = arr2;
EXPECT_TRUE(s1 != s2);
EXPECT_TRUE(s2 != s1);
EXPECT_FALSE(s1 == s2);
EXPECT_FALSE(s2 == s1);
EXPECT_TRUE(s1 < s2);
EXPECT_FALSE(s2 < s1);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s2 <= s1);
EXPECT_TRUE(s2 > s1);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s2 >= s1);
EXPECT_FALSE(s1 >= s2);
}
}
EXPECT_TRUE(s1 != s2);
EXPECT_TRUE(s2 != s1);
EXPECT_FALSE(s1 == s2);
EXPECT_FALSE(s2 == s1);
EXPECT_TRUE(s1 < s2);
EXPECT_FALSE(s2 < s1);
EXPECT_TRUE(s1 <= s2);
EXPECT_FALSE(s2 <= s1);
EXPECT_TRUE(s2 > s1);
EXPECT_FALSE(s1 > s2);
EXPECT_TRUE(s2 >= s1);
EXPECT_FALSE(s1 >= s2);
}
}
#endif // GSL_KERNEL_MODE

File diff suppressed because it is too large Load Diff

View File

@ -14,23 +14,33 @@
//
///////////////////////////////////////////////////////////////////////////////
#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
#include <gtest/gtest.h>
#include <gsl/pointers> // for not_null, operator<, operator<=, operator>
#include "deathTestCommon.h"
using namespace gsl;
namespace
{
GSL_SUPPRESS(f.4) // NO-FORMAT: attribute
// 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

@ -16,7 +16,7 @@
#include <gtest/gtest.h>
#include <gsl/assert> // for Expects, fail_fast (ptr only)
#include <gsl/assert> // for Expects, fail_fast (ptr only)
#include <gsl/pointers> // for owner
#include <gsl/span> // for span, dynamic_extent
#include <gsl/string_span> // for basic_string_span, operator==, ensure_z
@ -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