[flang-commits] [flang] [flang] Extension: accept NULL([MOLD=]) for ALLOCATABLE INTENT(IN) du… (PR #66256)

Peter Klausler via flang-commits flang-commits at lists.llvm.org
Mon Sep 18 11:59:13 PDT 2023


https://github.com/klausler updated https://github.com/llvm/llvm-project/pull/66256

>From dde1810fe898ea79910ee2fce9c7349f9452d83e Mon Sep 17 00:00:00 2001
From: Peter Klausler <pklausler at nvidia.com>
Date: Mon, 11 Sep 2023 13:16:48 -0700
Subject: [PATCH] [flang] Extension: accept NULL([MOLD=]) for ALLOCATABLE
 INTENT(IN) dummy argument

Several compilers accept a null pointer (with or without a MOLD=) as an
actual argument for association with an INTENT(IN) allocatable dummy argument.
At runtime, the allocatable dummy argument appears to be in the
unallocated state.  This seems useful, unambiguous, unlikely to
invalidate conforming code, and works with Intel, NAG, & XLF,
so it should be supported with an optional portability warning in
this compiler as well.

Pull request: https://github.com/llvm/llvm-project/pull/66256
---
 flang/docs/Extensions.md                      |  2 +
 flang/include/flang/Common/Fortran-features.h |  2 +-
 flang/lib/Semantics/check-call.cpp            | 53 ++++++++++++++-----
 flang/test/Semantics/call27.f90               |  8 +--
 4 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/flang/docs/Extensions.md b/flang/docs/Extensions.md
index 49e78a10fa6bcdb..1d6680a0708c0b5 100644
--- a/flang/docs/Extensions.md
+++ b/flang/docs/Extensions.md
@@ -298,6 +298,8 @@ end
 * Unrestricted `INTRINSIC` functions are accepted for use in
   `PROCEDURE` statements in generic interfaces, as in some other
   compilers.
+* A `NULL()` pointer is treated as an unallocated allocatable
+  when associated with an `INTENT(IN)` allocatable dummy argument.
 
 ### Extensions supported when enabled by options
 
diff --git a/flang/include/flang/Common/Fortran-features.h b/flang/include/flang/Common/Fortran-features.h
index 5cbe1d6e157f2f9..94a39c50e049b11 100644
--- a/flang/include/flang/Common/Fortran-features.h
+++ b/flang/include/flang/Common/Fortran-features.h
@@ -37,7 +37,7 @@ ENUM_CLASS(LanguageFeature, BackslashEscapes, OldDebugLines,
     DistinguishableSpecifics, DefaultSave, PointerInSeqType, NonCharacterFormat,
     SaveMainProgram, SaveBigMainProgramVariables,
     DistinctArrayConstructorLengths, PPCVector, RelaxedIntentInChecking,
-    ForwardRefImplicitNoneData)
+    ForwardRefImplicitNoneData, NullActualForAllocatable)
 
 // Portability and suspicious usage warnings for conforming code
 ENUM_CLASS(UsageWarning, Portability, PointerToUndefinable,
diff --git a/flang/lib/Semantics/check-call.cpp b/flang/lib/Semantics/check-call.cpp
index 428c29b9a6bced7..bf80dbecab009d9 100644
--- a/flang/lib/Semantics/check-call.cpp
+++ b/flang/lib/Semantics/check-call.cpp
@@ -661,17 +661,34 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
       dummy.attrs.test(characteristics::DummyDataObject::Attr::Optional)};
   bool actualIsNull{evaluate::IsNullPointer(actual)};
   if (dummyIsAllocatable) {
-    if (!actualIsAllocatable && !(actualIsNull && dummyIsOptional)) {
+    if (actualIsAllocatable) {
+      if (actualIsCoindexed && dummy.intent != common::Intent::In) {
+        messages.Say(
+            "ALLOCATABLE %s must have INTENT(IN) to be associated with a coindexed actual argument"_err_en_US,
+            dummyName);
+      }
+    } else if (actualIsNull) {
+      if (dummyIsOptional) {
+      } else if (dummy.intent == common::Intent::In) {
+        // Extension (Intel, NAG, XLF): a NULL() pointer is an acceptable
+        // actual argument for an INTENT(IN) allocatable dummy, and it
+        // is treated as an unassociated allocatable.
+        if (context.languageFeatures().ShouldWarn(
+                common::LanguageFeature::NullActualForAllocatable)) {
+          messages.Say(
+              "Allocatable %s is associated with a null pointer"_port_en_US,
+              dummyName);
+        }
+      } else {
+        messages.Say(
+            "A null pointer may not be associated with allocatable %s without INTENT(IN)"_err_en_US,
+            dummyName);
+      }
+    } else {
       messages.Say(
           "ALLOCATABLE %s must be associated with an ALLOCATABLE actual argument"_err_en_US,
           dummyName);
     }
-    if (actualIsAllocatable && actualIsCoindexed &&
-        dummy.intent != common::Intent::In) {
-      messages.Say(
-          "ALLOCATABLE %s must have INTENT(IN) to be associated with a coindexed actual argument"_err_en_US,
-          dummyName);
-    }
     if (!actualIsCoindexed && actualLastSymbol &&
         actualLastSymbol->Corank() != dummy.type.corank()) {
       messages.Say(
@@ -791,7 +808,8 @@ static void CheckExplicitDataArg(const characteristics::DummyDataObject &dummy,
   }
 
   // NULL(MOLD=) checking for non-intrinsic procedures
-  if (!intrinsic && !dummyIsPointer && !dummyIsOptional && actualIsNull) {
+  if (!intrinsic && !dummyIsAllocatableOrPointer && !dummyIsOptional &&
+      actualIsNull) {
     messages.Say(
         "Actual argument associated with %s may not be null pointer %s"_err_en_US,
         dummyName, actual.AsFortran());
@@ -1083,12 +1101,19 @@ static void CheckExplicitInterfaceArg(evaluate::ActualArgument &arg,
                 } else if (object.attrs.test(characteristics::DummyDataObject::
                                    Attr::Allocatable) &&
                     evaluate::IsNullPointer(*expr)) {
-                  // Unsupported extension that more or less naturally falls
-                  // out of other Fortran implementations that pass separate
-                  // base address and descriptor address physical arguments
-                  messages.Say(
-                      "Null actual argument '%s' may not be associated with allocatable %s"_err_en_US,
-                      expr->AsFortran(), dummyName);
+                  if (object.intent == common::Intent::In) {
+                    // Extension (Intel, NAG, XLF); see CheckExplicitDataArg.
+                    if (context.languageFeatures().ShouldWarn(common::
+                                LanguageFeature::NullActualForAllocatable)) {
+                      messages.Say(
+                          "Allocatable %s is associated with NULL()"_port_en_US,
+                          dummyName);
+                    }
+                  } else {
+                    messages.Say(
+                        "NULL() actual argument '%s' may not be associated with allocatable %s without INTENT(IN)"_err_en_US,
+                        expr->AsFortran(), dummyName);
+                  }
                 } else {
                   messages.Say(
                       "Actual argument '%s' associated with %s is not a variable or typed expression"_err_en_US,
diff --git a/flang/test/Semantics/call27.f90 b/flang/test/Semantics/call27.f90
index 965ec401953f430..062df6e45da8908 100644
--- a/flang/test/Semantics/call27.f90
+++ b/flang/test/Semantics/call27.f90
@@ -1,10 +1,10 @@
-! RUN: %python %S/test_errors.py %s %flang_fc1
+! RUN: %python %S/test_errors.py %s %flang_fc1 -pedantic
 ! Catch NULL() actual argument association with allocatable dummy argument
 program test
-  !ERROR: Null actual argument 'NULL()' may not be associated with allocatable dummy argument 'a='
+  !ERROR: NULL() actual argument 'NULL()' may not be associated with allocatable dummy argument 'a=' without INTENT(IN)
   call foo1(null())
-  !ERROR: Null actual argument 'NULL()' may not be associated with allocatable dummy argument 'a='
-  call foo2(null()) ! perhaps permissible later on user request
+  !PORTABILITY: Allocatable dummy argument 'a=' is associated with NULL()
+  call foo2(null())
   call foo3(null()) ! ok
  contains
   subroutine foo1(a)



More information about the flang-commits mailing list