[committed] libstdc++: Add nodiscard in

2024-03-14 Thread Jonathan Wakely
Tested aarch64-linux and x86_64-linux. Pushed to trunk.

I forgot to update the commit log to remove the speculation, because
Stephan Lavavej confirmed that MSVC doesn't mark those functions
nodiscard because it would result in too many false positives. Although
it might find some real bugs, it would also warn about a lot of
perfectly correct code.

-- >8 --

Add the [[nodiscard]] attribute to several functions in .
These all have no side effects and are only called for their return
value (e.g. std::count) or produce a result that must not be discarded
for correctness (e.g. std::remove).

I was intending to add the attribute to a number of other functions like
std::copy_if, std::unique_copy, std::set_union, and std::set_difference.
I stopped when I noticed that MSVC doesn't use it on those functions,
which I suspect is because they're often used with an insert iterator
(e.g. std::back_insert_iterator). In that case it doesn't matter if
you discard the result, because you have the container to tell you how
many elements were copied to the output range.

libstdc++-v3/ChangeLog:

* include/bits/stl_algo.h (find_end, all_of, none_of, any_of)
(find_if_not, is_partitioned, partition_point, remove)
(remove_if, unique, lower_bound, upper_bound, equal_range)
(binary_search, includes, is_sorted, is_sorted_until, minmax)
(minmax_element, is_permutation, clamp, find_if, find_first_of)
(adjacent_find, count, count_if, search, search_n, min_element)
(max_element): Add nodiscard attribute.
* include/bits/stl_algobase.h (min, max, lower_bound, equal)
(lexicographical_compare, lexicographical_compare_three_way)
(mismatch): Likewise.
* include/bits/stl_heap.h (is_heap, is_heap_until): Likewise.
* testsuite/25_algorithms/equal/debug/1_neg.cc: Add dg-warning.
* testsuite/25_algorithms/equal/debug/2_neg.cc: Likewise.
* testsuite/25_algorithms/equal/debug/3_neg.cc: Likewise.
* testsuite/25_algorithms/find_first_of/concept_check_1.cc:
Likewise.
* testsuite/25_algorithms/is_permutation/2.cc: Likewise.
* testsuite/25_algorithms/lexicographical_compare/71545.cc:
Likewise.
* testsuite/25_algorithms/lower_bound/33613.cc: Likewise.
* testsuite/25_algorithms/lower_bound/debug/irreflexive.cc:
Likewise.
* testsuite/25_algorithms/lower_bound/debug/partitioned_neg.cc:
Likewise.
* testsuite/25_algorithms/lower_bound/debug/partitioned_pred_neg.cc:
Likewise.
* testsuite/25_algorithms/minmax/3.cc: Likewise.
* testsuite/25_algorithms/search/78346.cc: Likewise.
* testsuite/25_algorithms/search_n/58358.cc: Likewise.
* testsuite/25_algorithms/unique/1.cc: Likewise.
* testsuite/25_algorithms/unique/11480.cc: Likewise.
* testsuite/25_algorithms/upper_bound/33613.cc: Likewise.
* testsuite/25_algorithms/upper_bound/debug/partitioned_neg.cc:
Likewise.
* testsuite/25_algorithms/upper_bound/debug/partitioned_pred_neg.cc:
Likewise.
* testsuite/ext/concept_checks.cc: Likewise.
* testsuite/ext/is_heap/47709.cc: Likewise.
* testsuite/ext/is_sorted/cxx0x.cc: Likewise.
---
 libstdc++-v3/include/bits/stl_algo.h  | 102 +-
 libstdc++-v3/include/bits/stl_algobase.h  |  32 +++---
 libstdc++-v3/include/bits/stl_heap.h  |   8 +-
 .../25_algorithms/equal/debug/1_neg.cc|   1 +
 .../25_algorithms/equal/debug/2_neg.cc|   1 +
 .../25_algorithms/equal/debug/3_neg.cc|   1 +
 .../find_first_of/concept_check_1.cc  |   1 +
 .../25_algorithms/is_permutation/2.cc |   1 +
 .../lexicographical_compare/71545.cc  |   1 +
 .../25_algorithms/lower_bound/33613.cc|   1 +
 .../lower_bound/debug/irreflexive.cc  |   1 +
 .../lower_bound/debug/partitioned_neg.cc  |   1 +
 .../lower_bound/debug/partitioned_pred_neg.cc |   1 +
 .../testsuite/25_algorithms/minmax/3.cc   |   1 +
 .../testsuite/25_algorithms/search/78346.cc   |   1 +
 .../testsuite/25_algorithms/search_n/58358.cc |   1 +
 .../testsuite/25_algorithms/unique/1.cc   |   1 +
 .../testsuite/25_algorithms/unique/11480.cc   |   2 +-
 .../25_algorithms/upper_bound/33613.cc|   1 +
 .../upper_bound/debug/partitioned_neg.cc  |   1 +
 .../upper_bound/debug/partitioned_pred_neg.cc |   1 +
 libstdc++-v3/testsuite/ext/concept_checks.cc  |   4 +
 libstdc++-v3/testsuite/ext/is_heap/47709.cc   |   1 +
 libstdc++-v3/testsuite/ext/is_sorted/cxx0x.cc |   1 +
 24 files changed, 95 insertions(+), 72 deletions(-)

