From 779563cff2e18e7891abf57aeee90e8db5035eb5 Mon Sep 17 00:00:00 2001 From: Jonathan Wakely Date: Sat, 4 Nov 2023 08:30:54 +0000 Subject: [PATCH] libstdc++: Add [[nodiscard]] to std::span members All std::span member functions are pure functions that have no side effects. They are only useful for their return value, so they should all warn if that value is not used. libstdc++-v3/ChangeLog: * include/std/span (span, as_bytes, as_writable_bytes): Add [[nodiscard]] attribute on all non-void functions. * testsuite/23_containers/span/back_assert_neg.cc: Suppress nodiscard warning. * testsuite/23_containers/span/back_neg.cc: Likewise. * testsuite/23_containers/span/first_2_assert_neg.cc: Likewise. * testsuite/23_containers/span/first_assert_neg.cc: Likewise. * testsuite/23_containers/span/first_neg.cc: Likewise. * testsuite/23_containers/span/front_assert_neg.cc: Likewise. * testsuite/23_containers/span/front_neg.cc: Likewise. * testsuite/23_containers/span/index_op_assert_neg.cc: Likewise. * testsuite/23_containers/span/index_op_neg.cc: Likewise. * testsuite/23_containers/span/last_2_assert_neg.cc: Likewise. * testsuite/23_containers/span/last_assert_neg.cc: Likewise. * testsuite/23_containers/span/last_neg.cc: Likewise. * testsuite/23_containers/span/subspan_2_assert_neg.cc: Likewise. * testsuite/23_containers/span/subspan_3_assert_neg.cc: Likewise. * testsuite/23_containers/span/subspan_4_assert_neg.cc: Likewise. * testsuite/23_containers/span/subspan_5_assert_neg.cc: Likewise. * testsuite/23_containers/span/subspan_6_assert_neg.cc: Likewise. * testsuite/23_containers/span/subspan_assert_neg.cc: Likewise. * testsuite/23_containers/span/subspan_neg.cc: Likewise. * testsuite/23_containers/span/nodiscard.cc: New test. (cherry picked from commit a92a434024c59f57dc24328d946f97a5e71cee94) --- libstdc++-v3/include/std/span | 26 ++++++++- .../23_containers/span/back_assert_neg.cc | 2 +- .../testsuite/23_containers/span/back_neg.cc | 2 +- .../23_containers/span/first_2_assert_neg.cc | 2 +- .../23_containers/span/first_assert_neg.cc | 2 +- .../testsuite/23_containers/span/first_neg.cc | 2 +- .../23_containers/span/front_assert_neg.cc | 2 +- .../testsuite/23_containers/span/front_neg.cc | 2 +- .../23_containers/span/index_op_assert_neg.cc | 2 +- .../23_containers/span/index_op_neg.cc | 2 +- .../23_containers/span/last_2_assert_neg.cc | 2 +- .../23_containers/span/last_assert_neg.cc | 2 +- .../testsuite/23_containers/span/last_neg.cc | 2 +- .../testsuite/23_containers/span/nodiscard.cc | 58 +++++++++++++++++++ .../span/subspan_2_assert_neg.cc | 2 +- .../span/subspan_3_assert_neg.cc | 2 +- .../span/subspan_4_assert_neg.cc | 2 +- .../span/subspan_5_assert_neg.cc | 2 +- .../span/subspan_6_assert_neg.cc | 2 +- .../23_containers/span/subspan_assert_neg.cc | 2 +- .../23_containers/span/subspan_neg.cc | 6 +- 21 files changed, 103 insertions(+), 23 deletions(-) create mode 100644 libstdc++-v3/testsuite/23_containers/span/nodiscard.cc diff --git a/libstdc++-v3/include/std/span b/libstdc++-v3/include/std/span index 676338996650..b70893779d84 100644 --- a/libstdc++-v3/include/std/span +++ b/libstdc++-v3/include/std/span @@ -248,20 +248,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // observers + [[nodiscard]] constexpr size_type size() const noexcept { return this->_M_extent._M_extent(); } + [[nodiscard]] constexpr size_type size_bytes() const noexcept { return this->_M_extent._M_extent() * sizeof(element_type); } - [[nodiscard]] constexpr bool + [[nodiscard]] + constexpr bool empty() const noexcept { return size() == 0; } // element access + [[nodiscard]] constexpr reference front() const noexcept { @@ -269,6 +273,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *this->_M_ptr; } + [[nodiscard]] constexpr reference back() const noexcept { @@ -276,6 +281,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *(this->_M_ptr + (size() - 1)); } + [[nodiscard]] constexpr reference operator[](size_type __idx) const noexcept { @@ -283,41 +289,50 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return *(this->_M_ptr + __idx); } + [[nodiscard]] constexpr pointer data() const noexcept { return this->_M_ptr; } // iterator support + [[nodiscard]] constexpr iterator begin() const noexcept { return iterator(this->_M_ptr); } + [[nodiscard]] constexpr iterator end() const noexcept { return iterator(this->_M_ptr + this->size()); } + [[nodiscard]] constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(this->end()); } + [[nodiscard]] constexpr reverse_iterator rend() const noexcept { return reverse_iterator(this->begin()); } #if __cplusplus > 202002L + [[nodiscard]] constexpr const_iterator cbegin() const noexcept { return begin(); } + [[nodiscard]] constexpr const_iterator cend() const noexcept { return end(); } + [[nodiscard]] constexpr const_reverse_iterator crbegin() const noexcept { return rbegin(); } + [[nodiscard]] constexpr const_reverse_iterator crend() const noexcept { return rend(); } @@ -326,6 +341,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION // subviews template + [[nodiscard]] constexpr span first() const noexcept { @@ -337,6 +353,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return _Sp{ this->data(), _Count }; } + [[nodiscard]] constexpr span first(size_type __count) const noexcept { @@ -345,6 +362,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + [[nodiscard]] constexpr span last() const noexcept { @@ -356,6 +374,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION return _Sp{ this->data() + (this->size() - _Count), _Count }; } + [[nodiscard]] constexpr span last(size_type __count) const noexcept { @@ -364,6 +383,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } template + [[nodiscard]] constexpr auto subspan() const noexcept -> span()> @@ -395,6 +415,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION } } + [[nodiscard]] constexpr span subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept @@ -436,6 +457,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION -> span>>; template + [[nodiscard]] inline span @@ -453,7 +475,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION inline span - as_writable_bytes(span<_Type, _Extent> __sp) noexcept + as_writable_bytes [[nodiscard]] (span<_Type, _Extent> __sp) noexcept { auto data = reinterpret_cast(__sp.data()); auto size = __sp.size_bytes(); diff --git a/libstdc++-v3/testsuite/23_containers/span/back_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/back_assert_neg.cc index 2b4dee6df9ac..a7048977f473 100644 --- a/libstdc++-v3/testsuite/23_containers/span/back_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/back_assert_neg.cc @@ -26,5 +26,5 @@ int main() { std::span s; - s.back(); + (void) s.back(); } diff --git a/libstdc++-v3/testsuite/23_containers/span/back_neg.cc b/libstdc++-v3/testsuite/23_containers/span/back_neg.cc index 01083e601688..8c252a7ea698 100644 --- a/libstdc++-v3/testsuite/23_containers/span/back_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/back_neg.cc @@ -25,7 +25,7 @@ test01(bool b) { std::span s; if (b || !s.empty()) - s.back(); + (void) s.back(); return true; } diff --git a/libstdc++-v3/testsuite/23_containers/span/first_2_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/first_2_assert_neg.cc index 93cd095495a0..4220a6bca0e9 100644 --- a/libstdc++-v3/testsuite/23_containers/span/first_2_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/first_2_assert_neg.cc @@ -27,5 +27,5 @@ int main() { int a[4]; std::span s(a); - s.first(5); + (void) s.first(5); } diff --git a/libstdc++-v3/testsuite/23_containers/span/first_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/first_assert_neg.cc index 4ff56bf65cff..26c6483f1d72 100644 --- a/libstdc++-v3/testsuite/23_containers/span/first_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/first_assert_neg.cc @@ -27,5 +27,5 @@ int main() { int a[4]; std::span s(a); - s.first<5>(); + (void) s.first<5>(); } diff --git a/libstdc++-v3/testsuite/23_containers/span/first_neg.cc b/libstdc++-v3/testsuite/23_containers/span/first_neg.cc index 8ed68296263b..790107017275 100644 --- a/libstdc++-v3/testsuite/23_containers/span/first_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/first_neg.cc @@ -25,6 +25,6 @@ test01() { int a[4]; std::span s(a); - s.first<5>(); // { dg-error "here" } + (void) s.first<5>(); // { dg-error "here" } } // { dg-error "static assertion failed" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/23_containers/span/front_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/front_assert_neg.cc index 2d4320d0fd98..e1b1ad3287ec 100644 --- a/libstdc++-v3/testsuite/23_containers/span/front_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/front_assert_neg.cc @@ -26,5 +26,5 @@ int main() { std::span s; - s.front(); + (void) s.front(); } diff --git a/libstdc++-v3/testsuite/23_containers/span/front_neg.cc b/libstdc++-v3/testsuite/23_containers/span/front_neg.cc index f8e8100bd7cb..8e688d30fd32 100644 --- a/libstdc++-v3/testsuite/23_containers/span/front_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/front_neg.cc @@ -25,7 +25,7 @@ test01(bool b) { std::span s; if (b || !s.empty()) - s.front(); + (void) s.front(); return true; } diff --git a/libstdc++-v3/testsuite/23_containers/span/index_op_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/index_op_assert_neg.cc index b2633cbfaabd..8a7ef3d14642 100644 --- a/libstdc++-v3/testsuite/23_containers/span/index_op_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/index_op_assert_neg.cc @@ -26,5 +26,5 @@ int main() { std::span s; - s[99]; + (void) s[99]; } diff --git a/libstdc++-v3/testsuite/23_containers/span/index_op_neg.cc b/libstdc++-v3/testsuite/23_containers/span/index_op_neg.cc index 8bbe8ea07375..810a7c2aa238 100644 --- a/libstdc++-v3/testsuite/23_containers/span/index_op_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/index_op_neg.cc @@ -25,7 +25,7 @@ test01(bool b) { std::span s; if (b || !s.empty()) - s[99]; + (void) s[99]; return true; } diff --git a/libstdc++-v3/testsuite/23_containers/span/last_2_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/last_2_assert_neg.cc index 906896911c0f..6046264593b4 100644 --- a/libstdc++-v3/testsuite/23_containers/span/last_2_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/last_2_assert_neg.cc @@ -27,5 +27,5 @@ int main() { int a[4]; std::span s(a); - s.last(5); + (void) s.last(5); } diff --git a/libstdc++-v3/testsuite/23_containers/span/last_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/last_assert_neg.cc index 59cd44acc3cf..a1a4def2b8b0 100644 --- a/libstdc++-v3/testsuite/23_containers/span/last_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/last_assert_neg.cc @@ -27,5 +27,5 @@ int main() { int a[4]; std::span s(a); - s.last<5>(); + (void) s.last<5>(); } diff --git a/libstdc++-v3/testsuite/23_containers/span/last_neg.cc b/libstdc++-v3/testsuite/23_containers/span/last_neg.cc index 9c360d2650ef..dc2e99ad0fd5 100644 --- a/libstdc++-v3/testsuite/23_containers/span/last_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/last_neg.cc @@ -25,6 +25,6 @@ test01() { int a[2]; std::span s(a); - s.last<3>(); // { dg-error "here" } + (void) s.last<3>(); // { dg-error "here" } } // { dg-error "static assertion failed" "" { target *-*-* } 0 } diff --git a/libstdc++-v3/testsuite/23_containers/span/nodiscard.cc b/libstdc++-v3/testsuite/23_containers/span/nodiscard.cc new file mode 100644 index 000000000000..3bccd1545c3a --- /dev/null +++ b/libstdc++-v3/testsuite/23_containers/span/nodiscard.cc @@ -0,0 +1,58 @@ +// { dg-do compile { target c++20 } } + +#include + +void +test_observers(std::span s) +{ + s.size(); // { dg-warning "ignoring return value" } + s.size_bytes(); // { dg-warning "ignoring return value" } + s.empty(); // { dg-warning "ignoring return value" } +} + +void +test_element_access(std::span s) +{ + s.front(); // { dg-warning "ignoring return value" } + s.back(); // { dg-warning "ignoring return value" } + s[1]; // { dg-warning "ignoring return value" } + s.data(); // { dg-warning "ignoring return value" } +} + +struct S { }; + +void +test_iterators(std::span s) +{ + s.begin(); // { dg-warning "ignoring return value" } + s.end(); // { dg-warning "ignoring return value" } + s.rbegin(); // { dg-warning "ignoring return value" } + s.rend(); // { dg-warning "ignoring return value" } + +#if __cplusplus > 202002L + s.cbegin(); // { dg-warning "ignoring return value" "" { target c++23 } } + s.cend(); // { dg-warning "ignoring return value" "" { target c++23 } } + s.crbegin(); // { dg-warning "ignoring return value" "" { target c++23 } } + s.crend(); // { dg-warning "ignoring return value" "" { target c++23 } } +#endif +} + +void +test_subviews(std::span s) +{ + s.first<5>(); // { dg-warning "ignoring return value" } + s.first(6); // { dg-warning "ignoring return value" } + s.last<7>(); // { dg-warning "ignoring return value" } + s.last(8); // { dg-warning "ignoring return value" } + s.subspan<1>(); // { dg-warning "ignoring return value" } + s.subspan<2, 3>(); // { dg-warning "ignoring return value" } + s.subspan(4); // { dg-warning "ignoring return value" } + s.subspan(5, 6); // { dg-warning "ignoring return value" } +} + +void +test_non_members(std::span s) +{ + std::as_bytes(s); // { dg-warning "ignoring return value" } + std::as_writable_bytes(s); // { dg-warning "ignoring return value" } +} diff --git a/libstdc++-v3/testsuite/23_containers/span/subspan_2_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/subspan_2_assert_neg.cc index 488b56069936..b047cbe57b4c 100644 --- a/libstdc++-v3/testsuite/23_containers/span/subspan_2_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/subspan_2_assert_neg.cc @@ -27,5 +27,5 @@ int main() { int a[4]; std::span s(a); - s.subspan<2, 5>(); + (void) s.subspan<2, 5>(); } diff --git a/libstdc++-v3/testsuite/23_containers/span/subspan_3_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/subspan_3_assert_neg.cc index 8324edfc49a7..154e58744494 100644 --- a/libstdc++-v3/testsuite/23_containers/span/subspan_3_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/subspan_3_assert_neg.cc @@ -27,5 +27,5 @@ int main() { int a[4]; std::span s(a); - s.subspan<2, 3>(); + (void) s.subspan<2, 3>(); } diff --git a/libstdc++-v3/testsuite/23_containers/span/subspan_4_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/subspan_4_assert_neg.cc index b1dbfe6902e7..1757c4efaedf 100644 --- a/libstdc++-v3/testsuite/23_containers/span/subspan_4_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/subspan_4_assert_neg.cc @@ -27,5 +27,5 @@ int main() { int a[4]; std::span s(a); - s.subspan(5, 0); + (void) s.subspan(5, 0); } diff --git a/libstdc++-v3/testsuite/23_containers/span/subspan_5_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/subspan_5_assert_neg.cc index 2102fd02cce5..d327f557c22b 100644 --- a/libstdc++-v3/testsuite/23_containers/span/subspan_5_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/subspan_5_assert_neg.cc @@ -27,5 +27,5 @@ int main() { int a[4]; std::span s(a); - s.subspan(2, 5); + (void) s.subspan(2, 5); } diff --git a/libstdc++-v3/testsuite/23_containers/span/subspan_6_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/subspan_6_assert_neg.cc index c003561032c2..a4227948f552 100644 --- a/libstdc++-v3/testsuite/23_containers/span/subspan_6_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/subspan_6_assert_neg.cc @@ -27,5 +27,5 @@ int main() { int a[4]; std::span s(a); - s.subspan(2, 3); + (void) s.subspan(2, 3); } diff --git a/libstdc++-v3/testsuite/23_containers/span/subspan_assert_neg.cc b/libstdc++-v3/testsuite/23_containers/span/subspan_assert_neg.cc index c46b78fe8bc6..1b4b63a22aff 100644 --- a/libstdc++-v3/testsuite/23_containers/span/subspan_assert_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/subspan_assert_neg.cc @@ -27,5 +27,5 @@ int main() { int a[4]; std::span s(a); - s.subspan<5, 0>(); + (void) s.subspan<5, 0>(); } diff --git a/libstdc++-v3/testsuite/23_containers/span/subspan_neg.cc b/libstdc++-v3/testsuite/23_containers/span/subspan_neg.cc index 205bafd39ddc..4ff764a37247 100644 --- a/libstdc++-v3/testsuite/23_containers/span/subspan_neg.cc +++ b/libstdc++-v3/testsuite/23_containers/span/subspan_neg.cc @@ -25,7 +25,7 @@ test01() { int a[4]; std::span s(a); - s.subspan<5, 0>(); // { dg-error "here" } + (void) s.subspan<5, 0>(); // { dg-error "here" } } void @@ -33,7 +33,7 @@ test02() { int a[4]; std::span s(a); - s.subspan<3, 5>(); // { dg-error "here" } + (void) s.subspan<3, 5>(); // { dg-error "here" } } void @@ -41,7 +41,7 @@ test03() { int a[4]; std::span s(a); - s.subspan<3, 2>(); // { dg-error "here" } + (void) s.subspan<3, 2>(); // { dg-error "here" } } // { dg-error "static assertion failed" "" { target *-*-* } 0 } -- 2.47.2