diff --git a/libcxx/include/span b/libcxx/include/span index 00793a210cbe..67d2ac241ff2 100644 --- a/libcxx/include/span +++ b/libcxx/include/span @@ -453,9 +453,10 @@ public: : __data{_VSTD::to_address(__first)}, __size{__count} {} template <__span_compatible_iterator _It, __span_compatible_sentinel_for<_It> _End> - _LIBCPP_INLINE_VISIBILITY - constexpr span(_It __first, _End __last) - : __data(_VSTD::to_address(__first)), __size(__last - __first) {} + _LIBCPP_INLINE_VISIBILITY constexpr span(_It __first, _End __last) + : __data(_VSTD::to_address(__first)), __size(__last - __first) { + _LIBCPP_ASSERT(__last - __first >= 0, "invalid range in span's constructor (iterator, sentinel)"); + } template _LIBCPP_INLINE_VISIBILITY diff --git a/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_sent.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_sent.pass.cpp new file mode 100644 index 000000000000..cd373e71b4b4 --- /dev/null +++ b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_sent.pass.cpp @@ -0,0 +1,48 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// +// +// constexpr span::span(Iterator it, Sentinel sent); +// +// Check that we ensure `Extent == sent - it` and also that `[it, sent)` is a valid range. +// +// +// constexpr span::span(Iterator it, Sentinel sent); +// +// Check that we ensure that `[it, sent)` is a valid range. + +// REQUIRES: has-unix-headers +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 + +#include +#include + +#include "check_assertion.h" + +int main(int, char**) { + { + std::array array{0, 1, 2}; + + auto invalid_range = [&] { std::span const s(array.end(), array.begin()); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(invalid_range(), "invalid range in span's constructor (iterator, sentinel)"); + } + { + std::array array{0, 1, 2}; + + auto invalid_range = [&] { std::span const s(array.end(), array.begin()); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(invalid_range(), "invalid range in span's constructor (iterator, sentinel)"); + + auto invalid_size = [&] { std::span const s(array.begin(), array.begin() + 2); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(invalid_size(), "invalid range in span's constructor (iterator, sentinel): last - first != extent"); + } + + return 0; +} diff --git a/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_size.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_size.pass.cpp new file mode 100644 index 000000000000..1888b4b5d0b2 --- /dev/null +++ b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.iter_size.pass.cpp @@ -0,0 +1,37 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// +// +// constexpr span::span(Iterator, size_type); +// +// Check that the passed size is equal to the statically known extent. +// Note that it doesn't make sense to validate the incoming size in the +// dynamic_extent version. + +// REQUIRES: has-unix-headers +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 + +#include +#include + +#include "check_assertion.h" + +int main(int, char**) { + std::array array{0, 1, 2}; + + auto too_large = [&] { std::span const s(array.data(), 4); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(too_large(), "size mismatch in span's constructor (iterator, len)"); + + auto too_small = [&] { std::span const s(array.data(), 2); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(too_small(), "size mismatch in span's constructor (iterator, len)"); + + return 0; +} diff --git a/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.other_span.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.other_span.pass.cpp new file mode 100644 index 000000000000..9e92e837f795 --- /dev/null +++ b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.other_span.pass.cpp @@ -0,0 +1,33 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// +// +// constexpr span::span(const span& other); +// +// Check that we ensure `other.size() == Extent`. + +// REQUIRES: has-unix-headers +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 + +#include +#include + +#include "check_assertion.h" + +int main(int, char**) { + std::array array{0, 1, 2}; + std::span other(array.data(), 3); + + auto invalid_source = [&] { std::span const s(other); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(invalid_source(), "size mismatch in span's constructor (other span)"); + + return 0; +} diff --git a/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.range.pass.cpp b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.range.pass.cpp new file mode 100644 index 000000000000..bf1233f207b3 --- /dev/null +++ b/libcxx/test/libcxx/containers/views/views.span/span.cons/assert.range.pass.cpp @@ -0,0 +1,32 @@ +//===----------------------------------------------------------------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// UNSUPPORTED: c++03, c++11, c++14, c++17 + +// +// +// constexpr span::span(Range&& r); +// +// Check that we ensure `size(r) == Extent`. + +// REQUIRES: has-unix-headers +// XFAIL: use_system_cxx_lib && target={{.+}}-apple-macosx{{10.9|10.10|10.11|10.12|10.13|10.14|10.15|11.0|12.0}} +// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ENABLE_ASSERTIONS=1 + +#include +#include + +#include "check_assertion.h" + +int main(int, char**) { + std::vector vec{0, 1, 2}; // must use std::vector instead of std::array, because std::span has a special constructor from std::array + + auto invalid_size = [&] { std::span const s(vec); (void)s; }; + TEST_LIBCPP_ASSERT_FAILURE(invalid_size(), "size mismatch in span's constructor (range)"); + + return 0; +}