Skip to content

Commit

Permalink
[flang] Preserve component array lower bounds in folding
Browse files Browse the repository at this point in the history
When a component array of a named constant is extracted as
a constant value, ensure that the lower bounds of the array
are properly acquired from the declaration of the component.

Differential Revision: https://reviews.llvm.org/D134499
  • Loading branch information
klausler committed Sep 24, 2022
1 parent 0d58a8c commit 3bbb2c2
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 26 deletions.
27 changes: 27 additions & 0 deletions flang/include/flang/Evaluate/tools.h
Expand Up @@ -1109,6 +1109,33 @@ std::optional<Expr<SomeType>> DataConstantConversionExtension(
std::optional<Expr<SomeType>> HollerithToBOZ(
FoldingContext &, const Expr<SomeType> &, const DynamicType &);

// Set explicit lower bounds on a constant array.
class ArrayConstantBoundChanger {
public:
explicit ArrayConstantBoundChanger(ConstantSubscripts &&lbounds)
: lbounds_{std::move(lbounds)} {}

template <typename A> A ChangeLbounds(A &&x) const {
return std::move(x); // default case
}
template <typename T> Constant<T> ChangeLbounds(Constant<T> &&x) {
x.set_lbounds(std::move(lbounds_));
return std::move(x);
}
template <typename T> Expr<T> ChangeLbounds(Parentheses<T> &&x) {
return ChangeLbounds(
std::move(x.left())); // Constant<> can be parenthesized
}
template <typename T> Expr<T> ChangeLbounds(Expr<T> &&x) {
return common::visit(
[&](auto &&x) { return Expr<T>{ChangeLbounds(std::move(x))}; },
std::move(x.u)); // recurse until we hit a constant
}

private:
ConstantSubscripts &&lbounds_;
};

} // namespace Fortran::evaluate

namespace Fortran::semantics {
Expand Down
27 changes: 1 addition & 26 deletions flang/lib/Evaluate/check-expression.cpp
Expand Up @@ -9,6 +9,7 @@
#include "flang/Evaluate/check-expression.h"
#include "flang/Evaluate/characteristics.h"
#include "flang/Evaluate/intrinsics.h"
#include "flang/Evaluate/tools.h"
#include "flang/Evaluate/traverse.h"
#include "flang/Evaluate/type.h"
#include "flang/Semantics/symbol.h"
Expand Down Expand Up @@ -363,32 +364,6 @@ bool IsInitialProcedureTarget(const Expr<SomeType> &expr) {
}
}

class ArrayConstantBoundChanger {
public:
ArrayConstantBoundChanger(ConstantSubscripts &&lbounds)
: lbounds_{std::move(lbounds)} {}

template <typename A> A ChangeLbounds(A &&x) const {
return std::move(x); // default case
}
template <typename T> Constant<T> ChangeLbounds(Constant<T> &&x) {
x.set_lbounds(std::move(lbounds_));
return std::move(x);
}
template <typename T> Expr<T> ChangeLbounds(Parentheses<T> &&x) {
return ChangeLbounds(
std::move(x.left())); // Constant<> can be parenthesized
}
template <typename T> Expr<T> ChangeLbounds(Expr<T> &&x) {
return common::visit(
[&](auto &&x) { return Expr<T>{ChangeLbounds(std::move(x))}; },
std::move(x.u)); // recurse until we hit a constant
}

private:
ConstantSubscripts &&lbounds_;
};

// Converts, folds, and then checks type, rank, and shape of an
// initialization expression for a named constant, a non-pointer
// variable static initialization, a component default initializer,
Expand Down
9 changes: 9 additions & 0 deletions flang/lib/Evaluate/fold.cpp
Expand Up @@ -10,6 +10,7 @@
#include "fold-implementation.h"
#include "flang/Evaluate/characteristics.h"
#include "flang/Evaluate/initial-image.h"
#include "flang/Evaluate/tools.h"

namespace Fortran::evaluate {

Expand Down Expand Up @@ -92,6 +93,14 @@ Expr<SomeDerived> FoldOperation(
} else {
isConstant &= *valueShape == *componentShape;
}
if (*valueShape == *componentShape) {
if (auto lbounds{AsConstantExtents(
context, GetLBOUNDs(context, NamedEntity{symbol}))}) {
expr =
ArrayConstantBoundChanger{std::move(*lbounds)}.ChangeLbounds(
std::move(expr));
}
}
}
}
}
Expand Down

0 comments on commit 3bbb2c2

Please sign in to comment.