Skip to content

Commit f08fa76

Browse files
klauslervdonaldson
authored andcommitted
[flang] Fix folding of ac-implied-do indices in structure c'tors
Array constructors with implied DO loops that oversee structure constructors were being prematurely folded into invalid constants containing symbolic references to the ac-implied-do indices, because they are indeed "constant expressions" as that term is used in the Fortran standard and implemented as IsConstantExpr(). What's actually needed in structure constructor folding is a test for actual constant values, which is what results from folding them later with repetition in the context of folding an ac-implied-do. Differential Revision: https://reviews.llvm.org/D115470
1 parent d8e0d69 commit f08fa76

File tree

3 files changed

+31
-14
lines changed

3 files changed

+31
-14
lines changed

flang/lib/Evaluate/fold-implementation.h

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1094,7 +1094,7 @@ Expr<ImpliedDoIndex::Result> FoldOperation(FoldingContext &, ImpliedDoIndex &&);
10941094
// Array constructor folding
10951095
template <typename T> class ArrayConstructorFolder {
10961096
public:
1097-
explicit ArrayConstructorFolder(const FoldingContext &c) : context_{c} {}
1097+
explicit ArrayConstructorFolder(FoldingContext &c) : context_{c} {}
10981098

10991099
Expr<T> FoldArray(ArrayConstructor<T> &&array) {
11001100
// Calls FoldArray(const ArrayConstructorValues<T> &) below
@@ -1118,8 +1118,8 @@ template <typename T> class ArrayConstructorFolder {
11181118
}
11191119

11201120
private:
1121-
bool FoldArray(const common::CopyableIndirection<Expr<T>> &expr) {
1122-
Expr<T> folded{Fold(context_, common::Clone(expr.value()))};
1121+
bool FoldArray(const Expr<T> &expr) {
1122+
Expr<T> folded{Fold(context_, common::Clone(expr))};
11231123
if (const auto *c{UnwrapConstantValue<T>(folded)}) {
11241124
// Copy elements in Fortran array element order
11251125
if (!c->empty()) {
@@ -1133,6 +1133,9 @@ template <typename T> class ArrayConstructorFolder {
11331133
return false;
11341134
}
11351135
}
1136+
bool FoldArray(const common::CopyableIndirection<Expr<T>> &expr) {
1137+
return FoldArray(expr.value());
1138+
}
11361139
bool FoldArray(const ImpliedDo<T> &iDo) {
11371140
Expr<SubscriptInteger> lower{
11381141
Fold(context_, Expr<SubscriptInteger>{iDo.lower()})};
@@ -1172,7 +1175,7 @@ template <typename T> class ArrayConstructorFolder {
11721175
return true;
11731176
}
11741177

1175-
FoldingContext context_;
1178+
FoldingContext &context_;
11761179
std::vector<Scalar<T>> elements_;
11771180
};
11781181

flang/lib/Evaluate/fold.cpp

Lines changed: 13 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -65,29 +65,32 @@ std::optional<Constant<SubscriptInteger>> GetConstantSubscript(
6565
Expr<SomeDerived> FoldOperation(
6666
FoldingContext &context, StructureConstructor &&structure) {
6767
StructureConstructor ctor{structure.derivedTypeSpec()};
68-
bool constantExtents{true};
68+
bool isConstant{true};
6969
for (auto &&[symbol, value] : std::move(structure)) {
7070
auto expr{Fold(context, std::move(value.value()))};
71-
if (!IsPointer(symbol)) {
72-
bool ok{false};
71+
if (IsPointer(symbol)) {
72+
if (IsProcedure(symbol)) {
73+
isConstant &= IsInitialProcedureTarget(expr);
74+
} else {
75+
isConstant &= IsInitialDataTarget(expr);
76+
}
77+
} else {
78+
isConstant &= IsActuallyConstant(expr);
7379
if (auto valueShape{GetConstantExtents(context, expr)}) {
7480
if (auto componentShape{GetConstantExtents(context, symbol)}) {
7581
if (GetRank(*componentShape) > 0 && GetRank(*valueShape) == 0) {
7682
expr = ScalarConstantExpander{std::move(*componentShape)}.Expand(
7783
std::move(expr));
78-
ok = expr.Rank() > 0;
84+
isConstant &= expr.Rank() > 0;
7985
} else {
80-
ok = *valueShape == *componentShape;
86+
isConstant &= *valueShape == *componentShape;
8187
}
8288
}
8389
}
84-
if (!ok) {
85-
constantExtents = false;
86-
}
8790
}
88-
ctor.Add(symbol, Fold(context, std::move(expr)));
91+
ctor.Add(symbol, std::move(expr));
8992
}
90-
if (constantExtents && IsConstantExpr(ctor)) {
93+
if (isConstant) {
9194
return Expr<SomeDerived>{Constant<SomeDerived>{std::move(ctor)}};
9295
} else {
9396
return Expr<SomeDerived>{std::move(ctor)};

flang/test/Evaluate/folding30.f90

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
! RUN: %python %S/test_folding.py %s %flang_fc1
2+
! Tests folding of structure constructors in array constructors
3+
module m
4+
type :: t1
5+
integer :: n
6+
end type
7+
type(t1), parameter :: xs1(*) = [(t1(j),j=1,5,2)]
8+
type(t1), parameter :: xs2(*) = [(t1(j),j=5,1,-2)]
9+
logical, parameter :: test_1 = all(xs1%n == [1, 3, 5])
10+
logical, parameter :: test_2 = all(xs2%n == [5, 3, 1])
11+
end module

0 commit comments

Comments
 (0)