[flang-commits] [flang] [flang] Fold character array constructor with unknown length (PR #123983)

via flang-commits flang-commits at lists.llvm.org
Wed Jan 22 10:46:18 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-semantics

Author: Peter Klausler (klausler)

<details>
<summary>Changes</summary>

When a character array constructor does not have an explicit type with a constant length, the compiler can still fold it if all of its elements are constants.  These array constructors will have been wrapped up in the internal %SET_LENGTH operation, which will determine the final length of the folded value, so use the maximum length of the constant elements as the length of the folded array constructor.

Fixes https://github.com/llvm/llvm-project/issues/123766.

---
Full diff: https://github.com/llvm/llvm-project/pull/123983.diff


2 Files Affected:

- (modified) flang/lib/Evaluate/fold-implementation.h (+16-6) 
- (added) flang/test/Evaluate/bug123766.f90 (+5) 


``````````diff
diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h
index 31d043f490fd85..56b36504c1dffd 100644
--- a/flang/lib/Evaluate/fold-implementation.h
+++ b/flang/lib/Evaluate/fold-implementation.h
@@ -1263,6 +1263,12 @@ template <typename T> class ArrayConstructorFolder {
   explicit ArrayConstructorFolder(FoldingContext &c) : context_{c} {}
 
   Expr<T> FoldArray(ArrayConstructor<T> &&array) {
+    if constexpr (T::category == TypeCategory::Character) {
+      if (const auto *len{array.LEN()}) {
+        charLength_ = ToInt64(Fold(context_, common::Clone(*len)));
+        knownCharLength_ = charLength_.has_value();
+      }
+    }
     // Calls FoldArray(const ArrayConstructorValues<T> &) below
     if (FoldArray(array)) {
       auto n{static_cast<ConstantSubscript>(elements_.size())};
@@ -1270,12 +1276,9 @@ template <typename T> class ArrayConstructorFolder {
         return Expr<T>{Constant<T>{array.GetType().GetDerivedTypeSpec(),
             std::move(elements_), ConstantSubscripts{n}}};
       } else if constexpr (T::category == TypeCategory::Character) {
-        if (const auto *len{array.LEN()}) {
-          auto length{Fold(context_, common::Clone(*len))};
-          if (std::optional<ConstantSubscript> lengthValue{ToInt64(length)}) {
-            return Expr<T>{Constant<T>{
-                *lengthValue, std::move(elements_), ConstantSubscripts{n}}};
-          }
+        if (charLength_) {
+          return Expr<T>{Constant<T>{
+              *charLength_, std::move(elements_), ConstantSubscripts{n}}};
         }
       } else {
         return Expr<T>{
@@ -1296,6 +1299,11 @@ template <typename T> class ArrayConstructorFolder {
           elements_.emplace_back(c->At(index));
         } while (c->IncrementSubscripts(index));
       }
+      if constexpr (T::category == TypeCategory::Character) {
+        if (!knownCharLength_) {
+          charLength_ = std::max(c->LEN(), charLength_.value_or(-1));
+        }
+      }
       return true;
     } else {
       return false;
@@ -1345,6 +1353,8 @@ template <typename T> class ArrayConstructorFolder {
 
   FoldingContext &context_;
   std::vector<Scalar<T>> elements_;
+  std::optional<ConstantSubscript> charLength_;
+  bool knownCharLength_{false};
 };
 
 template <typename T>
diff --git a/flang/test/Evaluate/bug123766.f90 b/flang/test/Evaluate/bug123766.f90
new file mode 100644
index 00000000000000..b58989e6c26d85
--- /dev/null
+++ b/flang/test/Evaluate/bug123766.f90
@@ -0,0 +1,5 @@
+! RUN: %python %S/test_folding.py %s %flang_fc1
+character(10), parameter :: a = '0123456789'
+character(3), parameter :: arr(3) = [(a(1:i), i=1,3)]
+logical, parameter :: test1 = all(arr == ["0", "01", "012"])
+end

``````````

</details>


https://github.com/llvm/llvm-project/pull/123983


More information about the flang-commits mailing list