-
Notifications
You must be signed in to change notification settings - Fork 10.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[flang] Correct definability checking for INTENT(IN) pointers #74158
Conversation
@llvm/pr-subscribers-flang-runtime @llvm/pr-subscribers-flang-semantics Author: Peter Klausler (klausler) ChangesAn INTENT(IN) attribute on a pointer dummy argument prevents modification of the pointer itself only, not modification of any component of its target. Fix this case without breaking definability checking for pointer components of non-pointer INTENT(IN) dummy arguments. Full diff: https://github.com/llvm/llvm-project/pull/74158.diff 3 Files Affected:
diff --git a/flang/lib/Semantics/definable.cpp b/flang/lib/Semantics/definable.cpp
index d5ffcabc7233ca9..270fecdcc30ab34 100644
--- a/flang/lib/Semantics/definable.cpp
+++ b/flang/lib/Semantics/definable.cpp
@@ -112,7 +112,8 @@ static std::optional<parser::Message> WhyNotDefinableBase(parser::CharBlock at,
return BlameSymbol(at, "'%s' is not a variable"_en_US, original);
} else if (IsProtected(ultimate) && IsUseAssociated(original, scope)) {
return BlameSymbol(at, "'%s' is protected in this scope"_en_US, original);
- } else if (IsIntentIn(ultimate)) {
+ } else if (IsIntentIn(ultimate) && !isPointerDefinition &&
+ !IsPointer(ultimate)) {
return BlameSymbol(
at, "'%s' is an INTENT(IN) dummy argument"_en_US, original);
}
@@ -165,8 +166,17 @@ static std::optional<parser::Message> WhyNotDefinableBase(parser::CharBlock at,
static std::optional<parser::Message> WhyNotDefinableLast(parser::CharBlock at,
const Scope &scope, DefinabilityFlags flags, const Symbol &original) {
const Symbol &ultimate{original.GetUltimate()};
+ if (const auto *association{ultimate.detailsIf<AssocEntityDetails>()}) {
+ if (auto dataRef{
+ evaluate::ExtractDataRef(*association->expr(), true, true)}) {
+ return WhyNotDefinableLast(at, scope, flags, dataRef->GetLastSymbol());
+ }
+ }
if (flags.test(DefinabilityFlag::PointerDefinition)) {
- if (flags.test(DefinabilityFlag::AcceptAllocatable)) {
+ if (IsIntentIn(ultimate)) {
+ return BlameSymbol(
+ at, "'%s' is an INTENT(IN) pointer dummy argument"_en_US, original);
+ } else if (flags.test(DefinabilityFlag::AcceptAllocatable)) {
if (!IsAllocatableOrObjectPointer(&ultimate)) {
return BlameSymbol(
at, "'%s' is neither a pointer nor an allocatable"_en_US, original);
diff --git a/flang/test/Semantics/definable01.f90 b/flang/test/Semantics/definable01.f90
index fff493fe7a4152f..f3975571f7ffcac 100644
--- a/flang/test/Semantics/definable01.f90
+++ b/flang/test/Semantics/definable01.f90
@@ -71,7 +71,7 @@ subroutine test3(objp, procp)
real, intent(in), pointer :: objp
procedure(sin), pointer, intent(in) :: procp
!CHECK: error: Actual argument associated with INTENT(IN OUT) dummy argument 'op=' is not definable
- !CHECK: because: 'objp' is an INTENT(IN) dummy argument
+ !CHECK: because: 'objp' is an INTENT(IN) pointer dummy argument
call test3a(objp)
!CHECK: error: Actual argument associated with procedure pointer dummy argument 'pp=' may not be INTENT(IN)
call test3b(procp)
@@ -82,4 +82,13 @@ subroutine test3a(op)
subroutine test3b(pp)
procedure(sin), pointer, intent(in out) :: pp
end subroutine
+ subroutine test4(p)
+ type(ptype), pointer, intent(in) :: p
+ p%x = 1.
+ p%ptr = 1. ! ok
+ nullify(p%ptr) ! ok
+ !CHECK: error: 'p' may not appear in NULLIFY
+ !CHECK: because: 'p' is an INTENT(IN) pointer dummy argument
+ nullify(p)
+ end
end module
diff --git a/flang/test/Semantics/select-rank03.f90 b/flang/test/Semantics/select-rank03.f90
index 8a965e950d38513..7716659ef172dfd 100644
--- a/flang/test/Semantics/select-rank03.f90
+++ b/flang/test/Semantics/select-rank03.f90
@@ -136,20 +136,20 @@ subroutine undefinable(p)
select rank(p)
rank (0)
!ERROR: The left-hand side of a pointer assignment is not definable
- !BECAUSE: 'p' is an INTENT(IN) dummy argument
+ !BECAUSE: 'p' is an INTENT(IN) pointer dummy argument
p => t
!ERROR: Name in DEALLOCATE statement is not definable
- !BECAUSE: 'p' is an INTENT(IN) dummy argument
+ !BECAUSE: 'p' is an INTENT(IN) pointer dummy argument
deallocate(p)
!ERROR: RANK (*) cannot be used when selector is POINTER or ALLOCATABLE
rank (*)
!ERROR: Whole assumed-size array 'p' may not appear here without subscripts
!ERROR: Name in DEALLOCATE statement is not definable
- !BECAUSE: 'p' is an INTENT(IN) dummy argument
+ !BECAUSE: 'p' is an INTENT(IN) pointer dummy argument
deallocate(p)
rank default
!ERROR: Name in DEALLOCATE statement is not definable
- !BECAUSE: 'p' is an INTENT(IN) dummy argument
+ !BECAUSE: 'p' is an INTENT(IN) pointer dummy argument
deallocate(p)
end select
end
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
21018e4
to
0539350
Compare
An INTENT(IN) attribute on a pointer dummy argument prevents modification of the pointer itself only, not modification of any component of its target. Fix this case without breaking definability checking for pointer components of non-pointer INTENT(IN) dummy arguments.
An INTENT(IN) attribute on a pointer dummy argument prevents modification of the pointer itself only, not modification of any component of its target. Fix this case without breaking definability checking for pointer components of non-pointer INTENT(IN) dummy arguments.