@@ -122,6 +122,10 @@ class DoConcurrentBodyEnforce {
122
122
}
123
123
return true ;
124
124
}
125
+ bool Pre (const parser::ConcurrentHeader &) {
126
+ // handled in CheckConcurrentHeader
127
+ return false ;
128
+ }
125
129
template <typename T> void Post (const T &) {}
126
130
127
131
// C1140 -- Can't deallocate a polymorphic entity in a DO CONCURRENT.
@@ -375,8 +379,13 @@ class DoConcurrentVariableEnforce {
375
379
// Find a DO or FORALL and enforce semantics checks on its body
376
380
class DoContext {
377
381
public:
378
- DoContext (SemanticsContext &context, IndexVarKind kind, bool isNested)
379
- : context_{context}, kind_{kind}, isNested_{isNested} {}
382
+ DoContext (SemanticsContext &context, IndexVarKind kind,
383
+ const std::list<IndexVarKind> nesting)
384
+ : context_{context}, kind_{kind} {
385
+ if (!nesting.empty ()) {
386
+ concurrentNesting_ = nesting.back ();
387
+ }
388
+ }
380
389
381
390
// Mark this DO construct as a point of definition for the DO variables
382
391
// or index-names it contains. If they're already defined, emit an error
@@ -439,8 +448,8 @@ class DoContext {
439
448
common::visitors{[&](const auto &x) { return GetAssignment (x); }},
440
449
stmt.u )}) {
441
450
CheckForallIndexesUsed (*assignment);
442
- CheckForImpureCall (assignment->lhs );
443
- CheckForImpureCall (assignment->rhs );
451
+ CheckForImpureCall (assignment->lhs , kind_ );
452
+ CheckForImpureCall (assignment->rhs , kind_ );
444
453
445
454
if (IsVariable (assignment->lhs )) {
446
455
if (const Symbol * symbol{GetLastSymbol (assignment->lhs )}) {
@@ -455,23 +464,23 @@ class DoContext {
455
464
456
465
if (const auto *proc{
457
466
std::get_if<evaluate::ProcedureRef>(&assignment->u )}) {
458
- CheckForImpureCall (*proc);
467
+ CheckForImpureCall (*proc, kind_ );
459
468
}
460
469
common::visit (
461
470
common::visitors{
462
471
[](const evaluate::Assignment::Intrinsic &) {},
463
472
[&](const evaluate::ProcedureRef &proc) {
464
- CheckForImpureCall (proc);
473
+ CheckForImpureCall (proc, kind_ );
465
474
},
466
475
[&](const evaluate::Assignment::BoundsSpec &bounds) {
467
476
for (const auto &bound : bounds) {
468
- CheckForImpureCall (SomeExpr{bound});
477
+ CheckForImpureCall (SomeExpr{bound}, kind_ );
469
478
}
470
479
},
471
480
[&](const evaluate::Assignment::BoundsRemapping &bounds) {
472
481
for (const auto &bound : bounds) {
473
- CheckForImpureCall (SomeExpr{bound.first });
474
- CheckForImpureCall (SomeExpr{bound.second });
482
+ CheckForImpureCall (SomeExpr{bound.first }, kind_ );
483
+ CheckForImpureCall (SomeExpr{bound.second }, kind_ );
475
484
}
476
485
},
477
486
},
@@ -754,12 +763,10 @@ class DoContext {
754
763
if (indexName.symbol ) {
755
764
indexNames.insert (*indexName.symbol );
756
765
}
757
- if (isNested_) {
758
- CheckForImpureCall (std::get<1 >(control.t ));
759
- CheckForImpureCall (std::get<2 >(control.t ));
760
- if (const auto &stride{std::get<3 >(control.t )}) {
761
- CheckForImpureCall (*stride);
762
- }
766
+ CheckForImpureCall (std::get<1 >(control.t ), concurrentNesting_);
767
+ CheckForImpureCall (std::get<2 >(control.t ), concurrentNesting_);
768
+ if (const auto &stride{std::get<3 >(control.t )}) {
769
+ CheckForImpureCall (*stride, concurrentNesting_);
763
770
}
764
771
}
765
772
if (!indexNames.empty ()) {
@@ -819,20 +826,29 @@ class DoContext {
819
826
CheckConcurrentHeader (std::get<parser::ConcurrentHeader>(concurrent.t ));
820
827
}
821
828
822
- template <typename T> void CheckForImpureCall (const T &x) const {
829
+ template <typename T>
830
+ void CheckForImpureCall (
831
+ const T &x, std::optional<IndexVarKind> nesting) const {
823
832
if (auto bad{FindImpureCall (context_.foldingContext (), x)}) {
824
- context_.Say (
825
- " Impure procedure '%s' may not be referenced in a %s" _err_en_US, *bad,
826
- LoopKindName ());
833
+ if (nesting) {
834
+ context_.Say (
835
+ " Impure procedure '%s' may not be referenced in a %s" _err_en_US,
836
+ *bad, LoopKindName (*nesting));
837
+ } else {
838
+ context_.Say (
839
+ " Impure procedure '%s' should not be referenced in a %s header" _warn_en_US,
840
+ *bad, LoopKindName (kind_));
841
+ }
827
842
}
828
843
}
829
- void CheckForImpureCall (const parser::ScalarIntExpr &x) const {
844
+ void CheckForImpureCall (const parser::ScalarIntExpr &x,
845
+ std::optional<IndexVarKind> nesting) const {
830
846
const auto &parsedExpr{x.thing .thing .value ()};
831
847
auto oldLocation{context_.location ()};
832
848
context_.set_location (parsedExpr.source );
833
849
if (const auto &typedExpr{parsedExpr.typedExpr }) {
834
850
if (const auto &expr{typedExpr->v }) {
835
- CheckForImpureCall (*expr);
851
+ CheckForImpureCall (*expr, nesting );
836
852
}
837
853
}
838
854
context_.set_location (oldLocation);
@@ -885,54 +901,59 @@ class DoContext {
885
901
}
886
902
887
903
// For messages where the DO loop must be DO CONCURRENT, make that explicit.
888
- const char *LoopKindName () const {
889
- return kind_ == IndexVarKind::DO ? " DO CONCURRENT" : " FORALL" ;
904
+ const char *LoopKindName (IndexVarKind kind ) const {
905
+ return kind == IndexVarKind::DO ? " DO CONCURRENT" : " FORALL" ;
890
906
}
907
+ const char *LoopKindName () const { return LoopKindName (kind_); }
891
908
892
909
SemanticsContext &context_;
893
910
const IndexVarKind kind_;
894
911
parser::CharBlock currentStatementSourcePosition_;
895
- bool isNested_{ false } ;
912
+ std::optional<IndexVarKind> concurrentNesting_ ;
896
913
}; // class DoContext
897
914
898
915
void DoForallChecker::Enter (const parser::DoConstruct &doConstruct) {
899
- DoContext doContext{context_, IndexVarKind::DO, constructNesting_ > 0 };
916
+ DoContext doContext{context_, IndexVarKind::DO, nestedWithinConcurrent_};
917
+ if (doConstruct.IsDoConcurrent ()) {
918
+ nestedWithinConcurrent_.push_back (IndexVarKind::DO);
919
+ }
900
920
doContext.DefineDoVariables (doConstruct);
921
+ doContext.Check (doConstruct);
901
922
}
902
923
903
924
void DoForallChecker::Leave (const parser::DoConstruct &doConstruct) {
904
- DoContext doContext{context_, IndexVarKind::DO, constructNesting_ > 0 };
905
- ++constructNesting_;
906
- doContext.Check (doConstruct);
925
+ DoContext doContext{context_, IndexVarKind::DO, nestedWithinConcurrent_};
907
926
doContext.ResetDoVariables (doConstruct);
908
- --constructNesting_;
927
+ if (doConstruct.IsDoConcurrent ()) {
928
+ nestedWithinConcurrent_.pop_back ();
929
+ }
909
930
}
910
931
911
932
void DoForallChecker::Enter (const parser::ForallConstruct &construct) {
912
- DoContext doContext{context_, IndexVarKind::FORALL, constructNesting_ > 0 };
933
+ DoContext doContext{context_, IndexVarKind::FORALL, nestedWithinConcurrent_ };
913
934
doContext.ActivateIndexVars (GetControls (construct));
914
- ++constructNesting_ ;
935
+ nestedWithinConcurrent_. push_back (IndexVarKind::FORALL) ;
915
936
doContext.Check (construct);
916
937
}
917
938
void DoForallChecker::Leave (const parser::ForallConstruct &construct) {
918
- DoContext doContext{context_, IndexVarKind::FORALL, constructNesting_ > 0 };
939
+ DoContext doContext{context_, IndexVarKind::FORALL, nestedWithinConcurrent_ };
919
940
doContext.DeactivateIndexVars (GetControls (construct));
920
- --constructNesting_ ;
941
+ nestedWithinConcurrent_. pop_back () ;
921
942
}
922
943
923
944
void DoForallChecker::Enter (const parser::ForallStmt &stmt) {
924
- DoContext doContext{context_, IndexVarKind::FORALL, constructNesting_ > 0 };
925
- ++constructNesting_ ;
945
+ DoContext doContext{context_, IndexVarKind::FORALL, nestedWithinConcurrent_ };
946
+ nestedWithinConcurrent_. push_back (IndexVarKind::FORALL) ;
926
947
doContext.Check (stmt);
927
948
doContext.ActivateIndexVars (GetControls (stmt));
928
949
}
929
950
void DoForallChecker::Leave (const parser::ForallStmt &stmt) {
930
- DoContext doContext{context_, IndexVarKind::FORALL, constructNesting_ > 0 };
951
+ DoContext doContext{context_, IndexVarKind::FORALL, nestedWithinConcurrent_ };
931
952
doContext.DeactivateIndexVars (GetControls (stmt));
932
- --constructNesting_ ;
953
+ nestedWithinConcurrent_. pop_back () ;
933
954
}
934
955
void DoForallChecker::Leave (const parser::ForallAssignmentStmt &stmt) {
935
- DoContext doContext{context_, IndexVarKind::FORALL, constructNesting_ > 0 };
956
+ DoContext doContext{context_, IndexVarKind::FORALL, nestedWithinConcurrent_ };
936
957
doContext.Check (stmt);
937
958
}
938
959
0 commit comments