Bug 63674 - [F03] procedure pointer and non/pure procedure
Summary: [F03] procedure pointer and non/pure procedure
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.9.1
: P3 normal
Target Milestone: ---
Assignee: janus
URL:
Keywords: accepts-invalid
Depends on:
Blocks:
 
Reported: 2014-10-29 10:58 UTC by Valery Weber
Modified: 2014-12-15 10:35 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2014-12-10 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Valery Weber 2014-10-29 10:58:03 UTC
Dear All

the following code is compiling fine with 4.9.1, but shouldnt gcc complain
about calling a nonpure procedure from a pure one?

v

cat gcc_pure.f90
module test
  interface
     function func_interface ( ) RESULT( reslt )
       INTEGER :: reslt
     end function func_interface
  end interface
  type :: t
     procedure(func_interface), nopass, pointer :: f => NULL()
  end type t
contains
  function func_1 ( ) RESULT( reslt )
    integer :: reslt
    reslt = 1
  end function func_1
  pure subroutine eval( a, reslt )
    type(t), intent(in) :: a
    integer, intent(out) :: reslt
    reslt = a%f()
    !reslt = func_1()
  end subroutine eval
end module test

program prog
  use test
  type(t) :: a
  integer :: reslt
  a%f=>func_1
  call eval(a,reslt)
  write(*,*) reslt
end program prog

gfortran-4.9.1   gcc_pure.f90
./a.out 
           1
