Skip to content

Commit d056a20

Browse files
committed
[libc++][mdspan] Applied [[nodiscard]]
`[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue. - https://libcxx.llvm.org/CodingGuidelines.html#apply-nodiscard-where-relevant
1 parent 13ed14f commit d056a20

File tree

3 files changed

+93
-22
lines changed

3 files changed

+93
-22
lines changed

libcxx/include/__mdspan/extents.h

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -299,11 +299,13 @@ class extents {
299299

300300
public:
301301
// [mdspan.extents.obs], observers of multidimensional index space
302-
_LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank() noexcept { return __rank_; }
303-
_LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept { return __rank_dynamic_; }
302+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank() noexcept { return __rank_; }
303+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept { return __rank_dynamic_; }
304304

305-
_LIBCPP_HIDE_FROM_ABI constexpr index_type extent(rank_type __r) const noexcept { return __vals_.__value(__r); }
306-
_LIBCPP_HIDE_FROM_ABI static constexpr size_t static_extent(rank_type __r) noexcept {
305+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr index_type extent(rank_type __r) const noexcept {
306+
return __vals_.__value(__r);
307+
}
308+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr size_t static_extent(rank_type __r) noexcept {
307309
return _Values::__static_value(__r);
308310
}
309311

libcxx/include/__mdspan/mdspan.h

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -87,12 +87,14 @@ class mdspan {
8787
using data_handle_type = typename accessor_type::data_handle_type;
8888
using reference = typename accessor_type::reference;
8989

90-
_LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank() noexcept { return extents_type::rank(); }
91-
_LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept { return extents_type::rank_dynamic(); }
92-
_LIBCPP_HIDE_FROM_ABI static constexpr size_t static_extent(rank_type __r) noexcept {
90+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank() noexcept { return extents_type::rank(); }
91+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr rank_type rank_dynamic() noexcept {
92+
return extents_type::rank_dynamic();
93+
}
94+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr size_t static_extent(rank_type __r) noexcept {
9395
return extents_type::static_extent(__r);
9496
}
95-
_LIBCPP_HIDE_FROM_ABI constexpr index_type extent(rank_type __r) const noexcept {
97+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr index_type extent(rank_type __r) const noexcept {
9698
return __map_.extents().extent(__r);
9799
};
98100

@@ -185,7 +187,7 @@ class mdspan {
185187
requires((is_convertible_v<_OtherIndexTypes, index_type> && ...) &&
186188
(is_nothrow_constructible_v<index_type, _OtherIndexTypes> && ...) &&
187189
(sizeof...(_OtherIndexTypes) == rank()))
188-
_LIBCPP_HIDE_FROM_ABI constexpr reference operator[](_OtherIndexTypes... __indices) const {
190+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](_OtherIndexTypes... __indices) const {
189191
// Note the standard layouts would also check this, but user provided ones may not, so we
190192
// check the precondition here
191193
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__mdspan_detail::__is_multidimensional_index_in(extents(), __indices...),
@@ -196,7 +198,8 @@ class mdspan {
196198
template <class _OtherIndexType>
197199
requires(is_convertible_v<const _OtherIndexType&, index_type> &&
198200
is_nothrow_constructible_v<index_type, const _OtherIndexType&>)
199-
_LIBCPP_HIDE_FROM_ABI constexpr reference operator[](const array< _OtherIndexType, rank()>& __indices) const {
201+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference
202+
operator[](const array< _OtherIndexType, rank()>& __indices) const {
200203
return __acc_.access(__ptr_, [&]<size_t... _Idxs>(index_sequence<_Idxs...>) {
201204
return __map_(__indices[_Idxs]...);
202205
}(make_index_sequence<rank()>()));
@@ -205,7 +208,7 @@ class mdspan {
205208
template <class _OtherIndexType>
206209
requires(is_convertible_v<const _OtherIndexType&, index_type> &&
207210
is_nothrow_constructible_v<index_type, const _OtherIndexType&>)
208-
_LIBCPP_HIDE_FROM_ABI constexpr reference operator[](span<_OtherIndexType, rank()> __indices) const {
211+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference operator[](span<_OtherIndexType, rank()> __indices) const {
209212
return __acc_.access(__ptr_, [&]<size_t... _Idxs>(index_sequence<_Idxs...>) {
210213
return __map_(__indices[_Idxs]...);
211214
}(make_index_sequence<rank()>()));
@@ -237,24 +240,28 @@ class mdspan {
237240
swap(__x.__acc_, __y.__acc_);
238241
}
239242

240-
_LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept { return __map_.extents(); };
241-
_LIBCPP_HIDE_FROM_ABI constexpr const data_handle_type& data_handle() const noexcept { return __ptr_; };
242-
_LIBCPP_HIDE_FROM_ABI constexpr const mapping_type& mapping() const noexcept { return __map_; };
243-
_LIBCPP_HIDE_FROM_ABI constexpr const accessor_type& accessor() const noexcept { return __acc_; };
243+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const extents_type& extents() const noexcept {
244+
return __map_.extents();
245+
};
246+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const data_handle_type& data_handle() const noexcept { return __ptr_; };
247+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const mapping_type& mapping() const noexcept { return __map_; };
248+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr const accessor_type& accessor() const noexcept { return __acc_; };
244249

245250
// per LWG-4021 "mdspan::is_always_meow() should be noexcept"
246-
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept { return mapping_type::is_always_unique(); };
247-
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept {
251+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_unique() noexcept {
252+
return mapping_type::is_always_unique();
253+
};
254+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_exhaustive() noexcept {
248255
return mapping_type::is_always_exhaustive();
249256
};
250-
_LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept {
257+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI static constexpr bool is_always_strided() noexcept {
251258
return mapping_type::is_always_strided();
252259
};
253260

254-
_LIBCPP_HIDE_FROM_ABI constexpr bool is_unique() const { return __map_.is_unique(); };
255-
_LIBCPP_HIDE_FROM_ABI constexpr bool is_exhaustive() const { return __map_.is_exhaustive(); };
256-
_LIBCPP_HIDE_FROM_ABI constexpr bool is_strided() const { return __map_.is_strided(); };
257-
_LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const { return __map_.stride(__r); };
261+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool is_unique() const { return __map_.is_unique(); };
262+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool is_exhaustive() const { return __map_.is_exhaustive(); };
263+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool is_strided() const { return __map_.is_strided(); };
264+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr index_type stride(rank_type __r) const { return __map_.stride(__r); };
258265

259266
private:
260267
_LIBCPP_NO_UNIQUE_ADDRESS data_handle_type __ptr_{};
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
//===----------------------------------------------------------------------===//
2+
//
3+
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4+
// See https://llvm.org/LICENSE.txt for license information.
5+
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6+
//
7+
//===----------------------------------------------------------------------===//
8+
9+
// REQUIRES: std-at-least-c++23
10+
11+
// <span>
12+
13+
// Check that functions are marked [[nodiscard]]
14+
15+
#include <array>
16+
#include <mdspan>
17+
#include <span>
18+
19+
void test() {
20+
// mdspan<>
21+
22+
std::array<int, 4> data;
23+
std::mdspan<int, std::extents<std::size_t, 2, 2>> mdsp{data.data(), 2, 2};
24+
25+
mdsp[0, 1]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
26+
std::array arr{0, 1};
27+
mdsp[arr]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
28+
std::span sp{arr};
29+
mdsp[sp]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
30+
31+
mdsp.rank(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
32+
mdsp.rank_dynamic(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
33+
mdsp.static_extent(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
34+
mdsp.extent(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
35+
36+
mdsp.extents(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
37+
mdsp.data_handle(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
38+
mdsp.mapping(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
39+
mdsp.accessor(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
40+
41+
mdsp.is_always_unique(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
42+
mdsp.is_always_exhaustive(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
43+
mdsp.is_always_strided(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
44+
mdsp.is_unique(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
45+
mdsp.is_exhaustive(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
46+
mdsp.is_strided(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
47+
mdsp.stride(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
48+
49+
// Helpers
50+
51+
std::extents<int, 1, 2> ex;
52+
ex.rank(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
53+
ex.rank_dynamic(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
54+
ex.static_extent(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
55+
ex.extent(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
56+
57+
std::dextents<int, 2> dex;
58+
dex.rank(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
59+
dex.rank_dynamic(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
60+
dex.static_extent(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
61+
dex.extent(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
62+
}

0 commit comments

Comments
 (0)