From ec6b2c63d93d8f8edeafcc7330d0b2349463d73d Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Mon, 27 Jan 2025 08:56:58 -0800 Subject: [PATCH] [flang] Fold character array constructor with unknown length (#123983) 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. --- flang/lib/Evaluate/fold-implementation.h | 22 ++++++++++++++++------ flang/test/Evaluate/bug123766.f90 | 5 +++++ 2 files changed, 21 insertions(+), 6 deletions(-) create mode 100644 flang/test/Evaluate/bug123766.f90 diff --git a/flang/lib/Evaluate/fold-implementation.h b/flang/lib/Evaluate/fold-implementation.h index 4dcc737688ca..b0f39e63d094 100644 --- a/flang/lib/Evaluate/fold-implementation.h +++ b/flang/lib/Evaluate/fold-implementation.h @@ -1267,6 +1267,12 @@ public: explicit ArrayConstructorFolder(FoldingContext &c) : context_{c} {} Expr FoldArray(ArrayConstructor &&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 &) below if (FoldArray(array)) { auto n{static_cast(elements_.size())}; @@ -1274,12 +1280,9 @@ public: return Expr{Constant{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 lengthValue{ToInt64(length)}) { - return Expr{Constant{ - *lengthValue, std::move(elements_), ConstantSubscripts{n}}}; - } + if (charLength_) { + return Expr{Constant{ + *charLength_, std::move(elements_), ConstantSubscripts{n}}}; } } else { return Expr{ @@ -1300,6 +1303,11 @@ private: 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; @@ -1349,6 +1357,8 @@ private: FoldingContext &context_; std::vector> elements_; + std::optional charLength_; + bool knownCharLength_{false}; }; template diff --git a/flang/test/Evaluate/bug123766.f90 b/flang/test/Evaluate/bug123766.f90 new file mode 100644 index 000000000000..b58989e6c26d --- /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