Comment 1 janus 2014-12-10 22:02:50 UTC
(In reply to Valery Weber from comment #0)
> the following code is compiling fine with 4.9.1, but shouldnt gcc complain
> about calling a nonpure procedure from a pure one?

It definitely should, and the problem also occurs with the 5.0 trunk.

The part that checks for pureness in 'resolve_function' is apparently not applied to procedure-pointer components, but could e.g. be transferred to 'resolve_expr_ppc' like this:


Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(Revision 218598)
+++ gcc/fortran/resolve.c	(Arbeitskopie)
@@ -6048,6 +6048,7 @@ static bool
 resolve_expr_ppc (gfc_expr* e)
 {
   gfc_component *comp;
+  const char *name = NULL;
 
   comp = gfc_get_proc_ptr_comp (e);
   gcc_assert (comp != NULL);
@@ -6074,6 +6075,32 @@ resolve_expr_ppc (gfc_expr* e)
   if (!update_ppc_arglist (e))
     return false;
 
+  if (!pure_function (e, &name))
+    {
+      if (forall_flag)
+        {
+          gfc_error ("Reference to non-PURE function '%s' at %L inside a "
+                     "FORALL %s", comp->name, &e->where,
+                     forall_flag == 2 ? "mask" : "block");
+          return false;
+        }
+      else if (gfc_do_concurrent_flag)
+        {
+          gfc_error ("Reference to non-PURE function '%s' at %L inside a "
+                     "DO CONCURRENT %s", comp->name, &e->where,
+                     gfc_do_concurrent_flag == 2 ? "mask" : "block");
+          return false;
+        }
+      else if (gfc_pure (NULL))
+        {
+          gfc_error ("Reference to non-PURE function '%s' at %L "
+                     "within a PURE procedure", comp->name, &e->where);
+          return false;
+        }
+
+      gfc_unset_implicit_pure (NULL);
+    }
+
   gfc_ppc_use (comp, &e->value.compcall.actual, &e->where);
 
   return true;


This is sufficient to trigger the right error for the test case, but more work needs to be done: 'pure_function' needs to be taught to handle PPCs and one needs to add a pureness check for procedure-pointer assignments. Finally it should be checked if the same problem also applies to 'ordinary' procedure pointers (which are not a type component) and to the case of subroutines (instead of functions).
Comment 2 janus 2014-12-10 22:12:29 UTC
Test case for ordinary procedure pointers:


module test
  interface
     function func_interface ( ) RESULT( reslt )
       INTEGER :: reslt
     end function func_interface
  end interface
contains
  function func_1 ( ) RESULT( reslt )
    integer :: reslt
    reslt = 1
  end function func_1
  pure subroutine eval( reslt )
    integer, intent(out) :: reslt
    procedure(func_interface), pointer :: f
    f=>func_1
    reslt = f()
!     reslt = func_1()
  end subroutine eval
end module test

program prog
  use test
  integer :: reslt

  call eval(reslt)
  write(*,*) reslt
end program prog


This gives the expected error message with 4.9 and trunk, which shows that the problem only occurs for PPCs.
Comment 3 janus 2014-12-10 22:18:39 UTC
Another test case, this time for a PPC pointing to a subroutine:


module test
  interface
     subroutine sub_interface ( )
     end subroutine
  end interface
  type :: t
     procedure(sub_interface), nopass, pointer :: s => NULL()
  end type t
contains
  subroutine sub_1 ( )
  end subroutine
  pure subroutine eval( a )
    type(t), intent(in) :: a
    call a%s()
!     call sub_1()
  end subroutine eval
end module test

program prog
  use test
  type(t) :: a
  a%s=>sub_1
  call eval(a)
end program prog


Should give an error, but is accepted by 4.9 and trunk (even with the patch in comment #1).
Comment 4 janus 2014-12-14 12:05:21 UTC
Author: janus
Date: Sun Dec 14 12:04:49 2014
New Revision: 218717

URL: https://gcc.gnu.org/viewcvs?rev=218717&root=gcc&view=rev
Log:
2014-12-14  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/63674
	* resolve.c (pure_function): Treat procedure-pointer components.
	(check_pure_function): New function.
	(resolve_function): Use it.
	(pure_subroutine): Return a bool to indicate success and modify
	arguments.
	(resolve_generic_s0,resolve_specific_s0,resolve_unknown_s): Use return
	value of 'pure_subroutine'.
	(resolve_ppc_call): Call 'pure_subroutine'.
	(resolve_expr_ppc): Call 'check_pure_function'.


2014-12-14  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/63674
	* gfortran.dg/proc_ptr_comp_39.f90: New.
	* gfortran.dg/pure_dummy_length_1.f90: Modified error message.
	* gfortran.dg/stfunc_6.f90: Ditto.
	* gfortran.dg/typebound_operator_4.f90: Ditto.

Added:
    trunk/gcc/testsuite/gfortran.dg/proc_ptr_comp_39.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/pure_dummy_length_1.f90
    trunk/gcc/testsuite/gfortran.dg/stfunc_6.f90
    trunk/gcc/testsuite/gfortran.dg/typebound_operator_4.f03
Comment 5 janus 2014-12-14 12:07:11 UTC
Fixed with r218717. Closing. Thanks for the report!
Comment 6 janus 2014-12-15 10:35:18 UTC
Author: janus
Date: Mon Dec 15 10:34:46 2014
New Revision: 218738

URL: https://gcc.gnu.org/viewcvs?rev=218738&root=gcc&view=rev
Log:
2014-12-15  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/63674
	* resolve.c (check_pure_function): Rewording in error message.


2014-12-15  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/63674
	* gfortran.dg/forall_5.f90: Modified error message.
	* gfortran.dg/proc_ptr_comp_39.f90: Ditto.
	* gfortran.dg/pure_dummy_length_1.f90: Ditto.
	* gfortran.dg/stfunc_6.f90: Ditto.
	* gfortran.dg/typebound_operator_4.f90: Ditto.

Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/resolve.c
    trunk/gcc/testsuite/ChangeLog
    trunk/gcc/testsuite/gfortran.dg/forall_5.f90
    trunk/gcc/testsuite/gfortran.dg/proc_ptr_comp_39.f90
    trunk/gcc/testsuite/gfortran.dg/pure_dummy_length_1.f90
    trunk/gcc/testsuite/gfortran.dg/stfunc_6.f90
    trunk/gcc/testsuite/gfortran.dg/typebound_operator_4.f03