[flang-commits] [flang] [flang] Avoid left shifts of negative signed values (PR #84786)

Krzysztof Parzyszek via flang-commits flang-commits at lists.llvm.org
Mon Mar 11 09:24:39 PDT 2024


https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/84786

Shifting left a signed, negative value is an undefined behavior in C++.

This was detected by the undefined behavior sanitizer.

>From 566a9a5b09d66ee531b326ac1f4eae8ed5e241ee Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Mon, 11 Mar 2024 10:22:16 -0500
Subject: [PATCH] [flang] Avoid left shifts of negative signed values

Shifting left a signed, negative value is an undefined behavior in C++.

This was detected by the undefined behavior sanitizer.
---
 flang/include/flang/Evaluate/integer.h | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

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;
   }



More information about the flang-commits mailing list