@@ -269,8 +269,7 @@ class DoConcurrentBodyEnforce {
269
269
const parser::CharBlock statementLocation{
270
270
GetImageControlStmtLocation (construct)};
271
271
auto &msg{context_.Say (statementLocation,
272
- " An image control statement is not allowed in DO"
273
- " CONCURRENT" _err_en_US)};
272
+ " An image control statement is not allowed in DO CONCURRENT" _err_en_US)};
274
273
if (auto coarrayMsg{GetImageControlStmtCoarrayMsg (construct)}) {
275
274
msg.Attach (statementLocation, *coarrayMsg);
276
275
}
@@ -372,8 +371,8 @@ class DoConcurrentVariableEnforce {
372
371
// Find a DO or FORALL and enforce semantics checks on its body
373
372
class DoContext {
374
373
public:
375
- DoContext (SemanticsContext &context, IndexVarKind kind)
376
- : context_{context}, kind_{kind} {}
374
+ DoContext (SemanticsContext &context, IndexVarKind kind, bool isNested )
375
+ : context_{context}, kind_{kind}, isNested_{isNested} {}
377
376
378
377
// Mark this DO construct as a point of definition for the DO variables
379
378
// or index-names it contains. If they're already defined, emit an error
@@ -743,13 +742,21 @@ class DoContext {
743
742
std::get<std::optional<parser::ScalarLogicalExpr>>(header.t )}) {
744
743
CheckMaskIsPure (*mask);
745
744
}
746
- auto &controls{std::get<std::list<parser::ConcurrentControl>>(header.t )};
745
+ const auto &controls{
746
+ std::get<std::list<parser::ConcurrentControl>>(header.t )};
747
747
UnorderedSymbolSet indexNames;
748
748
for (const parser::ConcurrentControl &control : controls) {
749
749
const auto &indexName{std::get<parser::Name>(control.t )};
750
750
if (indexName.symbol ) {
751
751
indexNames.insert (*indexName.symbol );
752
752
}
753
+ if (isNested_) {
754
+ CheckForImpureCall (std::get<1 >(control.t ));
755
+ CheckForImpureCall (std::get<2 >(control.t ));
756
+ if (const auto &stride{std::get<3 >(control.t )}) {
757
+ CheckForImpureCall (*stride);
758
+ }
759
+ }
753
760
}
754
761
if (!indexNames.empty ()) {
755
762
for (const parser::ConcurrentControl &control : controls) {
@@ -808,13 +815,24 @@ class DoContext {
808
815
CheckConcurrentHeader (std::get<parser::ConcurrentHeader>(concurrent.t ));
809
816
}
810
817
811
- template <typename T> void CheckForImpureCall (const T &x) {
818
+ template <typename T> void CheckForImpureCall (const T &x) const {
812
819
if (auto bad{FindImpureCall (context_.foldingContext (), x)}) {
813
820
context_.Say (
814
821
" Impure procedure '%s' may not be referenced in a %s" _err_en_US, *bad,
815
822
LoopKindName ());
816
823
}
817
824
}
825
+ void CheckForImpureCall (const parser::ScalarIntExpr &x) const {
826
+ const auto &parsedExpr{x.thing .thing .value ()};
827
+ auto oldLocation{context_.location ()};
828
+ context_.set_location (parsedExpr.source );
829
+ if (const auto &typedExpr{parsedExpr.typedExpr }) {
830
+ if (const auto &expr{typedExpr->v }) {
831
+ CheckForImpureCall (*expr);
832
+ }
833
+ }
834
+ context_.set_location (oldLocation);
835
+ }
818
836
819
837
// Each index should be used on the LHS of each assignment in a FORALL
820
838
void CheckForallIndexesUsed (const evaluate::Assignment &assignment) {
@@ -870,40 +888,47 @@ class DoContext {
870
888
SemanticsContext &context_;
871
889
const IndexVarKind kind_;
872
890
parser::CharBlock currentStatementSourcePosition_;
891
+ bool isNested_{false };
873
892
}; // class DoContext
874
893
875
894
void DoForallChecker::Enter (const parser::DoConstruct &doConstruct) {
876
- DoContext doContext{context_, IndexVarKind::DO};
895
+ DoContext doContext{context_, IndexVarKind::DO, constructNesting_ > 0 };
877
896
doContext.DefineDoVariables (doConstruct);
878
897
}
879
898
880
899
void DoForallChecker::Leave (const parser::DoConstruct &doConstruct) {
881
- DoContext doContext{context_, IndexVarKind::DO};
900
+ DoContext doContext{context_, IndexVarKind::DO, constructNesting_ > 0 };
901
+ ++constructNesting_;
882
902
doContext.Check (doConstruct);
883
903
doContext.ResetDoVariables (doConstruct);
904
+ --constructNesting_;
884
905
}
885
906
886
907
void DoForallChecker::Enter (const parser::ForallConstruct &construct) {
887
- DoContext doContext{context_, IndexVarKind::FORALL};
908
+ DoContext doContext{context_, IndexVarKind::FORALL, constructNesting_ > 0 };
888
909
doContext.ActivateIndexVars (GetControls (construct));
910
+ ++constructNesting_;
911
+ doContext.Check (construct);
889
912
}
890
913
void DoForallChecker::Leave (const parser::ForallConstruct &construct) {
891
- DoContext doContext{context_, IndexVarKind::FORALL};
892
- doContext.Check (construct);
914
+ DoContext doContext{context_, IndexVarKind::FORALL, constructNesting_ > 0 };
893
915
doContext.DeactivateIndexVars (GetControls (construct));
916
+ --constructNesting_;
894
917
}
895
918
896
919
void DoForallChecker::Enter (const parser::ForallStmt &stmt) {
897
- DoContext doContext{context_, IndexVarKind::FORALL};
920
+ DoContext doContext{context_, IndexVarKind::FORALL, constructNesting_ > 0 };
921
+ ++constructNesting_;
922
+ doContext.Check (stmt);
898
923
doContext.ActivateIndexVars (GetControls (stmt));
899
924
}
900
925
void DoForallChecker::Leave (const parser::ForallStmt &stmt) {
901
- DoContext doContext{context_, IndexVarKind::FORALL};
902
- doContext.Check (stmt);
926
+ DoContext doContext{context_, IndexVarKind::FORALL, constructNesting_ > 0 };
903
927
doContext.DeactivateIndexVars (GetControls (stmt));
928
+ --constructNesting_;
904
929
}
905
930
void DoForallChecker::Leave (const parser::ForallAssignmentStmt &stmt) {
906
- DoContext doContext{context_, IndexVarKind::FORALL};
931
+ DoContext doContext{context_, IndexVarKind::FORALL, constructNesting_ > 0 };
907
932
doContext.Check (stmt);
908
933
}
909
934
0 commit comments