diff --git a/libstdc++-v3/include/bits/stl_algo.h 
b/libstdc++-v3/include/bits/stl_algo.h
index 7a0cf6b6737..1a996aa61da 100644
--- a/libstdc++-v3/include/bits/stl_algo.h
+++ b/libstdc++-v3/include/bits/stl_algo.h
@@ -320,7 +320,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  [__first1,__last1-(__last2-__first2))
   

[committed] libstdc++: Add [[nodiscard]] to std::span members

2023-11-10 Thread Jonathan Wakely
Tested x86_64-linux. Pushed to trunk.

-- >8 --

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.
---
 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 d5644a196a2..90d08f18d2c 100644
--- a/libstdc++-v3/include/std/span
+++ b/libstdc++-v3/include/std/span
@@ -246,20 +246,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
   {
@@ -267,6 +271,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *this->_M_ptr;
   }
 
+  [[nodiscard]]
   constexpr reference
   back() const noexcept
   {
@@ -274,6 +279,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return *(this->_M_ptr + (size() - 1));
   }
 
+  [[nodiscard]]
   constexpr reference
   operator[](size_type __idx) const noexcept
   {
@@ -281,41 +287,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]]
   

[committed] libstdc++: Add [[nodiscard]] to lock types

2023-11-10 Thread Jonathan Wakely
Tested x86_64-linux. Pushed to trunk.

-- >8 --

Adding this attribute means users get a warning when they accidentally
create a temporary lock instead of creating an automatic variable with
block scope.

For std::lock_guard both constructors have side effects (they both take
a mutex and so both cause it to be unlocked at the end of the full
expression when a temporary is constructed). Ideally we would just put
the attribute on the class instead of the constructors, but that doesn't
work with GCC (PR c++/85973).

For std::unique_lock the default constructor and std::defer_lock_t
constructor do not cause any locking or unlocking, so do not need to
give a warning. It might still be a mistake to create a temporary using
those constructors, but it's harmless and seems unlikely anyway. For a
lock object created with one of those constructors you would expect the
lock object to be referred to later in the function, and that would not
even compile if it was constructed as an unnamed temporary.

std::scoped_lock gets the same treatment as std::lock_guard, except that
the explicit specialization for zero lockables has no side effects so
doesn't need to warn.

libstdc++-v3/ChangeLog:

* include/bits/std_mutex.h (lock_guard): Add [[nodiscard]]
attribute to constructors.
* include/bits/unique_lock.h (unique_lock): Likewise.
* include/std/mutex (scoped_lock, scoped_lock): Likewise.
* testsuite/30_threads/lock_guard/cons/nodiscard.cc: New test.
* testsuite/30_threads/scoped_lock/cons/nodiscard.cc: New test.
* testsuite/30_threads/unique_lock/cons/nodiscard.cc: New test.
---
 libstdc++-v3/include/bits/std_mutex.h |  2 +
 libstdc++-v3/include/bits/unique_lock.h   |  5 +++
 libstdc++-v3/include/std/mutex|  5 +++
 .../30_threads/lock_guard/cons/nodiscard.cc   | 20 ++
 .../30_threads/scoped_lock/cons/nodiscard.cc  | 29 ++
 .../30_threads/unique_lock/cons/nodiscard.cc  | 40 +++
 6 files changed, 101 insertions(+)
 create mode 100644 
libstdc++-v3/testsuite/30_threads/lock_guard/cons/nodiscard.cc
 create mode 100644 
libstdc++-v3/testsuite/30_threads/scoped_lock/cons/nodiscard.cc
 create mode 100644 
libstdc++-v3/testsuite/30_threads/unique_lock/cons/nodiscard.cc

diff --git a/libstdc++-v3/include/bits/std_mutex.h 
b/libstdc++-v3/include/bits/std_mutex.h
index 4693055269d..9ac8c76c9fb 100644
--- a/libstdc++-v3/include/bits/std_mutex.h
+++ b/libstdc++-v3/include/bits/std_mutex.h
@@ -245,9 +245,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 public:
   typedef _Mutex mutex_type;
 
+  [[__nodiscard__]]
   explicit lock_guard(mutex_type& __m) : _M_device(__m)
   { _M_device.lock(); }
 
+  [[__nodiscard__]]
   lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m)
   { } // calling thread owns mutex
 
diff --git a/libstdc++-v3/include/bits/unique_lock.h 
b/libstdc++-v3/include/bits/unique_lock.h
index c28e6456ad5..07474d26db5 100644
--- a/libstdc++-v3/include/bits/unique_lock.h
+++ b/libstdc++-v3/include/bits/unique_lock.h
@@ -66,6 +66,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   : _M_device(0), _M_owns(false)
   { }
 
