[flang-commits] [flang] [flang] Correct definability checking for INTENT(IN) pointers (PR #74158)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Fri Dec 1 15:34:36 PST 2023


https://github.com/klausler created https://github.com/llvm/llvm-project/pull/74158

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.

>From aa35454a3d186ffa01fe9958bdf6bef7de2488b3 Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Fri, 1 Dec 2023 15:29:52 -0800
Subject: [PATCH] [flang] Correct definability checking for INTENT(IN) pointers

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.
---
 flang/lib/Semantics/definable.cpp      | 14 ++++++++++++--
 flang/test/Semantics/definable01.f90   | 11 ++++++++++-
 flang/test/Semantics/select-rank03.f90 |  8 ++++----
 3 files changed, 26 insertions(+), 7 deletions(-)

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



More information about the flang-commits mailing list