Skip to content

Commit ec6b2c6

Browse files
authored
[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 #123766.
1 parent f5ddb10 commit ec6b2c6

File tree

2 files changed

+21
-6
lines changed

2 files changed

+21
-6
lines changed

flang/lib/Evaluate/fold-implementation.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1267,19 +1267,22 @@ template <typename T> class ArrayConstructorFolder {
12671267
explicit ArrayConstructorFolder(FoldingContext &c) : context_{c} {}
12681268

12691269
Expr<T> FoldArray(ArrayConstructor<T> &&array) {
1270+
if constexpr (T::category == TypeCategory::Character) {
1271+
if (const auto *len{array.LEN()}) {
1272+
charLength_ = ToInt64(Fold(context_, common::Clone(*len)));
1273+
knownCharLength_ = charLength_.has_value();
1274+
}
1275+
}
12701276
// Calls FoldArray(const ArrayConstructorValues<T> &) below
12711277
if (FoldArray(array)) {
12721278
auto n{static_cast<ConstantSubscript>(elements_.size())};
12731279
if constexpr (std::is_same_v<T, SomeDerived>) {
12741280
return Expr<T>{Constant<T>{array.GetType().GetDerivedTypeSpec(),
12751281
std::move(elements_), ConstantSubscripts{n}}};
12761282
} else if constexpr (T::category == TypeCategory::Character) {
1277-
if (const auto *len{array.LEN()}) {
1278-
auto length{Fold(context_, common::Clone(*len))};
1279-
if (std::optional<ConstantSubscript> lengthValue{ToInt64(length)}) {
1280-
return Expr<T>{Constant<T>{
1281-
*lengthValue, std::move(elements_), ConstantSubscripts{n}}};
1282-
}
1283+
if (charLength_) {
1284+
return Expr<T>{Constant<T>{
1285+
*charLength_, std::move(elements_), ConstantSubscripts{n}}};
12831286
}
12841287
} else {
12851288
return Expr<T>{
@@ -1300,6 +1303,11 @@ template <typename T> class ArrayConstructorFolder {
13001303
elements_.emplace_back(c->At(index));
13011304
} while (c->IncrementSubscripts(index));
13021305
}
1306+
if constexpr (T::category == TypeCategory::Character) {
1307+
if (!knownCharLength_) {
1308+
charLength_ = std::max(c->LEN(), charLength_.value_or(-1));
1309+
}
1310+
}
13031311
return true;
13041312
} else {
13051313
return false;
@@ -1349,6 +1357,8 @@ template <typename T> class ArrayConstructorFolder {
13491357

13501358
FoldingContext &context_;
13511359
std::vector<Scalar<T>> elements_;
1360+
std::optional<ConstantSubscript> charLength_;
1361+
bool knownCharLength_{false};
13521362
};
13531363

13541364
template <typename T>

flang/test/Evaluate/bug123766.f90

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
! RUN: %python %S/test_folding.py %s %flang_fc1
2+
character(10), parameter :: a = '0123456789'
3+
character(3), parameter :: arr(3) = [(a(1:i), i=1,3)]
4+
logical, parameter :: test1 = all(arr == ["0", "01", "012"])
5+
end

0 commit comments

Comments
 (0)