[flang] Fix shape analysis of RESHAPE result

Shape analysis of RESHAPE(..., SHAPE=s) should of course return
the SHAPE= actual argument when it is constant; but when it is
not, its length is still known, and thus so is the rank of the
result of RESHAPE(), and shape analysis should at least return
a shape vector of the right length rather than a result that
makes the result appear to be a scalar, which can lead to some
bogus error messages.

Also, while here: rename a private GetShapeHelper::AsShape()
routine so that it can't be confused with the ones in the API
of shape.h.

Differential Revision: https://reviews.llvm.org/D123712
This commit is contained in:
Peter Klausler 2022-04-01 16:01:04 -07:00
parent 5955a0f937
commit d054959786
4 changed files with 25 additions and 20 deletions

View File

@ -161,7 +161,7 @@ public:
private:
static Result ScalarShape() { return Shape{}; }
static Shape ConstantShape(const Constant<ExtentType> &);
Result AsShape(ExtentExpr &&) const;
Result AsShapeResult(ExtentExpr &&) const;
static Shape CreateShape(int rank, NamedEntity &);
template <typename T>

View File

@ -1513,7 +1513,7 @@ std::optional<SpecificCall> IntrinsicInterface::Match(
if (auto shape{GetShape(context, *arg)}) {
if (auto constShape{AsConstantShape(context, *shape)}) {
shapeArgSize = constShape->At(ConstantSubscripts{1}).ToInt64();
CHECK(shapeArgSize >= 0);
CHECK(*shapeArgSize >= 0);
argOk = true;
}
}

View File

@ -53,7 +53,7 @@ Shape GetShapeHelper::ConstantShape(const Constant<ExtentType> &arrayConstant) {
return result;
}
auto GetShapeHelper::AsShape(ExtentExpr &&arrayExpr) const -> Result {
auto GetShapeHelper::AsShapeResult(ExtentExpr &&arrayExpr) const -> Result {
if (context_) {
arrayExpr = Fold(*context_, std::move(arrayExpr));
}
@ -63,17 +63,17 @@ auto GetShapeHelper::AsShape(ExtentExpr &&arrayExpr) const -> Result {
if (auto *constructor{UnwrapExpr<ArrayConstructor<ExtentType>>(arrayExpr)}) {
Shape result;
for (auto &value : *constructor) {
if (auto *expr{std::get_if<ExtentExpr>(&value.u)}) {
if (expr->Rank() == 0) {
result.emplace_back(std::move(*expr));
continue;
}
auto *expr{std::get_if<ExtentExpr>(&value.u)};
if (expr && expr->Rank() == 0) {
result.emplace_back(std::move(*expr));
} else {
return std::nullopt;
}
return std::nullopt;
}
return result;
} else {
return std::nullopt;
}
return std::nullopt;
}
Shape GetShapeHelper::CreateShape(int rank, NamedEntity &base) {
@ -847,15 +847,6 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
}
}
}
} else if (intrinsic->name == "reshape") {
if (call.arguments().size() >= 2 && call.arguments().at(1)) {
// SHAPE(RESHAPE(array,shape)) -> shape
if (const auto *shapeExpr{
call.arguments().at(1).value().UnwrapExpr()}) {
auto shape{std::get<Expr<SomeInteger>>(shapeExpr->u)};
return AsShape(ConvertToType<ExtentType>(std::move(shape)));
}
}
} else if (intrinsic->name == "pack") {
if (call.arguments().size() >= 3 && call.arguments().at(2)) {
// SHAPE(PACK(,,VECTOR=v)) -> SHAPE(v)
@ -891,6 +882,18 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
}
}
}
} else if (intrinsic->name == "reshape") {
if (call.arguments().size() >= 2 && call.arguments().at(1)) {
// SHAPE(RESHAPE(array,shape)) -> shape
if (const auto *shapeExpr{
call.arguments().at(1).value().UnwrapExpr()}) {
auto shapeArg{std::get<Expr<SomeInteger>>(shapeExpr->u)};
if (auto result{AsShapeResult(
ConvertToType<ExtentType>(std::move(shapeArg)))}) {
return result;
}
}
}
} else if (intrinsic->name == "spread") {
// SHAPE(SPREAD(ARRAY,DIM,NCOPIES)) = SHAPE(ARRAY) with NCOPIES inserted
// at position DIM.
@ -966,7 +969,8 @@ auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
// TODO: shapes of other non-elemental intrinsic results
}
}
return std::nullopt;
// The rank is always known even if the extents are not.
return Shape(static_cast<std::size_t>(call.Rank()), MaybeExtentExpr{});
}
// Check conformance of the passed shapes.

View File

@ -228,6 +228,7 @@ module m01
real :: a(*)
!ERROR: Scalar actual argument may not be associated with assumed-shape dummy argument 'x='
call assumedshape(scalar)
call assumedshape(reshape(matrix,shape=[size(matrix)])) ! ok
!ERROR: Rank of dummy argument is 1, but actual argument has rank 2
call assumedshape(matrix)
!ERROR: Assumed-size array may not be associated with assumed-shape dummy argument 'x='