2020-02-25 23:11:52 +08:00
|
|
|
//===-- lib/Evaluate/shape.cpp --------------------------------------------===//
|
2019-04-02 06:22:45 +08:00
|
|
|
//
|
2019-12-21 04:52:07 +08:00
|
|
|
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
|
|
|
|
// See https://llvm.org/LICENSE.txt for license information.
|
|
|
|
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
|
2019-04-02 06:22:45 +08:00
|
|
|
//
|
2020-01-11 04:12:03 +08:00
|
|
|
//===----------------------------------------------------------------------===//
|
2019-04-02 06:22:45 +08:00
|
|
|
|
2020-02-25 23:11:52 +08:00
|
|
|
#include "flang/Evaluate/shape.h"
|
|
|
|
#include "flang/Common/idioms.h"
|
|
|
|
#include "flang/Common/template.h"
|
|
|
|
#include "flang/Evaluate/characteristics.h"
|
|
|
|
#include "flang/Evaluate/fold.h"
|
|
|
|
#include "flang/Evaluate/intrinsics.h"
|
|
|
|
#include "flang/Evaluate/tools.h"
|
|
|
|
#include "flang/Evaluate/type.h"
|
|
|
|
#include "flang/Parser/message.h"
|
|
|
|
#include "flang/Semantics/symbol.h"
|
2019-10-09 06:21:09 +08:00
|
|
|
#include <functional>
|
|
|
|
|
2020-03-29 12:00:16 +08:00
|
|
|
using namespace std::placeholders; // _1, _2, &c. for std::bind()
|
2019-04-02 06:22:45 +08:00
|
|
|
|
|
|
|
namespace Fortran::evaluate {
|
2019-04-04 07:04:13 +08:00
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
bool IsImpliedShape(const Symbol &original) {
|
|
|
|
const Symbol &symbol{ResolveAssociations(original)};
|
[flang] Improve initializer semantics, esp. for component default values
This patch plugs many holes in static initializer semantics, improves error
messages for default initial values and other component properties in
parameterized derived type instantiations, and cleans up several small
issues noticed during development. We now do proper scalar expansion,
folding, and type, rank, and shape conformance checking for component
default initializers in derived types and PDT instantiations.
The initial values of named constants are now guaranteed to have been folded
when installed in the symbol table, and are no longer folded or
scalar-expanded at each use in expression folding. Semantics documentation
was extended with information about the various kinds of initializations
in Fortran and when each of them are processed in the compiler.
Some necessary concomitant changes have bulked this patch out a bit:
* contextual messages attachments, which are now produced for parameterized
derived type instantiations so that the user can figure out which
instance caused a problem with a component, have been added as part
of ContextualMessages, and their implementation was debugged
* several APIs in evaluate::characteristics was changed so that a FoldingContext
is passed as an argument rather than just its intrinsic procedure table;
this affected client call sites in many files
* new tools in Evaluate/check-expression.cpp to determine when an Expr
actually is a single constant value and to validate a non-pointer
variable initializer or object component default value
* shape conformance checking has additional arguments that control
whether scalar expansion is allowed
* several now-unused functions and data members noticed and removed
* several crashes and bogus errors exposed by testing this new code
were fixed
* a -fdebug-stack-trace option to enable LLVM's stack tracing on
a crash, which might be useful in the future
TL;DR: Initialization processing does more and takes place at the right
times for all of the various kinds of things that can be initialized.
Differential Review: https://reviews.llvm.org/D92783
2020-12-08 04:08:58 +08:00
|
|
|
const auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()};
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return details && symbol.attrs().test(semantics::Attr::PARAMETER) &&
|
[flang] Improve initializer semantics, esp. for component default values
This patch plugs many holes in static initializer semantics, improves error
messages for default initial values and other component properties in
parameterized derived type instantiations, and cleans up several small
issues noticed during development. We now do proper scalar expansion,
folding, and type, rank, and shape conformance checking for component
default initializers in derived types and PDT instantiations.
The initial values of named constants are now guaranteed to have been folded
when installed in the symbol table, and are no longer folded or
scalar-expanded at each use in expression folding. Semantics documentation
was extended with information about the various kinds of initializations
in Fortran and when each of them are processed in the compiler.
Some necessary concomitant changes have bulked this patch out a bit:
* contextual messages attachments, which are now produced for parameterized
derived type instantiations so that the user can figure out which
instance caused a problem with a component, have been added as part
of ContextualMessages, and their implementation was debugged
* several APIs in evaluate::characteristics was changed so that a FoldingContext
is passed as an argument rather than just its intrinsic procedure table;
this affected client call sites in many files
* new tools in Evaluate/check-expression.cpp to determine when an Expr
actually is a single constant value and to validate a non-pointer
variable initializer or object component default value
* shape conformance checking has additional arguments that control
whether scalar expansion is allowed
* several now-unused functions and data members noticed and removed
* several crashes and bogus errors exposed by testing this new code
were fixed
* a -fdebug-stack-trace option to enable LLVM's stack tracing on
a crash, which might be useful in the future
TL;DR: Initialization processing does more and takes place at the right
times for all of the various kinds of things that can be initialized.
Differential Review: https://reviews.llvm.org/D92783
2020-12-08 04:08:58 +08:00
|
|
|
details->shape().IsImpliedShape();
|
2019-05-22 07:58:46 +08:00
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
bool IsExplicitShape(const Symbol &original) {
|
|
|
|
const Symbol &symbol{ResolveAssociations(original)};
|
2019-05-22 07:58:46 +08:00
|
|
|
if (const auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
|
2019-08-07 04:36:18 +08:00
|
|
|
const auto &shape{details->shape()};
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return shape.Rank() == 0 ||
|
|
|
|
shape.IsExplicitShape(); // true when scalar, too
|
2019-05-22 07:58:46 +08:00
|
|
|
} else {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return symbol
|
|
|
|
.has<semantics::AssocEntityDetails>(); // exprs have explicit shape
|
2019-05-22 07:58:46 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
Shape GetShapeHelper::ConstantShape(const Constant<ExtentType> &arrayConstant) {
|
2019-04-05 08:10:07 +08:00
|
|
|
CHECK(arrayConstant.Rank() == 1);
|
2019-04-05 04:12:21 +08:00
|
|
|
Shape result;
|
2019-04-05 08:10:07 +08:00
|
|
|
std::size_t dimensions{arrayConstant.size()};
|
2019-04-05 04:12:21 +08:00
|
|
|
for (std::size_t j{0}; j < dimensions; ++j) {
|
2019-04-05 08:10:07 +08:00
|
|
|
Scalar<ExtentType> extent{arrayConstant.values().at(j)};
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
result.emplace_back(MaybeExtentExpr{ExtentExpr{std::move(extent)}});
|
2019-04-05 04:12:21 +08:00
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
auto GetShapeHelper::AsShape(ExtentExpr &&arrayExpr) const -> Result {
|
|
|
|
if (context_) {
|
|
|
|
arrayExpr = Fold(*context_, std::move(arrayExpr));
|
|
|
|
}
|
2019-05-22 07:58:46 +08:00
|
|
|
if (const auto *constArray{UnwrapConstantValue<ExtentType>(arrayExpr)}) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return ConstantShape(*constArray);
|
2019-04-05 08:10:07 +08:00
|
|
|
}
|
|
|
|
if (auto *constructor{UnwrapExpr<ArrayConstructor<ExtentType>>(arrayExpr)}) {
|
|
|
|
Shape result;
|
2019-04-19 05:11:15 +08:00
|
|
|
for (auto &value : *constructor) {
|
2019-04-09 07:16:55 +08:00
|
|
|
if (auto *expr{std::get_if<ExtentExpr>(&value.u)}) {
|
2019-04-06 02:38:10 +08:00
|
|
|
if (expr->Rank() == 0) {
|
|
|
|
result.emplace_back(std::move(*expr));
|
2019-04-05 08:10:07 +08:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
Shape GetShapeHelper::CreateShape(int rank, NamedEntity &base) {
|
|
|
|
Shape shape;
|
|
|
|
for (int dimension{0}; dimension < rank; ++dimension) {
|
|
|
|
shape.emplace_back(GetExtent(base, dimension));
|
|
|
|
}
|
|
|
|
return shape;
|
|
|
|
}
|
|
|
|
|
2019-04-19 05:11:15 +08:00
|
|
|
std::optional<ExtentExpr> AsExtentArrayExpr(const Shape &shape) {
|
2019-04-05 04:58:46 +08:00
|
|
|
ArrayConstructorValues<ExtentType> values;
|
2019-04-05 04:12:21 +08:00
|
|
|
for (const auto &dim : shape) {
|
2019-11-10 01:29:31 +08:00
|
|
|
if (dim) {
|
2019-04-05 04:58:46 +08:00
|
|
|
values.Push(common::Clone(*dim));
|
|
|
|
} else {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return ExtentExpr{ArrayConstructor<ExtentType>{std::move(values)}};
|
|
|
|
}
|
|
|
|
|
2019-10-09 06:21:09 +08:00
|
|
|
std::optional<Constant<ExtentType>> AsConstantShape(
|
|
|
|
FoldingContext &context, const Shape &shape) {
|
2019-04-19 05:11:15 +08:00
|
|
|
if (auto shapeArray{AsExtentArrayExpr(shape)}) {
|
2019-10-09 06:21:09 +08:00
|
|
|
auto folded{Fold(context, std::move(*shapeArray))};
|
2019-05-22 07:58:46 +08:00
|
|
|
if (auto *p{UnwrapConstantValue<ExtentType>(folded)}) {
|
2019-04-05 04:58:46 +08:00
|
|
|
return std::move(*p);
|
2019-04-05 04:12:21 +08:00
|
|
|
}
|
|
|
|
}
|
2019-04-05 04:58:46 +08:00
|
|
|
return std::nullopt;
|
2019-04-05 04:12:21 +08:00
|
|
|
}
|
|
|
|
|
2019-05-22 07:58:46 +08:00
|
|
|
Constant<SubscriptInteger> AsConstantShape(const ConstantSubscripts &shape) {
|
|
|
|
using IntType = Scalar<SubscriptInteger>;
|
|
|
|
std::vector<IntType> result;
|
|
|
|
for (auto dim : shape) {
|
|
|
|
result.emplace_back(dim);
|
|
|
|
}
|
|
|
|
return {std::move(result), ConstantSubscripts{GetRank(shape)}};
|
|
|
|
}
|
|
|
|
|
2019-04-19 05:11:15 +08:00
|
|
|
ConstantSubscripts AsConstantExtents(const Constant<ExtentType> &shape) {
|
|
|
|
ConstantSubscripts result;
|
|
|
|
for (const auto &extent : shape.values()) {
|
|
|
|
result.push_back(extent.ToInt64());
|
|
|
|
}
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2019-10-09 06:21:09 +08:00
|
|
|
std::optional<ConstantSubscripts> AsConstantExtents(
|
|
|
|
FoldingContext &context, const Shape &shape) {
|
|
|
|
if (auto shapeConstant{AsConstantShape(context, shape)}) {
|
2019-04-19 05:11:15 +08:00
|
|
|
return AsConstantExtents(*shapeConstant);
|
|
|
|
} else {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
Shape Fold(FoldingContext &context, Shape &&shape) {
|
|
|
|
for (auto &dim : shape) {
|
|
|
|
dim = Fold(context, std::move(dim));
|
|
|
|
}
|
|
|
|
return std::move(shape);
|
|
|
|
}
|
|
|
|
|
|
|
|
std::optional<Shape> Fold(
|
|
|
|
FoldingContext &context, std::optional<Shape> &&shape) {
|
|
|
|
if (shape) {
|
|
|
|
return Fold(context, std::move(*shape));
|
|
|
|
} else {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static ExtentExpr ComputeTripCount(
|
|
|
|
ExtentExpr &&lower, ExtentExpr &&upper, ExtentExpr &&stride) {
|
2019-04-05 04:12:21 +08:00
|
|
|
ExtentExpr strideCopy{common::Clone(stride)};
|
|
|
|
ExtentExpr span{
|
|
|
|
(std::move(upper) - std::move(lower) + std::move(strideCopy)) /
|
|
|
|
std::move(stride)};
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return ExtentExpr{
|
2019-10-31 23:03:16 +08:00
|
|
|
Extremum<ExtentType>{Ordering::Greater, std::move(span), ExtentExpr{0}}};
|
2019-04-05 04:12:21 +08:00
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
ExtentExpr CountTrips(
|
|
|
|
ExtentExpr &&lower, ExtentExpr &&upper, ExtentExpr &&stride) {
|
2019-04-05 04:12:21 +08:00
|
|
|
return ComputeTripCount(
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
std::move(lower), std::move(upper), std::move(stride));
|
2019-04-05 04:12:21 +08:00
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
ExtentExpr CountTrips(const ExtentExpr &lower, const ExtentExpr &upper,
|
|
|
|
const ExtentExpr &stride) {
|
|
|
|
return ComputeTripCount(
|
|
|
|
common::Clone(lower), common::Clone(upper), common::Clone(stride));
|
2019-04-05 04:12:21 +08:00
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
MaybeExtentExpr CountTrips(MaybeExtentExpr &&lower, MaybeExtentExpr &&upper,
|
|
|
|
MaybeExtentExpr &&stride) {
|
2019-10-09 06:21:09 +08:00
|
|
|
std::function<ExtentExpr(ExtentExpr &&, ExtentExpr &&, ExtentExpr &&)> bound{
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
std::bind(ComputeTripCount, _1, _2, _3)};
|
2019-04-05 04:12:21 +08:00
|
|
|
return common::MapOptional(
|
2019-10-09 06:21:09 +08:00
|
|
|
std::move(bound), std::move(lower), std::move(upper), std::move(stride));
|
2019-04-05 04:12:21 +08:00
|
|
|
}
|
|
|
|
|
2019-05-22 07:58:46 +08:00
|
|
|
MaybeExtentExpr GetSize(Shape &&shape) {
|
2019-04-05 04:12:21 +08:00
|
|
|
ExtentExpr extent{1};
|
|
|
|
for (auto &&dim : std::move(shape)) {
|
2019-11-10 01:29:31 +08:00
|
|
|
if (dim) {
|
2019-04-05 04:12:21 +08:00
|
|
|
extent = std::move(extent) * std::move(*dim);
|
|
|
|
} else {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return extent;
|
|
|
|
}
|
|
|
|
|
2019-04-19 05:11:15 +08:00
|
|
|
bool ContainsAnyImpliedDoIndex(const ExtentExpr &expr) {
|
2019-09-20 03:19:17 +08:00
|
|
|
struct MyVisitor : public AnyTraverse<MyVisitor> {
|
|
|
|
using Base = AnyTraverse<MyVisitor>;
|
|
|
|
MyVisitor() : Base{*this} {}
|
|
|
|
using Base::operator();
|
|
|
|
bool operator()(const ImpliedDoIndex &) { return true; }
|
2019-04-19 05:11:15 +08:00
|
|
|
};
|
2019-09-20 03:19:17 +08:00
|
|
|
return MyVisitor{}(expr);
|
2019-04-19 05:11:15 +08:00
|
|
|
}
|
|
|
|
|
2020-03-12 04:17:03 +08:00
|
|
|
// Determines lower bound on a dimension. This can be other than 1 only
|
|
|
|
// for a reference to a whole array object or component. (See LBOUND, 16.9.109).
|
|
|
|
// ASSOCIATE construct entities may require tranversal of their referents.
|
|
|
|
class GetLowerBoundHelper : public Traverse<GetLowerBoundHelper, ExtentExpr> {
|
|
|
|
public:
|
|
|
|
using Result = ExtentExpr;
|
|
|
|
using Base = Traverse<GetLowerBoundHelper, ExtentExpr>;
|
|
|
|
using Base::operator();
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
explicit GetLowerBoundHelper(int d) : Base{*this}, dimension_{d} {}
|
2020-03-12 04:17:03 +08:00
|
|
|
static ExtentExpr Default() { return ExtentExpr{1}; }
|
|
|
|
static ExtentExpr Combine(Result &&, Result &&) { return Default(); }
|
|
|
|
ExtentExpr operator()(const Symbol &);
|
|
|
|
ExtentExpr operator()(const Component &);
|
|
|
|
|
|
|
|
private:
|
|
|
|
int dimension_;
|
|
|
|
};
|
|
|
|
|
|
|
|
auto GetLowerBoundHelper::operator()(const Symbol &symbol0) -> Result {
|
|
|
|
const Symbol &symbol{symbol0.GetUltimate()};
|
2019-04-02 06:22:45 +08:00
|
|
|
if (const auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
|
2019-04-04 07:04:13 +08:00
|
|
|
int j{0};
|
2019-04-02 06:22:45 +08:00
|
|
|
for (const auto &shapeSpec : details->shape()) {
|
2020-03-12 04:17:03 +08:00
|
|
|
if (j++ == dimension_) {
|
2019-04-04 07:04:13 +08:00
|
|
|
if (const auto &bound{shapeSpec.lbound().GetExplicit()}) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return *bound;
|
2020-07-08 06:30:47 +08:00
|
|
|
} else if (IsDescriptor(symbol)) {
|
2020-03-12 04:17:03 +08:00
|
|
|
return ExtentExpr{DescriptorInquiry{NamedEntity{symbol0},
|
|
|
|
DescriptorInquiry::Field::LowerBound, dimension_}};
|
2019-08-01 05:13:42 +08:00
|
|
|
} else {
|
|
|
|
break;
|
2019-04-04 07:04:13 +08:00
|
|
|
}
|
2019-04-02 06:22:45 +08:00
|
|
|
}
|
|
|
|
}
|
2020-03-12 04:17:03 +08:00
|
|
|
} else if (const auto *assoc{
|
|
|
|
symbol.detailsIf<semantics::AssocEntityDetails>()}) {
|
|
|
|
return (*this)(assoc->expr());
|
2019-04-02 06:22:45 +08:00
|
|
|
}
|
2020-03-12 04:17:03 +08:00
|
|
|
return Default();
|
2019-04-02 06:22:45 +08:00
|
|
|
}
|
|
|
|
|
2020-03-12 04:17:03 +08:00
|
|
|
auto GetLowerBoundHelper::operator()(const Component &component) -> Result {
|
|
|
|
if (component.base().Rank() == 0) {
|
|
|
|
const Symbol &symbol{component.GetLastSymbol().GetUltimate()};
|
|
|
|
if (const auto *details{
|
|
|
|
symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
|
|
|
|
int j{0};
|
|
|
|
for (const auto &shapeSpec : details->shape()) {
|
|
|
|
if (j++ == dimension_) {
|
|
|
|
if (const auto &bound{shapeSpec.lbound().GetExplicit()}) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return *bound;
|
2020-07-08 06:30:47 +08:00
|
|
|
} else if (IsDescriptor(symbol)) {
|
2020-03-12 04:17:03 +08:00
|
|
|
return ExtentExpr{
|
|
|
|
DescriptorInquiry{NamedEntity{common::Clone(component)},
|
|
|
|
DescriptorInquiry::Field::LowerBound, dimension_}};
|
|
|
|
} else {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2019-06-22 07:13:34 +08:00
|
|
|
}
|
2019-08-02 01:07:11 +08:00
|
|
|
}
|
2019-06-22 07:13:34 +08:00
|
|
|
}
|
2020-03-12 04:17:03 +08:00
|
|
|
return Default();
|
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
ExtentExpr GetLowerBound(const NamedEntity &base, int dimension) {
|
|
|
|
return GetLowerBoundHelper{dimension}(base);
|
|
|
|
}
|
|
|
|
|
2020-03-12 04:17:03 +08:00
|
|
|
ExtentExpr GetLowerBound(
|
|
|
|
FoldingContext &context, const NamedEntity &base, int dimension) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return Fold(context, GetLowerBound(base, dimension));
|
|
|
|
}
|
|
|
|
|
|
|
|
Shape GetLowerBounds(const NamedEntity &base) {
|
|
|
|
Shape result;
|
|
|
|
int rank{base.Rank()};
|
|
|
|
for (int dim{0}; dim < rank; ++dim) {
|
|
|
|
result.emplace_back(GetLowerBound(base, dim));
|
|
|
|
}
|
|
|
|
return result;
|
2020-03-12 04:17:03 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
Shape GetLowerBounds(FoldingContext &context, const NamedEntity &base) {
|
|
|
|
Shape result;
|
|
|
|
int rank{base.Rank()};
|
|
|
|
for (int dim{0}; dim < rank; ++dim) {
|
|
|
|
result.emplace_back(GetLowerBound(context, base, dim));
|
|
|
|
}
|
2019-06-22 07:13:34 +08:00
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
MaybeExtentExpr GetExtent(const NamedEntity &base, int dimension) {
|
2019-05-22 07:58:46 +08:00
|
|
|
CHECK(dimension >= 0);
|
2019-08-01 05:13:42 +08:00
|
|
|
const Symbol &symbol{ResolveAssociations(base.GetLastSymbol())};
|
2019-05-14 00:33:18 +08:00
|
|
|
if (const auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
|
2019-05-22 07:58:46 +08:00
|
|
|
if (IsImpliedShape(symbol)) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
Shape shape{GetShape(symbol).value()};
|
2019-05-22 07:58:46 +08:00
|
|
|
return std::move(shape.at(dimension));
|
2019-05-14 00:33:18 +08:00
|
|
|
}
|
2019-04-04 07:04:13 +08:00
|
|
|
int j{0};
|
|
|
|
for (const auto &shapeSpec : details->shape()) {
|
|
|
|
if (j++ == dimension) {
|
2019-08-07 04:36:18 +08:00
|
|
|
if (shapeSpec.ubound().isExplicit()) {
|
2019-04-04 07:04:13 +08:00
|
|
|
if (const auto &ubound{shapeSpec.ubound().GetExplicit()}) {
|
2019-05-14 00:33:18 +08:00
|
|
|
if (const auto &lbound{shapeSpec.lbound().GetExplicit()}) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return common::Clone(ubound.value()) -
|
|
|
|
common::Clone(lbound.value()) + ExtentExpr{1};
|
2019-05-14 00:33:18 +08:00
|
|
|
} else {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return ubound.value();
|
2019-05-14 00:33:18 +08:00
|
|
|
}
|
2019-04-04 07:04:13 +08:00
|
|
|
}
|
2019-05-14 00:33:18 +08:00
|
|
|
} else if (details->IsAssumedSize() && j == symbol.Rank()) {
|
|
|
|
return std::nullopt;
|
2019-07-03 04:47:02 +08:00
|
|
|
} else if (semantics::IsDescriptor(symbol)) {
|
2019-04-05 04:12:21 +08:00
|
|
|
return ExtentExpr{DescriptorInquiry{
|
2019-06-26 04:07:32 +08:00
|
|
|
NamedEntity{base}, DescriptorInquiry::Field::Extent, dimension}};
|
2019-04-04 07:04:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-11 07:13:09 +08:00
|
|
|
} else if (const auto *assoc{
|
|
|
|
symbol.detailsIf<semantics::AssocEntityDetails>()}) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
if (auto shape{GetShape(assoc->expr())}) {
|
2020-03-11 07:13:09 +08:00
|
|
|
if (dimension < static_cast<int>(shape->size())) {
|
|
|
|
return std::move(shape->at(dimension));
|
|
|
|
}
|
|
|
|
}
|
2019-04-02 06:22:45 +08:00
|
|
|
}
|
2019-04-04 07:04:13 +08:00
|
|
|
return std::nullopt;
|
2019-04-02 06:22:45 +08:00
|
|
|
}
|
2019-04-04 07:04:13 +08:00
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
MaybeExtentExpr GetExtent(
|
|
|
|
FoldingContext &context, const NamedEntity &base, int dimension) {
|
|
|
|
return Fold(context, GetExtent(base, dimension));
|
|
|
|
}
|
|
|
|
|
|
|
|
MaybeExtentExpr GetExtent(
|
|
|
|
const Subscript &subscript, const NamedEntity &base, int dimension) {
|
2019-04-02 06:22:45 +08:00
|
|
|
return std::visit(
|
|
|
|
common::visitors{
|
2019-05-22 07:58:46 +08:00
|
|
|
[&](const Triplet &triplet) -> MaybeExtentExpr {
|
|
|
|
MaybeExtentExpr upper{triplet.upper()};
|
2019-11-10 01:29:31 +08:00
|
|
|
if (!upper) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
upper = GetUpperBound(base, dimension);
|
2019-04-04 07:04:13 +08:00
|
|
|
}
|
2019-05-22 07:58:46 +08:00
|
|
|
MaybeExtentExpr lower{triplet.lower()};
|
2019-11-10 01:29:31 +08:00
|
|
|
if (!lower) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
lower = GetLowerBound(base, dimension);
|
2019-04-02 06:22:45 +08:00
|
|
|
}
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return CountTrips(std::move(lower), std::move(upper),
|
2019-05-22 07:58:46 +08:00
|
|
|
MaybeExtentExpr{triplet.stride()});
|
2019-04-02 06:22:45 +08:00
|
|
|
},
|
2019-05-22 07:58:46 +08:00
|
|
|
[&](const IndirectSubscriptIntegerExpr &subs) -> MaybeExtentExpr {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
if (auto shape{GetShape(subs.value())}) {
|
2019-05-22 07:58:46 +08:00
|
|
|
if (GetRank(*shape) > 0) {
|
2020-03-29 12:00:16 +08:00
|
|
|
CHECK(GetRank(*shape) == 1); // vector-valued subscript
|
2019-04-02 06:22:45 +08:00
|
|
|
return std::move(shape->at(0));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
},
|
|
|
|
},
|
|
|
|
subscript.u);
|
|
|
|
}
|
2019-04-04 07:04:13 +08:00
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
MaybeExtentExpr GetExtent(FoldingContext &context, const Subscript &subscript,
|
|
|
|
const NamedEntity &base, int dimension) {
|
|
|
|
return Fold(context, GetExtent(subscript, base, dimension));
|
|
|
|
}
|
|
|
|
|
2019-08-03 01:17:10 +08:00
|
|
|
MaybeExtentExpr ComputeUpperBound(
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
ExtentExpr &&lower, MaybeExtentExpr &&extent) {
|
2019-11-10 01:29:31 +08:00
|
|
|
if (extent) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return std::move(*extent) - std::move(lower) + ExtentExpr{1};
|
2019-05-22 07:58:46 +08:00
|
|
|
} else {
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
MaybeExtentExpr ComputeUpperBound(
|
|
|
|
FoldingContext &context, ExtentExpr &&lower, MaybeExtentExpr &&extent) {
|
|
|
|
return Fold(context, ComputeUpperBound(std::move(lower), std::move(extent)));
|
|
|
|
}
|
|
|
|
|
|
|
|
MaybeExtentExpr GetUpperBound(const NamedEntity &base, int dimension) {
|
2019-08-01 05:13:42 +08:00
|
|
|
const Symbol &symbol{ResolveAssociations(base.GetLastSymbol())};
|
2019-07-31 07:51:25 +08:00
|
|
|
if (const auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
|
|
|
|
int j{0};
|
|
|
|
for (const auto &shapeSpec : details->shape()) {
|
|
|
|
if (j++ == dimension) {
|
|
|
|
if (const auto &bound{shapeSpec.ubound().GetExplicit()}) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return *bound;
|
2019-07-31 07:51:25 +08:00
|
|
|
} else if (details->IsAssumedSize() && dimension + 1 == symbol.Rank()) {
|
|
|
|
break;
|
|
|
|
} else {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return ComputeUpperBound(
|
|
|
|
GetLowerBound(base, dimension), GetExtent(base, dimension));
|
2019-07-31 07:51:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-03-11 07:13:09 +08:00
|
|
|
} else if (const auto *assoc{
|
|
|
|
symbol.detailsIf<semantics::AssocEntityDetails>()}) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
if (auto shape{GetShape(assoc->expr())}) {
|
2020-03-11 07:13:09 +08:00
|
|
|
if (dimension < static_cast<int>(shape->size())) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return ComputeUpperBound(
|
|
|
|
GetLowerBound(base, dimension), std::move(shape->at(dimension)));
|
2020-03-11 07:13:09 +08:00
|
|
|
}
|
|
|
|
}
|
2019-07-31 07:51:25 +08:00
|
|
|
}
|
|
|
|
return std::nullopt;
|
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
MaybeExtentExpr GetUpperBound(
|
|
|
|
FoldingContext &context, const NamedEntity &base, int dimension) {
|
|
|
|
return Fold(context, GetUpperBound(base, dimension));
|
|
|
|
}
|
|
|
|
|
|
|
|
Shape GetUpperBounds(const NamedEntity &base) {
|
2019-08-02 01:07:11 +08:00
|
|
|
const Symbol &symbol{ResolveAssociations(base.GetLastSymbol())};
|
|
|
|
if (const auto *details{symbol.detailsIf<semantics::ObjectEntityDetails>()}) {
|
|
|
|
Shape result;
|
|
|
|
int dim{0};
|
|
|
|
for (const auto &shapeSpec : details->shape()) {
|
|
|
|
if (const auto &bound{shapeSpec.ubound().GetExplicit()}) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
result.push_back(*bound);
|
2019-08-02 01:07:11 +08:00
|
|
|
} else if (details->IsAssumedSize()) {
|
|
|
|
CHECK(dim + 1 == base.Rank());
|
2020-03-29 12:00:16 +08:00
|
|
|
result.emplace_back(std::nullopt); // UBOUND folding replaces with -1
|
2019-08-02 01:07:11 +08:00
|
|
|
} else {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
result.emplace_back(
|
|
|
|
ComputeUpperBound(GetLowerBound(base, dim), GetExtent(base, dim)));
|
2019-08-02 01:07:11 +08:00
|
|
|
}
|
|
|
|
++dim;
|
|
|
|
}
|
|
|
|
CHECK(GetRank(result) == symbol.Rank());
|
|
|
|
return result;
|
|
|
|
} else {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return std::move(GetShape(symbol).value());
|
2019-07-31 07:51:25 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
Shape GetUpperBounds(FoldingContext &context, const NamedEntity &base) {
|
|
|
|
return Fold(context, GetUpperBounds(base));
|
|
|
|
}
|
|
|
|
|
2019-09-20 05:56:12 +08:00
|
|
|
auto GetShapeHelper::operator()(const Symbol &symbol) const -> Result {
|
|
|
|
return std::visit(
|
2019-08-02 03:32:17 +08:00
|
|
|
common::visitors{
|
2019-10-09 06:21:09 +08:00
|
|
|
[&](const semantics::ObjectEntityDetails &object) {
|
|
|
|
if (IsImpliedShape(symbol)) {
|
|
|
|
return (*this)(object.init());
|
|
|
|
} else {
|
|
|
|
int n{object.shape().Rank()};
|
|
|
|
NamedEntity base{symbol};
|
[flang]Semantics for SELECT RANK.
Summary:
Initially on github I worked on semantic checks.Then I tried some compile-time
test of the rank value, they were failing as there were no symbols
generated for them inside SELECT RANK's scope.So I went further to
add new symbol in each scope, also added the respective 'rank: '
field for a symbol when we dump the symboltable. I added a field to
keep track of the rank in AssocEntityDetails class.This caused shape
analysis framework to become inconsistent. So shape analysis framework
was updated to handle this new representation.
* I added more tests for above changes.
* On phabricator I addressed some minor changes.
* Lastly I worked on review comments.
Reviewers: klausler,sscalpone,DavidTruby,kiranchandramohan,tskeith,anchu-rajendran,kiranktp
Reviewed By:klausler, DavidTruby, tskeith
Subscribers:#flang-commits, #llvm-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78623
2020-04-22 17:16:37 +08:00
|
|
|
return Result{CreateShape(n, base)};
|
2019-10-09 06:21:09 +08:00
|
|
|
}
|
|
|
|
},
|
2019-10-25 07:08:06 +08:00
|
|
|
[](const semantics::EntityDetails &) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return ScalarShape(); // no dimensions seen
|
2019-10-09 06:21:09 +08:00
|
|
|
},
|
|
|
|
[&](const semantics::ProcEntityDetails &proc) {
|
|
|
|
if (const Symbol * interface{proc.interface().symbol()}) {
|
|
|
|
return (*this)(*interface);
|
|
|
|
} else {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return ScalarShape();
|
2019-10-09 06:21:09 +08:00
|
|
|
}
|
2019-08-02 03:32:17 +08:00
|
|
|
},
|
|
|
|
[&](const semantics::AssocEntityDetails &assoc) {
|
[flang]Semantics for SELECT RANK.
Summary:
Initially on github I worked on semantic checks.Then I tried some compile-time
test of the rank value, they were failing as there were no symbols
generated for them inside SELECT RANK's scope.So I went further to
add new symbol in each scope, also added the respective 'rank: '
field for a symbol when we dump the symboltable. I added a field to
keep track of the rank in AssocEntityDetails class.This caused shape
analysis framework to become inconsistent. So shape analysis framework
was updated to handle this new representation.
* I added more tests for above changes.
* On phabricator I addressed some minor changes.
* Lastly I worked on review comments.
Reviewers: klausler,sscalpone,DavidTruby,kiranchandramohan,tskeith,anchu-rajendran,kiranktp
Reviewed By:klausler, DavidTruby, tskeith
Subscribers:#flang-commits, #llvm-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78623
2020-04-22 17:16:37 +08:00
|
|
|
if (!assoc.rank()) {
|
|
|
|
return (*this)(assoc.expr());
|
|
|
|
} else {
|
|
|
|
int n{assoc.rank().value()};
|
|
|
|
NamedEntity base{symbol};
|
|
|
|
return Result{CreateShape(n, base)};
|
|
|
|
}
|
2019-08-02 03:32:17 +08:00
|
|
|
},
|
|
|
|
[&](const semantics::SubprogramDetails &subp) {
|
|
|
|
if (subp.isFunction()) {
|
2019-09-20 05:56:12 +08:00
|
|
|
return (*this)(subp.result());
|
2019-08-02 03:32:17 +08:00
|
|
|
} else {
|
2019-09-20 05:56:12 +08:00
|
|
|
return Result{};
|
2019-08-02 03:32:17 +08:00
|
|
|
}
|
|
|
|
},
|
|
|
|
[&](const semantics::ProcBindingDetails &binding) {
|
2019-09-20 05:56:12 +08:00
|
|
|
return (*this)(binding.symbol());
|
|
|
|
},
|
|
|
|
[&](const semantics::UseDetails &use) {
|
|
|
|
return (*this)(use.symbol());
|
2019-08-02 03:32:17 +08:00
|
|
|
},
|
|
|
|
[&](const semantics::HostAssocDetails &assoc) {
|
2019-09-20 05:56:12 +08:00
|
|
|
return (*this)(assoc.symbol());
|
2019-08-02 03:32:17 +08:00
|
|
|
},
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
[](const semantics::TypeParamDetails &) { return ScalarShape(); },
|
2019-10-25 07:08:06 +08:00
|
|
|
[](const auto &) { return Result{}; },
|
2019-08-02 03:32:17 +08:00
|
|
|
},
|
|
|
|
symbol.details());
|
2019-06-26 04:07:32 +08:00
|
|
|
}
|
|
|
|
|
2019-09-20 05:56:12 +08:00
|
|
|
auto GetShapeHelper::operator()(const Component &component) const -> Result {
|
2019-10-09 06:21:09 +08:00
|
|
|
const Symbol &symbol{component.GetLastSymbol()};
|
|
|
|
int rank{symbol.Rank()};
|
|
|
|
if (rank == 0) {
|
2019-09-20 05:56:12 +08:00
|
|
|
return (*this)(component.base());
|
2019-10-09 06:21:09 +08:00
|
|
|
} else if (symbol.has<semantics::ObjectEntityDetails>()) {
|
|
|
|
NamedEntity base{Component{component}};
|
[flang]Semantics for SELECT RANK.
Summary:
Initially on github I worked on semantic checks.Then I tried some compile-time
test of the rank value, they were failing as there were no symbols
generated for them inside SELECT RANK's scope.So I went further to
add new symbol in each scope, also added the respective 'rank: '
field for a symbol when we dump the symboltable. I added a field to
keep track of the rank in AssocEntityDetails class.This caused shape
analysis framework to become inconsistent. So shape analysis framework
was updated to handle this new representation.
* I added more tests for above changes.
* On phabricator I addressed some minor changes.
* Lastly I worked on review comments.
Reviewers: klausler,sscalpone,DavidTruby,kiranchandramohan,tskeith,anchu-rajendran,kiranktp
Reviewed By:klausler, DavidTruby, tskeith
Subscribers:#flang-commits, #llvm-commits
Tags: #flang, #llvm
Differential Revision: https://reviews.llvm.org/D78623
2020-04-22 17:16:37 +08:00
|
|
|
return CreateShape(rank, base);
|
|
|
|
} else if (symbol.has<semantics::AssocEntityDetails>()) {
|
|
|
|
NamedEntity base{Component{component}};
|
|
|
|
return Result{CreateShape(rank, base)};
|
2019-08-02 03:32:17 +08:00
|
|
|
} else {
|
2019-09-20 05:56:12 +08:00
|
|
|
return (*this)(symbol);
|
2019-04-04 07:04:13 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-20 05:56:12 +08:00
|
|
|
auto GetShapeHelper::operator()(const ArrayRef &arrayRef) const -> Result {
|
2019-04-02 06:22:45 +08:00
|
|
|
Shape shape;
|
2019-04-04 07:04:13 +08:00
|
|
|
int dimension{0};
|
2019-10-09 06:21:09 +08:00
|
|
|
const NamedEntity &base{arrayRef.base()};
|
2019-04-04 03:57:24 +08:00
|
|
|
for (const Subscript &ss : arrayRef.subscript()) {
|
|
|
|
if (ss.Rank() > 0) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
shape.emplace_back(GetExtent(ss, base, dimension));
|
2019-04-02 06:22:45 +08:00
|
|
|
}
|
2019-04-04 07:04:13 +08:00
|
|
|
++dimension;
|
2019-04-02 06:22:45 +08:00
|
|
|
}
|
|
|
|
if (shape.empty()) {
|
2019-10-09 06:21:09 +08:00
|
|
|
if (const Component * component{base.UnwrapComponent()}) {
|
|
|
|
return (*this)(component->base());
|
|
|
|
}
|
2019-04-02 06:22:45 +08:00
|
|
|
}
|
2019-10-09 06:21:09 +08:00
|
|
|
return shape;
|
2019-04-02 06:22:45 +08:00
|
|
|
}
|
2019-04-04 07:04:13 +08:00
|
|
|
|
2019-09-20 05:56:12 +08:00
|
|
|
auto GetShapeHelper::operator()(const CoarrayRef &coarrayRef) const -> Result {
|
2019-06-26 04:07:32 +08:00
|
|
|
NamedEntity base{coarrayRef.GetBase()};
|
2019-10-09 06:21:09 +08:00
|
|
|
if (coarrayRef.subscript().empty()) {
|
2019-09-20 05:56:12 +08:00
|
|
|
return (*this)(base);
|
2019-04-04 03:57:24 +08:00
|
|
|
} else {
|
2019-10-09 06:21:09 +08:00
|
|
|
Shape shape;
|
|
|
|
int dimension{0};
|
|
|
|
for (const Subscript &ss : coarrayRef.subscript()) {
|
|
|
|
if (ss.Rank() > 0) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
shape.emplace_back(GetExtent(ss, base, dimension));
|
2019-10-09 06:21:09 +08:00
|
|
|
}
|
|
|
|
++dimension;
|
|
|
|
}
|
2019-09-21 00:46:00 +08:00
|
|
|
return shape;
|
2019-04-04 03:57:24 +08:00
|
|
|
}
|
|
|
|
}
|
2019-04-04 07:04:13 +08:00
|
|
|
|
2019-09-20 05:56:12 +08:00
|
|
|
auto GetShapeHelper::operator()(const Substring &substring) const -> Result {
|
|
|
|
return (*this)(substring.parent());
|
|
|
|
}
|
|
|
|
|
|
|
|
auto GetShapeHelper::operator()(const ProcedureRef &call) const -> Result {
|
2019-04-04 07:04:13 +08:00
|
|
|
if (call.Rank() == 0) {
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return ScalarShape();
|
2019-04-04 07:04:13 +08:00
|
|
|
} else if (call.IsElemental()) {
|
|
|
|
for (const auto &arg : call.arguments()) {
|
2019-11-10 01:29:31 +08:00
|
|
|
if (arg && arg->Rank() > 0) {
|
2019-09-20 05:56:12 +08:00
|
|
|
return (*this)(*arg);
|
2019-04-04 07:04:13 +08:00
|
|
|
}
|
|
|
|
}
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return ScalarShape();
|
2019-04-04 07:04:13 +08:00
|
|
|
} else if (const Symbol * symbol{call.proc().GetSymbol()}) {
|
2019-09-20 05:56:12 +08:00
|
|
|
return (*this)(*symbol);
|
2019-10-09 06:21:09 +08:00
|
|
|
} else if (const auto *intrinsic{call.proc().GetSpecificIntrinsic()}) {
|
2019-04-04 07:04:13 +08:00
|
|
|
if (intrinsic->name == "shape" || intrinsic->name == "lbound" ||
|
|
|
|
intrinsic->name == "ubound") {
|
2019-10-17 01:35:34 +08:00
|
|
|
// These are the array-valued cases for LBOUND and UBOUND (no DIM=).
|
2019-05-22 07:58:46 +08:00
|
|
|
const auto *expr{call.arguments().front().value().UnwrapExpr()};
|
2019-11-10 01:29:31 +08:00
|
|
|
CHECK(expr);
|
2019-09-20 05:56:12 +08:00
|
|
|
return Shape{MaybeExtentExpr{ExtentExpr{expr->Rank()}}};
|
2019-10-17 02:53:03 +08:00
|
|
|
} else if (intrinsic->name == "all" || intrinsic->name == "any" ||
|
|
|
|
intrinsic->name == "count" || intrinsic->name == "iall" ||
|
|
|
|
intrinsic->name == "iany" || intrinsic->name == "iparity" ||
|
2021-01-15 04:54:31 +08:00
|
|
|
intrinsic->name == "maxval" || intrinsic->name == "minval" ||
|
2019-10-17 02:53:03 +08:00
|
|
|
intrinsic->name == "norm2" || intrinsic->name == "parity" ||
|
|
|
|
intrinsic->name == "product" || intrinsic->name == "sum") {
|
|
|
|
// Reduction with DIM=
|
|
|
|
if (call.arguments().size() >= 2) {
|
|
|
|
auto arrayShape{
|
|
|
|
(*this)(UnwrapExpr<Expr<SomeType>>(call.arguments().at(0)))};
|
|
|
|
const auto *dimArg{UnwrapExpr<Expr<SomeType>>(call.arguments().at(1))};
|
2019-11-10 01:29:31 +08:00
|
|
|
if (arrayShape && dimArg) {
|
2019-10-17 02:53:03 +08:00
|
|
|
if (auto dim{ToInt64(*dimArg)}) {
|
|
|
|
if (*dim >= 1 &&
|
|
|
|
static_cast<std::size_t>(*dim) <= arrayShape->size()) {
|
|
|
|
arrayShape->erase(arrayShape->begin() + (*dim - 1));
|
|
|
|
return std::move(*arrayShape);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-01-15 04:54:31 +08:00
|
|
|
} else if (intrinsic->name == "maxloc" || intrinsic->name == "minloc") {
|
|
|
|
// TODO: FINDLOC
|
|
|
|
if (call.arguments().size() >= 2) {
|
|
|
|
if (auto arrayShape{
|
|
|
|
(*this)(UnwrapExpr<Expr<SomeType>>(call.arguments().at(0)))}) {
|
|
|
|
auto rank{static_cast<int>(arrayShape->size())};
|
|
|
|
if (const auto *dimArg{
|
|
|
|
UnwrapExpr<Expr<SomeType>>(call.arguments()[1])}) {
|
|
|
|
auto dim{ToInt64(*dimArg)};
|
|
|
|
if (dim && *dim >= 1 && *dim <= rank) {
|
|
|
|
arrayShape->erase(arrayShape->begin() + (*dim - 1));
|
|
|
|
return std::move(*arrayShape);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// xxxLOC(no DIM=) result is vector(1:RANK(ARRAY=))
|
|
|
|
return Shape{ExtentExpr{rank}};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-10-17 02:53:03 +08:00
|
|
|
} else if (intrinsic->name == "cshift" || intrinsic->name == "eoshift") {
|
|
|
|
if (!call.arguments().empty()) {
|
|
|
|
return (*this)(call.arguments()[0]);
|
|
|
|
}
|
2020-06-20 09:11:46 +08:00
|
|
|
} else if (intrinsic->name == "matmul") {
|
|
|
|
if (call.arguments().size() == 2) {
|
|
|
|
if (auto ashape{(*this)(call.arguments()[0])}) {
|
|
|
|
if (auto bshape{(*this)(call.arguments()[1])}) {
|
|
|
|
if (ashape->size() == 1 && bshape->size() == 2) {
|
|
|
|
bshape->erase(bshape->begin());
|
|
|
|
return std::move(*bshape); // matmul(vector, matrix)
|
|
|
|
} else if (ashape->size() == 2 && bshape->size() == 1) {
|
|
|
|
ashape->pop_back();
|
|
|
|
return std::move(*ashape); // matmul(matrix, vector)
|
|
|
|
} else if (ashape->size() == 2 && bshape->size() == 2) {
|
|
|
|
(*ashape)[1] = std::move((*bshape)[1]);
|
|
|
|
return std::move(*ashape); // matmul(matrix, matrix)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-04-05 08:10:07 +08:00
|
|
|
} else if (intrinsic->name == "reshape") {
|
2019-11-10 01:29:31 +08:00
|
|
|
if (call.arguments().size() >= 2 && call.arguments().at(1)) {
|
2019-04-06 06:19:13 +08:00
|
|
|
// SHAPE(RESHAPE(array,shape)) -> shape
|
2019-10-17 00:39:37 +08:00
|
|
|
if (const auto *shapeExpr{
|
|
|
|
call.arguments().at(1).value().UnwrapExpr()}) {
|
|
|
|
auto shape{std::get<Expr<SomeInteger>>(shapeExpr->u)};
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
return AsShape(ConvertToType<ExtentType>(std::move(shape)));
|
2019-10-17 00:39:37 +08:00
|
|
|
}
|
|
|
|
}
|
2019-12-21 05:03:30 +08:00
|
|
|
} else if (intrinsic->name == "pack") {
|
|
|
|
if (call.arguments().size() >= 3 && call.arguments().at(2)) {
|
|
|
|
// SHAPE(PACK(,,VECTOR=v)) -> SHAPE(v)
|
|
|
|
return (*this)(call.arguments().at(2));
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
} else if (call.arguments().size() >= 2 && context_) {
|
2019-12-21 05:03:30 +08:00
|
|
|
if (auto maskShape{(*this)(call.arguments().at(1))}) {
|
|
|
|
if (maskShape->size() == 0) {
|
|
|
|
// Scalar MASK= -> [MERGE(SIZE(ARRAY=), 0, mask)]
|
|
|
|
if (auto arrayShape{(*this)(call.arguments().at(0))}) {
|
|
|
|
auto arraySize{GetSize(std::move(*arrayShape))};
|
|
|
|
CHECK(arraySize);
|
|
|
|
ActualArguments toMerge{
|
|
|
|
ActualArgument{AsGenericExpr(std::move(*arraySize))},
|
|
|
|
ActualArgument{AsGenericExpr(ExtentExpr{0})},
|
|
|
|
common::Clone(call.arguments().at(1))};
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
auto specific{context_->intrinsics().Probe(
|
|
|
|
CallCharacteristics{"merge"}, toMerge, *context_)};
|
2019-12-21 05:03:30 +08:00
|
|
|
CHECK(specific);
|
|
|
|
return Shape{ExtentExpr{FunctionRef<ExtentType>{
|
|
|
|
ProcedureDesignator{std::move(specific->specificIntrinsic)},
|
|
|
|
std::move(specific->arguments)}}};
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// Non-scalar MASK= -> [COUNT(mask)]
|
|
|
|
ActualArguments toCount{ActualArgument{common::Clone(
|
|
|
|
DEREF(call.arguments().at(1).value().UnwrapExpr()))}};
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
auto specific{context_->intrinsics().Probe(
|
|
|
|
CallCharacteristics{"count"}, toCount, *context_)};
|
2019-12-21 05:03:30 +08:00
|
|
|
CHECK(specific);
|
|
|
|
return Shape{ExtentExpr{FunctionRef<ExtentType>{
|
|
|
|
ProcedureDesignator{std::move(specific->specificIntrinsic)},
|
|
|
|
std::move(specific->arguments)}}};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-10-17 01:35:34 +08:00
|
|
|
} else if (intrinsic->name == "spread") {
|
|
|
|
// SHAPE(SPREAD(ARRAY,DIM,NCOPIES)) = SHAPE(ARRAY) with NCOPIES inserted
|
|
|
|
// at position DIM.
|
|
|
|
if (call.arguments().size() == 3) {
|
|
|
|
auto arrayShape{
|
|
|
|
(*this)(UnwrapExpr<Expr<SomeType>>(call.arguments().at(0)))};
|
|
|
|
const auto *dimArg{UnwrapExpr<Expr<SomeType>>(call.arguments().at(1))};
|
|
|
|
const auto *nCopies{
|
|
|
|
UnwrapExpr<Expr<SomeInteger>>(call.arguments().at(2))};
|
2019-11-10 01:29:31 +08:00
|
|
|
if (arrayShape && dimArg && nCopies) {
|
2019-10-17 01:35:34 +08:00
|
|
|
if (auto dim{ToInt64(*dimArg)}) {
|
|
|
|
if (*dim >= 1 &&
|
|
|
|
static_cast<std::size_t>(*dim) <= arrayShape->size() + 1) {
|
|
|
|
arrayShape->emplace(arrayShape->begin() + *dim - 1,
|
|
|
|
ConvertToType<ExtentType>(common::Clone(*nCopies)));
|
|
|
|
return std::move(*arrayShape);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2020-08-13 07:38:28 +08:00
|
|
|
} else if (intrinsic->name == "transfer") {
|
|
|
|
if (call.arguments().size() == 3 && call.arguments().at(2)) {
|
|
|
|
// SIZE= is present; shape is vector [SIZE=]
|
|
|
|
if (const auto *size{
|
|
|
|
UnwrapExpr<Expr<SomeInteger>>(call.arguments().at(2))}) {
|
|
|
|
return Shape{
|
|
|
|
MaybeExtentExpr{ConvertToType<ExtentType>(common::Clone(*size))}};
|
|
|
|
}
|
[flang] Fix classification of shape inquiries in specification exprs
In some contexts, including the motivating case of determining whether
the expressions that define the shape of a variable are "constant expressions"
in the sense of the Fortran standard, expression rewriting via Fold()
is not necessary, and should not be required. The inquiry intrinsics LBOUND,
UBOUND, and SIZE work correctly now in specification expressions and are
classified correctly as being constant expressions (or not). Getting this right
led to a fair amount of API clean-up as a consequence, including the
folding of shapes and TypeAndShape objects, and new APIs for shapes
that do not fold for those cases where folding isn't needed. Further,
the symbol-testing predicate APIs in Evaluate/tools.h now all resolve any
associations of their symbols and work transparently on use-, host-, and
construct-association symbols; the tools used to resolve those associations have
been defined and documented more precisely, and their clients adjusted as needed.
Differential Revision: https://reviews.llvm.org/D94561
2021-01-13 07:36:45 +08:00
|
|
|
} else if (context_) {
|
|
|
|
if (auto moldTypeAndShape{characteristics::TypeAndShape::Characterize(
|
|
|
|
call.arguments().at(1), *context_)}) {
|
|
|
|
if (GetRank(moldTypeAndShape->shape()) == 0) {
|
|
|
|
// SIZE= is absent and MOLD= is scalar: result is scalar
|
|
|
|
return ScalarShape();
|
|
|
|
} else {
|
|
|
|
// SIZE= is absent and MOLD= is array: result is vector whose
|
|
|
|
// length is determined by sizes of types. See 16.9.193p4 case(ii).
|
|
|
|
if (auto sourceTypeAndShape{
|
|
|
|
characteristics::TypeAndShape::Characterize(
|
|
|
|
call.arguments().at(0), *context_)}) {
|
|
|
|
auto sourceBytes{
|
|
|
|
sourceTypeAndShape->MeasureSizeInBytes(*context_)};
|
|
|
|
auto moldElementBytes{
|
|
|
|
moldTypeAndShape->type().MeasureSizeInBytes(*context_, true)};
|
|
|
|
if (sourceBytes && moldElementBytes) {
|
|
|
|
ExtentExpr extent{Fold(*context_,
|
|
|
|
(std::move(*sourceBytes) +
|
|
|
|
common::Clone(*moldElementBytes) - ExtentExpr{1}) /
|
|
|
|
common::Clone(*moldElementBytes))};
|
|
|
|
return Shape{MaybeExtentExpr{std::move(extent)}};
|
|
|
|
}
|
2020-08-13 07:38:28 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-10-17 02:53:03 +08:00
|
|
|
} else if (intrinsic->name == "transpose") {
|
|
|
|
if (call.arguments().size() >= 1) {
|
|
|
|
if (auto shape{(*this)(call.arguments().at(0))}) {
|
|
|
|
if (shape->size() == 2) {
|
|
|
|
std::swap((*shape)[0], (*shape)[1]);
|
|
|
|
return shape;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2021-01-15 04:54:31 +08:00
|
|
|
} else if (intrinsic->name == "unpack") {
|
|
|
|
if (call.arguments().size() >= 2) {
|
|
|
|
return (*this)(call.arguments()[1]); // MASK=
|
|
|
|
}
|
2019-10-09 06:21:09 +08:00
|
|
|
} else if (intrinsic->characteristics.value().attrs.test(characteristics::
|
2020-03-29 12:00:16 +08:00
|
|
|
Procedure::Attr::NullPointer)) { // NULL(MOLD=)
|
2019-10-09 06:21:09 +08:00
|
|
|
return (*this)(call.arguments());
|
2019-04-05 08:10:07 +08:00
|
|
|
} else {
|
|
|
|
// TODO: shapes of other non-elemental intrinsic results
|
2019-04-04 07:04:13 +08:00
|
|
|
}
|
|
|
|
}
|
2019-09-20 05:56:12 +08:00
|
|
|
return std::nullopt;
|
2019-04-04 07:04:13 +08:00
|
|
|
}
|
|
|
|
|
2020-11-14 01:31:41 +08:00
|
|
|
// Check conformance of the passed shapes. Only return true if we can verify
|
|
|
|
// that they conform
|
2019-05-04 02:29:15 +08:00
|
|
|
bool CheckConformance(parser::ContextualMessages &messages, const Shape &left,
|
[flang] Improve initializer semantics, esp. for component default values
This patch plugs many holes in static initializer semantics, improves error
messages for default initial values and other component properties in
parameterized derived type instantiations, and cleans up several small
issues noticed during development. We now do proper scalar expansion,
folding, and type, rank, and shape conformance checking for component
default initializers in derived types and PDT instantiations.
The initial values of named constants are now guaranteed to have been folded
when installed in the symbol table, and are no longer folded or
scalar-expanded at each use in expression folding. Semantics documentation
was extended with information about the various kinds of initializations
in Fortran and when each of them are processed in the compiler.
Some necessary concomitant changes have bulked this patch out a bit:
* contextual messages attachments, which are now produced for parameterized
derived type instantiations so that the user can figure out which
instance caused a problem with a component, have been added as part
of ContextualMessages, and their implementation was debugged
* several APIs in evaluate::characteristics was changed so that a FoldingContext
is passed as an argument rather than just its intrinsic procedure table;
this affected client call sites in many files
* new tools in Evaluate/check-expression.cpp to determine when an Expr
actually is a single constant value and to validate a non-pointer
variable initializer or object component default value
* shape conformance checking has additional arguments that control
whether scalar expansion is allowed
* several now-unused functions and data members noticed and removed
* several crashes and bogus errors exposed by testing this new code
were fixed
* a -fdebug-stack-trace option to enable LLVM's stack tracing on
a crash, which might be useful in the future
TL;DR: Initialization processing does more and takes place at the right
times for all of the various kinds of things that can be initialized.
Differential Review: https://reviews.llvm.org/D92783
2020-12-08 04:08:58 +08:00
|
|
|
const Shape &right, const char *leftIs, const char *rightIs,
|
2020-12-16 02:54:36 +08:00
|
|
|
bool leftScalarExpandable, bool rightScalarExpandable,
|
|
|
|
bool leftIsDeferredShape, bool rightIsDeferredShape) {
|
2020-09-01 02:54:48 +08:00
|
|
|
int n{GetRank(left)};
|
[flang] Improve initializer semantics, esp. for component default values
This patch plugs many holes in static initializer semantics, improves error
messages for default initial values and other component properties in
parameterized derived type instantiations, and cleans up several small
issues noticed during development. We now do proper scalar expansion,
folding, and type, rank, and shape conformance checking for component
default initializers in derived types and PDT instantiations.
The initial values of named constants are now guaranteed to have been folded
when installed in the symbol table, and are no longer folded or
scalar-expanded at each use in expression folding. Semantics documentation
was extended with information about the various kinds of initializations
in Fortran and when each of them are processed in the compiler.
Some necessary concomitant changes have bulked this patch out a bit:
* contextual messages attachments, which are now produced for parameterized
derived type instantiations so that the user can figure out which
instance caused a problem with a component, have been added as part
of ContextualMessages, and their implementation was debugged
* several APIs in evaluate::characteristics was changed so that a FoldingContext
is passed as an argument rather than just its intrinsic procedure table;
this affected client call sites in many files
* new tools in Evaluate/check-expression.cpp to determine when an Expr
actually is a single constant value and to validate a non-pointer
variable initializer or object component default value
* shape conformance checking has additional arguments that control
whether scalar expansion is allowed
* several now-unused functions and data members noticed and removed
* several crashes and bogus errors exposed by testing this new code
were fixed
* a -fdebug-stack-trace option to enable LLVM's stack tracing on
a crash, which might be useful in the future
TL;DR: Initialization processing does more and takes place at the right
times for all of the various kinds of things that can be initialized.
Differential Review: https://reviews.llvm.org/D92783
2020-12-08 04:08:58 +08:00
|
|
|
if (n == 0 && leftScalarExpandable) {
|
|
|
|
return true;
|
|
|
|
}
|
2020-09-01 02:54:48 +08:00
|
|
|
int rn{GetRank(right)};
|
[flang] Improve initializer semantics, esp. for component default values
This patch plugs many holes in static initializer semantics, improves error
messages for default initial values and other component properties in
parameterized derived type instantiations, and cleans up several small
issues noticed during development. We now do proper scalar expansion,
folding, and type, rank, and shape conformance checking for component
default initializers in derived types and PDT instantiations.
The initial values of named constants are now guaranteed to have been folded
when installed in the symbol table, and are no longer folded or
scalar-expanded at each use in expression folding. Semantics documentation
was extended with information about the various kinds of initializations
in Fortran and when each of them are processed in the compiler.
Some necessary concomitant changes have bulked this patch out a bit:
* contextual messages attachments, which are now produced for parameterized
derived type instantiations so that the user can figure out which
instance caused a problem with a component, have been added as part
of ContextualMessages, and their implementation was debugged
* several APIs in evaluate::characteristics was changed so that a FoldingContext
is passed as an argument rather than just its intrinsic procedure table;
this affected client call sites in many files
* new tools in Evaluate/check-expression.cpp to determine when an Expr
actually is a single constant value and to validate a non-pointer
variable initializer or object component default value
* shape conformance checking has additional arguments that control
whether scalar expansion is allowed
* several now-unused functions and data members noticed and removed
* several crashes and bogus errors exposed by testing this new code
were fixed
* a -fdebug-stack-trace option to enable LLVM's stack tracing on
a crash, which might be useful in the future
TL;DR: Initialization processing does more and takes place at the right
times for all of the various kinds of things that can be initialized.
Differential Review: https://reviews.llvm.org/D92783
2020-12-08 04:08:58 +08:00
|
|
|
if (rn == 0 && rightScalarExpandable) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
if (n != rn) {
|
|
|
|
messages.Say("Rank of %1$s is %2$d, but %3$s has rank %4$d"_err_en_US,
|
|
|
|
leftIs, n, rightIs, rn);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
for (int j{0}; j < n; ++j) {
|
2020-12-16 02:54:36 +08:00
|
|
|
if (auto leftDim{ToInt64(left[j])}) {
|
|
|
|
if (auto rightDim{ToInt64(right[j])}) {
|
|
|
|
if (*leftDim != *rightDim) {
|
|
|
|
messages.Say("Dimension %1$d of %2$s has extent %3$jd, "
|
|
|
|
"but %4$s has extent %5$jd"_err_en_US,
|
|
|
|
j + 1, leftIs, *leftDim, rightIs, *rightDim);
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (!rightIsDeferredShape) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
} else if (!leftIsDeferredShape) {
|
2019-05-04 02:29:15 +08:00
|
|
|
return false;
|
2019-04-19 05:11:15 +08:00
|
|
|
}
|
|
|
|
}
|
2019-05-04 02:29:15 +08:00
|
|
|
return true;
|
2019-04-19 05:11:15 +08:00
|
|
|
}
|
2020-06-19 08:17:04 +08:00
|
|
|
|
|
|
|
bool IncrementSubscripts(
|
|
|
|
ConstantSubscripts &indices, const ConstantSubscripts &extents) {
|
|
|
|
std::size_t rank(indices.size());
|
|
|
|
CHECK(rank <= extents.size());
|
|
|
|
for (std::size_t j{0}; j < rank; ++j) {
|
|
|
|
if (extents[j] < 1) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
for (std::size_t j{0}; j < rank; ++j) {
|
|
|
|
if (indices[j]++ < extents[j]) {
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
indices[j] = 1;
|
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
2020-03-29 12:00:16 +08:00
|
|
|
} // namespace Fortran::evaluate
|