Dear all,

the testcase in the PR shows a case where the pureness of a function
is not properly determined, even though the function is resolved, and
its attributes clearly show that it is pure, because gfc_pure_function
relies on isym or esym being set.  This does not happen here, probably
because the function is used as a dummy here.

The least invasive fix seems to be to look at the symbol's attributes
when isym or esym is not set.

Regression testing lead to additional redundant error messages for two
testcases, so I opted to restrict the change to the case of functions
as dummy arguments, making this patch very safe.

Regtested on x86_64-pc-linux-gnu.  OK for mainline?

Thanks,
Harald

From 5ebb5bb438e8ccf6ea30559604a9f27a75dea0ef Mon Sep 17 00:00:00 2001
From: Harald Anlauf <anl...@gmx.de>
Date: Tue, 15 Apr 2025 20:43:05 +0200
Subject: [PATCH] Fortran: pure subroutine with pure procedure as dummy
 [PR106948]

	PR fortran/106948

gcc/fortran/ChangeLog:

	* resolve.cc (gfc_pure_function): If a function has been resolved,
	but esym is not yet set, look at its attributes to see whether it
	is pure or elemental.

gcc/testsuite/ChangeLog:

	* gfortran.dg/pure_formal_proc_4.f90: New test.
---
 gcc/fortran/resolve.cc                        |  7 +++
 .../gfortran.dg/pure_formal_proc_4.f90        | 49 +++++++++++++++++++
 2 files changed, 56 insertions(+)
 create mode 100644 gcc/testsuite/gfortran.dg/pure_formal_proc_4.f90

diff --git a/gcc/fortran/resolve.cc b/gcc/fortran/resolve.cc
index cdf043b6411..410ff685906 100644
--- a/gcc/fortran/resolve.cc
+++ b/gcc/fortran/resolve.cc
@@ -3190,6 +3190,13 @@ gfc_pure_function (gfc_expr *e, const char **name)
 	     || e->value.function.isym->elemental;
       *name = e->value.function.isym->name;
     }
+  else if (e->symtree && e->symtree->n.sym && e->symtree->n.sym->attr.dummy)
+    {
+      /* The function has been resolved, but esym is not yet set.
+	 This can happen with functions as dummy argument.  */
+      pure = e->symtree->n.sym->attr.pure || e->symtree->n.sym->attr.elemental;
+      *name = e->symtree->n.sym->name;
+    }
   else
     {
       /* Implicit functions are not pure.  */
diff --git a/gcc/testsuite/gfortran.dg/pure_formal_proc_4.f90 b/gcc/testsuite/gfortran.dg/pure_formal_proc_4.f90
new file mode 100644
index 00000000000..92640e2d2f4
--- /dev/null
+++ b/gcc/testsuite/gfortran.dg/pure_formal_proc_4.f90
@@ -0,0 +1,49 @@
+! { dg-do compile }
+! PR fortran/106948 - check that passing of PURE procedures works
+!
+! Contributed by Jim Feng
+
+module a
+  implicit none
+
+  interface new
+    pure module subroutine b(x, f)
+      integer, intent(inout) :: x
+      interface
+        pure function f(x) result(r)
+          real, intent(in) :: x
+          real :: r
+        end function f
+      end interface
+    end subroutine b
+  end interface new
+end module a
+
+submodule(a) a_b
+  implicit none
+
+contains
+  module procedure b
+    x = int(f(real(x)) * 0.15)
+  end procedure b
+end submodule a_b
+
+program test
+  use a
+  implicit none
+
+  integer :: x
+
+  x = 100
+  call new(x, g)
+  print *, x
+
+contains
+
+  pure function g(y) result(r)
+    real, intent(in) :: y
+    real :: r
+
+    r = sqrt(y)
+  end function g
+end program test
-- 
2.43.0

Reply via email to