Skip to content

Commit 9512c4a

Browse files
committed
[libc++][span] Mark functions as [[nodiscard]]
1 parent 80ae168 commit 9512c4a

File tree

2 files changed

+129
-35
lines changed

2 files changed

+129
-35
lines changed

libcxx/include/span

Lines changed: 51 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -310,30 +310,32 @@ public:
310310
}
311311

312312
template <size_t _Count>
313-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> first() const noexcept {
313+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> first() const noexcept {
314314
static_assert(_Count <= _Extent, "span<T, N>::first<Count>(): Count out of range");
315315
return span<element_type, _Count>{data(), _Count};
316316
}
317317

318318
template <size_t _Count>
319-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> last() const noexcept {
319+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> last() const noexcept {
320320
static_assert(_Count <= _Extent, "span<T, N>::last<Count>(): Count out of range");
321321
return span<element_type, _Count>{data() + size() - _Count, _Count};
322322
}
323323

324-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept {
324+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
325+
first(size_type __count) const noexcept {
325326
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::first(count): count out of range");
326327
return {data(), __count};
327328
}
328329

329-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept {
330+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
331+
last(size_type __count) const noexcept {
330332
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T, N>::last(count): count out of range");
331333
return {data() + size() - __count, __count};
332334
}
333335

334336
template <size_t _Offset, size_t _Count = dynamic_extent>
335-
_LIBCPP_HIDE_FROM_ABI constexpr auto
336-
subspan() const noexcept -> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset> {
337+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr auto subspan() const noexcept
338+
-> span<element_type, _Count != dynamic_extent ? _Count : _Extent - _Offset> {
337339
static_assert(_Offset <= _Extent, "span<T, N>::subspan<Offset, Count>(): Offset out of range");
338340
static_assert(_Count == dynamic_extent || _Count <= _Extent - _Offset,
339341
"span<T, N>::subspan<Offset, Count>(): Offset + Count out of range");
@@ -342,7 +344,7 @@ public:
342344
return _ReturnType{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
343345
}
344346

345-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
347+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
346348
subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept {
347349
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__offset <= size(), "span<T, N>::subspan(offset, count): offset out of range");
348350
if (__count == dynamic_extent)
@@ -352,8 +354,10 @@ public:
352354
return {data() + __offset, __count};
353355
}
354356

355-
_LIBCPP_HIDE_FROM_ABI constexpr size_type size() const noexcept { return _Extent; }
356-
_LIBCPP_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept { return _Extent * sizeof(element_type); }
357+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_type size() const noexcept { return _Extent; }
358+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept {
359+
return _Extent * sizeof(element_type);
360+
}
357361
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const noexcept { return _Extent == 0; }
358362

359363
_LIBCPP_HIDE_FROM_ABI constexpr reference operator[](size_type __idx) const noexcept {
@@ -362,42 +366,46 @@ public:
362366
}
363367

364368
# if _LIBCPP_STD_VER >= 26
365-
_LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const {
369+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const {
366370
if (__index >= size())
367371
std::__throw_out_of_range("span");
368372
return __data_[__index];
369373
}
370374
# endif
371375

372-
_LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
376+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
373377
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::front() on empty span");
374378
return __data_[0];
375379
}
376380

377-
_LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
381+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
378382
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T, N>::back() on empty span");
379383
return __data_[size() - 1];
380384
}
381385

382-
_LIBCPP_HIDE_FROM_ABI constexpr pointer data() const noexcept { return __data_; }
386+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr pointer data() const noexcept { return __data_; }
383387

384388
// [span.iter], span iterator support
385-
_LIBCPP_HIDE_FROM_ABI constexpr iterator begin() const noexcept {
389+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() const noexcept {
386390
# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
387391
return std::__make_bounded_iter(data(), data(), data() + size());
388392
# else
389393
return iterator(data());
390394
# endif
391395
}
392-
_LIBCPP_HIDE_FROM_ABI constexpr iterator end() const noexcept {
396+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator end() const noexcept {
393397
# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
394398
return std::__make_bounded_iter(data() + size(), data(), data() + size());
395399
# else
396400
return iterator(data() + size());
397401
# endif
398402
}
399-
_LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
400-
_LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
403+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rbegin() const noexcept {
404+
return reverse_iterator(end());
405+
}
406+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rend() const noexcept {
407+
return reverse_iterator(begin());
408+
}
401409

402410
_LIBCPP_HIDE_FROM_ABI span<const byte, _Extent * sizeof(element_type)> __as_bytes() const noexcept {
403411
return span<const byte, _Extent * sizeof(element_type)>{reinterpret_cast<const byte*>(data()), size_bytes()};
@@ -478,36 +486,38 @@ public:
478486
: __data_{__other.data()}, __size_{__other.size()} {}
479487

480488
template <size_t _Count>
481-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> first() const noexcept {
489+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> first() const noexcept {
482490
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::first<Count>(): Count out of range");
483491
return span<element_type, _Count>{data(), _Count};
484492
}
485493

486494
template <size_t _Count>
487-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> last() const noexcept {
495+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> last() const noexcept {
488496
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count <= size(), "span<T>::last<Count>(): Count out of range");
489497
return span<element_type, _Count>{data() + size() - _Count, _Count};
490498
}
491499

492-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> first(size_type __count) const noexcept {
500+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
501+
first(size_type __count) const noexcept {
493502
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::first(count): count out of range");
494503
return {data(), __count};
495504
}
496505

497-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent> last(size_type __count) const noexcept {
506+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, dynamic_extent>
507+
last(size_type __count) const noexcept {
498508
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__count <= size(), "span<T>::last(count): count out of range");
499509
return {data() + size() - __count, __count};
500510
}
501511

502512
template <size_t _Offset, size_t _Count = dynamic_extent>
503-
_LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> subspan() const noexcept {
513+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr span<element_type, _Count> subspan() const noexcept {
504514
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Offset <= size(), "span<T>::subspan<Offset, Count>(): Offset out of range");
505515
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(_Count == dynamic_extent || _Count <= size() - _Offset,
506516
"span<T>::subspan<Offset, Count>(): Offset + Count out of range");
507517
return span<element_type, _Count>{data() + _Offset, _Count == dynamic_extent ? size() - _Offset : _Count};
508518
}
509519

510-
constexpr span<element_type, dynamic_extent> _LIBCPP_HIDE_FROM_ABI
520+
[[nodiscard]] constexpr span<element_type, dynamic_extent> _LIBCPP_HIDE_FROM_ABI
511521
subspan(size_type __offset, size_type __count = dynamic_extent) const noexcept {
512522
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__offset <= size(), "span<T>::subspan(offset, count): offset out of range");
513523
if (__count == dynamic_extent)
@@ -517,8 +527,10 @@ public:
517527
return {data() + __offset, __count};
518528
}
519529

520-
_LIBCPP_HIDE_FROM_ABI constexpr size_type size() const noexcept { return __size_; }
521-
_LIBCPP_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept { return __size_ * sizeof(element_type); }
530+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_type size() const noexcept { return __size_; }
531+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr size_type size_bytes() const noexcept {
532+
return __size_ * sizeof(element_type);
533+
}
522534
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool empty() const noexcept { return __size_ == 0; }
523535

524536
_LIBCPP_HIDE_FROM_ABI constexpr reference operator[](size_type __idx) const noexcept {
@@ -527,42 +539,46 @@ public:
527539
}
528540

529541
# if _LIBCPP_STD_VER >= 26
530-
_LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const {
542+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference at(size_type __index) const {
531543
if (__index >= size())
532544
std::__throw_out_of_range("span");
533545
return __data_[__index];
534546
}
535547
# endif
536548

537-
_LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
549+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference front() const noexcept {
538550
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::front() on empty span");
539551
return __data_[0];
540552
}
541553

542-
_LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
554+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reference back() const noexcept {
543555
_LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(!empty(), "span<T>::back() on empty span");
544556
return __data_[size() - 1];
545557
}
546558

547-
_LIBCPP_HIDE_FROM_ABI constexpr pointer data() const noexcept { return __data_; }
559+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr pointer data() const noexcept { return __data_; }
548560

549561
// [span.iter], span iterator support
550-
_LIBCPP_HIDE_FROM_ABI constexpr iterator begin() const noexcept {
562+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator begin() const noexcept {
551563
# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
552564
return std::__make_bounded_iter(data(), data(), data() + size());
553565
# else
554566
return iterator(data());
555567
# endif
556568
}
557-
_LIBCPP_HIDE_FROM_ABI constexpr iterator end() const noexcept {
569+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr iterator end() const noexcept {
558570
# ifdef _LIBCPP_ABI_BOUNDED_ITERATORS
559571
return std::__make_bounded_iter(data() + size(), data(), data() + size());
560572
# else
561573
return iterator(data() + size());
562574
# endif
563575
}
564-
_LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator(end()); }
565-
_LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rend() const noexcept { return reverse_iterator(begin()); }
576+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rbegin() const noexcept {
577+
return reverse_iterator(end());
578+
}
579+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr reverse_iterator rend() const noexcept {
580+
return reverse_iterator(begin());
581+
}
566582

567583
_LIBCPP_HIDE_FROM_ABI span<const byte, dynamic_extent> __as_bytes() const noexcept {
568584
return {reinterpret_cast<const byte*>(data()), size_bytes()};
@@ -585,13 +601,13 @@ inline constexpr bool ranges::enable_view<span<_ElementType, _Extent>> = true;
585601

586602
// as_bytes & as_writable_bytes
587603
template <class _Tp, size_t _Extent>
588-
_LIBCPP_HIDE_FROM_ABI auto as_bytes(span<_Tp, _Extent> __s) noexcept {
604+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto as_bytes(span<_Tp, _Extent> __s) noexcept {
589605
return __s.__as_bytes();
590606
}
591607

592608
template <class _Tp, size_t _Extent>
593609
requires(!is_const_v<_Tp>)
594-
_LIBCPP_HIDE_FROM_ABI auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept {
610+
[[nodiscard]] _LIBCPP_HIDE_FROM_ABI auto as_writable_bytes(span<_Tp, _Extent> __s) noexcept {
595611
return __s.__as_writable_bytes();
596612
}
597613

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
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++20
10+
11+
// <span>
12+
13+
// Check that functions are marked [[nodiscard]]
14+
15+
#include <array>
16+
#include <span>
17+
#include <vector>
18+
19+
#include "test_macros.h"
20+
21+
void test() {
22+
{ // Test with a static extent
23+
std::array arr{94, 92};
24+
std::span sp{arr};
25+
26+
sp.first<1>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
27+
sp.last<1>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
28+
sp.first(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
29+
sp.last(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
30+
sp.subspan<0, 1>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
31+
sp.subspan(0, 1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
32+
sp.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
33+
sp.size_bytes(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
34+
sp.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
35+
#if TEST_STD_VER >= 26
36+
sp.at(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
37+
#endif
38+
sp.front(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
39+
sp.back(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
40+
sp.data(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
41+
sp.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
42+
sp.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
43+
sp.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
44+
sp.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
45+
46+
std::as_bytes(sp); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
47+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
48+
std::as_writable_bytes(sp);
49+
}
50+
{ // Test with a dynamic extent
51+
std::vector vec{94, 92};
52+
std::span sp{vec};
53+
54+
sp.first<1>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
55+
sp.last<1>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
56+
sp.first(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
57+
sp.last(1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
58+
sp.subspan<0, 1>(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
59+
sp.subspan(0, 1); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
60+
sp.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
61+
sp.size_bytes(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
62+
sp.empty(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
63+
#if TEST_STD_VER >= 26
64+
sp.at(0); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
65+
#endif
66+
sp.front(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
67+
sp.back(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
68+
sp.data(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
69+
sp.begin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
70+
sp.end(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
71+
sp.rbegin(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
72+
sp.rend(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
73+
74+
std::as_bytes(sp); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
75+
// expected-warning@+1 {{ignoring return value of function declared with 'nodiscard' attribute}}
76+
std::as_writable_bytes(sp);
77+
}
78+
}

0 commit comments

Comments
 (0)