[flang-commits] [flang] a70d729 - [flang] Avoid left shifts of negative signed values (#84786)
via flang-commits
flang-commits at lists.llvm.org
Mon Mar 11 12:30:33 PDT 2024
Author: Krzysztof Parzyszek
Date: 2024-03-11T14:30:30-05:00
New Revision: a70d7298818aae94ee62cd50c3ba195aaa10acb1
URL: https://github.com/llvm/llvm-project/commit/a70d7298818aae94ee62cd50c3ba195aaa10acb1
DIFF: https://github.com/llvm/llvm-project/commit/a70d7298818aae94ee62cd50c3ba195aaa10acb1.diff
LOG: [flang] Avoid left shifts of negative signed values (#84786)
Shifting left a signed, negative value is an undefined behavior in C++.
This was detected by the undefined behavior sanitizer.
Added:
Modified:
flang/include/flang/Evaluate/integer.h
Removed:
################################################################################
diff --git a/flang/include/flang/Evaluate/integer.h b/flang/include/flang/Evaluate/integer.h
index 977d35c7eecf48..31768c21daae62 100644
--- a/flang/include/flang/Evaluate/integer.h
+++ b/flang/include/flang/Evaluate/integer.h
@@ -150,7 +150,10 @@ class Integer {
}
}
} else {
- INT signExtension{-(n < 0)};
+ // Avoid left shifts of negative signed values (that's an undefined
+ // behavior in C++).
+ auto signExtension{std::make_unsigned_t<INT>(n < 0)};
+ signExtension = ~signExtension + 1;
static_assert(nBits >= partBits);
if constexpr (nBits > partBits) {
signExtension <<= nBits - partBits;
@@ -474,7 +477,12 @@ class Integer {
SINT n = ToUInt<UINT>();
constexpr std::size_t maxBits{CHAR_BIT * sizeof n};
if constexpr (bits < maxBits) {
- n |= -(n >> (bits - 1)) << bits;
+ // Avoid left shifts of negative signed values (that's an undefined
+ // behavior in C++).
+ auto u{std::make_unsigned_t<SINT>(ToUInt())};
+ u = (u >> (bits - 1)) << (bits - 1); // Get the sign bit only.
+ u = ~u + 1; // Negate top bits if not 0.
+ n |= static_cast<SINT>(u);
}
return n;
}
More information about the flang-commits
mailing list