+  [[__nodiscard__]]
   explicit unique_lock(mutex_type& __m)
   : _M_device(std::__addressof(__m)), _M_owns(false)
   {
@@ -77,10 +78,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   : _M_device(std::__addressof(__m)), _M_owns(false)
   { }
 
+  [[__nodiscard__]]
   unique_lock(mutex_type& __m, try_to_lock_t)
   : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock())
   { }
 
+  [[__nodiscard__]]
   unique_lock(mutex_type& __m, adopt_lock_t) noexcept
   : _M_device(std::__addressof(__m)), _M_owns(true)
   {
@@ -88,6 +91,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 
   template
+   [[__nodiscard__]]
unique_lock(mutex_type& __m,
const chrono::time_point<_Clock, _Duration>& __atime)
: _M_device(std::__addressof(__m)),
@@ -95,6 +99,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{ }
 
   template
+   [[__nodiscard__]]
unique_lock(mutex_type& __m,
const chrono::duration<_Rep, _Period>& __rtime)
: _M_device(std::__addressof(__m)),
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index bd3a1cbd94d..9d22ce80045 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -744,9 +744,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 class scoped_lock
 {
 public:
+
+  [[nodiscard]]
   explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...))
   { std::lock(__m...); }
 
+  [[nodiscard]]
   explicit scoped_lock(adopt_lock_t, _MutexTypes&... __m) noexcept
   : _M_devices(std::tie(__m...))
   { } // calling thread owns mutex
@@ -779,9 +782,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 public:
   using mutex_type = _Mutex;
 
+

[committed] libstdc++: Add [[nodiscard]] in

2022-12-22 Thread Jonathan Wakely via Gcc-patches
Tested x86_64-linux. Pushed to trunk.

-- >8 --

libstdc++-v3/ChangeLog:

* include/std/chrono: Use nodiscard attribute.
---
 libstdc++-v3/include/std/chrono | 46 +
 1 file changed, 29 insertions(+), 17 deletions(-)

diff --git a/libstdc++-v3/include/std/chrono b/libstdc++-v3/include/std/chrono
index 4c5fbfaeb83..33653f8efb1 100644
--- a/libstdc++-v3/include/std/chrono
+++ b/libstdc++-v3/include/std/chrono
@@ -128,11 +128,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   using time_point= chrono::time_point;
   static constexpr bool is_steady = false;
 
+  [[nodiscard]]
   static time_point
   now()
   { return from_sys(system_clock::now()); }
 
   template
