Skip to content

Commit 07b3bba

Browse files
authored
[flang] Allow LOCK_TYPE & al. to associate with INTENT(IN OUT) (#121413)
We're emitting a bogus semantic error message about an actual argument being undefinable when associating LOCK_TYPE, EVENT_TYPE, and someday NOTIFY_TYPE with an INTENT(IN OUT) dummy argument. These types indeed make many definition contexts invalid, and the actual argument associated with an INTENT(IN OUT) dummy argument must indeed be definable, but the argument association itself is not a problem.
1 parent 9496391 commit 07b3bba

File tree

5 files changed

+42
-14
lines changed

5 files changed

+42
-14
lines changed

flang/lib/Semantics/assignment.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -66,8 +66,13 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
6666
const SomeExpr &rhs{assignment->rhs};
6767
auto lhsLoc{std::get<parser::Variable>(stmt.t).GetSource()};
6868
const Scope &scope{context_.FindScope(lhsLoc)};
69-
if (auto whyNot{WhyNotDefinable(lhsLoc, scope,
70-
DefinabilityFlags{DefinabilityFlag::VectorSubscriptIsOk}, lhs)}) {
69+
DefinabilityFlags flags{DefinabilityFlag::VectorSubscriptIsOk};
70+
bool isDefinedAssignment{
71+
std::holds_alternative<evaluate::ProcedureRef>(assignment->u)};
72+
if (isDefinedAssignment) {
73+
flags.set(DefinabilityFlag::AllowEventLockOrNotifyType);
74+
}
75+
if (auto whyNot{WhyNotDefinable(lhsLoc, scope, flags, lhs)}) {
7176
if (whyNot->IsFatal()) {
7277
if (auto *msg{Say(lhsLoc,
7378
"Left-hand side of assignment is not definable"_err_en_US)}) {
@@ -79,9 +84,7 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
7984
}
8085
}
8186
auto rhsLoc{std::get<parser::Expr>(stmt.t).source};
82-
if (std::holds_alternative<evaluate::ProcedureRef>(assignment->u)) {
83-
// it's a defined ASSIGNMENT(=)
84-
} else {
87+
if (!isDefinedAssignment) {
8588
CheckForPureContext(rhs, rhsLoc);
8689
}
8790
if (whereDepth_ > 0) {

flang/lib/Semantics/check-call.cpp

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -703,12 +703,14 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
703703
// Problems with polymorphism are caught in the callee's definition.
704704
if (scope) {
705705
std::optional<parser::MessageFixedText> undefinableMessage;
706-
if (dummy.intent == common::Intent::Out) {
707-
undefinableMessage =
708-
"Actual argument associated with INTENT(OUT) %s is not definable"_err_en_US;
709-
} else if (dummy.intent == common::Intent::InOut) {
706+
DefinabilityFlags flags{DefinabilityFlag::PolymorphicOkInPure};
707+
if (dummy.intent == common::Intent::InOut) {
708+
flags.set(DefinabilityFlag::AllowEventLockOrNotifyType);
710709
undefinableMessage =
711710
"Actual argument associated with INTENT(IN OUT) %s is not definable"_err_en_US;
711+
} else if (dummy.intent == common::Intent::Out) {
712+
undefinableMessage =
713+
"Actual argument associated with INTENT(OUT) %s is not definable"_err_en_US;
712714
} else if (context.ShouldWarn(common::LanguageFeature::
713715
UndefinableAsynchronousOrVolatileActual)) {
714716
if (dummy.attrs.test(
@@ -722,7 +724,6 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
722724
}
723725
}
724726
if (undefinableMessage) {
725-
DefinabilityFlags flags{DefinabilityFlag::PolymorphicOkInPure};
726727
if (isElemental) { // 15.5.2.4(21)
727728
flags.set(DefinabilityFlag::VectorSubscriptIsOk);
728729
}

flang/lib/Semantics/definable.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,8 @@ static std::optional<parser::Message> WhyNotDefinableLast(parser::CharBlock at,
204204
}
205205
return std::nullopt; // pointer assignment - skip following checks
206206
}
207-
if (IsOrContainsEventOrLockComponent(ultimate)) {
207+
if (!flags.test(DefinabilityFlag::AllowEventLockOrNotifyType) &&
208+
IsOrContainsEventOrLockComponent(ultimate)) {
208209
return BlameSymbol(at,
209210
"'%s' is an entity with either an EVENT_TYPE or LOCK_TYPE"_en_US,
210211
original);

flang/lib/Semantics/definable.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ ENUM_CLASS(DefinabilityFlag,
3232
AcceptAllocatable, // treat allocatable as if it were a pointer
3333
SourcedAllocation, // ALLOCATE(a,SOURCE=)
3434
PolymorphicOkInPure, // don't check for polymorphic type in pure subprogram
35-
DoNotNoteDefinition) // context does not imply definition
35+
DoNotNoteDefinition, // context does not imply definition
36+
AllowEventLockOrNotifyType)
3637

3738
using DefinabilityFlags =
3839
common::EnumSet<DefinabilityFlag, DefinabilityFlag_enumSize>;

flang/test/Semantics/definable01.f90

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,29 @@ pure function test6(lp)
109109
end
110110
pure subroutine test7(lp)
111111
type(list), pointer :: lp
112-
!CHECK-NOT: error:
113-
lp%next%next => null()
112+
lp%next%next => null() ! ok
114113
end
115114
end module
115+
program main
116+
use iso_fortran_env, only: lock_type
117+
type(lock_type) lock
118+
interface
119+
subroutine inlock(lock)
120+
import lock_type
121+
type(lock_type), intent(in) :: lock
122+
end
123+
subroutine outlock(lock)
124+
import lock_type
125+
!CHECK: error: An INTENT(OUT) dummy argument may not be, or contain, EVENT_TYPE or LOCK_TYPE
126+
type(lock_type), intent(out) :: lock
127+
end
128+
subroutine inoutlock(lock)
129+
import lock_type
130+
type(lock_type), intent(in out) :: lock
131+
end
132+
end interface
133+
call inlock(lock) ! ok
134+
call inoutlock(lock) ! ok
135+
!CHECK: error: Actual argument associated with INTENT(OUT) dummy argument 'lock=' is not definable
136+
call outlock(lock)
137+
end

0 commit comments

Comments
 (0)