[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.
This commit is contained in:
Peter Klausler
2025-01-27 08:56:58 -08:00
committed by GitHub
parent f5ddb1012d
commit ec6b2c63d9
2 changed files with 21 additions and 6 deletions

View File

@@ -1267,6 +1267,12 @@ public:
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())};
@@ -1274,12 +1280,9 @@ public:
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>{
@@ -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<Scalar<T>> elements_;
std::optional<ConstantSubscript> charLength_;
bool knownCharLength_{false};
};
template <typename T>

View File

@@ -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