prevent overflow in size_bytes. fix compilation issue for clang 3.6 and 3.7

This commit is contained in:
Jordan Maples [MSFT] 2020-02-05 12:58:49 -08:00
parent d7e1611137
commit 5cf1610cfe
2 changed files with 40 additions and 9 deletions

View File

@ -163,7 +163,7 @@ namespace details
constexpr span_iterator operator++(int) noexcept
{
auto ret{*this};
span_iterator ret = {*this};
++*this;
return ret;
}
@ -178,7 +178,7 @@ namespace details
constexpr span_iterator operator--(int) noexcept
{
auto ret{*this};
span_iterator ret = {*this};
--*this;
return ret;
}
@ -194,7 +194,7 @@ namespace details
constexpr span_iterator operator+(const difference_type n) const noexcept
{
auto ret{*this};
span_iterator ret = {*this};
return ret += n;
}
@ -215,7 +215,7 @@ namespace details
constexpr span_iterator operator-(const difference_type n) const noexcept
{
auto ret{*this};
span_iterator ret = {*this};
return ret -= n;
}
@ -238,7 +238,8 @@ namespace details
std::enable_if_t<std::is_same<std::remove_cv_t<Type2>, value_type>::value, int> = 0>
constexpr bool operator==(const span_iterator<Type2>& rhs) const noexcept
{
return begin_ == rhs.begin_ && end_ == rhs.end_ && current_ == rhs.current_;
Expects(begin_ == rhs.begin_ && end_ == rhs.end_);
return current_ == rhs.current_;
}
template <
@ -452,7 +453,7 @@ public:
std::is_convertible<typename Container::pointer, pointer>::value &&
std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>>
constexpr span(Container& cont) noexcept : span(cont.data(), narrow<size_type>(cont.size()))
constexpr span(Container& cont) noexcept : span(cont.data(), cont.size())
{}
template <class Container,
@ -462,7 +463,7 @@ public:
std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>>
constexpr span(const Container& cont) noexcept
: span(cont.data(), narrow<size_type>(cont.size()))
: span(cont.data(), cont.size())
{}
constexpr span(const span& other) noexcept = default;
@ -526,10 +527,13 @@ public:
// [span.obs], span observers
constexpr size_type size() const noexcept { return storage_.size(); }
constexpr size_type size_bytes() const noexcept
{
return size() * narrow_cast<size_type>(sizeof(element_type));
Expects(size() < dynamic_extent / sizeof(element_type));
return size() * sizeof(element_type);
}
constexpr bool empty() const noexcept { return size() == 0; }
// [span.elem], span element access

View File

@ -1090,6 +1090,23 @@ TEST(span_test, from_array_constructor)
}
}
TEST(span_test, incomparable_iterators)
{
std::set_terminate([] {
std::cerr << "Expected Death. incomparable_iterators";
std::abort();
});
int a[] = {1, 2, 3, 4};
int b[] = {1, 2, 3, 4};
{
span<int> s = a;
span<int> s2 = b;
EXPECT_DEATH(s.begin() == s2.begin(), deathstring);
EXPECT_DEATH(s.begin() <= s2.begin(), deathstring);
}
}
TEST(span_test, begin_end)
{
std::set_terminate([] {
@ -1425,8 +1442,12 @@ TEST(span_test, from_array_constructor)
TEST(span_test, as_bytes)
{
int a[] = {1, 2, 3, 4};
std::set_terminate([] {
std::cerr << "Expected Death. as_bytes";
std::abort();
});
int a[] = {1, 2, 3, 4};
{
const span<const int> s = a;
EXPECT_TRUE(s.size() == 4);
@ -1451,6 +1472,12 @@ TEST(span_test, from_array_constructor)
EXPECT_TRUE(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
EXPECT_TRUE(bs.size() == s.size_bytes());
}
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);
}
}
TEST(span_test, as_writeable_bytes)