Skip to content

Commit e252c40

Browse files
authored
[flang] Fix spurious error due to bad expression shape calculation (#124323)
GetShape() needed to be called with a FoldingContext in order to properly construct an extent expression for the shape of an array constructor whose elements (nested in an implied DO loop) were not scalars. Fixes #124191.
1 parent fee393e commit e252c40

File tree

3 files changed

+33
-11
lines changed

3 files changed

+33
-11
lines changed

flang/include/flang/Evaluate/shape.h

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,9 @@ template <typename A>
7171
std::optional<Shape> GetShape(
7272
FoldingContext &, const A &, bool invariantOnly = true);
7373
template <typename A>
74+
std::optional<Shape> GetShape(
75+
FoldingContext *, const A &, bool invariantOnly = true);
76+
template <typename A>
7477
std::optional<Shape> GetShape(const A &, bool invariantOnly = true);
7578

7679
// The dimension argument to these inquiries is zero-based,
@@ -149,6 +152,8 @@ inline MaybeExtentExpr GetSize(const std::optional<Shape> &maybeShape) {
149152
// Utility predicate: does an expression reference any implied DO index?
150153
bool ContainsAnyImpliedDoIndex(const ExtentExpr &);
151154

155+
// GetShape()
156+
152157
class GetShapeHelper
153158
: public AnyTraverse<GetShapeHelper, std::optional<Shape>> {
154159
public:
@@ -261,23 +266,27 @@ class GetShapeHelper
261266

262267
template <typename A>
263268
std::optional<Shape> GetShape(
264-
FoldingContext &context, const A &x, bool invariantOnly) {
265-
if (auto shape{GetShapeHelper{&context, invariantOnly}(x)}) {
266-
return Fold(context, std::move(shape));
269+
FoldingContext *context, const A &x, bool invariantOnly) {
270+
if (auto shape{GetShapeHelper{context, invariantOnly}(x)}) {
271+
if (context) {
272+
return Fold(*context, std::move(shape));
273+
} else {
274+
return shape;
275+
}
267276
} else {
268277
return std::nullopt;
269278
}
270279
}
271280

272281
template <typename A>
273-
std::optional<Shape> GetShape(const A &x, bool invariantOnly) {
274-
return GetShapeHelper{/*context=*/nullptr, invariantOnly}(x);
282+
std::optional<Shape> GetShape(
283+
FoldingContext &context, const A &x, bool invariantOnly) {
284+
return GetShape(&context, x, invariantOnly);
275285
}
276286

277287
template <typename A>
278-
std::optional<Shape> GetShape(
279-
FoldingContext *context, const A &x, bool invariantOnly = true) {
280-
return GetShapeHelper{context, invariantOnly}(x);
288+
std::optional<Shape> GetShape(const A &x, bool invariantOnly) {
289+
return GetShape(/*context=*/nullptr, x, invariantOnly);
281290
}
282291

283292
template <typename A>

flang/lib/Evaluate/shape.cpp

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,13 +16,18 @@
1616
#include "flang/Evaluate/tools.h"
1717
#include "flang/Evaluate/type.h"
1818
#include "flang/Parser/message.h"
19+
#include "flang/Semantics/semantics.h"
1920
#include "flang/Semantics/symbol.h"
2021
#include <functional>
2122

2223
using namespace std::placeholders; // _1, _2, &c. for std::bind()
2324

2425
namespace Fortran::evaluate {
2526

27+
FoldingContext &GetFoldingContextFrom(const Symbol &symbol) {
28+
return symbol.owner().context().foldingContext();
29+
}
30+
2631
bool IsImpliedShape(const Symbol &original) {
2732
const Symbol &symbol{ResolveAssociations(original)};
2833
const auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()};
@@ -483,7 +488,7 @@ static MaybeExtentExpr GetAssociatedExtent(
483488
const Symbol &symbol, int dimension) {
484489
if (const auto *assoc{symbol.detailsIf<semantics::AssocEntityDetails>()};
485490
assoc && !assoc->rank()) { // not SELECT RANK case
486-
if (auto shape{GetShape(assoc->expr())};
491+
if (auto shape{GetShape(GetFoldingContextFrom(symbol), assoc->expr())};
487492
shape && dimension < static_cast<int>(shape->size())) {
488493
if (auto &extent{shape->at(dimension)};
489494
// Don't return a non-constant extent, as the variables that
@@ -519,7 +524,8 @@ MaybeExtentExpr GetExtent(
519524
}
520525
if (const auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
521526
if (IsImpliedShape(symbol) && details->init()) {
522-
if (auto shape{GetShape(symbol, invariantOnly)}) {
527+
if (auto shape{
528+
GetShape(GetFoldingContextFrom(symbol), symbol, invariantOnly)}) {
523529
if (dimension < static_cast<int>(shape->size())) {
524530
return std::move(shape->at(dimension));
525531
}
@@ -568,7 +574,8 @@ MaybeExtentExpr GetExtent(const Subscript &subscript, const NamedEntity &base,
568574
MaybeExtentExpr{triplet.stride()});
569575
},
570576
[&](const IndirectSubscriptIntegerExpr &subs) -> MaybeExtentExpr {
571-
if (auto shape{GetShape(subs.value())};
577+
if (auto shape{GetShape(
578+
GetFoldingContextFrom(base.GetLastSymbol()), subs.value())};
572579
shape && GetRank(*shape) == 1) {
573580
// vector-valued subscript
574581
return std::move(shape->at(0));

flang/test/Evaluate/bug124191.f90

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
! RUN: %flang_fc1 -fsyntax-only -pedantic %s 2>&1 | FileCheck --allow-empty %s
2+
! CHECK-NOT: error:
3+
! Regression test for https://github.com/llvm/llvm-project/issues/124191
4+
character(3) :: arr(5) = ['aa.', 'bb.', 'cc.', 'dd.', 'ee.']
5+
arr([(mod(iachar(arr(i:i-1:-1)(1:1)),5)+1, i=2,5,3)]) = arr(5:2:-1)
6+
end

0 commit comments

Comments
 (0)