Skip to content

Commit ec6b2c6

Browse files
authored
[flang] Fold character array constructor with unknown length (llvm#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 llvm#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)