[gcc r17-37] libstdc++: Include bool conversion in noexcept specification of indirect::operator==.

Tomasz Kaminski tkaminsk@gcc.gnu.org
Thu Apr 23 11:06:23 GMT 2026


https://gcc.gnu.org/g:2985bacae46a61f70ac5bfbf3b6d3a943e538860

commit r17-37-g2985bacae46a61f70ac5bfbf3b6d3a943e538860
Author: Tomasz Kamiński <tkaminsk@redhat.com>
Date:   Wed Apr 22 16:10:26 2026 +0200

    libstdc++: Include bool conversion in noexcept specification of indirect::operator==.
    
    This expands the resolution of LWG4325 to heterogenous comparision
    with T per standard draft (see corresponding commit [1]).
    
    [1] https://github.com/cplusplus/draft/pull/8935/changes/833d635d648cdbd06c9935acccf925ee0aea3c79
    
    libstdc++-v3/ChangeLog:
    
            * include/bits/indirect.h (indirect::operator==): Adjust
            noexcept specification.
            * testsuite/std/memory/indirect/relops.cc: New test for noexcept
            specification.
    
    Reviewed-by: Jonathan Wakely <jwakely@redhat.com>
    Signed-off-by: Tomasz Kamiński <tkaminsk@redhat.com>

Diff:
---
 libstdc++-v3/include/bits/indirect.h               |  4 +-
 .../testsuite/std/memory/indirect/relops.cc        | 72 ++++++++++++++++++++++
 2 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/libstdc++-v3/include/bits/indirect.h b/libstdc++-v3/include/bits/indirect.h
index 6490a77a5079..5be6713eaf3f 100644
--- a/libstdc++-v3/include/bits/indirect.h
+++ b/libstdc++-v3/include/bits/indirect.h
@@ -336,7 +336,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	requires requires (const _Tp& __t, const _Up& __u) { __t == __u; }
 	friend constexpr bool
 	operator==(const indirect& __lhs, const indirect<_Up, _Alloc2>& __rhs)
-	noexcept(noexcept(*__lhs == *__rhs))
+	noexcept(noexcept(bool(*__lhs == *__rhs)))
 	{
 	  if (!__lhs._M_objp || !__rhs._M_objp)
 	    return bool(__lhs._M_objp) == bool(__rhs._M_objp);
@@ -349,7 +349,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 	  && requires (const _Tp& __t, const _Up& __u) { __t == __u; }
 	friend constexpr bool
 	operator==(const indirect<_Vp, _Alloc>& __lhs, const _Up& __rhs)
-	noexcept(noexcept(*__lhs == __rhs))
+	noexcept(noexcept(bool(*__lhs == __rhs)))
 	{
 	  if (!__lhs._M_objp)
 	    return false;
diff --git a/libstdc++-v3/testsuite/std/memory/indirect/relops.cc b/libstdc++-v3/testsuite/std/memory/indirect/relops.cc
index 77d599c80861..fb957a7ad3d3 100644
--- a/libstdc++-v3/testsuite/std/memory/indirect/relops.cc
+++ b/libstdc++-v3/testsuite/std/memory/indirect/relops.cc
@@ -68,11 +68,83 @@ test_hash()
   (void)std::hash<std::indirect<Obj>>{}(i);
 }
 
+template<bool Noexcept>
+struct BoolConv
+{
+  bool b;
+
+  constexpr BoolConv(bool p) noexcept
+  : b(p)
+  { }
+
+  constexpr operator bool() const noexcept(Noexcept)
+  { return b; }
+};
+
+template<bool Noexcept, typename EqRet = bool>
+struct Comp
+{
+  friend constexpr EqRet
+  operator==(const Comp&, const Comp&) noexcept(Noexcept)
+  { return true; }
+
+  friend constexpr std::strong_ordering
+  operator<=>(const Comp&, const Comp&) noexcept(Noexcept)
+  { return std::strong_ordering::equal; }
+};
+
+template<bool Noexcept, typename T>
+void test_noexcept_eq(T t)
+{
+  std::indirect<T> i(t);
+  static_assert(noexcept(i == t) == Noexcept);
+  static_assert(noexcept(i != t) == Noexcept);
+  static_assert(noexcept(i == i) == Noexcept);
+  static_assert(noexcept(i != i) == Noexcept);
+}
+
+template<bool Noexcept, typename T>
+void test_noexcept_rel(T t)
+{
+  std::indirect<T> i(t);
+  static_assert(noexcept(i < t) == Noexcept);
+  static_assert(noexcept(i > t) == Noexcept);
+  static_assert(noexcept(i <= t) == Noexcept);
+  static_assert(noexcept(i >= t) == Noexcept);
+  static_assert(noexcept(i <=> t) == Noexcept);
+
+  static_assert(noexcept(t < i) == Noexcept);
+  static_assert(noexcept(t > i) == Noexcept);
+  static_assert(noexcept(t <= i) == Noexcept);
+  static_assert(noexcept(t >= i) == Noexcept);
+  static_assert(noexcept(t <=> i) == Noexcept);
+
+  static_assert(noexcept(i < i) == Noexcept);
+  static_assert(noexcept(i > i) == Noexcept);
+  static_assert(noexcept(i <= i) == Noexcept);
+  static_assert(noexcept(i >= i) == Noexcept);
+  static_assert(noexcept(i <=> i) == Noexcept);
+}
+
+void test_noexcept()
+{
+  test_noexcept_eq<true>(Comp<true>());
+  test_noexcept_eq<false>(Comp<false>());
+  test_noexcept_rel<true>(Comp<true>());
+  test_noexcept_rel<false>(Comp<false>());
+
+  test_noexcept_eq<true>(Comp<true, BoolConv<true>>());
+  test_noexcept_eq<false>(Comp<true, BoolConv<false>>());
+  test_noexcept_eq<false>(Comp<false, BoolConv<true>>());
+  test_noexcept_eq<false>(Comp<false, BoolConv<false>>());
+}
+
 int main()
 {
   test_relops();
   test_comp_with_t();
   test_hash();
+  test_noexcept();
 
   static_assert([] {
     test_relops();


More information about the Libstdc++-cvs mailing list