Skip to content

Commit 1dc397d

Browse files
authored
[flang] Enforce control flow restrictions on CHANGE TEAM (#131013)
Like DO CONCURRENT and CRITICAL constructs, control flow into and out of a CHANGE TEAM construct is disallowed.
1 parent abebac5 commit 1dc397d

File tree

3 files changed

+73
-23
lines changed

3 files changed

+73
-23
lines changed

flang/lib/Semantics/check-coarray.cpp

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,39 @@ class CriticalBodyEnforce {
6363
parser::CharBlock criticalSourcePosition_;
6464
};
6565

66+
class ChangeTeamBodyEnforce {
67+
public:
68+
ChangeTeamBodyEnforce(
69+
SemanticsContext &context, parser::CharBlock changeTeamSourcePosition)
70+
: context_{context}, changeTeamSourcePosition_{changeTeamSourcePosition} {
71+
}
72+
std::set<parser::Label> labels() { return labels_; }
73+
template <typename T> bool Pre(const T &) { return true; }
74+
template <typename T> void Post(const T &) {}
75+
76+
template <typename T> bool Pre(const parser::Statement<T> &statement) {
77+
currentStatementSourcePosition_ = statement.source;
78+
if (statement.label.has_value()) {
79+
labels_.insert(*statement.label);
80+
}
81+
return true;
82+
}
83+
84+
void Post(const parser::ReturnStmt &) {
85+
context_
86+
.Say(currentStatementSourcePosition_,
87+
"RETURN statement is not allowed in a CHANGE TEAM construct"_err_en_US)
88+
.Attach(
89+
changeTeamSourcePosition_, "Enclosing CHANGE TEAM construct"_en_US);
90+
}
91+
92+
private:
93+
SemanticsContext &context_;
94+
std::set<parser::Label> labels_;
95+
parser::CharBlock currentStatementSourcePosition_;
96+
parser::CharBlock changeTeamSourcePosition_;
97+
};
98+
6699
template <typename T>
67100
static void CheckTeamType(SemanticsContext &context, const T &x) {
68101
if (const auto *expr{GetExpr(context, x)}) {
@@ -361,17 +394,29 @@ void CoarrayChecker::Leave(const parser::FormTeamStmt &x) {
361394

362395
void CoarrayChecker::Enter(const parser::CriticalConstruct &x) {
363396
auto &criticalStmt{std::get<parser::Statement<parser::CriticalStmt>>(x.t)};
364-
365397
const parser::Block &block{std::get<parser::Block>(x.t)};
366398
CriticalBodyEnforce criticalBodyEnforce{context_, criticalStmt.source};
367399
parser::Walk(block, criticalBodyEnforce);
368-
369-
// C1119
400+
parser::Walk(std::get<parser::Statement<parser::EndCriticalStmt>>(x.t),
401+
criticalBodyEnforce);
370402
LabelEnforce criticalLabelEnforce{
371403
context_, criticalBodyEnforce.labels(), criticalStmt.source, "CRITICAL"};
372404
parser::Walk(block, criticalLabelEnforce);
373405
}
374406

407+
void CoarrayChecker::Enter(const parser::ChangeTeamConstruct &x) {
408+
auto &changeTeamStmt{
409+
std::get<parser::Statement<parser::ChangeTeamStmt>>(x.t)};
410+
const parser::Block &block{std::get<parser::Block>(x.t)};
411+
ChangeTeamBodyEnforce changeTeamBodyEnforce{context_, changeTeamStmt.source};
412+
parser::Walk(block, changeTeamBodyEnforce);
413+
parser::Walk(std::get<parser::Statement<parser::EndChangeTeamStmt>>(x.t),
414+
changeTeamBodyEnforce);
415+
LabelEnforce changeTeamLabelEnforce{context_, changeTeamBodyEnforce.labels(),
416+
changeTeamStmt.source, "CHANGE TEAM"};
417+
parser::Walk(block, changeTeamLabelEnforce);
418+
}
419+
375420
// Check that coarray names and selector names are all distinct.
376421
void CoarrayChecker::CheckNamesAreDistinct(
377422
const std::list<parser::CoarrayAssociation> &list) {

flang/lib/Semantics/check-coarray.h

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,6 @@
1212
#include "flang/Semantics/semantics.h"
1313
#include <list>
1414

15-
namespace Fortran::parser {
16-
class CharBlock;
17-
class MessageFixedText;
18-
struct ChangeTeamStmt;
19-
struct CriticalStmt;
20-
struct CoarrayAssociation;
21-
struct EndChangeTeamStmt;
22-
struct EventPostStmt;
23-
struct EventWaitStmt;
24-
struct FormTeamStmt;
25-
struct ImageSelector;
26-
struct NotifyWaitStmt;
27-
struct SyncAllStmt;
28-
struct SyncImagesStmt;
29-
struct SyncMemoryStmt;
30-
struct SyncTeamStmt;
31-
struct LockStmt;
32-
struct UnlockStmt;
33-
} // namespace Fortran::parser
34-
3515
namespace Fortran::semantics {
3616

3717
class CoarrayChecker : public virtual BaseChecker {
@@ -53,6 +33,7 @@ class CoarrayChecker : public virtual BaseChecker {
5333
void Leave(const parser::FormTeamStmt &);
5434

5535
void Enter(const parser::CriticalConstruct &);
36+
void Enter(const parser::ChangeTeamConstruct &);
5637

5738
private:
5839
SemanticsContext &context_;
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
! RUN: %python %S/test_errors.py %s %flang_fc1
2+
subroutine test
3+
use, intrinsic :: iso_fortran_env, only: team_type
4+
type(team_type) team
5+
loop1: do j = 1, 1
6+
goto 1 ! ok
7+
1 construct2: change team (team)
8+
goto 2 ! ok
9+
exit construct2 ! ok
10+
!ERROR: EXIT must not leave a CHANGE TEAM statement
11+
exit loop1
12+
!ERROR: EXIT must not leave a CHANGE TEAM statement
13+
exit
14+
!ERROR: CYCLE must not leave a CHANGE TEAM statement
15+
cycle
16+
!ERROR: RETURN statement is not allowed in a CHANGE TEAM construct
17+
return
18+
!ERROR: Control flow escapes from CHANGE TEAM
19+
goto 3
20+
!ERROR: Control flow escapes from CHANGE TEAM
21+
write(*,*,err=3)
22+
2 end team construct2
23+
3 end do loop1
24+
end

0 commit comments

Comments
 (0)