Skip to content

Commit 8c53566

Browse files
authored
[flang] Semantic checking of LOCK statement (#129806)
Add checks for the LOCK statement, and complete and enable their tests.
1 parent 33b061f commit 8c53566

File tree

3 files changed

+108
-42
lines changed

3 files changed

+108
-42
lines changed

flang/lib/Semantics/check-coarray.cpp

Lines changed: 72 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
//===----------------------------------------------------------------------===//
88

99
#include "check-coarray.h"
10+
#include "definable.h"
1011
#include "flang/Common/indirection.h"
1112
#include "flang/Evaluate/expression.h"
1213
#include "flang/Parser/message.h"
@@ -96,34 +97,37 @@ static void CheckCoindexedStatOrErrmsg(SemanticsContext &context,
9697
Fortran::common::visit(CoindexedCheck, statOrErrmsg.u);
9798
}
9899

100+
static void CheckSyncStat(SemanticsContext &context,
101+
const parser::StatOrErrmsg &statOrErrmsg, bool &gotStat, bool &gotMsg) {
102+
common::visit(
103+
common::visitors{
104+
[&](const parser::StatVariable &stat) {
105+
if (gotStat) {
106+
context.Say( // C1172
107+
"The stat-variable in a sync-stat-list may not be repeated"_err_en_US);
108+
}
109+
gotStat = true;
110+
},
111+
[&](const parser::MsgVariable &var) {
112+
WarnOnDeferredLengthCharacterScalar(context, GetExpr(context, var),
113+
var.v.thing.thing.GetSource(), "ERRMSG=");
114+
if (gotMsg) {
115+
context.Say( // C1172
116+
"The errmsg-variable in a sync-stat-list may not be repeated"_err_en_US);
117+
}
118+
gotMsg = true;
119+
},
120+
},
121+
statOrErrmsg.u);
122+
123+
CheckCoindexedStatOrErrmsg(context, statOrErrmsg, "sync-stat-list");
124+
}
125+
99126
static void CheckSyncStatList(
100127
SemanticsContext &context, const std::list<parser::StatOrErrmsg> &list) {
101128
bool gotStat{false}, gotMsg{false};
102-
103129
for (const parser::StatOrErrmsg &statOrErrmsg : list) {
104-
common::visit(
105-
common::visitors{
106-
[&](const parser::StatVariable &stat) {
107-
if (gotStat) {
108-
context.Say( // C1172
109-
"The stat-variable in a sync-stat-list may not be repeated"_err_en_US);
110-
}
111-
gotStat = true;
112-
},
113-
[&](const parser::MsgVariable &var) {
114-
WarnOnDeferredLengthCharacterScalar(context,
115-
GetExpr(context, var), var.v.thing.thing.GetSource(),
116-
"ERRMSG=");
117-
if (gotMsg) {
118-
context.Say( // C1172
119-
"The errmsg-variable in a sync-stat-list may not be repeated"_err_en_US);
120-
}
121-
gotMsg = true;
122-
},
123-
},
124-
statOrErrmsg.u);
125-
126-
CheckCoindexedStatOrErrmsg(context, statOrErrmsg, "sync-stat-list");
130+
CheckSyncStat(context, statOrErrmsg, gotStat, gotMsg);
127131
}
128132
}
129133

@@ -260,7 +264,51 @@ void CoarrayChecker::Leave(const parser::EventWaitStmt &x) {
260264
context_, std::get<std::list<parser::EventWaitSpec>>(x.t));
261265
}
262266

