[flang-commits] [flang] 2aad6a0 - [flang][msvc] Avoid a reinterpret_cast

peter klausler via flang-commits flang-commits at lists.llvm.org
Thu Oct 15 10:39:18 PDT 2020


Author: peter klausler
Date: 2020-10-15T10:38:48-07:00
New Revision: 2aad6a0884e3372fef8176902cf984d2f385d938

URL: https://github.com/llvm/llvm-project/commit/2aad6a0884e3372fef8176902cf984d2f385d938
DIFF: https://github.com/llvm/llvm-project/commit/2aad6a0884e3372fef8176902cf984d2f385d938.diff

LOG: [flang][msvc] Avoid a reinterpret_cast

The call to the binary->decimal formatter in real.cpp was cheating
by using a reinterpret_cast<> to extract its binary value.
Use a more principled and portable approach by extending the
API of evaluate::Integer<> to include ToUInt<>()/ToSInt<>()
member function templates that do the "right" thing.  Retain
ToUInt64()/ToSInt64() for compatibility.

Differential revision: https://reviews.llvm.org/D89435

Added: 
    

Modified: 
    flang/include/flang/Evaluate/integer.h
    flang/lib/Evaluate/real.cpp

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Evaluate/integer.h b/flang/include/flang/Evaluate/integer.h
index 20b6731768de8..35b42239ca751 100644
--- a/flang/include/flang/Evaluate/integer.h
+++ b/flang/include/flang/Evaluate/integer.h
@@ -462,21 +462,30 @@ class Integer {
     return CompareUnsigned(y);
   }
 
-  constexpr std::uint64_t ToUInt64() const {
-    std::uint64_t n{LEPart(0)};
-    int filled{partBits};
-    for (int j{1}; filled < 64 && j < parts; ++j, filled += partBits) {
-      n |= std::uint64_t{LEPart(j)} << filled;
+  template <typename UINT = std::uint64_t> constexpr UINT ToUInt() const {
+    UINT n{LEPart(0)};
+    std::size_t filled{partBits};
+    constexpr std::size_t maxBits{CHAR_BIT * sizeof n};
+    for (int j{1}; filled < maxBits && j < parts; ++j, filled += partBits) {
+      n |= UINT{LEPart(j)} << filled;
     }
     return n;
   }
 
-  constexpr std::int64_t ToInt64() const {
-    std::int64_t signExtended = ToUInt64();
-    if constexpr (bits < 64) {
-      signExtended |= -(signExtended >> (bits - 1)) << bits;
+  template <typename SINT = std::int64_t, typename UINT = std::uint64_t>
+  constexpr SINT ToSInt() const {
+    SINT n = ToUInt<UINT>();
+    constexpr std::size_t maxBits{CHAR_BIT * sizeof n};
+    if constexpr (bits < maxBits) {
+      n |= -(n >> (bits - 1)) << bits;
     }
-    return signExtended;
+    return n;
+  }
+
+  constexpr std::uint64_t ToUInt64() const { return ToUInt<std::uint64_t>(); }
+
+  constexpr std::int64_t ToInt64() const {
+    return ToSInt<std::int64_t, std::uint64_t>();
   }
 
   // Ones'-complement (i.e., C's ~)

diff  --git a/flang/lib/Evaluate/real.cpp b/flang/lib/Evaluate/real.cpp
index 58aa833dd6ddd..1428d52db0905 100644
--- a/flang/lib/Evaluate/real.cpp
+++ b/flang/lib/Evaluate/real.cpp
@@ -496,14 +496,15 @@ llvm::raw_ostream &Real<W, P>::AsFortran(
     }
   } else {
     using B = decimal::BinaryFloatingPointNumber<P>;
-    const auto *value{reinterpret_cast<const B *>(this)};
-    char buffer[24000]; // accommodate real*16
+    B value{word_.template ToUInt<typename B::RawType>()};
+    char buffer[common::MaxDecimalConversionDigits(P) +
+        EXTRA_DECIMAL_CONVERSION_SPACE];
     decimal::DecimalConversionFlags flags{}; // default: exact representation
     if (minimal) {
       flags = decimal::Minimize;
     }
     auto result{decimal::ConvertToDecimal<P>(buffer, sizeof buffer, flags,
-        static_cast<int>(sizeof buffer), decimal::RoundNearest, *value)};
+        static_cast<int>(sizeof buffer), decimal::RoundNearest, value)};
     const char *p{result.str};
     if (DEREF(p) == '-' || *p == '+') {
       o << *p++;


        


More information about the flang-commits mailing list