1010#include " assignment.h"
1111#include " definable.h"
1212#include " flang/Evaluate/fold.h"
13+ #include " flang/Evaluate/shape.h"
1314#include " flang/Evaluate/type.h"
1415#include " flang/Parser/parse-tree.h"
1516#include " flang/Parser/tools.h"
@@ -33,6 +34,7 @@ struct AllocateCheckerInfo {
3334 bool gotMold{false };
3435 bool gotStream{false };
3536 bool gotPinned{false };
37+ std::optional<evaluate::ConstantSubscripts> sourceExprShape;
3638};
3739
3840class AllocationCheckerHelper {
@@ -259,6 +261,9 @@ static std::optional<AllocateCheckerInfo> CheckAllocateOptions(
259261 CheckCopyabilityInPureScope (messages, *expr, scope);
260262 }
261263 }
264+ auto maybeShape{evaluate::GetShape (context.foldingContext (), *expr)};
265+ info.sourceExprShape =
266+ evaluate::AsConstantExtents (context.foldingContext (), maybeShape);
262267 } else {
263268 // Error already reported on source expression.
264269 // Do not continue allocate checks.
@@ -581,6 +586,52 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
581586 .Attach (
582587 ultimate_->name (), " Declared here with rank %d" _en_US, rank_);
583588 return false ;
589+ } else if (allocateInfo_.gotSource && allocateInfo_.sourceExprShape &&
590+ allocateInfo_.sourceExprShape ->size () ==
591+ static_cast <std::size_t >(allocateShapeSpecRank_)) {
592+ std::size_t j{0 };
593+ for (const auto &shapeSpec :
594+ std::get<std::list<parser::AllocateShapeSpec>>(allocation_.t )) {
595+ if (j >= allocateInfo_.sourceExprShape ->size ()) {
596+ break ;
597+ }
598+ std::optional<evaluate::ConstantSubscript> lbound;
599+ if (const auto &lb{std::get<0 >(shapeSpec.t )}) {
600+ lbound.reset ();
601+ const auto &lbExpr{lb->thing .thing .value ()};
602+ if (const auto *expr{GetExpr (context, lbExpr)}) {
603+ auto folded{
604+ evaluate::Fold (context.foldingContext (), SomeExpr (*expr))};
605+ lbound = evaluate::ToInt64 (folded);
606+ evaluate::SetExpr (lbExpr, std::move (folded));
607+ }
608+ } else {
609+ lbound = 1 ;
610+ }
611+ if (lbound) {
612+ const auto &ubExpr{std::get<1 >(shapeSpec.t ).thing .thing .value ()};
613+ if (const auto *expr{GetExpr (context, ubExpr)}) {
614+ auto folded{
615+ evaluate::Fold (context.foldingContext (), SomeExpr (*expr))};
616+ auto ubound{evaluate::ToInt64 (folded)};
617+ evaluate::SetExpr (ubExpr, std::move (folded));
618+ if (ubound) {
619+ auto extent{*ubound - *lbound + 1 };
620+ if (extent < 0 ) {
621+ extent = 0 ;
622+ }
623+ if (extent != allocateInfo_.sourceExprShape ->at (j)) {
624+ context.Say (name_.source ,
625+ " Allocation has extent %jd on dimension %d, but SOURCE= has extent %jd" _err_en_US,
626+ static_cast <std::intmax_t >(extent), j + 1 ,
627+ static_cast <std::intmax_t >(
628+ allocateInfo_.sourceExprShape ->at (j)));
629+ }
630+ }
631+ }
632+ }
633+ ++j;
634+ }
584635 }
585636 }
586637 } else { // allocating a scalar object
0 commit comments