Re: [PATCH] Fix PR125481 Wrong generic resolution between procedure pointer and variable actuals of same TKR

Jerry D <[email protected]>
Newsgroups gmane.comp.gcc.patches,gmane.comp.gcc.fortran
Message-ID <[email protected]>
On 5/31/26 3:28 PM, Jerry D wrote:
> On 5/31/26 1:28 PM, Harald Anlauf wrote:
>> Hi Jerry!
>>
>> Am 31.05.26 um 5:46 AM schrieb Jerry D:
>>> The attached patch regression tested on x86_64.
>>
>> Are you sure that the reference to F18:15.5.2.4 is correct?
>> I cannot find your quote there, at least not verbosely.
> 
> I am working off drafts here. I will hunt this down in 2023 which is more current.

I found this in my draft 2023:  F23:15.5.2.5, para 2
> 
>>
>> Furthermore, can you provide a testcase where the new error message
>> will be tested?
>>

New test case added to exercise two possible errors.

I have attached here a revised patch file. I have rerun regression tests on my 
worktree.

If this is OK I will apply to trunk and rerun all of testsuite there before I 
commit. I noticed some unrelated gfortran/gomp failures this morning. I dont 
know what that is about.
PR125481-generic-proc-ptr-resolution.patch (text/x-patch, 6.1 KB)
From dfcb755176cffab06783821bb8abf56c134be1d1 Mon Sep 17 00:00:00 2001
From: Jerry DeLisle <[email protected]>
Date: Tue, 26 May 2026 12:00:33 -0700
Subject: [PATCH] fortran: wrong generic resolution when actual argument is a
 procedure pointer

When a generic interface has two specific procedures -- one with a
procedure-pointer dummy and one with a data-object (e.g. REAL) dummy --
gfortran incorrectly resolved calls where the actual argument was a
procedure pointer to the data-object specific, resulting in the pointer
address being interpreted as a numeric value (wrong code).

The root cause was a missing check in gfc_compare_actual_formal: the
two existing checks guard the case where the formal is a proc_pointer
or FL_PROCEDURE but the actual is not; however the reverse direction
(actual is a proc_pointer but formal is a plain data object) was not
checked.  F23:15.5.2.5, para 2 forbids this pairing.

Assisted by: Claude Sonnet 4.6

gcc/fortran/ChangeLog:

	PR fortran/125481
	* interface.cc (gfc_compare_actual_formal): Add missing check that
	rejects a procedure-pointer actual argument corresponding to a
	data-object dummy argument (F23:15.5.2.5, para 2).  Restrict to
	EXPR_VARIABLE to avoid false positives on calls through procedure
	pointer components.

gcc/testsuite/ChangeLog:

	PR fortran/125481
	* gfortran.dg/generic_37.f90: New test.
	* gfortran.dg/generic_38.f90: New test.
---
 gcc/fortran/interface.cc                 | 18 ++++++
 gcc/testsuite/gfortran.dg/generic_37.f90 | 70 ++++++++++++++++++++++++
 gcc/testsuite/gfortran.dg/generic_38.f90 | 44 +++++++++++++++
 3 files changed, 132 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/generic_37.f90
 create mode 100644 gcc/testsuite/gfortran.dg/generic_38.f90

diff --git a/gcc/fortran/interface.cc b/gcc/fortran/interface.cc
index 7862783e588..b8f4087ef49 100644
--- a/gcc/fortran/interface.cc
+++ b/gcc/fortran/interface.cc
@@ -3817,6 +3817,24 @@ gfc_compare_actual_formal (gfc_actual_arglist **ap, gfc_formal_arglist *formal,
 	  goto match;
 	}
 