267+
static void CheckLockVariable(
268+
SemanticsContext &context, const parser::LockVariable &lockVar) {
269+
if (const SomeExpr * expr{GetExpr(lockVar)}) {
270+
if (auto dyType{expr->GetType()}) {
271+
auto at{parser::FindSourceLocation(lockVar)};
272+
if (dyType->category() != TypeCategory::Derived ||
273+
dyType->IsUnlimitedPolymorphic() ||
274+
!IsLockType(&dyType->GetDerivedTypeSpec())) {
275+
context.Say(at,
276+
"Lock variable must have type LOCK_TYPE from ISO_FORTRAN_ENV"_err_en_US);
277+
} else if (auto whyNot{WhyNotDefinable(at, context.FindScope(at),
278+
{DefinabilityFlag::DoNotNoteDefinition,
279+
DefinabilityFlag::AllowEventLockOrNotifyType},
280+
*expr)}) {
281+
whyNot->set_severity(parser::Severity::Because);
282+
context.Say(at, "Lock variable is not definable"_err_en_US)
283+
.Attach(std::move(*whyNot));
284+
}
285+
}
286+
}
287+
}
288+
289+
void CoarrayChecker::Leave(const parser::LockStmt &x) {
290+
CheckLockVariable(context_, std::get<parser::LockVariable>(x.t));
291+
bool gotAcquired{false}, gotStat{false}, gotMsg{false};
292+
for (const parser::LockStmt::LockStat &lockStat :
293+
std::get<std::list<parser::LockStmt::LockStat>>(x.t)) {
294+
if (const auto *statOrErrmsg{
295+
std::get_if<parser::StatOrErrmsg>(&lockStat.u)}) {
296+
CheckSyncStat(context_, *statOrErrmsg, gotStat, gotMsg);
297+
} else {
298+
CHECK(std::holds_alternative<
299+
parser::Scalar<parser::Logical<parser::Variable>>>(lockStat.u));
300+
if (gotAcquired) {
301+
context_.Say(parser::FindSourceLocation(lockStat),
302+
"Multiple ACQUIRED_LOCK specifiers"_err_en_US);
303+
} else {
304+
gotAcquired = true;
305+
}
306+
}
307+
}
308+
}
309+
263310
void CoarrayChecker::Leave(const parser::UnlockStmt &x) {
311+
CheckLockVariable(context_, std::get<parser::LockVariable>(x.t));
264312
CheckSyncStatList(context_, std::get<std::list<parser::StatOrErrmsg>>(x.t));
265313
}
266314

flang/lib/Semantics/check-coarray.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ struct SyncAllStmt;
2828
struct SyncImagesStmt;
2929
struct SyncMemoryStmt;
3030
struct SyncTeamStmt;
31+
struct LockStmt;
3132
struct UnlockStmt;
3233
} // namespace Fortran::parser
3334

