-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[flang] Avoid left shifts of negative signed values #84786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
Shifting left a signed, negative value is an undefined behavior in C++. This was detected by the undefined behavior sanitizer.
@llvm/pr-subscribers-flang-semantics Author: Krzysztof Parzyszek (kparzysz) ChangesShifting left a signed, negative value is an undefined behavior in C++. This was detected by the undefined behavior sanitizer. Full diff: https://github.com/llvm/llvm-project/pull/84786.diff 1 Files Affected:
diff --git a/flang/include/flang/Evaluate/integer.h b/flang/include/flang/Evaluate/integer.h
index 977d35c7eecf48..1e5f68104f72bf 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;
}
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use braced initialization in Flang front-end code.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
Shifting left a signed, negative value is an undefined behavior in C++.
This was detected by the undefined behavior sanitizer.