[libcxx-commits] [libcxx] 67c4033 - [libc++] LWG-4021 "`mdspan::is_always_meow()` should be `noexcept`", use `LIBCPP_STATIC_ASSERT` for `noexcept` strengthening (#74254)
via libcxx-commits
libcxx-commits at lists.llvm.org
Sun Dec 10 02:52:18 PST 2023
Author: Stephan T. Lavavej
Date: 2023-12-10T11:52:14+01:00
New Revision: 67c4033358f39adcba53e9b70bdd4799c5a306ac
URL: https://github.com/llvm/llvm-project/commit/67c4033358f39adcba53e9b70bdd4799c5a306ac
DIFF: https://github.com/llvm/llvm-project/commit/67c4033358f39adcba53e9b70bdd4799c5a306ac.diff
LOG: [libc++] LWG-4021 "`mdspan::is_always_meow()` should be `noexcept`", use `LIBCPP_STATIC_ASSERT` for `noexcept` strengthening (#74254)
Found while running libc++'s test suite with MSVC's STL.
* I've filed [LWG-4021](https://cplusplus.github.io/LWG/issue4021)
"`mdspan::is_always_meow()` should be `noexcept`" and implemented this
in libc++'s product and test code.
* Use `LIBCPP_STATIC_ASSERT` to avoid issues with `noexcept`
strengthening in MSVC's STL.
+ As permitted by the Standard, MSVC's STL conditionally strengthens
`mdspan` construction/`is_meow`/`stride` and `elements_view` iterator
`base() &&`, and always strengthens `basic_stringbuf` `swap`.
+ In `mdspan/properties.pass.cpp`, this also upgrades runtime `assert`s
to `static_assert`s.
* Improvement: Upgrade `assert` to `static_assert` when inspecting the
`noexcept`ness of `std::ranges::iter_move`. (These `!noexcept` tests
weren't causing issues for MSVC's STL, so I didn't change them to be
libc++-specific.)
Added:
Modified:
libcxx/include/__mdspan/mdspan.h
libcxx/include/mdspan
libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_array.pass.cpp
libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_extents.pass.cpp
libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_map.pass.cpp
libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_map_acc.pass.cpp
libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_span.pass.cpp
libcxx/test/std/containers/views/mdspan/mdspan/properties.pass.cpp
libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp
libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp
libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
Removed:
################################################################################
diff --git a/libcxx/include/__mdspan/mdspan.h b/libcxx/include/__mdspan/mdspan.h
index 58f3b9cf1b18a4..684828eb90ec7c 100644
--- a/libcxx/include/__mdspan/mdspan.h
+++ b/libcxx/include/__mdspan/mdspan.h
@@ -244,9 +244,14 @@ class mdspan {
_LIBCPP_HIDE_FROM_ABI constexpr const mapping_type& mapping() const noexcept { return __map_; };
_LIBCPP_HIDE_FROM_ABI constexpr const accessor_type& accessor() const noexcept { return __acc_; };
- _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() { return mapping_type::is_always_unique(); };
- _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() { return mapping_type::is_always_exhaustive(); };
- _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() { return mapping_type::is_always_strided(); };
+ // per LWG-4021 "mdspan::is_always_meow() should be noexcept"
+ _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return mapping_type::is_always_unique(); };
+ _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept {
+ return mapping_type::is_always_exhaustive();
+ };
+ _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept {
+ return mapping_type::is_always_strided();
+ };
_LIBCPP_HIDE_FROM_ABI constexpr bool is_unique() const { return __map_.is_unique(); };
_LIBCPP_HIDE_FROM_ABI constexpr bool is_exhaustive() const { return __map_.is_exhaustive(); };
diff --git a/libcxx/include/mdspan b/libcxx/include/mdspan
index d55cdc4a4df5c3..c13d9eef001ac9 100644
--- a/libcxx/include/mdspan
+++ b/libcxx/include/mdspan
@@ -334,11 +334,12 @@ namespace std {
constexpr const mapping_type& mapping() const noexcept { return map_; }
constexpr const accessor_type& accessor() const noexcept { return acc_; }
- static constexpr bool is_always_unique()
+ // per LWG-4021 "mdspan::is_always_meow() should be noexcept"
+ static constexpr bool is_always_unique() noexcept
{ return mapping_type::is_always_unique(); }
- static constexpr bool is_always_exhaustive()
+ static constexpr bool is_always_exhaustive() noexcept
{ return mapping_type::is_always_exhaustive(); }
- static constexpr bool is_always_strided()
+ static constexpr bool is_always_strided() noexcept
{ return mapping_type::is_always_strided(); }
constexpr bool is_unique() const
diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_array.pass.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_array.pass.cpp
index bbf8137a7cb85d..0e0c7667da3078 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_array.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_array.pass.cpp
@@ -65,7 +65,7 @@ test_mdspan_ctor_array(const H& handle, const M& map, const A&, std::array<typen
}
}
- static_assert(!noexcept(MDS(handle, exts)));
+ LIBCPP_STATIC_ASSERT(!noexcept(MDS(handle, exts)));
static_assert(check_mdspan_ctor_implicit<MDS, decltype(exts)> == (N == MDS::rank_dynamic()));
diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_extents.pass.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_extents.pass.cpp
index 0a8918028d13c8..40e82db9863509 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_extents.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_extents.pass.cpp
@@ -51,7 +51,7 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A&) {
assert((H::move_counter() == 1));
}
}
- static_assert(!noexcept(MDS(handle, map.extents())));
+ LIBCPP_STATIC_ASSERT(!noexcept(MDS(handle, map.extents())));
assert(m.extents() == map.extents());
if constexpr (std::equality_comparable<H>)
assert(m.data_handle() == handle);
diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_map.pass.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_map.pass.cpp
index 75b7722b445e5a..fa65848ac69b53 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_map.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_map.pass.cpp
@@ -48,7 +48,7 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A&) {
assert((H::move_counter() == 1));
}
}
- static_assert(!noexcept(MDS(handle, map)));
+ LIBCPP_STATIC_ASSERT(!noexcept(MDS(handle, map)));
assert(m.extents() == map.extents());
if constexpr (std::equality_comparable<H>)
assert(m.data_handle() == handle);
diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_map_acc.pass.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_map_acc.pass.cpp
index c2210f1dba9090..65d32f3d7a7f60 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_map_acc.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_map_acc.pass.cpp
@@ -43,7 +43,7 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) {
assert((H::move_counter() == 1));
}
}
- static_assert(!noexcept(MDS(handle, map, acc)));
+ LIBCPP_STATIC_ASSERT(!noexcept(MDS(handle, map, acc)));
assert(m.extents() == map.extents());
if constexpr (std::equality_comparable<H>)
assert(m.data_handle() == handle);
diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_span.pass.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_span.pass.cpp
index 980619795b5dfe..f4fb5e681d95f4 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_span.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/ctor.dh_span.pass.cpp
@@ -65,7 +65,7 @@ test_mdspan_ctor_span(const H& handle, const M& map, const A&, std::span<typenam
}
}
- static_assert(!noexcept(MDS(handle, exts)));
+ LIBCPP_STATIC_ASSERT(!noexcept(MDS(handle, exts)));
static_assert(check_mdspan_ctor_implicit<MDS, decltype(exts)> == (N == MDS::rank_dynamic()));
diff --git a/libcxx/test/std/containers/views/mdspan/mdspan/properties.pass.cpp b/libcxx/test/std/containers/views/mdspan/mdspan/properties.pass.cpp
index 35534fa8795481..ba1fef1df6779a 100644
--- a/libcxx/test/std/containers/views/mdspan/mdspan/properties.pass.cpp
+++ b/libcxx/test/std/containers/views/mdspan/mdspan/properties.pass.cpp
@@ -27,11 +27,12 @@
// constexpr const data_handle_type& data_handle() const noexcept { return ptr_; }
// constexpr const mapping_type& mapping() const noexcept { return map_; }
// constexpr const accessor_type& accessor() const noexcept { return acc_; }
-// static constexpr bool is_always_unique()
+// /* per LWG-4021 "mdspan::is_always_meow() should be noexcept" */
+// static constexpr bool is_always_unique() noexcept
// { return mapping_type::is_always_unique(); }
-// static constexpr bool is_always_exhaustive()
+// static constexpr bool is_always_exhaustive() noexcept
// { return mapping_type::is_always_exhaustive(); }
-// static constexpr bool is_always_strided()
+// static constexpr bool is_always_strided() noexcept
// { return mapping_type::is_always_strided(); }
//
// constexpr bool is_unique() const
@@ -141,15 +142,16 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) {
ASSERT_SAME_TYPE(decltype(m.is_unique()), bool);
ASSERT_SAME_TYPE(decltype(m.is_exhaustive()), bool);
ASSERT_SAME_TYPE(decltype(m.is_strided()), bool);
- assert(!noexcept(MDS::is_always_unique()));
- assert(!noexcept(MDS::is_always_exhaustive()));
- assert(!noexcept(MDS::is_always_strided()));
- assert(!noexcept(m.is_unique()));
- assert(!noexcept(m.is_exhaustive()));
- assert(!noexcept(m.is_strided()));
- assert(MDS::is_always_unique() == M::is_always_unique());
- assert(MDS::is_always_exhaustive() == M::is_always_exhaustive());
- assert(MDS::is_always_strided() == M::is_always_strided());
+ // per LWG-4021 "mdspan::is_always_meow() should be noexcept"
+ static_assert(noexcept(MDS::is_always_unique()));
+ static_assert(noexcept(MDS::is_always_exhaustive()));
+ static_assert(noexcept(MDS::is_always_strided()));
+ LIBCPP_STATIC_ASSERT(!noexcept(m.is_unique()));
+ LIBCPP_STATIC_ASSERT(!noexcept(m.is_exhaustive()));
+ LIBCPP_STATIC_ASSERT(!noexcept(m.is_strided()));
+ static_assert(MDS::is_always_unique() == M::is_always_unique());
+ static_assert(MDS::is_always_exhaustive() == M::is_always_exhaustive());
+ static_assert(MDS::is_always_strided() == M::is_always_strided());
assert(m.is_unique() == map.is_unique());
assert(m.is_exhaustive() == map.is_exhaustive());
assert(m.is_strided() == map.is_strided());
@@ -159,7 +161,7 @@ constexpr void test_mdspan_types(const H& handle, const M& map, const A& acc) {
if (m.is_strided()) {
for (typename MDS::rank_type r = 0; r < MDS::rank(); r++) {
ASSERT_SAME_TYPE(decltype(m.stride(r)), typename MDS::index_type);
- assert(!noexcept(m.stride(r)));
+ LIBCPP_STATIC_ASSERT(!noexcept(m.stride(r)));
assert(m.stride(r) == map.stride(r));
}
}
diff --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp
index 0a0128e44658f8..63e2293c530bd0 100644
--- a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/member_swap_noexcept.pass.cpp
@@ -84,7 +84,7 @@ static void test() {
{
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf1;
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf;
- static_assert(!noexcept(buf.swap(buf1)));
+ LIBCPP_STATIC_ASSERT(!noexcept(buf.swap(buf1)));
}
{
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_not_empty<CharT>> buf1;
diff --git a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp
index 4f41e3a4d716a2..a3706116f40907 100644
--- a/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp
+++ b/libcxx/test/std/input.output/string.streams/stringbuf/stringbuf.assign/nonmember_swap_noexcept.pass.cpp
@@ -83,7 +83,7 @@ static void test() {
{
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf1;
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_not_empty<CharT>> buf;
- static_assert(!noexcept(swap(buf, buf1)));
+ LIBCPP_STATIC_ASSERT(!noexcept(swap(buf, buf1)));
}
{
std::basic_stringbuf<CharT, std::char_traits<CharT>, test_alloc_propagate_on_container_swap_not_empty<CharT>> buf1;
diff --git a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
index 566638263e8875..9f293ff483cd86 100644
--- a/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
+++ b/libcxx/test/std/iterators/iterator.requirements/iterator.cust/iterator.cust.move/iter_move.pass.cpp
@@ -158,15 +158,15 @@ constexpr bool test() {
auto unscoped = check_unqualified_lookup::unscoped_enum::a;
assert(std::ranges::iter_move(unscoped) == check_unqualified_lookup::unscoped_enum::a);
- assert(!noexcept(std::ranges::iter_move(unscoped)));
+ static_assert(!noexcept(std::ranges::iter_move(unscoped)));
auto scoped = check_unqualified_lookup::scoped_enum::a;
assert(std::ranges::iter_move(scoped) == nullptr);
- assert(noexcept(std::ranges::iter_move(scoped)));
+ static_assert(noexcept(std::ranges::iter_move(scoped)));
auto some_union = check_unqualified_lookup::some_union{0};
assert(std::ranges::iter_move(some_union) == 0);
- assert(!noexcept(std::ranges::iter_move(some_union)));
+ static_assert(!noexcept(std::ranges::iter_move(some_union)));
// Check noexcept-correctness
static_assert(noexcept(std::ranges::iter_move(std::declval<WithADL<true>>())));
diff --git a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
index 3729c8e5431131..79c4e1f4183729 100644
--- a/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
+++ b/libcxx/test/std/ranges/range.adaptors/range.elements/iterator/base.pass.cpp
@@ -33,7 +33,7 @@ using ElementsIter = std::ranges::iterator_t<std::ranges::elements_view<BaseView
static_assert(IsBaseNoexcept<const ElementsIter&>);
static_assert(IsBaseNoexcept<ElementsIter&>);
static_assert(IsBaseNoexcept<const ElementsIter&&>);
-static_assert(!IsBaseNoexcept<ElementsIter&&>);
+LIBCPP_STATIC_ASSERT(!IsBaseNoexcept<ElementsIter&&>);
constexpr bool test() {
std::tuple<int> t{5};
More information about the libcxx-commits
mailing list