lmi-commits
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lmi-commits] [lmi] master 6ceb6c0 1/2: Resolve more '-Wconversion' issu


From: Greg Chicares
Subject: [lmi-commits] [lmi] master 6ceb6c0 1/2: Resolve more '-Wconversion' issues
Date: Wed, 30 May 2018 22:21:03 -0400 (EDT)

branch: master
commit 6ceb6c0ba5b6650d12d39be9c89b31f989a77a69
Author: Gregory W. Chicares <address@hidden>
Commit: Gregory W. Chicares <address@hidden>

    Resolve more '-Wconversion' issues
    
    * bourn_cast.hpp: Intruded static_cast into the integral-to-floating
    conversion, giving the rationale in a comment block. Incidentally
    aligned range comparisons thus:
      if(x < y)
      if(    y < z)
    to make it easier to see that 'y' is the same when it's a complicated
    expression. Similarly, added a static_cast to the floating-to-integral
    code, making it look more like 'narrow_cast' in TC++PL4 [11.5].
    
    * bourn_cast_test.cpp: Suppressed compiler warnings with pragmata. The
    static_cast workaround seemed less appealing here, in particular because
    one test converts a value both explicitly (with static_cast) and
    implicitly, then compares the converted values. (Perhaps that test can
    never fail, but, this close to the edge of UB, it could conceivably find
    a compiler defect.)
---
 bourn_cast.hpp      | 18 +++++++++++++-----
 bourn_cast_test.cpp | 14 ++++++++++++++
 2 files changed, 27 insertions(+), 5 deletions(-)

diff --git a/bourn_cast.hpp b/bourn_cast.hpp
index 407649a..b48e443 100644
--- a/bourn_cast.hpp
+++ b/bourn_cast.hpp
@@ -83,7 +83,7 @@ constexpr inline To bourn_cast(From from, std::false_type, 
std::false_type)
             ? -to_traits::infinity()
             :  to_traits::infinity()
             ;
-    if(from < to_traits::lowest())
+    if(                   from < to_traits::lowest())
         throw std::runtime_error("Cast would transgress lower limit.");
     if(to_traits::max() < from)
         throw std::runtime_error("Cast would transgress upper limit.");
@@ -91,6 +91,15 @@ constexpr inline To bourn_cast(From from, std::false_type, 
std::false_type)
 }
 
 /// Integral to floating.
+///
+/// The inequality comparisons in the 'if' statements cannot exhibit
+/// UB because of the static assertion immediately preceding them.
+/// Writing static_cast in these comparisons looks unnatural, because
+/// it doesn't change the outcome (without it, integral-to-floating
+/// conversion would take place anyway); it serves only to suppress
+/// compiler warnings, for which purpose it seems less unnatural (and
+/// is certainly more portable) than surrounding the 'if' statements
+/// with pragmata.
 
 template<typename To, typename From>
 constexpr inline To bourn_cast(From from, std::false_type, std::true_type)
@@ -99,12 +108,11 @@ constexpr inline To bourn_cast(From from, std::false_type, 
std::true_type)
     using from_traits = std::numeric_limits<From>;
     static_assert(!to_traits::is_integer && from_traits::is_integer);
 
-    // If this assertion fails, the comparisons below may be UB.
     static_assert(from_traits::digits < to_traits::max_exponent);
 
-    if(from < to_traits::lowest())
+    if(                   static_cast<To>(from) < to_traits::lowest())
         throw std::runtime_error("Cast would transgress lower limit.");
-    if(to_traits::max() < from)
+    if(to_traits::max() < static_cast<To>(from))
         throw std::runtime_error("Cast would transgress upper limit.");
     return static_cast<To>(from);
 }
@@ -180,7 +188,7 @@ constexpr inline To bourn_cast(From from, std::true_type, 
std::false_type)
     if(limit <= from)
         throw std::runtime_error("Cast would transgress upper limit.");
     To const r = static_cast<To>(from);
-    if(r != from)
+    if(static_cast<From>(r) != from)
         {
         throw std::runtime_error("Cast would not preserve value.");
         }
diff --git a/bourn_cast_test.cpp b/bourn_cast_test.cpp
index ed360bb..8fc25ba 100644
--- a/bourn_cast_test.cpp
+++ b/bourn_cast_test.cpp
@@ -463,7 +463,14 @@ void test_m64_neighborhood()
     // unsigned integer is UB.
 
     unsigned long long int const ull_max = ull_traits::max();
+#if defined __GNUC__
+#   pragma GCC diagnostic push
+#   pragma GCC diagnostic ignored "-Wfloat-conversion"
+#endif // defined __GNUC__
     float const f_ull_max = ull_max;
+#if defined __GNUC__
+#   pragma GCC diagnostic pop
+#endif // defined __GNUC__
     BOOST_TEST(f_ull_max == static_cast<float>(ull_max));
     // Suppressed because behavior is undefined:
     // BOOST_TEST(ull_max == static_cast<unsigned long long int>(f_ull_max));
@@ -495,8 +502,15 @@ void test_m64_neighborhood()
     // about half a trillion units.
 
     double const d_2_64 = nonstd::power(2.0, 64);
+#if defined __GNUC__
+#   pragma GCC diagnostic push
+#   pragma GCC diagnostic ignored "-Wfloat-conversion"
+#endif // defined __GNUC__
     double const d_interesting = 0.5 * (d_2_64 + std::nextafterf(d_2_64, 0));
     unsigned long long int const ull_interesting = d_interesting;
+#if defined __GNUC__
+#   pragma GCC diagnostic pop
+#endif // defined __GNUC__
     float const f_interesting = bourn_cast<float>(ull_interesting);
     BOOST_TEST_THROW
         (bourn_cast<unsigned long long int>(f_interesting)



reply via email to

[Prev in Thread] Current Thread [Next in Thread]