[libcxx-commits] [libcxx] [libc++] Fix bug in **tests** for std::atomic_ref<T*> increment and decrement operators (PR #122271)

Damien L-G via libcxx-commits libcxx-commits at lists.llvm.org
Thu Jan 9 05:12:53 PST 2025


https://github.com/dalg24 created https://github.com/llvm/llvm-project/pull/122271

Fix https://github.com/llvm/llvm-project/pull/121414/files#r1908697882

The implementation is fine and has the proper increment/decrement operators defined
https://github.com/llvm/llvm-project/blob/b4e17d4a314ed87ff6b40b4b05397d4b25b6636a/libcxx/include/__atomic/atomic_ref.h#L364-L367

The issue is in the tests
* a typo (`T` instead of `std::atomic_ref<T>`) when ensuring that increment/decrement operators are not defined in the primary template and specialization for floating point types, and
* the specialization for pointer types miscategorized.

>From 47ef4ac5560a62f0867a44731bc17f2ae497e71d Mon Sep 17 00:00:00 2001
From: Damien L-G <dalg24 at gmail.com>
Date: Thu, 9 Jan 2025 07:50:20 -0500
Subject: [PATCH 1/2] [libc++] Fix bug in atomic_ref<T*> test

---
 .../atomics.ref/increment_decrement.pass.cpp       | 14 +++++++-------
 1 file changed, 7 insertions(+), 7 deletions(-)

diff --git a/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp b/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp
index f26a0bdf3663a5..84777c95f05692 100644
--- a/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp
@@ -42,21 +42,21 @@ constexpr bool does_not_have_increment_nor_decrement_operators() {
 
 template <typename T>
 struct TestDoesNotHaveIncrementDecrement {
-  void operator()() const { static_assert(does_not_have_increment_nor_decrement_operators<T>()); }
+  void operator()() const { static_assert(does_not_have_increment_nor_decrement_operators<std::atomic_ref<T>>()); }
 };
 
 template <typename T>
 struct TestIncrementDecrement {
   void operator()() const {
-    static_assert(std::is_integral_v<T>);
+    static_assert(std::is_integral_v<T> || std::is_pointer_v<T>);
 
     T x(T(1));
     std::atomic_ref<T> const a(x);
 
     {
       std::same_as<T> decltype(auto) y = ++a;
-      assert(y == T(2));
-      assert(x == T(2));
+      assert(y == T(1) + 1);
+      assert(x == T(1) + 1);
       ASSERT_NOEXCEPT(++a);
     }
 
@@ -70,13 +70,13 @@ struct TestIncrementDecrement {
     {
       std::same_as<T> decltype(auto) y = a++;
       assert(y == T(1));
-      assert(x == T(2));
+      assert(x == T(1) + 1);
       ASSERT_NOEXCEPT(a++);
     }
 
     {
       std::same_as<T> decltype(auto) y = a--;
-      assert(y == T(2));
+      assert(y == T(1) + 1);
       assert(x == T(1));
       ASSERT_NOEXCEPT(a--);
     }
@@ -88,7 +88,7 @@ int main(int, char**) {
 
   TestEachFloatingPointType<TestDoesNotHaveIncrementDecrement>()();
 
-  TestEachPointerType<TestDoesNotHaveIncrementDecrement>()();
+  TestEachPointerType<TestIncrementDecrement>()();
 
   TestDoesNotHaveIncrementDecrement<bool>()();
   TestDoesNotHaveIncrementDecrement<UserAtomicType>()();

>From 2a6263c903b1ba7e98dc9eb263638c0cc86109a6 Mon Sep 17 00:00:00 2001
From: Damien L-G <dalg24 at gmail.com>
Date: Thu, 9 Jan 2025 08:01:15 -0500
Subject: [PATCH 2/2] Avoid abusing conversions and split up pointer testing

---
 .../atomics.ref/increment_decrement.pass.cpp  | 96 +++++++++++++------
 1 file changed, 66 insertions(+), 30 deletions(-)

diff --git a/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp b/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp
index 84777c95f05692..0dfd797a908371 100644
--- a/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.ref/increment_decrement.pass.cpp
@@ -49,36 +49,72 @@ template <typename T>
 struct TestIncrementDecrement {
   void operator()() const {
     static_assert(std::is_integral_v<T> || std::is_pointer_v<T>);
-
-    T x(T(1));
-    std::atomic_ref<T> const a(x);
-
-    {
-      std::same_as<T> decltype(auto) y = ++a;
-      assert(y == T(1) + 1);
-      assert(x == T(1) + 1);
-      ASSERT_NOEXCEPT(++a);
-    }
-
-    {
-      std::same_as<T> decltype(auto) y = --a;
-      assert(y == T(1));
-      assert(x == T(1));
-      ASSERT_NOEXCEPT(--a);
-    }
-
-    {
-      std::same_as<T> decltype(auto) y = a++;
-      assert(y == T(1));
-      assert(x == T(1) + 1);
-      ASSERT_NOEXCEPT(a++);
-    }
-
-    {
-      std::same_as<T> decltype(auto) y = a--;
-      assert(y == T(1) + 1);
-      assert(x == T(1));
-      ASSERT_NOEXCEPT(a--);
+    if constexpr (std::is_integral_v<T>) {
+      T x(T(1));
+      std::atomic_ref<T> const a(x);
+
+      {
+        std::same_as<T> decltype(auto) y = ++a;
+        assert(y == T(2));
+        assert(x == T(2));
+        ASSERT_NOEXCEPT(++a);
+      }
+
+      {
+        std::same_as<T> decltype(auto) y = --a;
+        assert(y == T(1));
+        assert(x == T(1));
+        ASSERT_NOEXCEPT(--a);
+      }
+
+      {
+        std::same_as<T> decltype(auto) y = a++;
+        assert(y == T(1));
+        assert(x == T(2));
+        ASSERT_NOEXCEPT(a++);
+      }
+
+      {
+        std::same_as<T> decltype(auto) y = a--;
+        assert(y == T(2));
+        assert(x == T(1));
+        ASSERT_NOEXCEPT(a--);
+      }
+    } else if constexpr (std::is_pointer_v<T>) {
+      using U = std::remove_pointer_t<T>;
+      U t[9]  = {};
+      T p{&t[1]};
+      std::atomic_ref<T> const a(p);
+
+      {
+        std::same_as<T> decltype(auto) y = ++a;
+        assert(y == &t[2]);
+        assert(p == &t[2]);
+        ASSERT_NOEXCEPT(++a);
+      }
+
+      {
+        std::same_as<T> decltype(auto) y = --a;
+        assert(y == &t[1]);
+        assert(p == &t[1]);
+        ASSERT_NOEXCEPT(--a);
+      }
+
+      {
+        std::same_as<T> decltype(auto) y = a++;
+        assert(y == &t[1]);
+        assert(p == &t[2]);
+        ASSERT_NOEXCEPT(a++);
+      }
+
+      {
+        std::same_as<T> decltype(auto) y = a--;
+        assert(y == &t[2]);
+        assert(p == &t[1]);
+        ASSERT_NOEXCEPT(a--);
+      }
+    } else {
+      static_assert(std::is_void_v<T>);
     }
   }
 };



More information about the libcxx-commits mailing list