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 constexpr span_iterator operator++(int) noexcept
{ {
auto ret{*this}; span_iterator ret = {*this};
++*this; ++*this;
return ret; return ret;
} }
@ -178,7 +178,7 @@ namespace details
constexpr span_iterator operator--(int) noexcept constexpr span_iterator operator--(int) noexcept
{ {
auto ret{*this}; span_iterator ret = {*this};
--*this; --*this;
return ret; return ret;
} }
@ -194,7 +194,7 @@ namespace details
constexpr span_iterator operator+(const difference_type n) const noexcept constexpr span_iterator operator+(const difference_type n) const noexcept
{ {
auto ret{*this}; span_iterator ret = {*this};
return ret += n; return ret += n;
} }
@ -215,7 +215,7 @@ namespace details
constexpr span_iterator operator-(const difference_type n) const noexcept constexpr span_iterator operator-(const difference_type n) const noexcept
{ {
auto ret{*this}; span_iterator ret = {*this};
return ret -= n; 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> 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 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 < template <
@ -452,7 +453,7 @@ public:
std::is_convertible<typename Container::pointer, pointer>::value && std::is_convertible<typename Container::pointer, pointer>::value &&
std::is_convertible<typename Container::pointer, std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>> 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, template <class Container,
@ -462,7 +463,7 @@ public:
std::is_convertible<typename Container::pointer, std::is_convertible<typename Container::pointer,
decltype(std::declval<Container>().data())>::value>> decltype(std::declval<Container>().data())>::value>>
constexpr span(const Container& cont) noexcept 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; constexpr span(const span& other) noexcept = default;
@ -526,10 +527,13 @@ public:
// [span.obs], span observers // [span.obs], span observers
constexpr size_type size() const noexcept { return storage_.size(); } constexpr size_type size() const noexcept { return storage_.size(); }
constexpr size_type size_bytes() const noexcept 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; } constexpr bool empty() const noexcept { return size() == 0; }
// [span.elem], span element access // [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) TEST(span_test, begin_end)
{ {
std::set_terminate([] { std::set_terminate([] {
@ -1425,8 +1442,12 @@ TEST(span_test, from_array_constructor)
TEST(span_test, as_bytes) 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; const span<const int> s = a;
EXPECT_TRUE(s.size() == 4); 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(static_cast<const void*>(bs.data()) == static_cast<const void*>(s.data()));
EXPECT_TRUE(bs.size() == s.size_bytes()); 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) TEST(span_test, as_writeable_bytes)