Skip to content

Conversation

@H-G-Hristov
Copy link
Contributor

@H-G-Hristov H-G-Hristov commented Dec 7, 2025

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

There appears to be an issue with annotating operator* and operator/, see: https://llvm.org/PR171031

@H-G-Hristov H-G-Hristov force-pushed the hgh/libcxx/nodiscard-to-complex branch from ded0d58 to 7973a9b Compare December 8, 2025 05:02
`[[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-complex branch from 7973a9b to 294251e Compare December 8, 2025 05:35
@Zingam Zingam marked this pull request as ready for review December 8, 2025 09:50
@Zingam Zingam requested a review from a team as a code owner December 8, 2025 09:50
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Dec 8, 2025
@llvmbot
Copy link
Member

llvmbot commented Dec 8, 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.

There appears to be an issue with annotating operator* and operator/, see: https://llvm.org/PR171031


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

3 Files Affected:

  • (modified) libcxx/include/complex (+77-65)
  • (added) libcxx/test/libcxx/numerics/complex.number/nodiscard.verify.cpp (+127)
  • (modified) libcxx/test/std/numerics/complex.number/complex.tuple/get.verify.cpp (+4-4)
diff --git a/libcxx/include/complex b/libcxx/include/complex
index d8ec3d95c10ed..49ab388113542 100644
--- a/libcxx/include/complex
+++ b/libcxx/include/complex
@@ -319,8 +319,8 @@ public:
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 complex(const complex<_Xp>& __c)
       : __re_(__c.real()), __im_(__c.imag()) {}
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type real() const { return __re_; }
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type imag() const { return __im_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type real() const { return __re_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 value_type imag() const { return __im_; }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
@@ -432,8 +432,8 @@ public:
   _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR complex(const complex<double>& __c);
   _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR complex(const complex<long double>& __c);
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float real() const { return __re_; }
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float imag() const { return __im_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float real() const { return __re_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR float imag() const { return __im_; }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
@@ -529,8 +529,8 @@ public:
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<float>& __c);
   _LIBCPP_HIDE_FROM_ABI explicit _LIBCPP_CONSTEXPR complex(const complex<long double>& __c);
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double real() const { return __re_; }
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double imag() const { return __im_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double real() const { return __re_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR double imag() const { return __im_; }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
@@ -630,8 +630,8 @@ public:
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<float>& __c);
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR complex(const complex<double>& __c);
 
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double real() const { return __re_; }
-  _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double imag() const { return __im_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double real() const { return __re_; }
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR long double imag() const { return __im_; }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void real(value_type __re) { __re_ = __re; }
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void imag(value_type __im) { __im_ = __im; }
@@ -732,7 +732,7 @@ inline _LIBCPP_CONSTEXPR complex<long double>::complex(const complex<double>& __
 // 26.3.6 operators:
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) {
   complex<_Tp> __t(__x);
   __t += __y;
@@ -740,7 +740,7 @@ operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) {
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator+(const complex<_Tp>& __x, const _Tp& __y) {
   complex<_Tp> __t(__x);
   __t += __y;
@@ -748,7 +748,7 @@ operator+(const complex<_Tp>& __x, const _Tp& __y) {
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator+(const _Tp& __x, const complex<_Tp>& __y) {
   complex<_Tp> __t(__y);
   __t += __x;
@@ -756,7 +756,7 @@ operator+(const _Tp& __x, const complex<_Tp>& __y) {
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) {
   complex<_Tp> __t(__x);
   __t -= __y;
@@ -764,7 +764,7 @@ operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) {
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator-(const complex<_Tp>& __x, const _Tp& __y) {
   complex<_Tp> __t(__x);
   __t -= __y;
@@ -772,7 +772,7 @@ operator-(const complex<_Tp>& __x, const _Tp& __y) {
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator-(const _Tp& __x, const complex<_Tp>& __y) {
   complex<_Tp> __t(-__y);
   __t += __x;
@@ -780,13 +780,13 @@ operator-(const _Tp& __x, const complex<_Tp>& __y) {
 }
 
 template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> >
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator*(const complex<_Tp>& __lhs, const complex<_Tp>& __rhs) {
   return complex<_Tp>(__from_builtin_tag(), __lhs.__builtin() * __rhs.__builtin());
 }
 
 template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> >
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) {
   _Tp __a = __z.real();
   _Tp __b = __z.imag();
@@ -797,7 +797,7 @@ operator*(const complex<_Tp>& __z, const complex<_Tp>& __w) {
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator*(const complex<_Tp>& __x, const _Tp& __y) {
   complex<_Tp> __t(__x);
   __t *= __y;
@@ -805,7 +805,7 @@ operator*(const complex<_Tp>& __x, const _Tp& __y) {
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator*(const _Tp& __x, const complex<_Tp>& __y) {
   complex<_Tp> __t(__y);
   __t *= __x;
@@ -813,13 +813,13 @@ operator*(const _Tp& __x, const complex<_Tp>& __y) {
 }
 
 template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> >
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator/(const complex<_Tp>& __lhs, const complex<_Tp>& __rhs) {
   return complex<_Tp>(__from_builtin_tag(), __lhs.__builtin() / __rhs.__builtin());
 }
 
 template <class _Tp, __enable_if_t<!is_floating_point<_Tp>::value, int> >
-_LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) {
   _Tp __a = __z.real();
   _Tp __b = __z.imag();
@@ -831,13 +831,13 @@ operator/(const complex<_Tp>& __z, const complex<_Tp>& __w) {
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator/(const complex<_Tp>& __x, const _Tp& __y) {
   return complex<_Tp>(__x.real() / __y, __x.imag() / __y);
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
 operator/(const _Tp& __x, const complex<_Tp>& __y) {
   complex<_Tp> __t(__x);
   __t /= __y;
@@ -845,12 +845,14 @@ operator/(const _Tp& __x, const complex<_Tp>& __y) {
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator+(const complex<_Tp>& __x) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+operator+(const complex<_Tp>& __x) {
   return __x;
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> operator-(const complex<_Tp>& __x) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+operator-(const complex<_Tp>& __x) {
   return complex<_Tp>(-__x.real(), -__x.imag());
 }
 
@@ -912,12 +914,13 @@ struct __libcpp_complex_overload_traits<_Tp, false, true> {
 // real
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp real(const complex<_Tp>& __c) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp real(const complex<_Tp>& __c) {
   return __c.real();
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __libcpp_complex_overload_traits<_Tp>::_ValueType
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
+typename __libcpp_complex_overload_traits<_Tp>::_ValueType
 real(_Tp __re) {
   return __re;
 }
@@ -925,12 +928,13 @@ real(_Tp __re) {
 // imag
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp imag(const complex<_Tp>& __c) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 _Tp imag(const complex<_Tp>& __c) {
   return __c.imag();
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14 typename __libcpp_complex_overload_traits<_Tp>::_ValueType
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX14
+typename __libcpp_complex_overload_traits<_Tp>::_ValueType
 imag(_Tp) {
   return 0;
 }
@@ -938,36 +942,36 @@ imag(_Tp) {
 // abs
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _Tp abs(const complex<_Tp>& __c) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _Tp abs(const complex<_Tp>& __c) {
   return std::hypot(__c.real(), __c.imag());
 }
 
 // arg
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _Tp arg(const complex<_Tp>& __c) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _Tp arg(const complex<_Tp>& __c) {
   return std::atan2(__c.imag(), __c.real());
 }
 
 template <class _Tp, __enable_if_t<is_same<_Tp, long double>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI long double arg(_Tp __re) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI long double arg(_Tp __re) {
   return std::atan2l(0.L, __re);
 }
 
 template <class _Tp, __enable_if_t<is_integral<_Tp>::value || is_same<_Tp, double>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI double arg(_Tp __re) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI double arg(_Tp __re) {
   return std::atan2(0., __re);
 }
 
 template <class _Tp, __enable_if_t<is_same<_Tp, float>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI float arg(_Tp __re) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI float arg(_Tp __re) {
   return std::atan2f(0.F, __re);
 }
 
 // norm
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp norm(const complex<_Tp>& __c) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp norm(const complex<_Tp>& __c) {
   if (std::__constexpr_isinf(__c.real()))
     return std::abs(__c.real());
   if (std::__constexpr_isinf(__c.imag()))
@@ -976,7 +980,8 @@ inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 _Tp norm(const comple
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __libcpp_complex_overload_traits<_Tp>::_ValueType
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+typename __libcpp_complex_overload_traits<_Tp>::_ValueType
 norm(_Tp __re) {
   typedef typename __libcpp_complex_overload_traits<_Tp>::_ValueType _ValueType;
   return static_cast<_ValueType>(__re) * __re;
@@ -985,12 +990,14 @@ norm(_Tp __re) {
 // conj
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp> conj(const complex<_Tp>& __c) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 complex<_Tp>
+conj(const complex<_Tp>& __c) {
   return complex<_Tp>(__c.real(), -__c.imag());
 }
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 typename __libcpp_complex_overload_traits<_Tp>::_ComplexType
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20
+typename __libcpp_complex_overload_traits<_Tp>::_ComplexType
 conj(_Tp __re) {
   typedef typename __libcpp_complex_overload_traits<_Tp>::_ComplexType _ComplexType;
   return _ComplexType(__re);
@@ -999,7 +1006,7 @@ conj(_Tp __re) {
 // proj
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> proj(const complex<_Tp>& __c) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> proj(const complex<_Tp>& __c) {
   complex<_Tp> __r = __c;
   if (std::isinf(__c.real()) || std::isinf(__c.imag()))
     __r = complex<_Tp>(INFINITY, std::copysign(_Tp(0), __c.imag()));
@@ -1007,14 +1014,16 @@ inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> proj(const complex<_Tp>& __c) {
 }
 
 template <class _Tp, __enable_if_t<is_floating_point<_Tp>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI typename __libcpp_complex_overload_traits<_Tp>::_ComplexType proj(_Tp __re) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI typename __libcpp_complex_overload_traits<_Tp>::_ComplexType
+proj(_Tp __re) {
   if (std::isinf(__re))
     __re = std::abs(__re);
   return complex<_Tp>(__re);
 }
 
 template <class _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI typename __libcpp_complex_overload_traits<_Tp>::_ComplexType proj(_Tp __re) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI typename __libcpp_complex_overload_traits<_Tp>::_ComplexType
+proj(_Tp __re) {
   typedef typename __libcpp_complex_overload_traits<_Tp>::_ComplexType _ComplexType;
   return _ComplexType(__re);
 }
@@ -1022,7 +1031,7 @@ inline _LIBCPP_HIDE_FROM_ABI typename __libcpp_complex_overload_traits<_Tp>::_Co
 // polar
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI complex<_Tp> polar(const _Tp& __rho, const _Tp& __theta = _Tp()) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI complex<_Tp> polar(const _Tp& __rho, const _Tp& __theta = _Tp()) {
   if (std::isnan(__rho) || std::signbit(__rho))
     return complex<_Tp>(_Tp(NAN), _Tp(NAN));
   if (std::isnan(__theta)) {
@@ -1047,21 +1056,21 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> polar(const _Tp& __rho, const _Tp& __theta =
 // log
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> log(const complex<_Tp>& __x) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> log(const complex<_Tp>& __x) {
   return complex<_Tp>(std::log(std::abs(__x)), std::arg(__x));
 }
 
 // log10
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> log10(const complex<_Tp>& __x) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> log10(const complex<_Tp>& __x) {
   return std::log(__x) / std::log(_Tp(10));
 }
 
 // sqrt
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI complex<_Tp> sqrt(const complex<_Tp>& __x) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI complex<_Tp> sqrt(const complex<_Tp>& __x) {
   if (std::isinf(__x.imag()))
     return complex<_Tp>(_Tp(INFINITY), __x.imag());
   if (std::isinf(__x.real())) {
@@ -1075,7 +1084,7 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> sqrt(const complex<_Tp>& __x) {
 // exp
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI complex<_Tp> exp(const complex<_Tp>& __x) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI complex<_Tp> exp(const complex<_Tp>& __x) {
   _Tp __i = __x.imag();
   if (__i == 0) {
     return complex<_Tp>(std::exp(__x.real()), std::copysign(_Tp(0), __x.imag()));
@@ -1097,24 +1106,27 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> exp(const complex<_Tp>& __x) {
 // pow
 
 template <class _Tp>
-inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> pow(const complex<_Tp>& __x, const complex<_Tp>& __y) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> pow(const complex<_Tp>& __x, const complex<_Tp>& __y) {
   return std::exp(__y * std::log(__x));
 }
 
 template <class _Tp, class _Up, __enable_if_t<is_floating_point<_Tp>::value && is_floating_point<_Up>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI complex<__promote_t<_Tp, _Up> > pow(const complex<_Tp>& __x, const complex<_Up>& __y) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI complex<__promote_t<_Tp, _Up> >
+pow(const complex<_Tp>& __x, const complex<_Up>& __y) {
   typedef complex<__promote_t<_Tp, _Up> > result_type;
   return std::pow(result_type(__x), result_type(__y));
 }
 
 template <class _Tp, class _Up, __enable_if_t<is_floating_point<_Tp>::value && is_arithmetic<_Up>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI complex<__promote_t<_Tp, _Up> > pow(const complex<_Tp>& __x, const _Up& __y) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI complex<__promote_t<_Tp, _Up> >
+pow(const complex<_Tp>& __x, const _Up& __y) {
   typedef complex<__promote_t<_Tp, _Up> > result_type;
   return std::pow(result_type(__x), result_type(__y));
 }
 
 template <class _Tp, class _Up, __enable_if_t<is_arithmetic<_Tp>::value && is_floating_point<_Up>::value, int> = 0>
-inline _LIBCPP_HIDE_FROM_ABI complex<__promote_t<_Tp, _Up> > pow(const _Tp& __x, const complex<_Up>& __y) {
+[[__nodiscard__]] inline _LIBCPP_HIDE_FROM_ABI complex<__promote_t<_Tp, _Up> >
+pow(const _Tp& __x, const complex<_Up>& __y) {
   typedef complex<__promote_t<_Tp, _Up> > result_type;
   return std::pow(result_type(__x), result_type(__y));
 }
@@ -1129,7 +1141,7 @@ inline _LIBCPP_HIDE_FROM_ABI complex<_Tp> __sqr(const complex<_Tp>& __x) {
 // asinh
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI complex<_Tp> asinh(const complex<_Tp>& __x) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI complex<_Tp> asinh(const complex<_Tp>& __x) {
   const _Tp __pi(atan2(+0., -0.));
   if (std::isinf(__x.real())) {
     if (std::isnan(__x.imag()))
@@ -1154,7 +1166,7 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> asinh(const complex<_Tp>& __x) {
 // acosh
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI complex<_Tp> acosh(const complex<_Tp>& __x) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI complex<_Tp> acosh(const complex<_Tp>& __x) {
   const _Tp __pi(atan2(+0., -0.));
   if (std::isinf(__x.real())) {
     if (std::isnan(__x.imag()))
@@ -1183,7 +1195,7 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> acosh(const complex<_Tp>& __x) {
 // atanh
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI complex<_Tp> atanh(const complex<_Tp>& __x) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI complex<_Tp> atanh(const complex<_Tp>& __x) {
   const _Tp __pi(atan2(+0., -0.));
   if (std::isinf(__x.imag())) {
     return complex<_Tp>(std::copysign(_Tp(0), __x.real()), std::copysign(__pi / _Tp(2), __x.imag()));
@@ -1209,7 +1221,7 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> atanh(const complex<_Tp>& __x) {
 // sinh
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI complex<_Tp> sinh(const complex<_Tp>& __x) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI complex<_Tp> sinh(const complex<_Tp>& __x) {
   if (std::isinf(__x.real()) && !std::isfinite(__x.imag()))
     return complex<_Tp>(__x.real(), _Tp(NAN));
   if (__x.real() == 0 && !std::isfinite(__x.imag()))
@@ -1222,7 +1234,7 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> sinh(const complex<_Tp>& __x) {
 // cosh
 
 template <class _Tp>
-_LIBCPP_HIDE_FROM_ABI complex<_Tp> cosh(const complex<_Tp>& __x) {
+[[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI complex<_Tp> cosh(const complex<_Tp>& __x) {
   if (std::isinf(__x.real()) && !std::isfinite(__x.imag()))
     return complex<_Tp>(std::abs(__x.real()), _Tp(NAN));
   if (__x.real() == 0 && !std::isfinite(__x.imag()))
@@ -1237,7 +1249,7 @@ _LIBCPP_HIDE_FROM_ABI complex<_Tp> cosh(con...
[truncated]

Copy link
Contributor

@frederick-vs-ja frederick-vs-ja left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's merge this once CI is green.

@frederick-vs-ja frederick-vs-ja added the pending-ci Merging the PR is only pending completion of CI label Dec 12, 2025
@Zingam
Copy link
Contributor

Zingam commented Dec 13, 2025

Thank you!

@Zingam Zingam merged commit d52d761 into llvm:main Dec 13, 2025
81 checks passed
anonymouspc pushed a commit to anonymouspc/llvm that referenced this pull request Dec 15, 2025
`[[nodiscard]]` should be applied to functions where discarding the
return value is most likely a correctness issue.

- https://libcxx.llvm.org/CodingGuidelines.html

There appears to be an issue with annotating `operator*` and
`operator/`, see: https://llvm.org/PR171031

---------

Co-authored-by: A. Jiang <[email protected]>
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. pending-ci Merging the PR is only pending completion of CI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants