[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