10
10
#include " assignment.h"
11
11
#include " definable.h"
12
12
#include " flang/Evaluate/fold.h"
13
+ #include " flang/Evaluate/shape.h"
13
14
#include " flang/Evaluate/type.h"
14
15
#include " flang/Parser/parse-tree.h"
15
16
#include " flang/Parser/tools.h"
@@ -33,6 +34,7 @@ struct AllocateCheckerInfo {
33
34
bool gotMold{false };
34
35
bool gotStream{false };
35
36
bool gotPinned{false };
37
+ std::optional<evaluate::ConstantSubscripts> sourceExprShape;
36
38
};
37
39
38
40
class AllocationCheckerHelper {
@@ -259,6 +261,9 @@ static std::optional<AllocateCheckerInfo> CheckAllocateOptions(
259
261
CheckCopyabilityInPureScope (messages, *expr, scope);
260
262
}
261
263
}
264
+ auto maybeShape{evaluate::GetShape (context.foldingContext (), *expr)};
265
+ info.sourceExprShape =
266
+ evaluate::AsConstantExtents (context.foldingContext (), maybeShape);
262
267
} else {
263
268
// Error already reported on source expression.
264
269
// Do not continue allocate checks.
@@ -581,6 +586,52 @@ bool AllocationCheckerHelper::RunChecks(SemanticsContext &context) {
581
586
.Attach (
582
587
ultimate_->name (), " Declared here with rank %d" _en_US, rank_);
583
588
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
+ }
584
635
}
585
636
}
586
637
} else { // allocating a scalar object
0 commit comments