Skip to content
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

Merged
merged 1 commit into from
Dec 11, 2023

Conversation

klausler
Copy link
Contributor

@klausler klausler commented Dec 1, 2023

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.

@llvmbot llvmbot added flang Flang issues not falling into any other category flang:semantics labels Dec 1, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Dec 1, 2023

@llvm/pr-subscribers-flang-runtime

@llvm/pr-subscribers-flang-semantics

Author: Peter Klausler (klausler)

Changes

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.


Full diff: https://github.com/llvm/llvm-project/pull/74158.diff

3 Files Affected:

  • (modified) flang/lib/Semantics/definable.cpp (+12-2)
  • (modified) flang/test/Semantics/definable01.f90 (+10-1)
  • (modified) flang/test/Semantics/select-rank03.f90 (+4-4)
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

Copy link
Contributor

@clementval clementval left a comment

Choose a reason for hiding this comment

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

LGTM

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.
@klausler klausler merged commit f58f089 into llvm:main Dec 11, 2023
4 checks passed
@klausler klausler deleted the bug1356 branch December 11, 2023 20:04
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
flang:runtime flang:semantics flang Flang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants