Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 8 additions & 5 deletions flang/lib/Semantics/assignment.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,13 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
const SomeExpr &rhs{assignment->rhs};
auto lhsLoc{std::get<parser::Variable>(stmt.t).GetSource()};
const Scope &scope{context_.FindScope(lhsLoc)};
if (auto whyNot{WhyNotDefinable(lhsLoc, scope,
DefinabilityFlags{DefinabilityFlag::VectorSubscriptIsOk}, lhs)}) {
DefinabilityFlags flags{DefinabilityFlag::VectorSubscriptIsOk};
bool isDefinedAssignment{
std::holds_alternative<evaluate::ProcedureRef>(assignment->u)};
if (isDefinedAssignment) {
flags.set(DefinabilityFlag::AllowEventLockOrNotifyType);
}
if (auto whyNot{WhyNotDefinable(lhsLoc, scope, flags, lhs)}) {
if (whyNot->IsFatal()) {
if (auto *msg{Say(lhsLoc,
"Left-hand side of assignment is not definable"_err_en_US)}) {
Expand All @@ -79,9 +84,7 @@ void AssignmentContext::Analyze(const parser::AssignmentStmt &stmt) {
}
}
auto rhsLoc{std::get<parser::Expr>(stmt.t).source};
if (std::holds_alternative<evaluate::ProcedureRef>(assignment->u)) {
// it's a defined ASSIGNMENT(=)
} else {
if (!isDefinedAssignment) {
CheckForPureContext(rhs, rhsLoc);
}
if (whereDepth_ > 0) {
Expand Down
11 changes: 6 additions & 5 deletions flang/lib/Semantics/check-call.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -703,12 +703,14 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
// Problems with polymorphism are caught in the callee's definition.
if (scope) {
std::optional<parser::MessageFixedText> undefinableMessage;
if (dummy.intent == common::Intent::Out) {
undefinableMessage =
"Actual argument associated with INTENT(OUT) %s is not definable"_err_en_US;
} else if (dummy.intent == common::Intent::InOut) {
DefinabilityFlags flags{DefinabilityFlag::PolymorphicOkInPure};
if (dummy.intent == common::Intent::InOut) {
flags.set(DefinabilityFlag::AllowEventLockOrNotifyType);
undefinableMessage =
"Actual argument associated with INTENT(IN OUT) %s is not definable"_err_en_US;
} else if (dummy.intent == common::Intent::Out) {
undefinableMessage =
"Actual argument associated with INTENT(OUT) %s is not definable"_err_en_US;
} else if (context.ShouldWarn(common::LanguageFeature::
UndefinableAsynchronousOrVolatileActual)) {
if (dummy.attrs.test(
Expand All @@ -722,7 +724,6 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
}
}
if (undefinableMessage) {
DefinabilityFlags flags{DefinabilityFlag::PolymorphicOkInPure};
if (isElemental) { // 15.5.2.4(21)
flags.set(DefinabilityFlag::VectorSubscriptIsOk);
}
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Semantics/definable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ static std::optional<parser::Message> WhyNotDefinableLast(parser::CharBlock at,
}
return std::nullopt; // pointer assignment - skip following checks
}
if (IsOrContainsEventOrLockComponent(ultimate)) {
if (!flags.test(DefinabilityFlag::AllowEventLockOrNotifyType) &&
IsOrContainsEventOrLockComponent(ultimate)) {
return BlameSymbol(at,
"'%s' is an entity with either an EVENT_TYPE or LOCK_TYPE"_en_US,
original);
Expand Down
3 changes: 2 additions & 1 deletion flang/lib/Semantics/definable.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ ENUM_CLASS(DefinabilityFlag,
AcceptAllocatable, // treat allocatable as if it were a pointer
SourcedAllocation, // ALLOCATE(a,SOURCE=)
PolymorphicOkInPure, // don't check for polymorphic type in pure subprogram
DoNotNoteDefinition) // context does not imply definition
DoNotNoteDefinition, // context does not imply definition
AllowEventLockOrNotifyType)

using DefinabilityFlags =
common::EnumSet<DefinabilityFlag, DefinabilityFlag_enumSize>;
Expand Down
26 changes: 24 additions & 2 deletions flang/test/Semantics/definable01.f90
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,29 @@ pure function test6(lp)
end
pure subroutine test7(lp)
type(list), pointer :: lp
!CHECK-NOT: error:
lp%next%next => null()
lp%next%next => null() ! ok
end
end module
program main
use iso_fortran_env, only: lock_type
type(lock_type) lock
interface
subroutine inlock(lock)
import lock_type
type(lock_type), intent(in) :: lock
end
subroutine outlock(lock)
import lock_type
!CHECK: error: An INTENT(OUT) dummy argument may not be, or contain, EVENT_TYPE or LOCK_TYPE
type(lock_type), intent(out) :: lock
end
subroutine inoutlock(lock)
import lock_type
type(lock_type), intent(in out) :: lock
Copy link
Contributor

@eugeneepshteyn eugeneepshteyn Jan 3, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should there also be a negative test for type(lock_type) passed as intent(in) and intent(out)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, will do.

end
end interface
call inlock(lock) ! ok
call inoutlock(lock) ! ok
!CHECK: error: Actual argument associated with INTENT(OUT) dummy argument 'lock=' is not definable
call outlock(lock)
end
Loading