[flang] Correct folding of TRANSFER(integer, character array)
authorPeter Klausler <pklausler@nvidia.com>
Fri, 15 Jul 2022 19:15:07 +0000 (12:15 -0700)
committerPeter Klausler <pklausler@nvidia.com>
Sat, 23 Jul 2022 00:28:08 +0000 (17:28 -0700)
The code that copies data from a constant source array into a character
array constant result was failing to copy its last element if it was
only partially defined due to misalignment.

Differential Revision: https://reviews.llvm.org/D130376

flang/lib/Evaluate/initial-image.cpp
flang/test/Evaluate/fold-transfer.f90

index 0daffea66d87be3d722cca422ff183cc56f27135..cf70b6e8887063f5cbbba7b037f00cc215524b69 100644 (file)
@@ -135,12 +135,22 @@ public:
       for (std::size_t j{0}; j < elements; ++j) {
         using Char = typename Scalar::value_type;
         auto at{static_cast<std::size_t>(offset_ + j * stride)};
-        if (at + length > image_.data_.size()) {
+        auto chunk{length};
+        if (at + chunk > image_.data_.size()) {
           CHECK(padWithZero_);
-          break;
+          if (at >= image_.data_.size()) {
+            chunk = 0;
+          } else {
+            chunk = image_.data_.size() - at;
+          }
+        }
+        if (chunk > 0) {
+          const Char *data{reinterpret_cast<const Char *>(&image_.data_[at])};
+          typedValue[j].assign(data, chunk);
+        }
+        if (chunk < length && padWithZero_) {
+          typedValue[j].append(length - chunk, Char{});
         }
-        const Char *data{reinterpret_cast<const Char *>(&image_.data_[at])};
-        typedValue[j].assign(data, length);
       }
       return AsGenericExpr(
           Const{length, std::move(typedValue), std::move(extents_)});
@@ -153,12 +163,15 @@ public:
         if (at + chunk > image_.data_.size()) {
           CHECK(padWithZero_);
           if (at >= image_.data_.size()) {
-            break;
+            chunk = 0;
+          } else {
+            chunk = image_.data_.size() - at;
           }
-          chunk = image_.data_.size() - at;
         }
         // TODO endianness
-        std::memcpy(&typedValue[j], &image_.data_[at], chunk);
+        if (chunk > 0) {
+          std::memcpy(&typedValue[j], &image_.data_[at], chunk);
+        }
       }
       return AsGenericExpr(Const{std::move(typedValue), std::move(extents_)});
     }
index ef5a52f83e0a113592a60397e69ee6159db67330..833c828a62966dc45b2fe9d0d09ac05ffb6b1907 100644 (file)
@@ -34,4 +34,9 @@ module m
   logical, parameter :: test_c2i_v_2 = all(jc3 == [int(z'61626364'), int(z'65666768')]) .or. all(jc3 == [int(z'64636261'), int(z'68676665')])
   integer, parameter :: jc4(*) = transfer(["abcd", "efgh"], 0, 1)
   logical, parameter :: test_c2i_vs_1 = all(jc4 == [int(z'61626364')]) .or. all(jc4 == [int(z'64636261')])
+
+  integer, parameter :: le1 = int(z'64636261', 4), be1 = int(z'65666768', 4)
+  character*5, parameter :: le1c(*) = transfer(le1, [character(5)::])
+  character*5, parameter :: be1c(*) = transfer(be1, [character(5)::])
+  logical, parameter :: test_i2c_s = all(le1c == ["abcd"//char(0)]) .or. all(be1c == ["efgh"//char(0)])
 end module