[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:
@@ -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>
|
||||
|
||||
5
flang/test/Evaluate/bug123766.f90
Normal file
5
flang/test/Evaluate/bug123766.f90
Normal 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
|
||||
Reference in New Issue
Block a user