+   [[nodiscard]]
static sys_time>
to_sys(const utc_time<_Duration>& __t)
{
@@ -145,6 +147,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
 
   template
+   [[nodiscard]]
static utc_time>
from_sys(const sys_time<_Duration>& __t)
{
@@ -171,11 +174,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   static constexpr bool is_steady = false; // XXX true for CLOCK_TAI?
 
   // TODO move into lib, use CLOCK_TAI on linux, add extension point.
+  [[nodiscard]]
   static time_point
   now()
   { return from_utc(utc_clock::now()); }
 
   template
+   [[nodiscard]]
static utc_time>
to_utc(const tai_time<_Duration>& __t)
{
@@ -184,6 +189,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
 
   template
+   [[nodiscard]]
static tai_time>
from_utc(const utc_time<_Duration>& __t)
{
@@ -208,11 +214,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   static constexpr bool is_steady = false; // XXX
 
   // TODO move into lib, add extension point.
+  [[nodiscard]]
   static time_point
   now()
   { return from_utc(utc_clock::now()); }
 
   template
+   [[nodiscard]]
static utc_time>
to_utc(const gps_time<_Duration>& __t)
{
@@ -221,6 +229,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
 
   template
+   [[nodiscard]]
static gps_time>
from_utc(const utc_time<_Duration>& __t)
{
@@ -394,6 +403,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 /// Convert a time point to a different clock.
 template
+  [[nodiscard]]
   inline auto
   clock_cast(const time_point<_SourceClock, _Duration>& __t)
   requires __detail::__clock_convs<_DestClock, _SourceClock, _Duration>
@@ -2620,6 +2630,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   leap_second(const leap_second&) = default;
   leap_second& operator=(const leap_second&) = default;
 
+  [[nodiscard]]
   constexpr sys_seconds
   date() const noexcept
   {
@@ -2628,6 +2639,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return sys_seconds(-_M_s);
   }
 
+  [[nodiscard]]
   constexpr seconds
   value() const noexcept
   {
@@ -2638,71 +2650,71 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   // This can be defaulted because the database will never contain two
   // leap_second objects with the same date but different signs.
-  friend constexpr bool
+  [[nodiscard]] friend constexpr bool
   operator==(const leap_second&, const leap_second&) noexcept = default;
 
-  friend constexpr strong_ordering
+  [[nodiscard]] friend constexpr strong_ordering
   operator<=>(const leap_second& __x, const leap_second& __y) noexcept
   { return __x.date() <=> __y.date(); }
 
   template
-   friend constexpr bool
+   [[nodiscard]] friend constexpr bool
operator==(const leap_second& __x,
   const sys_time<_Duration>& __y) noexcept
{ return __x.date() == __y; }
 
   template
-   friend constexpr bool
+   [[nodiscard]] friend constexpr bool
operator<(const leap_second& __x,
  const sys_time<_Duration>& __y) noexcept
{ return __x.date() < __y; }
 
   template
-   friend constexpr bool
+   [[nodiscard]] friend constexpr bool
operator<(const sys_time<_Duration>& __x,
  const leap_second& __y) noexcept
{ return __x < __y.date(); }
 
   template
-   friend constexpr bool
+   [[nodiscard]] friend constexpr bool
operator>(const leap_second& __x,
  const sys_time<_Duration>& __y) noexcept
{ return __y < __x.date(); }
 
   template
-   friend constexpr bool
+   [[nodiscard]] friend constexpr bool
operator>(const sys_time<_Duration>& __x,
  const leap_second& __y) noexcept
{ return __y.date() < __x; }
 
   template
-   friend constexpr bool
+   [[nodiscard]] friend constexpr bool
operator<=(const leap_second& __x,
- const sys_time<_Duration>& __y) noexcept
+  const sys_time<_Duration>& __y) noexcept
{ return !(__y < __x.date()); }
 
 

[committed] libstdc++: Add [[nodiscard]] to chrono conversion functions

2022-12-08 Thread Jonathan Wakely via Gcc-patches
Tested x86_64-linux. Pushed to trunk.

-- >8 --

Also add doxygen comments.

libstdc++-v3/ChangeLog:

* include/bits/chrono.h (duration_cast, floor, round, abs, ceil)
(time_point_cast): Add [[nodiscard]] attribute and doxygen
comments.
(treat_as_floating_point): Add doxygen commen.
---
 libstdc++-v3/include/bits/chrono.h | 139 +
 1 file changed, 123 insertions(+), 16 deletions(-)

diff --git a/libstdc++-v3/include/bits/chrono.h 
b/libstdc++-v3/include/bits/chrono.h
index 496e9485a73..22c0be3fbe6 100644
--- a/libstdc++-v3/include/bits/chrono.h
+++ b/libstdc++-v3/include/bits/chrono.h
@@ -246,8 +246,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 /// @endcond
 
-/// duration_cast
+/** Convert a `duration` to type `ToDur`.
+ *
+ * If the duration cannot be represented accurately in the result type,
+ * returns the result of integer truncation (i.e., rounded towards zero).
+ *
+ * @tparam _ToDur The result type must be a `duration`.
+ * @param __d A duration.
+ * @return The value of `__d` converted to type `_ToDur`.
+ * @since C++11
+ */
 template
+  _GLIBCXX_NODISCARD
   constexpr __enable_if_is_duration<_ToDur>
   duration_cast(const duration<_Rep, _Period>& __d)
   {
@@ -260,7 +270,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __dc::__cast(__d);
   }
 
-/// treat_as_floating_point
+/** Trait indicating whether to treat a type as a floating-point type.
+ *
+ * The chrono library uses this trait to tell whether a `duration` can
+ * represent fractional values of the given precision, or only integral
+ * values.
+ *
+ * You should specialize this trait for your own numeric types that are
+ * used with `duration` and can represent non-integral values.
+ *
+ * @since C++11
+ */
 template
   struct treat_as_floating_point
   : is_floating_point<_Rep>
@@ -320,8 +340,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #if __cplusplus >= 201703L
 # define __cpp_lib_chrono 201611L
 
+/** Convert a `duration` to type `ToDur` and round down.
+ *
+ * If the duration cannot be represented exactly in the result type,
+ * returns the closest value that is less than the argument.
+ *
+ * @tparam _ToDur The result type must be a `duration`.
+ * @param __d A duration.
+ * @return The value of `__d` converted to type `_ToDur`.
+ * @since C++17
+ */
 template
-  constexpr __enable_if_is_duration<_ToDur>
+  [[nodiscard]] constexpr __enable_if_is_duration<_ToDur>
   floor(const duration<_Rep, _Period>& __d)
   {
auto __to = chrono::duration_cast<_ToDur>(__d);
@@ -330,8 +360,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __to;
   }
 
+/** Convert a `duration` to type `ToDur` and round up.
+ *
+ * If the duration cannot be represented exactly in the result type,
+ * returns the closest value that is greater than the argument.
+ *
+ * @tparam _ToDur The result type must be a `duration`.
+ * @param __d A duration.
+ * @return The value of `__d` converted to type `_ToDur`.
+ * @since C++17
+ */
 template
-  constexpr __enable_if_is_duration<_ToDur>
+  [[nodiscard]] constexpr __enable_if_is_duration<_ToDur>
   ceil(const duration<_Rep, _Period>& __d)
   {
auto __to = chrono::duration_cast<_ToDur>(__d);
@@ -340,8 +380,20 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __to;
   }
 
+/** Convert a `duration` to type `ToDur` and round to the closest value.
+ *
+ * If the duration cannot be represented exactly in the result type,
+ * returns the closest value, rounding ties to even.
+ *
+ * @tparam _ToDur The result type must be a `duration` with a
+ *non-floating-point `rep` type.
+ * @param __d A duration.
+ * @return The value of `__d` converted to type `_ToDur`.
+ * @since C++17
+ */
 template 
-  constexpr enable_if_t<
+  [[nodiscard]] constexpr
+  enable_if_t<
__and_<__is_duration<_ToDur>,
   __not_>>::value,
_ToDur>
@@ -352,18 +404,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
auto __diff0 = __d - __t0;
auto __diff1 = __t1 - __d;
if (__diff0 == __diff1)
-   {
+ {
if (__t0.count() & 1)
-   return __t1;
+ return __t1;
return __t0;
-   }
+ }
else if (__diff0 < __diff1)
-   return __t0;
+ return __t0;
return __t1;
   }
 
+/** The absolute (non-negative) value of a duration.
+ *
+ * @param __d A duration with a signed `rep` type.
+ * @return A duration of the same type as the argument, with value |d|.
+ * @since C++17
+ */
 template
-  constexpr
+  [[nodiscard]] constexpr
   enable_if_t::is_signed, duration<_Rep, _Period>>
   

[committed] libstdc++: Add nodiscard attribute to mutex try_lock functions

2022-12-06 Thread Jonathan Wakely via Gcc-patches
Tested x86_64-linux. Pushed to trunk.

-- >8 --

libstdc++-v3/ChangeLog:

* include/bits/std_mutex.h (mutex): Add nodiscard attribute to
try_lock member function.
* include/bits/unique_lock.h (unique_lock): Likewise for
try_lock, try_lock_until, try_lock_for member functions, and
owns_lock and mutex member functions.
* include/std/mutex (recursive_mutex): Likewise for try_lock
member function.
(timed_mutex, recursive_timed_mutex, try_lock): Likewise for
try_lock, try_lock_until, try_lock_for member functions.
(try_lock): Likewise for non-member function.
* include/std/shared_mutex (shared_mutex): Likewise for try_lock
and try_lock_shared member functions.
(shared_timed_mutex): Likewise for try_lock, try_lock_for,
try_lock_shared, try_lock_shared_for, try_lock_until, and
try_lock_shared_until member functions.
(shared_lock): Likewise for try_lock, try_lock, try_lock_for,
try_lock_until, owns_lock, and mutex member functions.
* 
testsuite/30_threads/recursive_timed_mutex/try_lock_until/clock_neg.cc:
Cast discarded value expression to void.
* testsuite/30_threads/shared_lock/locking/3.cc: Likewise.
* testsuite/30_threads/shared_lock/locking/4.cc: Likewise.
* testsuite/30_threads/shared_lock/locking/clock_neg.cc:
Likewise.
* testsuite/30_threads/shared_timed_mutex/try_lock_until/clock_neg.cc:
Likewise.
* testsuite/30_threads/timed_mutex/try_lock_until/clock_neg.cc:
Likewise.
* testsuite/30_threads/try_lock/4.cc: Likewise.
* testsuite/30_threads/unique_lock/cons/60497.cc: Likewise.
* testsuite/30_threads/unique_lock/locking/3.cc: Likewise.
* testsuite/30_threads/unique_lock/locking/clock_neg.cc:
Likewise.
---
 libstdc++-v3/include/bits/std_mutex.h |  1 +
 libstdc++-v3/include/bits/unique_lock.h   |  5 +
 libstdc++-v3/include/std/mutex| 14 
 libstdc++-v3/include/std/shared_mutex | 22 ---
 .../try_lock_until/clock_neg.cc   |  4 ++--
 .../30_threads/shared_lock/locking/3.cc   |  2 +-
 .../30_threads/shared_lock/locking/4.cc   |  2 +-
 .../shared_lock/locking/clock_neg.cc  |  4 ++--
 .../try_lock_until/clock_neg.cc   |  4 ++--
 .../timed_mutex/try_lock_until/clock_neg.cc   |  4 ++--
 .../testsuite/30_threads/try_lock/4.cc|  2 +-
 .../30_threads/unique_lock/cons/60497.cc  |  2 +-
 .../30_threads/unique_lock/locking/3.cc   |  2 +-
 .../unique_lock/locking/clock_neg.cc  |  4 ++--
 14 files changed, 54 insertions(+), 18 deletions(-)

diff --git a/libstdc++-v3/include/bits/std_mutex.h 
b/libstdc++-v3/include/bits/std_mutex.h
index b22e0e12793..68f5fb9ed65 100644
--- a/libstdc++-v3/include/bits/std_mutex.h
+++ b/libstdc++-v3/include/bits/std_mutex.h
@@ -117,6 +117,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_system_error(__e);
 }
 
+_GLIBCXX_NODISCARD
 bool
 try_lock() noexcept
 {
diff --git a/libstdc++-v3/include/bits/unique_lock.h 
b/libstdc++-v3/include/bits/unique_lock.h
index 9ed7ba25766..c6402d94e85 100644
--- a/libstdc++-v3/include/bits/unique_lock.h
+++ b/libstdc++-v3/include/bits/unique_lock.h
@@ -143,6 +143,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
  }
   }
 
+  _GLIBCXX_NODISCARD
   bool
   try_lock()
   {
@@ -158,6 +159,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   }
 
   template
+   _GLIBCXX_NODISCARD
bool
try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime)
{
@@ -173,6 +175,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
}
 
   template
+   _GLIBCXX_NODISCARD
bool
try_lock_for(const chrono::duration<_Rep, _Period>& __rtime)
{
@@ -215,6 +218,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
return __ret;
   }
 
+  _GLIBCXX_NODISCARD
   bool
   owns_lock() const noexcept
   { return _M_owns; }
@@ -222,6 +226,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   explicit operator bool() const noexcept
   { return owns_lock(); }
 
+  _GLIBCXX_NODISCARD
   mutex_type*
   mutex() const noexcept
   { return _M_device; }
diff --git a/libstdc++-v3/include/std/mutex b/libstdc++-v3/include/std/mutex
index b310c15687d..aca5f91e03c 100644
--- a/libstdc++-v3/include/std/mutex
+++ b/libstdc++-v3/include/std/mutex
@@ -124,6 +124,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_system_error(__e);
 }
 
+_GLIBCXX_NODISCARD
 bool
 try_lock() noexcept
 {
@@ -253,6 +254,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__throw_system_error(__e);
 }
 
+_GLIBCXX_NODISCARD
 bool
 try_lock() noexcept
 {
@@ -261,11 +263,13 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 }
 
 template 
+  _GLIBCXX_NODISCARD
   bool
   try_lock_for(const 

[committed] libstdc++: Add nodiscard attribute to filesystem operations

2022-07-01 Thread Jonathan Wakely via Gcc-patches
Tested x86_64-linux, pushed to trunk.

-- >8 --

Some of these are not truly "pure" because they access the file system,
e.g. exists and file_size, but they do not modify anything and are only
useful for the return value.

If you really want to use one of those functions just to check whether
an error is reported (either via an exception or an error_code&
argument) you can still do so, but you need to cast the discarded result
to void.  Several tests need such a change, because they were indeed
only calling the functions to check for expected errors.

libstdc++-v3/ChangeLog:

* include/bits/fs_ops.h: Add nodiscard to all pure functions.
* include/experimental/bits/fs_ops.h: Likewise.
* testsuite/27_io/filesystem/operations/all.cc: Do not discard
results of absolute and canonical.
* testsuite/27_io/filesystem/operations/absolute.cc: Cast
discarded result to void.
* testsuite/27_io/filesystem/operations/canonical.cc: Likewise.
* testsuite/27_io/filesystem/operations/exists.cc: Likewise.
* testsuite/27_io/filesystem/operations/is_empty.cc: Likewise.
* testsuite/27_io/filesystem/operations/read_symlink.cc:
Likewise.
* testsuite/27_io/filesystem/operations/status.cc: Likewise.
* testsuite/27_io/filesystem/operations/symlink_status.cc:
Likewise.
* testsuite/27_io/filesystem/operations/temp_directory_path.cc:
Likewise.
* testsuite/experimental/filesystem/operations/canonical.cc:
Likewise.
* testsuite/experimental/filesystem/operations/exists.cc:
Likewise.
* testsuite/experimental/filesystem/operations/is_empty.cc:
Likewise.
* testsuite/experimental/filesystem/operations/read_symlink.cc:
Likewise.
* testsuite/experimental/filesystem/operations/temp_directory_path.cc:
Likewise.
---
 libstdc++-v3/include/bits/fs_ops.h| 79 +++
 .../include/experimental/bits/fs_ops.h| 71 +
 .../27_io/filesystem/operations/absolute.cc   |  2 +-
 .../27_io/filesystem/operations/all.cc|  8 +-
 .../27_io/filesystem/operations/canonical.cc  |  4 +-
 .../27_io/filesystem/operations/exists.cc |  2 +-
 .../27_io/filesystem/operations/is_empty.cc   |  4 +-
 .../filesystem/operations/read_symlink.cc |  2 +-
 .../27_io/filesystem/operations/status.cc |  2 +-
 .../filesystem/operations/symlink_status.cc   |  2 +-
 .../operations/temp_directory_path.cc |  4 +-
 .../filesystem/operations/canonical.cc|  6 +-
 .../filesystem/operations/exists.cc   |  2 +-
 .../filesystem/operations/is_empty.cc |  4 +-
 .../filesystem/operations/read_symlink.cc |  2 +-
 .../operations/temp_directory_path.cc |  4 +-
 16 files changed, 174 insertions(+), 24 deletions(-)

diff --git a/libstdc++-v3/include/bits/fs_ops.h 
b/libstdc++-v3/include/bits/fs_ops.h
index 0281c6540d0..1ae8fe12374 100644
--- a/libstdc++-v3/include/bits/fs_ops.h
+++ b/libstdc++-v3/include/bits/fs_ops.h
@@ -44,10 +44,16 @@ namespace filesystem
*  @{
*/
 
+  [[nodiscard]]
   path absolute(const path& __p);
+
+  [[nodiscard]]
   path absolute(const path& __p, error_code& __ec);
 
+  [[nodiscard]]
   path canonical(const path& __p);
+
+  [[nodiscard]]
   path canonical(const path& __p, error_code& __ec);
 
   inline void
@@ -100,25 +106,34 @@ namespace filesystem
   void create_symlink(const path& __to, const path& __new_symlink,
  error_code& __ec) noexcept;
 
+  [[nodiscard]]
   path current_path();
+
+  [[nodiscard]]
   path current_path(error_code& __ec);
+
   void current_path(const path& __p);
   void current_path(const path& __p, error_code& __ec) noexcept;
 
+  [[nodiscard]]
   bool
   equivalent(const path& __p1, const path& __p2);
 
+  [[nodiscard]]
   bool
   equivalent(const path& __p1, const path& __p2, error_code& __ec) noexcept;
 
+  [[nodiscard]]
   inline bool
   exists(file_status __s) noexcept
   { return status_known(__s) && __s.type() != file_type::not_found; }
 
+  [[nodiscard]]
   inline bool
   exists(const path& __p)
   { return exists(status(__p)); }
 
+  [[nodiscard]]
   inline bool
   exists(const path& __p, error_code& __ec) noexcept
   {
@@ -131,63 +146,85 @@ namespace filesystem
 return false;
   }
 
+  [[nodiscard]]
   uintmax_t file_size(const path& __p);
+
+  [[nodiscard]]
   uintmax_t file_size(const path& __p, error_code& __ec) noexcept;
 
+  [[nodiscard]]
   uintmax_t hard_link_count(const path& __p);
+
+  [[nodiscard]]
   uintmax_t hard_link_count(const path& __p, error_code& __ec) noexcept;
 
+  [[nodiscard]]
   inline bool
   is_block_file(file_status __s) noexcept
   { return __s.type() == file_type::block; }
 
+  [[nodiscard]]
   inline bool
   is_block_file(const path& __p)
   { return is_block_file(status(__p)); }
 
+  [[nodiscard]]
   inline bool
   is_block_file(const path& __p, error_code& __ec) noexcept
   

[committed] libstdc++: Add [[nodiscard]] to experimental::randint

2021-08-12 Thread Jonathan Wakely via Gcc-patches
Signed-off-by: Jonathan Wakely 

libstdc++-v3/ChangeLog:

* include/experimental/random (experimental::randint): Add
nodiscard attribute.

Tested powerpc64le-linux. Committed to trunk.

commit 20ce14c7991fbb498e32a0f5e3b01ae88c9f5e9a
Author: Jonathan Wakely 
Date:   Thu Aug 12 18:05:24 2021

libstdc++: Add [[nodiscard]] to experimental::randint

Signed-off-by: Jonathan Wakely 

libstdc++-v3/ChangeLog:

* include/experimental/random (experimental::randint): Add
nodiscard attribute.

diff --git a/libstdc++-v3/include/experimental/random 
b/libstdc++-v3/include/experimental/random
index 2c2b359ff41..d7431e33e98 100644
--- a/libstdc++-v3/include/experimental/random
+++ b/libstdc++-v3/include/experimental/random
@@ -50,6 +50,7 @@ inline namespace fundamentals_v2 {
 
   // 13.2.2.1, Function template randint
   template
+[[__nodiscard__]]
 inline _IntType
 randint(_IntType __a, _IntType __b)
 {


[committed] libstdc++: Add nodiscard attribute to cast-like functions

2021-04-06 Thread Jonathan Wakely via Gcc-patches
Add [[nodiscard]] to functions that are effectively just a static_cast,
as per P2351. Also add it to std::addressof.

libstdc++-v3/ChangeLog:

* include/bits/move.h (forward, move, move_if_noexcept)
(addressof): Add _GLIBCXX_NODISCARD.
* include/bits/ranges_cmp.h (identity::operator()): Add
nodiscard attribute.
* include/c_global/cstddef (to_integer): Likewise.
* include/std/bit (bit_cast): Likewise.
* include/std/utility (as_const, to_underlying): Likewise.

Tested powerpc64le-linux. Committed to trunk.

commit 406f58e1e38e92e4b881f3666b596843da308783
Author: Jonathan Wakely 
Date:   Tue Apr 6 14:41:29 2021

libstdc++: Add nodiscard attribute to cast-like functions

Add [[nodiscard]] to functions that are effectively just a static_cast,
as per P2351. Also add it to std::addressof.

libstdc++-v3/ChangeLog:

* include/bits/move.h (forward, move, move_if_noexcept)
(addressof): Add _GLIBCXX_NODISCARD.
* include/bits/ranges_cmp.h (identity::operator()): Add
nodiscard attribute.
* include/c_global/cstddef (to_integer): Likewise.
* include/std/bit (bit_cast): Likewise.
* include/std/utility (as_const, to_underlying): Likewise.

diff --git a/libstdc++-v3/include/bits/move.h b/libstdc++-v3/include/bits/move.h
index feacae084c9..3abbb37ceeb 100644
--- a/libstdc++-v3/include/bits/move.h
+++ b/libstdc++-v3/include/bits/move.h
@@ -72,6 +72,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  This function is used to implement "perfect forwarding".
*/
   template
+_GLIBCXX_NODISCARD
 constexpr _Tp&&
 forward(typename std::remove_reference<_Tp>::type& __t) noexcept
 { return static_cast<_Tp&&>(__t); }
@@ -83,6 +84,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  This function is used to implement "perfect forwarding".
*/
   template
+_GLIBCXX_NODISCARD
 constexpr _Tp&&
 forward(typename std::remove_reference<_Tp>::type&& __t) noexcept
 {
@@ -97,6 +99,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  @return The parameter cast to an rvalue-reference to allow moving it.
   */
   template
+_GLIBCXX_NODISCARD
 constexpr typename std::remove_reference<_Tp>::type&&
 move(_Tp&& __t) noexcept
 { return static_cast::type&&>(__t); }
@@ -116,6 +119,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  type is copyable, in which case an lvalue-reference is returned instead.
*/
   template
+_GLIBCXX_NODISCARD
 constexpr typename
 conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type
 move_if_noexcept(_Tp& __x) noexcept
@@ -136,6 +140,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
*  @return   The actual address.
   */
   template
+_GLIBCXX_NODISCARD
 inline _GLIBCXX17_CONSTEXPR _Tp*
 addressof(_Tp& __r) noexcept
 { return std::__addressof(__r); }
diff --git a/libstdc++-v3/include/bits/ranges_cmp.h 
b/libstdc++-v3/include/bits/ranges_cmp.h
index 3f71d31e5a6..f859a33b2c1 100644
--- a/libstdc++-v3/include/bits/ranges_cmp.h
+++ b/libstdc++-v3/include/bits/ranges_cmp.h
@@ -47,6 +47,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   struct identity
   {
 template
+  [[nodiscard]]
   constexpr _Tp&&
   operator()(_Tp&& __t) const noexcept
   { return std::forward<_Tp>(__t); }
diff --git a/libstdc++-v3/include/c_global/cstddef 
b/libstdc++-v3/include/c_global/cstddef
index 11c808cab28..13ef7f03c12 100644
--- a/libstdc++-v3/include/c_global/cstddef
+++ b/libstdc++-v3/include/c_global/cstddef
@@ -169,6 +169,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   { return __l = __l ^ __r; }
 
   template
+[[nodiscard]]
 constexpr _IntegerType
 to_integer(__byte_op_t<_IntegerType> __b) noexcept
 { return _IntegerType(__b); }
diff --git a/libstdc++-v3/include/std/bit b/libstdc++-v3/include/std/bit
index 8638a02c8a6..fb78578448c 100644
--- a/libstdc++-v3/include/std/bit
+++ b/libstdc++-v3/include/std/bit
@@ -54,6 +54,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
   /// Create a value of type `To` from the bits of `from`.
   template
+[[nodiscard]]
 constexpr _To
 bit_cast(const _From& __from) noexcept
 {
diff --git a/libstdc++-v3/include/std/utility b/libstdc++-v3/include/std/utility
index fb19d62968f..3e68f682e00 100644
--- a/libstdc++-v3/include/std/utility
+++ b/libstdc++-v3/include/std/utility
@@ -386,7 +386,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
 #define  __cpp_lib_as_const 201510
   template
-constexpr add_const_t<_Tp>& as_const(_Tp& __t) noexcept { return __t; }
+[[nodiscard]]
+constexpr add_const_t<_Tp>&
+as_const(_Tp& __t) noexcept
+{ return __t; }
 
   template
 void as_const(const _Tp&&) = delete;
@@ -466,6 +469,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #define __cpp_lib_to_underlying 202102L
   /// Convert an object of enumeration type to its underlying type.
   template
+[[nodiscard]]
 constexpr underlying_type_t<_Tp>