From b0f02cee2b5b9a767705db9b9aa0663b49742c4e Mon Sep 17 00:00:00 2001 From: Peter Klausler Date: Fri, 17 Mar 2023 16:01:47 -0700 Subject: [PATCH] [flang] Catch impure defined assignments in DO CONCURRENT The semantic checking of DO CONCURRENT bodies looks only at the parse tree, not the typed expressions produced from it, so it misses calls to defined assignment subroutines that arise from assignment statements that resolve via generic interfaces into subroutine calls. Extend the checking to peek into the typed assignment operations left on the parse tree by semantics. Differential Revision: https://reviews.llvm.org/D146585 --- flang/lib/Semantics/check-do-forall.cpp | 18 ++++++++++++++---- flang/test/Semantics/doconcurrent01.f90 | 31 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 4 deletions(-) diff --git a/flang/lib/Semantics/check-do-forall.cpp b/flang/lib/Semantics/check-do-forall.cpp index 65b2986..cf2a2c2 100644 --- a/flang/lib/Semantics/check-do-forall.cpp +++ b/flang/lib/Semantics/check-do-forall.cpp @@ -219,6 +219,16 @@ public: SayDeallocateWithImpureFinal(*entity, reason); } } + if (const auto *assignment{GetAssignment(stmt)}) { + if (const auto *call{ + std::get_if(&assignment->u)}) { + if (auto bad{FindImpureCall(context_.foldingContext(), *call)}) { + context_.Say(currentStatementSourcePosition_, + "The defined assignment subroutine '%s' is not pure"_err_en_US, + *bad); + } + } + } } // Deallocation from a DEALLOCATE statement @@ -431,10 +441,10 @@ public: } void Check(const parser::ForallAssignmentStmt &stmt) { - const evaluate::Assignment *assignment{common::visit( - common::visitors{[&](const auto &x) { return GetAssignment(x); }}, - stmt.u)}; - if (assignment) { + if (const evaluate::Assignment * + assignment{common::visit( + common::visitors{[&](const auto &x) { return GetAssignment(x); }}, + stmt.u)}) { CheckForallIndexesUsed(*assignment); CheckForImpureCall(assignment->lhs); CheckForImpureCall(assignment->rhs); diff --git a/flang/test/Semantics/doconcurrent01.f90 b/flang/test/Semantics/doconcurrent01.f90 index c44c1e2..0f4e13d 100644 --- a/flang/test/Semantics/doconcurrent01.f90 +++ b/flang/test/Semantics/doconcurrent01.f90 @@ -237,3 +237,34 @@ subroutine s7() end function pureFunc end subroutine s7 + +module m8 + type t + contains + procedure tbpAssign + generic :: assignment(=) => tbpAssign + end type + interface assignment(=) + module procedure nonTbpAssign + end interface + contains + impure elemental subroutine tbpAssign(to, from) + class(t), intent(out) :: to + class(t), intent(in) :: from + print *, 'impure due to I/O' + end + impure elemental subroutine nonTbpAssign(to, from) + type(t), intent(out) :: to + integer, intent(in) :: from + print *, 'impure due to I/O' + end + subroutine test + type(t) x, y + do concurrent (j=1:1) + !ERROR: The defined assignment subroutine 'tbpassign' is not pure + x = y + !ERROR: The defined assignment subroutine 'nontbpassign' is not pure + x = 666 + end do + end +end -- 2.7.4