Skip to content

Conversation

@H-G-Hristov
Copy link
Contributor

[[nodiscard]] should be applied to functions where discarding the return value is most likely a correctness issue.

@H-G-Hristov H-G-Hristov requested a review from a team as a code owner December 6, 2025 21:40
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 6, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 6, 2025

@llvm/pr-subscribers-libcxx

Author: Hristo Hristov (H-G-Hristov)

Changes

[[nodiscard]] should be applied to functions where discarding the return value is most likely a correctness issue.


Patch is 23.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/170996.diff

2 Files Affected:

  • (modified) libcxx/include/valarray (+55-50)
  • (added) libcxx/test/libcxx/numerics/numarray/nodiscard.verify.cpp (+96)
diff --git a/libcxx/include/valarray b/libcxx/include/valarray
index 215811d5ba475..5df49fb442132 100644
--- a/libcxx/include/valarray
+++ b/libcxx/include/valarray
@@ -396,9 +396,9 @@ public:
   _LIBCPP_HIDE_FROM_ABI slice(size_t __start, size_t __size, size_t __stride)
       : __start_(__start), __size_(__size), __stride_(__stride) {}
 
-  _LIBCPP_HIDE_FROM_ABI size_t start() const { return __start_; }
-  _LIBCPP_HIDE_FROM_ABI size_t size() const { return __size_; }
-  _LIBCPP_HIDE_FROM_ABI size_t stride() const { return __stride_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t start() const { return __start_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t size() const { return __size_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t stride() const { return __stride_; }
 
 #  if _LIBCPP_STD_VER >= 20
 
@@ -822,36 +822,41 @@ public:
   _LIBCPP_HIDE_FROM_ABI valarray& operator=(const __val_expr<_ValExpr>& __v);
 
   // element access:
-  _LIBCPP_HIDE_FROM_ABI const value_type& operator[](size_t __i) const {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI const value_type& operator[](size_t __i) const {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < size(), "valarray::operator[] index out of bounds");
     return __begin_[__i];
   }
 
-  _LIBCPP_HIDE_FROM_ABI value_type& operator[](size_t __i) {
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI value_type& operator[](size_t __i) {
     _LIBCPP_ASSERT_VALID_ELEMENT_ACCESS(__i < size(), "valarray::operator[] index out of bounds");
     return __begin_[__i];
   }
 
   // subset operations:
-  _LIBCPP_HIDE_FROM_ABI __val_expr<__slice_expr<const valarray&> > operator[](slice __s) const;
-  _LIBCPP_HIDE_FROM_ABI slice_array<value_type> operator[](slice __s);
-  _LIBCPP_HIDE_FROM_ABI __val_expr<__indirect_expr<const valarray&> > operator[](const gslice& __gs) const;
-  _LIBCPP_HIDE_FROM_ABI gslice_array<value_type> operator[](const gslice& __gs);
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI __val_expr<__slice_expr<const valarray&> > operator[](slice __s) const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI slice_array<value_type> operator[](slice __s);
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI __val_expr<__indirect_expr<const valarray&> >
+  operator[](const gslice& __gs) const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI gslice_array<value_type> operator[](const gslice& __gs);
 #  ifndef _LIBCPP_CXX03_LANG
-  _LIBCPP_HIDE_FROM_ABI __val_expr<__indirect_expr<const valarray&> > operator[](gslice&& __gs) const;
-  _LIBCPP_HIDE_FROM_ABI gslice_array<value_type> operator[](gslice&& __gs);
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI __val_expr<__indirect_expr<const valarray&> > operator[](gslice&& __gs) const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI gslice_array<value_type> operator[](gslice&& __gs);
 #  endif // _LIBCPP_CXX03_LANG
+  [[__nodiscard__]]
   _LIBCPP_HIDE_FROM_ABI __val_expr<__mask_expr<const valarray&> > operator[](const valarray<bool>& __vb) const;
-  _LIBCPP_HIDE_FROM_ABI mask_array<value_type> operator[](const valarray<bool>& __vb);
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI mask_array<value_type> operator[](const valarray<bool>& __vb);
 #  ifndef _LIBCPP_CXX03_LANG
+  [[__nodiscard__]]
   _LIBCPP_HIDE_FROM_ABI __val_expr<__mask_expr<const valarray&> > operator[](valarray<bool>&& __vb) const;
-  _LIBCPP_HIDE_FROM_ABI mask_array<value_type> operator[](valarray<bool>&& __vb);
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI mask_array<value_type> operator[](valarray<bool>&& __vb);
 #  endif // _LIBCPP_CXX03_LANG
+  [[__nodiscard__]]
   _LIBCPP_HIDE_FROM_ABI __val_expr<__indirect_expr<const valarray&> > operator[](const valarray<size_t>& __vs) const;
-  _LIBCPP_HIDE_FROM_ABI indirect_array<value_type> operator[](const valarray<size_t>& __vs);
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI indirect_array<value_type> operator[](const valarray<size_t>& __vs);
 #  ifndef _LIBCPP_CXX03_LANG
+  [[__nodiscard__]]
   _LIBCPP_HIDE_FROM_ABI __val_expr<__indirect_expr<const valarray&> > operator[](valarray<size_t>&& __vs) const;
-  _LIBCPP_HIDE_FROM_ABI indirect_array<value_type> operator[](valarray<size_t>&& __vs);
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI indirect_array<value_type> operator[](valarray<size_t>&& __vs);
 #  endif // _LIBCPP_CXX03_LANG
 
   // unary operators:
@@ -905,16 +910,16 @@ public:
   // member functions:
   _LIBCPP_HIDE_FROM_ABI void swap(valarray& __v) _NOEXCEPT;
 
-  _LIBCPP_HIDE_FROM_ABI size_t size() const { return static_cast<size_t>(__end_ - __begin_); }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t size() const { return static_cast<size_t>(__end_ - __begin_); }
 
-  _LIBCPP_HIDE_FROM_ABI value_type sum() const;
-  _LIBCPP_HIDE_FROM_ABI value_type min() const;
-  _LIBCPP_HIDE_FROM_ABI value_type max() const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI value_type sum() const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI value_type min() const;
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI value_type max() const;
 
-  valarray shift(int __i) const;
-  valarray cshift(int __i) const;
-  valarray apply(value_type __f(value_type)) const;
-  valarray apply(value_type __f(const value_type&)) const;
+  [[__nodiscard__]] valarray shift(int __i) const;
+  [[__nodiscard__]] valarray cshift(int __i) const;
+  [[__nodiscard__]] valarray apply(value_type __f(value_type)) const;
+  [[__nodiscard__]] valarray apply(value_type __f(const value_type&)) const;
   void resize(size_t __n, value_type __x = value_type());
 
 private:
@@ -1249,11 +1254,11 @@ public:
 
 #  endif // _LIBCPP_CXX03_LANG
 
-  _LIBCPP_HIDE_FROM_ABI size_t start() const { return __1d_.size() ? __1d_[0] : 0; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI size_t start() const { return __1d_.size() ? __1d_[0] : 0; }
 
-  _LIBCPP_HIDE_FROM_ABI valarray<size_t> size() const { return __size_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI valarray<size_t> size() const { return __size_; }
 
-  _LIBCPP_HIDE_FROM_ABI valarray<size_t> stride() const { return __stride_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI valarray<size_t> stride() const { return __stride_; }
 
 private:
   void __init(size_t __start);
@@ -3106,7 +3111,7 @@ operator>=(const typename _Expr::value_type& __x, const _Expr& __y) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__abs_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__abs_expr<typename _Expr::value_type>, _Expr> >
 abs(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__abs_expr<value_type>, _Expr> _Op;
@@ -3114,7 +3119,7 @@ abs(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__acos_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__acos_expr<typename _Expr::value_type>, _Expr> >
 acos(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__acos_expr<value_type>, _Expr> _Op;
@@ -3122,7 +3127,7 @@ acos(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__asin_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__asin_expr<typename _Expr::value_type>, _Expr> >
 asin(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__asin_expr<value_type>, _Expr> _Op;
@@ -3130,7 +3135,7 @@ asin(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__atan_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__atan_expr<typename _Expr::value_type>, _Expr> >
 atan(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__atan_expr<value_type>, _Expr> _Op;
@@ -3140,7 +3145,7 @@ atan(const _Expr& __x) {
 template <class _Expr1,
           class _Expr2,
           __enable_if_t<__is_val_expr<_Expr1>::value && __is_val_expr<_Expr2>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_BinaryOp<__atan2_expr<typename _Expr1::value_type>, _Expr1, _Expr2> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_BinaryOp<__atan2_expr<typename _Expr1::value_type>, _Expr1, _Expr2> >
 atan2(const _Expr1& __x, const _Expr2& __y) {
   typedef typename _Expr1::value_type value_type;
   typedef _BinaryOp<__atan2_expr<value_type>, _Expr1, _Expr2> _Op;
@@ -3148,7 +3153,7 @@ atan2(const _Expr1& __x, const _Expr2& __y) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
 __val_expr<_BinaryOp<__atan2_expr<typename _Expr::value_type>, _Expr, __scalar_expr<typename _Expr::value_type> > >
 atan2(const _Expr& __x, const typename _Expr::value_type& __y) {
   typedef typename _Expr::value_type value_type;
@@ -3157,7 +3162,7 @@ atan2(const _Expr& __x, const typename _Expr::value_type& __y) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
 __val_expr<_BinaryOp<__atan2_expr<typename _Expr::value_type>, __scalar_expr<typename _Expr::value_type>, _Expr> >
 atan2(const typename _Expr::value_type& __x, const _Expr& __y) {
   typedef typename _Expr::value_type value_type;
@@ -3166,7 +3171,7 @@ atan2(const typename _Expr::value_type& __x, const _Expr& __y) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__cos_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__cos_expr<typename _Expr::value_type>, _Expr> >
 cos(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__cos_expr<value_type>, _Expr> _Op;
@@ -3174,7 +3179,7 @@ cos(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__cosh_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__cosh_expr<typename _Expr::value_type>, _Expr> >
 cosh(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__cosh_expr<value_type>, _Expr> _Op;
@@ -3182,7 +3187,7 @@ cosh(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__exp_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__exp_expr<typename _Expr::value_type>, _Expr> >
 exp(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__exp_expr<value_type>, _Expr> _Op;
@@ -3190,7 +3195,7 @@ exp(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__log_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__log_expr<typename _Expr::value_type>, _Expr> >
 log(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__log_expr<value_type>, _Expr> _Op;
@@ -3198,7 +3203,7 @@ log(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__log10_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__log10_expr<typename _Expr::value_type>, _Expr> >
 log10(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__log10_expr<value_type>, _Expr> _Op;
@@ -3208,7 +3213,7 @@ log10(const _Expr& __x) {
 template <class _Expr1,
           class _Expr2,
           __enable_if_t<__is_val_expr<_Expr1>::value && __is_val_expr<_Expr2>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_BinaryOp<__pow_expr<typename _Expr1::value_type>, _Expr1, _Expr2> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_BinaryOp<__pow_expr<typename _Expr1::value_type>, _Expr1, _Expr2> >
 pow(const _Expr1& __x, const _Expr2& __y) {
   typedef typename _Expr1::value_type value_type;
   typedef _BinaryOp<__pow_expr<value_type>, _Expr1, _Expr2> _Op;
@@ -3216,7 +3221,7 @@ pow(const _Expr1& __x, const _Expr2& __y) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
 __val_expr<_BinaryOp<__pow_expr<typename _Expr::value_type>, _Expr, __scalar_expr<typename _Expr::value_type> > >
 pow(const _Expr& __x, const typename _Expr::value_type& __y) {
   typedef typename _Expr::value_type value_type;
@@ -3225,7 +3230,7 @@ pow(const _Expr& __x, const typename _Expr::value_type& __y) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI
 __val_expr<_BinaryOp<__pow_expr<typename _Expr::value_type>, __scalar_expr<typename _Expr::value_type>, _Expr> >
 pow(const typename _Expr::value_type& __x, const _Expr& __y) {
   typedef typename _Expr::value_type value_type;
@@ -3234,7 +3239,7 @@ pow(const typename _Expr::value_type& __x, const _Expr& __y) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__sin_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__sin_expr<typename _Expr::value_type>, _Expr> >
 sin(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__sin_expr<value_type>, _Expr> _Op;
@@ -3242,7 +3247,7 @@ sin(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__sinh_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__sinh_expr<typename _Expr::value_type>, _Expr> >
 sinh(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__sinh_expr<value_type>, _Expr> _Op;
@@ -3250,7 +3255,7 @@ sinh(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__sqrt_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__sqrt_expr<typename _Expr::value_type>, _Expr> >
 sqrt(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__sqrt_expr<value_type>, _Expr> _Op;
@@ -3258,7 +3263,7 @@ sqrt(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__tan_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__tan_expr<typename _Expr::value_type>, _Expr> >
 tan(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__tan_expr<value_type>, _Expr> _Op;
@@ -3266,7 +3271,7 @@ tan(const _Expr& __x) {
 }
 
 template <class _Expr, __enable_if_t<__is_val_expr<_Expr>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__tanh_expr<typename _Expr::value_type>, _Expr> >
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI __val_expr<_UnaryOp<__tanh_expr<typename _Expr::value_type>, _Expr> >
 tanh(const _Expr& __x) {
   typedef typename _Expr::value_type value_type;
   typedef _UnaryOp<__tanh_expr<value_type>, _Expr> _Op;
@@ -3274,22 +3279,22 @@ tanh(const _Expr& __x) {
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _Tp* begin(valarray<_Tp>& __v) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _Tp* begin(valarray<_Tp>& __v) {
   return __v.__begin_;
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI const _Tp* begin(const valarray<_Tp>& __v) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI const _Tp* begin(const valarray<_Tp>& __v) {
   return __v.__begin_;
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _Tp* end(valarray<_Tp>& __v) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _Tp* end(valarray<_Tp>& __v) {
   return __v.__end_;
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI const _Tp* end(const valarray<_Tp>& __v) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI const _Tp* end(const valarray<_Tp>& __v) {
   return __v.__end_;
 }
 
diff --git a/libcxx/test/libcxx/numerics/numarray/nodiscard.verify.cpp b/libcxx/test/libcxx/numerics/numarray/nodiscard.verify.cpp
new file mode 100644
index 0000000000000..84e810f6dfe25
--- /dev/null
+++ b/libcxx/test/libcxx/numerics/numarray/nodiscard.verify.cpp
@@ -0,0 +1,96 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// <valarray>
+
+// Check that functions are marked [[nodiscard]]
+
+#include <valarray>
+#include <utility>
+
+#include "test_macros.h"
+
+int func(int);
+
+int cfunc(const int&);
+
+void test() {
+  std::slice s;
+
+  s.size();   // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  s.start();  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  s.stride(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+  std::gslice gs;
+
+  std::valarray<int> va;
+  const std::valarray<int> cva;
+
+  std::valarray<bool> bva;
+  std::valarray<std::size_t> sva;
+
+  cva[0];   // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  va[0];    // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  cva[s];   // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  va[s];    // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  cva[gs];  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  va[gs];   // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  cva[bva]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  va[bva];  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if TEST_STD_VER >= 11
+  cva[std::move(bva)]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  cva[std::move(bva)]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+  cva[sva]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  va[sva];  // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#if TEST_STD_VER >= 11
+  cva[std::move(sva)]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  cva[std::move(sva)]; // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+#endif
+
+  va.size(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+  va.sum(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  va.min(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  va.max(); // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+
+  va.shift(1);     // expected-warning {{ignoring return value of function declared with 'nodiscard' attribute}}
+  va.cshift(1);    // expected-warning {{ignoring return value of function declared with 'nodis...
[truncated]

@github-actions
Copy link

github-actions bot commented Dec 6, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

`[[nodiscard]]` should be applied to functions where discarding the return value is most likely a correctness issue.

- https://libcxx.llvm.org/CodingGuidelines.html
@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/nodiscard-to-valarray branch from 9b2770a to e159024 Compare December 6, 2025 21:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants