[libcxx-commits] [libcxx] [libc++][test] Avoid truncation warnings from `double` to `float` (PR #74184)

Stephan T. Lavavej via libcxx-commits libcxx-commits at lists.llvm.org
Fri Dec 1 22:58:27 PST 2023


https://github.com/StephanTLavavej created https://github.com/llvm/llvm-project/pull/74184

Found while running libc++'s test suite with MSVC's STL, where we use both MSVC's compiler and Clang/LLVM.

MSVC really enjoys emitting "warning C4305: 'initializing': truncation from 'double' to 'float'". It might look repetitive, but `T(value)` avoids this warning. (According to my understanding, the compiler looks at the immediate context, and if it's a functional-style cast, it's satisfied that the truncation was intentional. Not even the direct-initialization context of `T unexpected(-9999.99)` is enough to activate that "ok, the programmer knows what they're getting" codepath.)

I usually prefer to use `static_cast` instead of functional-style casts, but I chose to remain consistent with the surrounding code.

By the way, you might notice that `1.5` doesn't need these changes. This is because it's exactly representable as both a `double` and a `float`. Values like `3.125` instead of `3.1` would similarly avoid truncation warnings without the need for casts, but I didn't want to intrusively change the test code.

>From f5b324fdef030e126a992ebcf32fa243b92f25a1 Mon Sep 17 00:00:00 2001
From: "Stephan T. Lavavej" <stl at nuwen.net>
Date: Thu, 30 Nov 2023 22:32:03 -0800
Subject: [PATCH] Avoid warning C4305: 'initializing': truncation from 'double'
 to 'float'

It might look repetitive, but T(value) is what avoids this warning.

I usually prefer to use static_cast instead of functional-style casts, but I chose to remain consistent with the surrounding code.
---
 .../atomics.types.float/assign.pass.cpp            |  2 +-
 .../compare_exchange_strong.pass.cpp               | 14 +++++++-------
 .../compare_exchange_weak.pass.cpp                 | 14 +++++++-------
 .../atomics.types.float/exchange.pass.cpp          |  2 +-
 .../atomics.types.float/fetch_add.pass.cpp         |  4 ++--
 .../atomics.types.float/fetch_sub.pass.cpp         |  4 ++--
 .../atomics.types.float/load.pass.cpp              |  2 +-
 .../atomics.types.float/notify_all.pass.cpp        |  2 +-
 .../atomics.types.float/notify_one.pass.cpp        |  2 +-
 .../atomics.types.float/operator.float.pass.cpp    |  2 +-
 .../operator.minus_equals.pass.cpp                 |  4 ++--
 .../operator.plus_equals.pass.cpp                  |  4 ++--
 .../atomics.types.float/store.pass.cpp             |  2 +-
 .../atomics.types.float/test_helper.h              |  2 +-
 .../atomics.types.float/wait.pass.cpp              |  2 +-
 15 files changed, 31 insertions(+), 31 deletions(-)

diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/assign.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/assign.pass.cpp
index 3daf3aba71fc9f2..66f6c91b802cb0c 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/assign.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/assign.pass.cpp
@@ -31,7 +31,7 @@ void test_impl() {
 
   // assignment
   {
-    MaybeVolatile<std::atomic<T>> a(3.1);
+    MaybeVolatile<std::atomic<T>> a(T(3.1));
     std::same_as<T> decltype(auto) r = (a = T(1.2));
     assert(a.load() == T(1.2));
     assert(r == T(1.2));
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/compare_exchange_strong.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/compare_exchange_strong.pass.cpp
index b010e7c7a4d79d9..711b49ddc233028 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/compare_exchange_strong.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/compare_exchange_strong.pass.cpp
@@ -44,8 +44,8 @@ void testBasic(MemoryOrder... memory_order) {
   // compare pass
   {
     MaybeVolatile<std::atomic<T>> a(T(1.2));
-    T expected(1.2);
-    const T desired(2.3);
+    T expected(T(1.2));
+    const T desired(T(2.3));
     std::same_as<bool> decltype(auto) r = a.compare_exchange_strong(expected, desired, memory_order...);
 
     assert(r);
@@ -57,7 +57,7 @@ void testBasic(MemoryOrder... memory_order) {
   {
     MaybeVolatile<std::atomic<T>> a(T(1.2));
     T expected(1.5);
-    const T desired(2.3);
+    const T desired(T(2.3));
     std::same_as<bool> decltype(auto) r = a.compare_exchange_strong(expected, desired, memory_order...);
 
     assert(!r);
@@ -168,7 +168,7 @@ void test_impl() {
     auto store = [](MaybeVolatile<std::atomic<T>>& x, T, T new_val) { x.store(new_val, std::memory_order::release); };
     auto load  = [](MaybeVolatile<std::atomic<T>>& x) {
       auto result = x.load(std::memory_order::relaxed);
-      T unexpected(-9999.99);
+      T unexpected(T(-9999.99));
       bool r = x.compare_exchange_strong(unexpected, unexpected, std::memory_order_relaxed, std::memory_order_acquire);
       assert(!r);
       return result;
@@ -177,7 +177,7 @@ void test_impl() {
 
     auto load_one_arg = [](MaybeVolatile<std::atomic<T>>& x) {
       auto result = x.load(std::memory_order::relaxed);
-      T unexpected(-9999.99);
+      T unexpected(T(-9999.99));
       bool r = x.compare_exchange_strong(unexpected, unexpected, std::memory_order_acquire);
       assert(!r);
       return result;
@@ -187,7 +187,7 @@ void test_impl() {
     // acq_rel replaced by acquire
     auto load_one_arg_acq_rel = [](MaybeVolatile<std::atomic<T>>& x) {
       auto result = x.load(std::memory_order::relaxed);
-      T unexpected(-9999.99);
+      T unexpected(T(-9999.99));
       bool r = x.compare_exchange_strong(unexpected, unexpected, std::memory_order_acq_rel);
       assert(!r);
       return result;
@@ -200,7 +200,7 @@ void test_impl() {
     auto store = [](MaybeVolatile<std::atomic<T>>& x, T, T new_val) { x.store(new_val, std::memory_order::seq_cst); };
     auto load  = [](MaybeVolatile<std::atomic<T>>& x) {
       auto result = x.load(std::memory_order::relaxed);
-      T unexpected(-9999.99);
+      T unexpected(T(-9999.99));
       bool r = x.compare_exchange_strong(unexpected, unexpected, std::memory_order_relaxed, std::memory_order::seq_cst);
       assert(!r);
       return result;
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/compare_exchange_weak.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/compare_exchange_weak.pass.cpp
index 27853ef08c7482c..ee1a00c284276c8 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/compare_exchange_weak.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/compare_exchange_weak.pass.cpp
@@ -44,8 +44,8 @@ void testBasic(MemoryOrder... memory_order) {
   // compare pass
   {
     MaybeVolatile<std::atomic<T>> a(T(1.2));
-    T expected(1.2);
-    const T desired(2.3);
+    T expected(T(1.2));
+    const T desired(T(2.3));
     std::same_as<bool> decltype(auto) r = a.compare_exchange_weak(expected, desired, memory_order...);
 
     // could be false spuriously
@@ -61,7 +61,7 @@ void testBasic(MemoryOrder... memory_order) {
   {
     MaybeVolatile<std::atomic<T>> a(T(1.2));
     T expected(1.5);
-    const T desired(2.3);
+    const T desired(T(2.3));
     std::same_as<bool> decltype(auto) r = a.compare_exchange_weak(expected, desired, memory_order...);
 
     assert(!r);
@@ -183,7 +183,7 @@ void test_impl() {
     auto store = [](MaybeVolatile<std::atomic<T>>& x, T, T new_val) { x.store(new_val, std::memory_order::release); };
     auto load  = [](MaybeVolatile<std::atomic<T>>& x) {
       auto result = x.load(std::memory_order::relaxed);
-      T unexpected(-9999.99);
+      T unexpected(T(-9999.99));
       bool r = x.compare_exchange_weak(unexpected, unexpected, std::memory_order_relaxed, std::memory_order_acquire);
       assert(!r);
       return result;
@@ -192,7 +192,7 @@ void test_impl() {
 
     auto load_one_arg = [](MaybeVolatile<std::atomic<T>>& x) {
       auto result = x.load(std::memory_order::relaxed);
-      T unexpected(-9999.99);
+      T unexpected(T(-9999.99));
       bool r = x.compare_exchange_weak(unexpected, unexpected, std::memory_order_acquire);
       assert(!r);
       return result;
@@ -202,7 +202,7 @@ void test_impl() {
     // acq_rel replaced by acquire
     auto load_one_arg_acq_rel = [](MaybeVolatile<std::atomic<T>>& x) {
       auto result = x.load(std::memory_order::relaxed);
-      T unexpected(-9999.99);
+      T unexpected(T(-9999.99));
       bool r = x.compare_exchange_weak(unexpected, unexpected, std::memory_order_acq_rel);
       assert(!r);
       return result;
@@ -215,7 +215,7 @@ void test_impl() {
     auto store = [](MaybeVolatile<std::atomic<T>>& x, T, T new_val) { x.store(new_val, std::memory_order::seq_cst); };
     auto load  = [](MaybeVolatile<std::atomic<T>>& x) {
       auto result = x.load(std::memory_order::relaxed);
-      T unexpected(-9999.99);
+      T unexpected(T(-9999.99));
       bool r = x.compare_exchange_weak(unexpected, unexpected, std::memory_order_relaxed, std::memory_order::seq_cst);
       assert(!r);
       return result;
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/exchange.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/exchange.pass.cpp
index 9c67d7e671cfa71..c0d1eb686db7a08 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/exchange.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/exchange.pass.cpp
@@ -34,7 +34,7 @@ void test_impl() {
 
   // exchange
   {
-    MaybeVolatile<std::atomic<T>> a(3.1);
+    MaybeVolatile<std::atomic<T>> a(T(3.1));
     std::same_as<T> decltype(auto) r = a.exchange(T(1.2), std::memory_order::relaxed);
     assert(a.load() == T(1.2));
     assert(r == T(3.1));
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_add.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_add.pass.cpp
index 664185fc243f9a2..c31243053e69fba 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_add.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_add.pass.cpp
@@ -42,7 +42,7 @@ void test_impl() {
 
   // fetch_add
   {
-    MaybeVolatile<std::atomic<T>> a(3.1);
+    MaybeVolatile<std::atomic<T>> a(T(3.1));
     std::same_as<T> decltype(auto) r = a.fetch_add(T(1.2), std::memory_order::relaxed);
     assert(r == T(3.1));
     assert(a.load() == T(3.1) + T(1.2));
@@ -78,7 +78,7 @@ void test_impl() {
       return res;
     };
 
-    assert(at.load() == times(1.234, number_of_threads * loop));
+    assert(at.load() == times(T(1.234), number_of_threads * loop));
   }
 #endif
 
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_sub.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_sub.pass.cpp
index c4e33538de74178..d26d21dec1b3346 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_sub.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/fetch_sub.pass.cpp
@@ -43,7 +43,7 @@ void test_impl() {
 
   // fetch_sub
   {
-    MaybeVolatile<std::atomic<T>> a(3.1);
+    MaybeVolatile<std::atomic<T>> a(T(3.1));
     std::same_as<T> decltype(auto) r = a.fetch_sub(T(1.2), std::memory_order::relaxed);
     assert(r == T(3.1));
     assert(a.load() == T(3.1) - T(1.2));
@@ -79,7 +79,7 @@ void test_impl() {
       return res;
     };
 
-    assert(at.load() == accu_neg(1.234, number_of_threads * loop));
+    assert(at.load() == accu_neg(T(1.234), number_of_threads * loop));
   }
 #endif
 
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/load.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/load.pass.cpp
index b495d04989e2007..b567af457dcaecd 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/load.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/load.pass.cpp
@@ -41,7 +41,7 @@ void test_impl() {
 
   // load
   {
-    MaybeVolatile<std::atomic<T>> a(3.1);
+    MaybeVolatile<std::atomic<T>> a(T(3.1));
     a.store(T(1.2));
     std::same_as<T> decltype(auto) r = a.load(std::memory_order::relaxed);
     assert(r == T(1.2));
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/notify_all.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/notify_all.pass.cpp
index eca7a19e5c57da0..b50c0ad9ee92efb 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/notify_all.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/notify_all.pass.cpp
@@ -37,7 +37,7 @@ void test_impl() {
   // should x87 80bit long double work at all?
   if constexpr (!std::same_as<T, long double>) {
     for (auto i = 0; i < 100; ++i) {
-      const T old = 3.1;
+      const T old = T(3.1);
       MaybeVolatile<std::atomic<T>> a(old);
 
       bool done                      = false;
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/notify_one.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/notify_one.pass.cpp
index 183cf18b820e746..aee4af186b9ffe3 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/notify_one.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/notify_one.pass.cpp
@@ -37,7 +37,7 @@ void test_impl() {
   // should x87 80bit long double work at all?
   if constexpr (!std::same_as<T, long double>) {
     for (auto i = 0; i < 100; ++i) {
-      const T old = 3.1;
+      const T old = T(3.1);
       MaybeVolatile<std::atomic<T>> a(old);
 
       std::atomic_bool started = false;
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.float.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.float.pass.cpp
index 58c8da6c1042b26..5d957ca68404a23 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.float.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.float.pass.cpp
@@ -28,7 +28,7 @@ void test_impl() {
 
   // operator float
   {
-    MaybeVolatile<std::atomic<T>> a(3.1);
+    MaybeVolatile<std::atomic<T>> a(T(3.1));
     T r = a;
     assert(r == T(3.1));
   }
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.minus_equals.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.minus_equals.pass.cpp
index b1ef276d870cf50..269eb819524f9d4 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.minus_equals.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.minus_equals.pass.cpp
@@ -39,7 +39,7 @@ void test_impl() {
 
   // -=
   {
-    MaybeVolatile<std::atomic<T>> a(3.1);
+    MaybeVolatile<std::atomic<T>> a(T(3.1));
     std::same_as<T> decltype(auto) r = a -= T(1.2);
     assert(r == T(3.1) - T(1.2));
     assert(a.load() == T(3.1) - T(1.2));
@@ -75,7 +75,7 @@ void test_impl() {
       return res;
     };
 
-    assert(at.load() == accu_neg(1.234, number_of_threads * loop));
+    assert(at.load() == accu_neg(T(1.234), number_of_threads * loop));
   }
 #endif
 
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.plus_equals.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.plus_equals.pass.cpp
index 0b1781bf8e571b9..9a2298ea46d660b 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.plus_equals.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/operator.plus_equals.pass.cpp
@@ -39,7 +39,7 @@ void test_impl() {
 
   // +=
   {
-    MaybeVolatile<std::atomic<T>> a(3.1);
+    MaybeVolatile<std::atomic<T>> a(T(3.1));
     std::same_as<T> decltype(auto) r = a += T(1.2);
     assert(r == T(3.1) + T(1.2));
     assert(a.load() == T(3.1) + T(1.2));
@@ -75,7 +75,7 @@ void test_impl() {
       return res;
     };
 
-    assert(at.load() == times(1.234, number_of_threads * loop));
+    assert(at.load() == times(T(1.234), number_of_threads * loop));
   }
 
   // memory_order::seq_cst
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/store.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/store.pass.cpp
index 81d17cd32a6c502..b0888aac67dbbf5 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/store.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/store.pass.cpp
@@ -41,7 +41,7 @@ void test_impl() {
 
   // store
   {
-    MaybeVolatile<std::atomic<T>> a(3.1);
+    MaybeVolatile<std::atomic<T>> a(T(3.1));
     a.store(T(1.2), std::memory_order::relaxed);
     assert(a.load() == T(1.2));
   }
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/test_helper.h b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/test_helper.h
index b831b774fbd3073..d0da1f20f550507 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/test_helper.h
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/test_helper.h
@@ -23,7 +23,7 @@
 
 template <class T>
 bool approximately_equals(T x, T y) {
-  T epsilon = 0.001;
+  T epsilon = T(0.001);
   return std::abs(x - y) < epsilon;
 }
 
diff --git a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/wait.pass.cpp b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/wait.pass.cpp
index d95801e25d35e03..8e003a7e365da1a 100644
--- a/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/wait.pass.cpp
+++ b/libcxx/test/std/atomics/atomics.types.generic/atomics.types.float/wait.pass.cpp
@@ -51,7 +51,7 @@ void test_impl() {
   // should x87 80bit long double work at all?
   if constexpr (!std::same_as<T, long double>) {
     for (auto i = 0; i < 100; ++i) {
-      const T old = 3.1;
+      const T old = T(3.1);
       MaybeVolatile<std::atomic<T>> a(old);
 
       std::atomic_bool started = false;



More information about the libcxx-commits mailing list