]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Fortran: improve checks of NULL without MOLD as actual argument [PR104819]
authorHarald Anlauf <anlauf@gmx.de>
Fri, 1 Mar 2024 18:21:27 +0000 (19:21 +0100)
committerHarald Anlauf <anlauf@gmx.de>
Fri, 1 Mar 2024 18:22:30 +0000 (19:22 +0100)
gcc/fortran/ChangeLog:

PR fortran/104819
* check.cc (gfc_check_null): Handle nested NULL()s.
(is_c_interoperable): Check for MOLD argument of NULL() as part of
the interoperability check.
* interface.cc (gfc_compare_actual_formal): Extend checks for NULL()
actual arguments for presence of MOLD argument when required by
Interp J3/22-146.

gcc/testsuite/ChangeLog:

PR fortran/104819
* gfortran.dg/assumed_rank_9.f90: Adjust testcase use of NULL().
* gfortran.dg/pr101329.f90: Adjust testcase to conform to interp.
* gfortran.dg/null_actual_4.f90: New test.

gcc/fortran/check.cc
gcc/fortran/interface.cc
gcc/testsuite/gfortran.dg/assumed_rank_9.f90
gcc/testsuite/gfortran.dg/null_actual_4.f90 [new file with mode: 0644]
gcc/testsuite/gfortran.dg/pr101329.f90

index d661cf37f01e9235a6361e8588a68a7a8945762a..db74dcf3f40b97b146f9ba635b92bc70515190c9 100644 (file)
@@ -4384,6 +4384,9 @@ gfc_check_null (gfc_expr *mold)
   if (mold == NULL)
     return true;
 
+  if (mold->expr_type == EXPR_NULL)
+    return true;
+
   if (!variable_check (mold, 0, true))
     return false;
 
@@ -5216,7 +5219,7 @@ is_c_interoperable (gfc_expr *expr, const char **msg, bool c_loc, bool c_f_ptr)
 {
   *msg = NULL;
 
-  if (expr->expr_type == EXPR_NULL)
+  if (expr->expr_type == EXPR_NULL && expr->ts.type == BT_UNKNOWN)
     {
       *msg = "NULL() is not interoperable";
       return false;
index 231f2f252afeba6dbb97244d037b49682a69e50d..64b90550be2aa655220e3f472549a47345c98a0a 100644 (file)
@@ -3296,6 +3296,36 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
          && a->expr->ts.type != BT_ASSUMED)
        gfc_find_vtab (&a->expr->ts);
 
+      /* Interp J3/22-146:
+        "If the context of the reference to NULL is an <actual argument>
+        corresponding to an <assumed-rank> dummy argument, MOLD shall be
+        present."  */
+      if (a->expr->expr_type == EXPR_NULL
+         && a->expr->ts.type == BT_UNKNOWN
+         && f->sym->as
+         && f->sym->as->type == AS_ASSUMED_RANK)
+       {
+         gfc_error ("Intrinsic %<NULL()%> without %<MOLD%> argument at %L "
+                    "passed to assumed-rank dummy %qs",
+                    &a->expr->where, f->sym->name);
+         ok = false;
+         goto match;
+       }
+
+      if (a->expr->expr_type == EXPR_NULL
+         && a->expr->ts.type == BT_UNKNOWN
+         && f->sym->ts.type == BT_CHARACTER
+         && !f->sym->ts.deferred
+         && f->sym->ts.u.cl
+         && f->sym->ts.u.cl->length == NULL)
+       {
+         gfc_error ("Intrinsic %<NULL()%> without %<MOLD%> argument at %L "
+                    "passed to assumed-length dummy %qs",
+                    &a->expr->where, f->sym->name);
+         ok = false;
+         goto match;
+       }
+
       if (a->expr->expr_type == EXPR_NULL
          && ((f->sym->ts.type != BT_CLASS && !f->sym->attr.pointer
               && (f->sym->attr.allocatable || !f->sym->attr.optional
index 1296d068959cbbcc73dcbdf2c957fd0f4080f399..5e59ec136c9c20f294fff781c20811a390e42a6f 100644 (file)
@@ -26,19 +26,20 @@ program main
 
   type(t), target :: y
   class(t), allocatable, target :: yac
-  
+  type(t),  pointer             :: ypt
+
   y%i = 489
   allocate (yac)
   yac%i = 489
   j = 0
   call fc()
-  call fc(null())
+  call fc(null(yac))
   call fc(y)
   call fc(yac)
   if (j /= 2) STOP 1
 
   j = 0
-  call gc(null())
+! call gc(null(yac)) ! ICE
   call gc(y)
   call gc(yac)
   deallocate (yac)
@@ -54,13 +55,14 @@ program main
 
   j = 0
   call ft()
-  call ft(null())
+  call ft(null(yac))
   call ft(y)
   call ft(yac)
   if (j /= 2) STOP 4
 
   j = 0
-  call gt(null())
+  call gt(null(ypt))
+! call gt(null(yac)) ! ICE
   call gt(y)
   call gt(yac)
   deallocate (yac)
@@ -73,6 +75,7 @@ program main
   yac%i = 489
   call ht(yac)
   if (j /= 1) STOP 6
+  deallocate (yac)
 
 contains
 
diff --git a/gcc/testsuite/gfortran.dg/null_actual_4.f90 b/gcc/testsuite/gfortran.dg/null_actual_4.f90
new file mode 100644 (file)
index 0000000..e03d5c8
--- /dev/null
@@ -0,0 +1,35 @@
+! { dg-do compile }
+! PR fortran/104819
+!
+! Reject NULL without MOLD as actual to an assumed-rank dummy.
+! See also interpretation request at
+! https://j3-fortran.org/doc/year/22/22-101r1.txt
+!
+! Test nested NULL()
+
+program p
+  implicit none
+  integer, pointer :: a, a3(:,:,:)
+  character(10), pointer :: c
+
+  call foo (a)
+  call foo (a3)
+  call foo (null (a))
+  call foo (null (a3))
+  call foo (null (null (a)))  ! Valid: nested NULL()s
+  call foo (null (null (a3))) ! Valid: nested NULL()s
+  call foo (null ())          ! { dg-error "passed to assumed-rank dummy" }
+
+  call str (null (c))
+  call str (null (null (c)))
+  call str (null ())          ! { dg-error "passed to assumed-length dummy" }
+contains
+  subroutine foo (x)
+    integer, pointer, intent(in) :: x(..)
+    print *, rank (x)
+  end
+
+  subroutine str (x)
+    character(len=*), pointer, intent(in) :: x
+  end
+end
index b82210d4e28ea766897ecf37c108e2a3ea2ff227..aca171bd4f8dc9ab20acdc8fbbb60d0ad2cee9b7 100644 (file)
@@ -8,6 +8,6 @@ program p
   integer(c_int64_t), pointer :: ip8
   print *, c_sizeof (c_null_ptr) ! valid
   print *, c_sizeof (null ())    ! { dg-error "is not interoperable" }
-  print *, c_sizeof (null (ip4)) ! { dg-error "is not interoperable" }
-  print *, c_sizeof (null (ip8)) ! { dg-error "is not interoperable" }
+  print *, c_sizeof (null (ip4)) ! valid
+  print *, c_sizeof (null (ip8)) ! valid
 end