https://gcc.gnu.org/g:4dbf4c0fdb188e1c348688de91e010f696cd59fc

commit r15-4974-g4dbf4c0fdb188e1c348688de91e010f696cd59fc
Author: Paul Thomas <pa...@gcc.gnu.org>
Date:   Wed Nov 6 07:17:25 2024 +0000

    Fortran: F2008 passing of internal procs to a proc pointer [PR117434]
    
    2024-11-06  Paul Thomas  <pa...@gcc.gnu.org>
    
    gcc/fortran
            PR fortran/117434
            * interface.cc (gfc_compare_actual_formal): Skip 'Expected a
            procedure pointer error' if the formal argument typespec has an
            interface and the type of the actual arg is BT_PROCEDURE.
    
    gcc/testsuite/
            PR fortran/117434
            * gfortran.dg/proc_ptr_54.f90: New test. This is temporarily
            compile-only until one one seven four five five is fixed.
            * gfortran.dg/proc_ptr_55.f90: New test.
            * gfortran.dg/proc_ptr_56.f90: New test.

Diff:
---
 gcc/fortran/interface.cc                  |  9 ++-
 gcc/testsuite/gfortran.dg/proc_ptr_54.f90 | 95 +++++++++++++++++++++++++++++++
 gcc/testsuite/gfortran.dg/proc_ptr_55.f90 | 87 ++++++++++++++++++++++++++++
 gcc/testsuite/gfortran.dg/proc_ptr_56.f90 | 45 +++++++++++++++
 4 files changed, 234 insertions(+), 2 deletions(-)

diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc
index 69519fe3168e..61c506bfdb5d 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -3513,12 +3513,17 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, 
gfc_formal_arglist *formal,
 
      skip_size_check:
 