@@ -45,6 +46,7 @@ class CoarrayChecker : public virtual BaseChecker {
4546
void Leave(const parser::NotifyWaitStmt &);
4647
void Leave(const parser::EventPostStmt &);
4748
void Leave(const parser::EventWaitStmt &);
49+
void Leave(const parser::LockStmt &);
4850
void Leave(const parser::UnlockStmt &);
4951
void Leave(const parser::CriticalStmt &);
5052
void Leave(const parser::ImageSelector &);

flang/test/Semantics/lockstmt03.f90

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
! RUN: %python %S/test_errors.py %s %flang_fc1
2-
! XFAIL: *
32
! This test checks for semantic errors in lock statements based on the
43
! statement specification in section 11.6.10 of the Fortran 2018 standard.
54

@@ -10,14 +9,16 @@ program test_lock_stmt
109
character(len=128) error_message, msg_array(10), coindexed_msg[*], repeated_msg
1110
integer status, stat_array(10), coindexed_int[*], non_bool, repeated_stat
1211
logical non_integer, bool, bool_array(10), non_char, coindexed_logical[*], repeated_bool
13-
type(lock_type) :: lock_var[*], lock_array(10)[*], non_coarray_lock
12+
type(lock_type) :: lock_var[*], lock_array(10)[*]
13+
!ERROR: Variable 'non_coarray_lock' with EVENT_TYPE or LOCK_TYPE must be a coarray
14+
type(lock_type) :: non_coarray_lock
1415
type(event_type) :: not_lock_var[*]
1516

1617
!___ non-standard-conforming statements ___
1718

1819
! type mismatches
1920

20-
!ERROR: to be determined
21+
!ERROR: Lock variable must have type LOCK_TYPE from ISO_FORTRAN_ENV
2122
lock(not_lock_var)
2223

2324
!ERROR: Must have LOGICAL type, but is INTEGER(4)
@@ -45,50 +46,65 @@ program test_lock_stmt
4546

4647
! corank mismatch
4748

48-
!ERROR: to be determined
49-
lock(non_coarray_lock)
49+
lock(non_coarray_lock) ! caught above
5050

5151
! C1173 - stat-variable and errmsg-variable shall not be a coindexed object
5252

53-
!ERROR: to be determined
53+
!ERROR: The stat-variable or errmsg-variable in a sync-stat-list may not be a coindexed object
5454
lock(lock_var, stat=coindexed_int[1])
5555

56-
!ERROR: to be determined
56+
!ERROR: The stat-variable or errmsg-variable in a sync-stat-list may not be a coindexed object
5757
lock(lock_var, errmsg=coindexed_msg[1])
5858

59-
!ERROR: to be determined
59+
!ERROR: The stat-variable or errmsg-variable in a sync-stat-list may not be a coindexed object
60+
!ERROR: The stat-variable or errmsg-variable in a sync-stat-list may not be a coindexed object
6061
lock(lock_var, acquired_lock=coindexed_logical[1], stat=coindexed_int[1], errmsg=coindexed_msg[1])
6162

6263
! C1181 - No specifier shall appear more than once in a given lock-stat-list
6364

64-
!ERROR: to be determined
65+
!ERROR: Multiple ACQUIRED_LOCK specifiers
6566
lock(lock_var, acquired_lock=bool, acquired_lock=repeated_bool)
6667

67-
!ERROR: to be determined
68+
!ERROR: The stat-variable in a sync-stat-list may not be repeated
6869
lock(lock_var, stat=status, stat=repeated_stat)
6970

70-
!ERROR: to be determined
71+
!ERROR: The errmsg-variable in a sync-stat-list may not be repeated
7172
lock(lock_var, errmsg=error_message, errmsg=repeated_msg)
7273

73-
!ERROR: to be determined
74+
!ERROR: Multiple ACQUIRED_LOCK specifiers
7475
lock(lock_var, acquired_lock=bool, stat=status, errmsg=error_message, acquired_lock=repeated_bool)
7576

76-
!ERROR: to be determined
77+
!ERROR: The stat-variable in a sync-stat-list may not be repeated
7778
lock(lock_var, acquired_lock=bool, stat=status, errmsg=error_message, stat=repeated_stat)
7879

79-
!ERROR: to be determined
80+
!ERROR: The errmsg-variable in a sync-stat-list may not be repeated
8081
lock(lock_var, acquired_lock=bool, stat=status, errmsg=error_message, errmsg=repeated_msg)
8182

82-
!ERROR: to be determined
83+
!ERROR: The stat-variable in a sync-stat-list may not be repeated
84+
!ERROR: Multiple ACQUIRED_LOCK specifiers
8385
lock(lock_var, acquired_lock=bool, stat=status, errmsg=error_message, acquired_lock=repeated_bool, stat=repeated_stat)
8486

85-
!ERROR: to be determined
87+
!ERROR: The errmsg-variable in a sync-stat-list may not be repeated
88+
!ERROR: Multiple ACQUIRED_LOCK specifiers
8689
lock(lock_var, acquired_lock=bool, stat=status, errmsg=error_message, acquired_lock=repeated_bool, errmsg=repeated_msg)
8790

88-
!ERROR: to be determined
91+
!ERROR: The stat-variable in a sync-stat-list may not be repeated
92+
!ERROR: The errmsg-variable in a sync-stat-list may not be repeated
8993
lock(lock_var, acquired_lock=bool, stat=status, errmsg=error_message, stat=repeated_stat, errmsg=repeated_msg)
9094

91-
!ERROR: to be determined
95+
!ERROR: The stat-variable in a sync-stat-list may not be repeated
96+
!ERROR: The errmsg-variable in a sync-stat-list may not be repeated
97+
!ERROR: Multiple ACQUIRED_LOCK specifiers
9298
lock(lock_var, acquired_lock=bool, stat=status, errmsg=error_message, acquired_lock=repeated_bool, stat=repeated_stat, errmsg=repeated_msg)
9399

100+
contains
101+
subroutine lockit(x)
102+
type(lock_type), intent(in) :: x[*]
103+
!ERROR: Lock variable is not definable
104+
!BECAUSE: 'x' is an INTENT(IN) dummy argument
105+
lock(x)
106+
!ERROR: Lock variable is not definable
107+
!BECAUSE: 'x' is an INTENT(IN) dummy argument
108+
unlock(x)
109+
end
94110
end program test_lock_stmt

0 commit comments

Comments
 (0)