[flang-commits] [flang] 066aecf - [flang] INTENT(IN) pointer may not be forwarded to INTENT(IN OUT) or (OUT) dummy

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Sat Dec 3 16:28:24 PST 2022


Author: Peter Klausler
Date: 2022-12-03T16:28:17-08:00
New Revision: 066aecff9272bdb0c02ff9379ede1bdbd854880e

URL: https://github.com/llvm/llvm-project/commit/066aecff9272bdb0c02ff9379ede1bdbd854880e
DIFF: https://github.com/llvm/llvm-project/commit/066aecff9272bdb0c02ff9379ede1bdbd854880e.diff

LOG: [flang] INTENT(IN) pointer may not be forwarded to INTENT(IN OUT) or (OUT) dummy

19.6.8 forbids using an INTENT(IN) pointer dummy argument in a pointer association
context, and associated such a pointer with a dummy argument of INTENT(IN OUT) or
INTENT(OUT) is a circumstance that needs to be caught as an error.

Differential Revision: https://reviews.llvm.org/D139138

Added: 
    flang/test/Semantics/definable01.f90

Modified: 
    flang/lib/Semantics/check-call.cpp

Removed: 
    flang/test/Semantics/modifiable01.f90


################################################################################
diff  --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 5c12cea565d7a..9fa8e995273ea 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -391,25 +391,28 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
   }
 
   // Definability
-  if (scope) {
-    const char *reason{nullptr};
+  const char *reason{nullptr};
+  if (dummy.intent == common::Intent::Out) {
+    reason = "INTENT(OUT)";
+  } else if (dummy.intent == common::Intent::InOut) {
+    reason = "INTENT(IN OUT)";
+  }
+  bool dummyIsPointer{
+      dummy.attrs.test(characteristics::DummyDataObject::Attr::Pointer)};
+  if (reason && scope) {
     // Problems with polymorphism are caught in the callee's definition.
     DefinabilityFlags flags{DefinabilityFlag::PolymorphicOkInPure};
-    if (dummy.intent == common::Intent::Out) {
-      reason = "INTENT(OUT)";
-    } else if (dummy.intent == common::Intent::InOut) {
-      reason = "INTENT(IN OUT)";
+    if (isElemental || dummyIsValue) { // 15.5.2.4(21)
+      flags.set(DefinabilityFlag::VectorSubscriptIsOk);
     }
-    if (reason) {
-      if (isElemental || dummyIsValue) { // 15.5.2.4(21)
-        flags.set(DefinabilityFlag::VectorSubscriptIsOk);
-      }
-      if (auto whyNot{WhyNotDefinable(messages.at(), *scope, flags, actual)}) {
-        if (auto *msg{messages.Say(
-                "Actual argument associated with %s %s is not definable"_err_en_US,
-                reason, dummyName)}) {
-          msg->Attach(std::move(*whyNot));
-        }
+    if (actualIsPointer && dummyIsPointer) { // 19.6.8
+      flags.set(DefinabilityFlag::PointerDefinition);
+    }
+    if (auto whyNot{WhyNotDefinable(messages.at(), *scope, flags, actual)}) {
+      if (auto *msg{messages.Say(
+              "Actual argument associated with %s %s is not definable"_err_en_US,
+              reason, dummyName)}) {
+        msg->Attach(std::move(*whyNot));
       }
     }
   }
@@ -418,8 +421,6 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
   bool actualIsContiguous{IsSimplyContiguous(actual, context)};
   bool dummyIsAssumedShape{dummy.type.attrs().test(
       characteristics::TypeAndShape::Attr::AssumedShape)};
-  bool dummyIsPointer{
-      dummy.attrs.test(characteristics::DummyDataObject::Attr::Pointer)};
   bool dummyIsContiguous{
       dummy.attrs.test(characteristics::DummyDataObject::Attr::Contiguous)};
   if ((actualIsAsynchronous || actualIsVolatile) &&
@@ -691,9 +692,15 @@ static void CheckProcedureArg(evaluate::ActualArgument &arg,
     }
     if (dummyIsPointer && dummy.intent != common::Intent::In) {
       const Symbol *last{GetLastSymbol(*expr)};
-      if (!(last && IsProcedurePointer(*last)) &&
-          !(dummy.intent == common::Intent::Default &&
-              IsNullProcedurePointer(*expr))) {
+      if (last && IsProcedurePointer(*last)) {
+        if (dummy.intent != common::Intent::Default &&
+            IsIntentIn(last->GetUltimate())) { // 19.6.8
+          messages.Say(
+              "Actual argument associated with procedure pointer %s may not be INTENT(IN)"_err_en_US,
+              dummyName);
+        }
+      } else if (!(dummy.intent == common::Intent::Default &&
+                     IsNullProcedurePointer(*expr))) {
         // 15.5.2.9(5) -- dummy procedure POINTER
         // Interface compatibility has already been checked above
         messages.Say(

diff  --git a/flang/test/Semantics/modifiable01.f90 b/flang/test/Semantics/definable01.f90
similarity index 75%
rename from flang/test/Semantics/modifiable01.f90
rename to flang/test/Semantics/definable01.f90
index d6babc8735984..fff493fe7a415 100644
--- a/flang/test/Semantics/modifiable01.f90
+++ b/flang/test/Semantics/definable01.f90
@@ -1,5 +1,5 @@
 ! RUN: not %flang_fc1 -fsyntax-only %s 2>&1 | FileCheck %s
-! Test WhyNotModifiable() explanations
+! Test WhyNotDefinable() explanations
 
 module prot
   real, protected :: prot
@@ -67,4 +67,19 @@ pure subroutine test2(ptr)
     !CHECK: because: 'ptr' is externally visible via 'ptr' and not definable in a pure subprogram
     read(internal,*) ptr
   end subroutine
+  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
+    call test3a(objp)
+    !CHECK: error: Actual argument associated with procedure pointer dummy argument 'pp=' may not be INTENT(IN)
+    call test3b(procp)
+  end subroutine
+  subroutine test3a(op)
+    real, intent(in out), pointer :: op
+  end subroutine
+  subroutine test3b(pp)
+    procedure(sin), pointer, intent(in out) :: pp
+  end subroutine
 end module


        


More information about the flang-commits mailing list