[flang-commits] [flang] [flang][semantic] Implement semantic checks and new data structure (PR #203030)
Eugene Epshteyn via flang-commits
flang-commits at lists.llvm.org
Wed Jul 1 07:45:07 PDT 2026
================
@@ -343,11 +350,138 @@ void ArraySpecAnalyzer::Analyze(const parser::ExplicitShapeSpec &x) {
std::get<parser::SpecificationExpr>(x.t));
}
+std::optional<ArraySpecAnalyzer::ExplicitShapeBoundsResult>
+ArraySpecAnalyzer::checkExplicitShapeBoundsSpec(
+ const parser::ExplicitShapeBoundsSpec &x) {
+ const auto &lowerBoundOpt{std::get<0>(x.t)};
+ const auto &upperBound{std::get<1>(x.t)};
+
+ // Analyze, validate, fold, and wrap one bound expression in a Bound.
+ // Returns the Bound and, for rank-1, the constant extent; for scalar
+ // the extent is 0 (meaning "broadcast").
+ bool hasError{false};
+ auto analyzeBound =
+ [&](const auto &parseBound,
+ bool isUpper) -> std::optional<std::pair<Bound, std::int64_t>> {
+ MaybeExpr expr{AnalyzeExpr(context_, parseBound.thing)};
+ if (expr->Rank() > 1) {
+ context_.Say(parser::FindSourceLocation(parseBound),
+ "Integer array used as %s bounds in DECLARATION must be rank-1 "
+ "but is rank-%d"_err_en_US,
+ isUpper ? "upper" : "lower", expr->Rank());
+ hasError = true;
+ return std::nullopt;
+ }
+ auto folded{evaluate::Fold(context_.foldingContext(), std::move(*expr))};
+ const auto *someInt{evaluate::UnwrapExpr<SomeIntExpr>(folded)};
+ if (!someInt) {
+ hasError = true;
+ return std::nullopt;
+ }
+ auto asSI{evaluate::Fold(context_.foldingContext(),
+ evaluate::ConvertToType<evaluate::SubscriptInteger>(
+ common::Clone(*someInt)))};
+ if (folded.Rank() == 0) {
+ return std::make_pair(
+ Bound{MaybeSubscriptIntExpr{std::move(asSI)}}, std::int64_t{0});
+ }
+ // Rank-1: must have constant extent.
+ auto extents{
+ evaluate::GetConstantExtents(context_.foldingContext(), folded)};
----------------
eugeneepshteyn wrote:
Please check empty array extents handling. How does this work?
```
subroutine e1()
integer, parameter :: empty(0) = [integer::]
integer :: a(empty)
end subroutine
```
Also, what happens if lower bound exists, but is empty, but the upper bound is not? That should be legal, right?
```
integer, parameter :: lo(0) = [integer::]
integer, parameter :: hi(2) = [10, 20]
integer :: a(lo : hi)
```
https://github.com/llvm/llvm-project/pull/203030
More information about the flang-commits
mailing list