+      /* F23:15.5.2.5, para 2: A procedure pointer actual argument cannot correspond
+	 to a data-object dummy argument (reverse of the two checks above).
+	 Only flag EXPR_VARIABLE to avoid false positives on function calls
+	 through procedure pointer components (e.g. o%f(args)).  */
+      if (!f->sym->attr.proc_pointer
+	  && f->sym->attr.flavor != FL_PROCEDURE
+	  && a->expr->expr_type == EXPR_VARIABLE
+	  && (a->expr->symtree->n.sym->attr.proc_pointer
+	      || gfc_is_proc_ptr_comp (a->expr)))
+	{
+	  if (where)
+	    gfc_error ("Procedure pointer actual argument at %L cannot "
+		       "be passed to data-object dummy argument %qs",
+		       &a->expr->where, f->sym->name);
+	  ok = false;
+	  goto match;
+	}
+
       /* Class array variables and expressions store array info in a
 	 different place from non-class objects; consolidate the logic
 	 to access it here instead of repeating it below.  Note that
diff --git a/gcc/testsuite/gfortran.dg/generic_37.f90 b/gcc/testsuite/gfortran.dg/generic_37.f90
new file mode 100644
index 00000000000..e6b82d95ca3
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/generic_37.f90
@@ -0,0 +1,70 @@
+! { dg-do run }
+!
+! PR fortran/125481
+!
+! Wrong generic resolution when actual argument is a procedure pointer and
+! the generic has two specific procedures -- one with a procedure-pointer
+! dummy argument and one with a REAL(8) dummy argument.  gfortran was
+! selecting the REAL(8) specific (F23:15.5.2.5, para 2 violation).
+
+module m
+  implicit none
+
+  abstract interface
+    pure function init_i (x) result (y)
+      real (8), intent (in) :: x(:)
+      real (8), allocatable :: y(:)
+    end function
+  end interface
+
+  type :: t
+    real (8), allocatable :: vals(:)
+  end type
+
+  interface make_t
+    module procedure make_t_from_func   ! first dummy: procedure pointer
+    module procedure make_t_constant    ! first dummy: real(8)
+  end interface
+
+contains
+
+  function make_t_from_func (f, n) result (r)
+    procedure (init_i), pointer :: f
+    integer, intent (in) :: n
+    type (t) :: r
+    integer :: i
+    r%vals = f ([(real (i, 8), i = 1, n)])
+  end function
+
+  function make_t_constant (c, n) result (r)
+    real (8), intent (in) :: c
+    integer, intent (in) :: n
+    type (t) :: r
+    integer :: i
+    r%vals = [(c, i = 1, n)]
+  end function
+
+  pure function identity (x) result (y)
+    real (8), intent (in) :: x(:)
+    real (8), allocatable :: y(:)
+    y = x
+  end function
+
+end module m
+
+program test
+  use m
+  implicit none
+  procedure (init_i), pointer :: f => identity
+  type (t) :: x
+  integer :: i
+
+  x = make_t (f, 4)
+  do i = 1, 4
+    if (abs (x%vals(i) - real (i, 8)) > epsilon (x%vals(i))) STOP 1
+  end do
+
+  x = make_t (42.0d0, 4)
+  if (any (abs (x%vals - 42.0d0) > epsilon (x%vals(1)))) stop 2
+
+end program test
diff --git a/gcc/testsuite/gfortran.dg/generic_38.f90 b/gcc/testsuite/gfortran.dg/generic_38.f90
new file mode 100644
index 00000000000..93b9ff4ba4b
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/generic_38.f90
@@ -0,0 +1,44 @@
+! { dg-do compile }
+!
+! PR fortran/125481
+!
+! Verify that passing a procedure pointer actual argument to a plain
+! data-object dummy argument is rejected with a clear diagnostic
+! (F23:15.5.2.5, para 2).
+
+module m_err
+  implicit none
+
+  abstract interface
+    function func_t (x) result (y)
+      real(8), intent(in) :: x
+      real(8) :: y
+    end function
+  end interface
+
+  type :: t
+    procedure(func_t), pointer, nopass :: fp => null()
+  end type
+
+contains
+
+  subroutine takes_data (x)
+    real(8), intent(in) :: x
+    print *, x
+  end subroutine
+
+end module m_err
+
+program test
+  use m_err
+  implicit none
+  procedure(func_t), pointer :: f => null()
+  type(t) :: obj
+
+  ! Procedure pointer variable passed to a data-object dummy.
+  call takes_data (f)       ! { dg-error "cannot be passed to data-object dummy argument" }
+
+  ! Procedure pointer component passed to a data-object dummy.
+  call takes_data (obj%fp)  ! { dg-error "cannot be passed to data-object dummy argument" }
+
+end program test
-- 
2.54.0
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.