https://gcc.gnu.org/g:21814c1470de32bb742c2f0a1b505323e1b8ff26

commit r17-5066-g21814c1470de32bb742c2f0a1b505323e1b8ff26
Author: Jerry DeLisle <[email protected]>
Date:   Wed Jun 10 08:37:01 2026 -0700

    fortran: [PR125724] ICE passing NULL() to an allocatable dummy argument
    
    Pass a NULL() actual argument for a non-class, non-character
    allocatable dummy through conv_null_actual, as for derived-type
    dummies.
    
    Assisted-by: Claude Opus 5.5
    
            PR fortran/125724
    
    gcc/fortran/ChangeLog:
    
            * trans-expr.cc (conv_null_actual): Handle intrinsic allocatable
            and pointer dummies.
            (gfc_conv_procedure_call): Use conv_null_actual for a NULL()
            actual with a non-class, non-character allocatable dummy.
    
    gcc/testsuite/ChangeLog:
    
            * gfortran.dg/null_actual_8.f90: New test.

Diff:
---
 gcc/fortran/trans-expr.cc                   | 10 +++++---
 gcc/testsuite/gfortran.dg/null_actual_8.f90 | 38 +++++++++++++++++++++++++++++
 2 files changed, 45 insertions(+), 3 deletions(-)

diff --git a/gcc/fortran/trans-expr.cc b/gcc/fortran/trans-expr.cc
index 8ebaba045adf..10ca0995ec04 100644
--- a/gcc/fortran/trans-expr.cc
+++ b/gcc/fortran/trans-expr.cc
@@ -7068,7 +7068,9 @@ conv_null_actual (gfc_se * parmse, gfc_expr * e, 
gfc_symbol * fsym)
            }
        }
     }
-  else if (fsym->ts.type == BT_DERIVED)
+  else if (fsym->ts.type == BT_DERIVED
+          || ((fsym->attr.allocatable || fsym->attr.pointer)
+              && fsym->ts.type != BT_CLASS))
     {
       if (e->ts.type != BT_UNKNOWN)
        /* MOLD is present.  Pass a corresponding temporary NULL pointer.
@@ -7407,9 +7409,11 @@ gfc_conv_procedure_call (gfc_se * se, gfc_symbol * sym,
            }
        }
       else if (e->expr_type == EXPR_NULL
-              && (e->ts.type == BT_UNKNOWN || e->ts.type == BT_DERIVED)
               && fsym && attr && (attr->pointer || attr->allocatable)
-              && fsym->ts.type == BT_DERIVED)
+              && ((fsym->ts.type == BT_DERIVED
+                   && (e->ts.type == BT_UNKNOWN || e->ts.type == BT_DERIVED))
+                  || (fsym->attr.allocatable && fsym->ts.type != BT_CLASS
+                      && fsym->ts.type != BT_CHARACTER)))
        {
          gfc_init_se (&parmse, NULL);
          gfc_conv_expr_reference (&parmse, e);
diff --git a/gcc/testsuite/gfortran.dg/null_actual_8.f90 
b/gcc/testsuite/gfortran.dg/null_actual_8.f90
new file mode 100644
index 000000000000..d07a14c92ffb
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/null_actual_8.f90
@@ -0,0 +1,38 @@
+! { dg-do run }
+!
+! PR 125724
+!
+! Passing NULL() as an actual argument to an allocatable dummy used to ICE in
+! gfc_conv_procedure_call (a gcc_assert that the dummy was optional and not
+! allocatable).  The dummy must be received as an unallocated allocatable.
+
+program p
+  ! Scalar allocatable, INTENT(IN).
+  call s_scalar (null ())
+
+  ! Allocatable array: unallocated on entry, then usable.
+  call s_array (null ())
+
+  ! Optional allocatable: NULL() is present-but-unallocated.
+  call s_opt (null ())
+contains
+  subroutine s_scalar (a)
+    integer, allocatable, intent(in) :: a
+    if (allocated (a)) stop 1
+  end subroutine
+
+  subroutine s_array (a)
+    integer, allocatable :: a(:)
+    if (allocated (a)) stop 2
+    allocate (a(3))
+    a = [1, 2, 3]
+    if (any (a /= [1, 2, 3])) stop 3
+    deallocate (a)
+  end subroutine
+
+  subroutine s_opt (a)
+    integer, allocatable, optional :: a(:)
+    if (.not. present (a)) stop 4
+    if (allocated (a)) stop 5
+  end subroutine
+end program p

Reply via email to