-      /* Satisfy F03:12.4.1.3 by ensuring that a procedure pointer actual
-         argument is provided for a procedure pointer formal argument.  */
+      /* Satisfy either: F03:12.4.1.3 by ensuring that a procedure pointer
+        actual argument is provided for a procedure pointer formal argument;
+        or: F08:12.5.2.9 (F18:15.5.2.10) by ensuring that the effective
+        argument shall be an external, internal, module, or dummy procedure.
+        The interfaces are checked elsewhere.  */
       if (f->sym->attr.proc_pointer
          && !((a->expr->expr_type == EXPR_VARIABLE
                && (a->expr->symtree->n.sym->attr.proc_pointer
                    || gfc_is_proc_ptr_comp (a->expr)))
+              || (a->expr->ts.type == BT_PROCEDURE
+                  && f->sym->ts.interface)
               || (a->expr->expr_type == EXPR_FUNCTION
                   && is_procptr_result (a->expr))))
        {
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_54.f90 
b/gcc/testsuite/gfortran.dg/proc_ptr_54.f90
new file mode 100644
index 000000000000..e03ecb507400
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_54.f90
@@ -0,0 +1,95 @@
+! { dg-do compile }
+!
+! Test the fix for pr117434, in which the F2008 addition of being permitted to
+! pass an external, internal or module procedure to a dummy procedure pointer
+! gave the error "Expected a procedure pointer for argument ‘<arg_name>’ at 
(1).
+!
+! This testcase checks for correct results.
+!
+! Contributed by Damian Rouson  <damian@archaeologic.codes>
+!
+module julienne_test_description_m
+  implicit none
+
+  abstract interface
+    logical function test_function_i(arg)
+      integer, intent(in) :: arg
+    end function
+  end interface
+
+  type test_description_t
+    procedure(test_function_i), pointer, nopass :: test_function_
+  end type
+
+
+contains
+
+  type(test_description_t) function new_test_description(test_function)
+    procedure(test_function_i), intent(in), pointer :: test_function
+    new_test_description%test_function_ => test_function
+  end function
+
+end module
+
+module test_mod
+
+contains
+
+  logical function mod_test(arg)
+    integer, intent(in) :: arg
+    if (arg == 1) then
+      mod_test = .true.
+    else
+      mod_test = .false.
+    endif
+  end function
+
+end
+
+logical function ext_test(arg)
+  integer, intent(in) :: arg
+  if (arg == 2) then
+    ext_test = .true.
+  else
+    ext_test = .false.
+  endif
+end function
+
+  use julienne_test_description_m
+  use test_mod
+  implicit none
+  type(test_description_t) test_description
+
+  interface
+    logical function ext_test(arg)
+      integer, intent(in) :: arg
+    end function
+  end interface
+
+  test_description = new_test_description(test)
+  if (test_description%test_function_(1) &
+      .or. test_description%test_function_(2) &
+      .or. .not.test_description%test_function_(3)) stop 1
+
+  test_description = new_test_description(mod_test)
+  if (test_description%test_function_(2) &
+      .or. test_description%test_function_(3) &
+      .or. .not.test_description%test_function_(1)) stop 2
+
+  test_description = new_test_description(ext_test)
+  if (test_description%test_function_(1) &
+      .or. test_description%test_function_(3) &
+      .or. .not.test_description%test_function_(2)) stop 3
+
+contains
+
+  logical function test(arg)
+    integer, intent(in) :: arg
+    if (arg == 3) then
+      test = .true.
+    else
+      test = .false.
+    endif
+  end function
+
+end
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_55.f90 
b/gcc/testsuite/gfortran.dg/proc_ptr_55.f90
new file mode 100644
index 000000000000..7028634b54ee
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_55.f90
@@ -0,0 +1,87 @@
+! { dg-do compile }
+!
+! Test the fix for pr117434, in which the F2008 addition of being permitted to
+! pass an external, internal or module procedure to a dummy procedure pointer
+! gave the error "Expected a procedure pointer for argument ‘<arg_name>’ at 
(1).
+!
+! This testcase tests that interface checking is OK in this situation.
+!
+! Contributed by Damian Rouson  <damian@archaeologic.codes>
+!
+module julienne_test_description_m
+  implicit none
+
+  abstract interface
+    logical function test_function_i(arg)
+      integer, intent(in) :: arg
+    end function
+  end interface
+
+  type test_description_t
+    procedure(test_function_i), pointer, nopass :: test_function_
+  end type
+
+
+contains
+
+  type(test_description_t) function new_test_description(test_function)
+    procedure(test_function_i), intent(in), pointer :: test_function
+    new_test_description%test_function_ => test_function
+  end function
+
+end module
+
+  use julienne_test_description_m
+  implicit none
+  type(test_description_t) test_description
+
+  test_description = new_test_description(test1)
+  test_description = new_test_description(test2) ! { dg-error "Type mismatch 
in function" }
+  test_description = new_test_description(test3) ! { dg-error "wrong number of 
arguments" }
+  test_description = new_test_description(test4) ! { dg-error "Rank mismatch 
in argument" }
+  test_description = new_test_description(test5) ! { dg-error "Rank mismatch 
in function result" }
+
+contains
+
+  logical function test1(arg)
+    integer, intent(in) :: arg
+    if (arg == 3) then
+      test1 = .true.
+    else
+      test1 = .false.
+    endif
+  end function
+
+  real function test2(arg)
+    integer, intent(in) :: arg
+    if (arg == 3) then
+      test2 = 1.0
+    else
+      test2 = 0.0
+    endif
+  end function
+
+  logical function test3()
+    test3 = .false.
+  end function
+
+  logical function test4(arg)
+    integer, intent(in) :: arg(:)
+    if (sum (arg) == 3) then
+      test4 = .true.
+    else
+      test4 = .false.
+    endif
+  end function
+
+  function test5(arg) result(res)
+    integer, intent(in) :: arg
+    logical :: res(2)
+    if (arg == 3) then
+      res = .true.
+    else
+      res = .false.
+    endif
+  end function
+
+end
diff --git a/gcc/testsuite/gfortran.dg/proc_ptr_56.f90 
b/gcc/testsuite/gfortran.dg/proc_ptr_56.f90
new file mode 100644
index 000000000000..ca5bed7e8f0f
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/proc_ptr_56.f90
@@ -0,0 +1,45 @@
+! { dg-do compile }
+! { dg-options "-std=f2003" }
+!
+! Test the fix for pr117434, in which the F2008 addition of being permitted to
+! pass an external, internal or module procedure to a dummy procedure pointer
+! gave the error "Expected a procedure pointer for argument ‘<arg_name>’ at 
(1).
+!
+! This testcase checks that -std=f2008 or later is required..
+!
+! Contributed by Damian Rouson  <damian@archaeologic.codes>
+!
+module julienne_test_description_m
+  implicit none
+
+  abstract interface
+    logical function test_function_i()
+    end function
+  end interface
+
+  type test_description_t
+    procedure(test_function_i), pointer, nopass :: test_function_
+  end type
+
+contains
+
+  type(test_description_t) function new_test_description(test_function)
+    procedure(test_function_i), intent(in), pointer :: test_function
+    new_test_description%test_function_ => test_function
+  end function
+
+end module
+
+  use julienne_test_description_m
+  implicit none
+  type(test_description_t) test_description
+
+  test_description = new_test_description(test) ! { dg-error "Fortran 2008:" }
+
+contains
+
+  logical function test()
+    test = .true.
+  end function
+
+end

Reply via email to