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)
// 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
{
return *this->_M_ptr;
}
+ [[nodiscard]]
constexpr reference
back() const noexcept
{
return *(this->_M_ptr + (size() - 1));
}
+ [[nodiscard]]
constexpr reference
operator[](size_type __idx) const noexcept
{
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(); }
// subviews
template<size_t _Count>
+ [[nodiscard]]
constexpr span<element_type, _Count>
first() const noexcept
{
return _Sp{ this->data(), _Count };
}
+ [[nodiscard]]
constexpr span<element_type, dynamic_extent>
first(size_type __count) const noexcept
{
}
template<size_t _Count>
+ [[nodiscard]]
constexpr span<element_type, _Count>
last() const noexcept
{
return _Sp{ this->data() + (this->size() - _Count), _Count };
}
+ [[nodiscard]]
constexpr span<element_type, dynamic_extent>
last(size_type __count) const noexcept
{
}
template<size_t _Offset, size_t _Count = dynamic_extent>
+ [[nodiscard]]
constexpr auto
subspan() const noexcept
-> span<element_type, _S_subspan_extent<_Offset, _Count>()>
}
}
+ [[nodiscard]]
constexpr span<element_type, dynamic_extent>
subspan(size_type __offset, size_type __count = dynamic_extent) const
noexcept
-> span<remove_reference_t<ranges::range_reference_t<_Range&>>>;
template<typename _Type, size_t _Extent>
+ [[nodiscard]]
inline
span<const byte, _Extent == dynamic_extent
? dynamic_extent : _Extent * sizeof(_Type)>
inline
span<byte, _Extent == dynamic_extent
? dynamic_extent : _Extent * sizeof(_Type)>
- as_writable_bytes(span<_Type, _Extent> __sp) noexcept
+ as_writable_bytes [[nodiscard]] (span<_Type, _Extent> __sp) noexcept
{
auto data = reinterpret_cast<byte*>(__sp.data());
auto size = __sp.size_bytes();
int main()
{
std::span<int, std::dynamic_extent> s;
- s.back();
+ (void) s.back();
}
{
std::span<int, 0> s;
if (b || !s.empty())
- s.back();
+ (void) s.back();
return true;
}
{
int a[4];
std::span<int, std::dynamic_extent> s(a);
- s.first(5);
+ (void) s.first(5);
}
{
int a[4];
std::span<int, std::dynamic_extent> s(a);
- s.first<5>();
+ (void) s.first<5>();
}
{
int a[4];
std::span<int, 4> s(a);
- s.first<5>(); // { dg-error "here" }
+ (void) s.first<5>(); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }
int main()
{
std::span<int, std::dynamic_extent> s;
- s.front();
+ (void) s.front();
}
{
std::span<int, 0> s;
if (b || !s.empty())
- s.front();
+ (void) s.front();
return true;
}
int main()
{
std::span<int, std::dynamic_extent> s;
- s[99];
+ (void) s[99];
}
{
std::span<int, 0> s;
if (b || !s.empty())
- s[99];
+ (void) s[99];
return true;
}
{
int a[4];
std::span<int, std::dynamic_extent> s(a);
- s.last(5);
+ (void) s.last(5);
}
{
int a[4];
std::span<int, std::dynamic_extent> s(a);
- s.last<5>();
+ (void) s.last<5>();
}
{
int a[2];
std::span<int, 2> s(a);
- s.last<3>(); // { dg-error "here" }
+ (void) s.last<3>(); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }
--- /dev/null
+// { dg-do compile { target c++20 } }
+
+#include <span>
+
+void
+test_observers(std::span<int> 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<float> 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)
+{
+ 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<long, 20> 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, 20> s)
+{
+ std::as_bytes(s); // { dg-warning "ignoring return value" }
+ std::as_writable_bytes(s); // { dg-warning "ignoring return value" }
+}
{
int a[4];
std::span<int, std::dynamic_extent> s(a);
- s.subspan<2, 5>();
+ (void) s.subspan<2, 5>();
}
{
int a[4];
std::span<int, std::dynamic_extent> s(a);
- s.subspan<2, 3>();
+ (void) s.subspan<2, 3>();
}
{
int a[4];
std::span<int, std::dynamic_extent> s(a);
- s.subspan(5, 0);
+ (void) s.subspan(5, 0);
}
{
int a[4];
std::span<int, std::dynamic_extent> s(a);
- s.subspan(2, 5);
+ (void) s.subspan(2, 5);
}
{
int a[4];
std::span<int, std::dynamic_extent> s(a);
- s.subspan(2, 3);
+ (void) s.subspan(2, 3);
}
{
int a[4];
std::span<int, std::dynamic_extent> s(a);
- s.subspan<5, 0>();
+ (void) s.subspan<5, 0>();
}
{
int a[4];
std::span<int, 4> s(a);
- s.subspan<5, 0>(); // { dg-error "here" }
+ (void) s.subspan<5, 0>(); // { dg-error "here" }
}
void
{
int a[4];
std::span<int, 4> s(a);
- s.subspan<3, 5>(); // { dg-error "here" }
+ (void) s.subspan<3, 5>(); // { dg-error "here" }
}
void
{
int a[4];
std::span<int, 4> s(a);
- s.subspan<3, 2>(); // { dg-error "here" }
+ (void) s.subspan<3, 2>(); // { dg-error "here" }
}
// { dg-error "static assertion failed" "" { target *-*-* } 0 }