[flang-commits] [flang] [flang] Enforce control flow restrictions on CHANGE TEAM (PR #131013)
via flang-commits
flang-commits at lists.llvm.org
Wed Mar 12 12:16:37 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-flang-semantics
Author: Peter Klausler (klausler)
<details>
<summary>Changes</summary>
Like DO CONCURRENT and CRITICAL constructs, control flow into and out of a CHANGE TEAM construct is disallowed.
---
Full diff: https://github.com/llvm/llvm-project/pull/131013.diff
3 Files Affected:
- (modified) flang/lib/Semantics/check-coarray.cpp (+48-3)
- (modified) flang/lib/Semantics/check-coarray.h (+1-20)
- (added) flang/test/Semantics/change_team02.f90 (+24)
``````````diff
diff --git a/flang/lib/Semantics/check-coarray.cpp b/flang/lib/Semantics/check-coarray.cpp
index 833a08899308a..789f3449772ca 100644
--- a/flang/lib/Semantics/check-coarray.cpp
+++ b/flang/lib/Semantics/check-coarray.cpp
@@ -63,6 +63,39 @@ class CriticalBodyEnforce {
parser::CharBlock criticalSourcePosition_;
};
+class ChangeTeamBodyEnforce {
+public:
+ ChangeTeamBodyEnforce(
+ SemanticsContext &context, parser::CharBlock changeTeamSourcePosition)
+ : context_{context}, changeTeamSourcePosition_{changeTeamSourcePosition} {
+ }
+ std::set<parser::Label> labels() { return labels_; }
+ template <typename T> bool Pre(const T &) { return true; }
+ template <typename T> void Post(const T &) {}
+
+ template <typename T> bool Pre(const parser::Statement<T> &statement) {
+ currentStatementSourcePosition_ = statement.source;
+ if (statement.label.has_value()) {
+ labels_.insert(*statement.label);
+ }
+ return true;
+ }
+
+ void Post(const parser::ReturnStmt &) {
+ context_
+ .Say(currentStatementSourcePosition_,
+ "RETURN statement is not allowed in a CHANGE TEAM construct"_err_en_US)
+ .Attach(
+ changeTeamSourcePosition_, "Enclosing CHANGE TEAM construct"_en_US);
+ }
+
+private:
+ SemanticsContext &context_;
+ std::set<parser::Label> labels_;
+ parser::CharBlock currentStatementSourcePosition_;
+ parser::CharBlock changeTeamSourcePosition_;
+};
+
template <typename T>
static void CheckTeamType(SemanticsContext &context, const T &x) {
if (const auto *expr{GetExpr(context, x)}) {
@@ -361,17 +394,29 @@ void CoarrayChecker::Leave(const parser::FormTeamStmt &x) {
void CoarrayChecker::Enter(const parser::CriticalConstruct &x) {
auto &criticalStmt{std::get<parser::Statement<parser::CriticalStmt>>(x.t)};
-
const parser::Block &block{std::get<parser::Block>(x.t)};
CriticalBodyEnforce criticalBodyEnforce{context_, criticalStmt.source};
parser::Walk(block, criticalBodyEnforce);
-
- // C1119
+ parser::Walk(std::get<parser::Statement<parser::EndCriticalStmt>>(x.t),
+ criticalBodyEnforce);
LabelEnforce criticalLabelEnforce{
context_, criticalBodyEnforce.labels(), criticalStmt.source, "CRITICAL"};
parser::Walk(block, criticalLabelEnforce);
}
+void CoarrayChecker::Enter(const parser::ChangeTeamConstruct &x) {
+ auto &changeTeamStmt{
+ std::get<parser::Statement<parser::ChangeTeamStmt>>(x.t)};
+ const parser::Block &block{std::get<parser::Block>(x.t)};
+ ChangeTeamBodyEnforce changeTeamBodyEnforce{context_, changeTeamStmt.source};
+ parser::Walk(block, changeTeamBodyEnforce);
+ parser::Walk(std::get<parser::Statement<parser::EndChangeTeamStmt>>(x.t),
+ changeTeamBodyEnforce);
+ LabelEnforce changeTeamLabelEnforce{context_, changeTeamBodyEnforce.labels(),
+ changeTeamStmt.source, "CHANGE TEAM"};
+ parser::Walk(block, changeTeamLabelEnforce);
+}
+
// Check that coarray names and selector names are all distinct.
void CoarrayChecker::CheckNamesAreDistinct(
const std::list<parser::CoarrayAssociation> &list) {
diff --git a/flang/lib/Semantics/check-coarray.h b/flang/lib/Semantics/check-coarray.h
index a968585b48be7..f156959019383 100644
--- a/flang/lib/Semantics/check-coarray.h
+++ b/flang/lib/Semantics/check-coarray.h
@@ -12,26 +12,6 @@
#include "flang/Semantics/semantics.h"
#include <list>
-namespace Fortran::parser {
-class CharBlock;
-class MessageFixedText;
-struct ChangeTeamStmt;
-struct CriticalStmt;
-struct CoarrayAssociation;
-struct EndChangeTeamStmt;
-struct EventPostStmt;
-struct EventWaitStmt;
-struct FormTeamStmt;
-struct ImageSelector;
-struct NotifyWaitStmt;
-struct SyncAllStmt;
-struct SyncImagesStmt;
-struct SyncMemoryStmt;
-struct SyncTeamStmt;
-struct LockStmt;
-struct UnlockStmt;
-} // namespace Fortran::parser
-
namespace Fortran::semantics {
class CoarrayChecker : public virtual BaseChecker {
@@ -53,6 +33,7 @@ class CoarrayChecker : public virtual BaseChecker {
void Leave(const parser::FormTeamStmt &);
void Enter(const parser::CriticalConstruct &);
+ void Enter(const parser::ChangeTeamConstruct &);
private:
SemanticsContext &context_;
diff --git a/flang/test/Semantics/change_team02.f90 b/flang/test/Semantics/change_team02.f90
new file mode 100644
index 0000000000000..a4cba3639f27b
--- /dev/null
+++ b/flang/test/Semantics/change_team02.f90
@@ -0,0 +1,24 @@
+! RUN: %python %S/test_errors.py %s %flang_fc1
+subroutine test
+ use, intrinsic :: iso_fortran_env, only: team_type
+ type(team_type) team
+loop1: do j = 1, 1
+ goto 1 ! ok
+1 construct2: change team (team)
+ goto 2 ! ok
+ exit construct2 ! ok
+ !ERROR: EXIT must not leave a CHANGE TEAM statement
+ exit loop1
+ !ERROR: EXIT must not leave a CHANGE TEAM statement
+ exit
+ !ERROR: CYCLE must not leave a CHANGE TEAM statement
+ cycle
+ !ERROR: RETURN statement is not allowed in a CHANGE TEAM construct
+ return
+ !ERROR: Control flow escapes from CHANGE TEAM
+ goto 3
+ !ERROR: Control flow escapes from CHANGE TEAM
+ write(*,*,err=3)
+2 end team construct2
+3 end do loop1
+end
``````````
</details>
https://github.com/llvm/llvm-project/pull/131013
More information about the flang-commits
mailing list