Bug 46067 - [F03] invalid procedure pointer assignment not detected
[F03] invalid procedure pointer assignment not detected
Status: RESOLVED FIXED
Product: gcc
Classification: Unclassified
Component: fortran
4.6.0
: P3 normal
: ---
Assigned To: janus
: accepts-invalid
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2010-10-18 15:00 UTC by Stephen J. Bespalko
Modified: 2010-10-21 09:27 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2010-10-20 13:11:39


Attachments
code demonstrating bug referenced in report (922 bytes, application/octet-stream)
2010-10-18 15:00 UTC, Stephen J. Bespalko
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Stephen J. Bespalko 2010-10-18 15:00:49 UTC
Created attachment 22077 [details]
code demonstrating bug referenced in report

Compiling the attached module, with gfortran 4.6 trunk results in the following error message:

==============
gfortran test_2.f90
test_2.f90:6.52:

  procedure(fun_interface), pointer, pass :: fun_ptr
                                                    1
Error: Non-polymorphic passed-object dummy argument of 'fun_ptr' at (1)

==============

potential problem 1 : the error message appears incorrect because the target of the passed-object dummy argument isn't polymorphic.

potential problem 2: if the error message is correct and if the type of the passed-object dummy argument in the sample code is changed from a declaration of "type" to "class", the module compiles but hangs when the passed-object dummy argument is referenced. 

The relevant statements are labeled in the attached file.

============


et:blotII2 sjbespa$ /volumes/dev/gfortran-4.6-trunk/bin/gfortran -v
Using built-in specs.
COLLECT_GCC=/volumes/dev/gfortran-4.6-trunk/bin/gfortran
COLLECT_LTO_WRAPPER=/Volumes/dev/gfortran-4.6-trunk/bin/../libexec/gcc/x86_64-apple-darwin10/4.6.0/lto-wrapper
Target: x86_64-apple-darwin10
Configured with: ../gfortran-4.6-src/configure --prefix=/volumes/dev/gfortran-4.6-trunk --enable-languages=fortran --host=x86_64-apple-darwin10 --build=x86_64-apple-darwin10 --target=x86_64-apple-darwin10
Thread model: posix
gcc version 4.6.0 20101013 (experimental) (GCC)
Comment 1 janus 2010-10-18 17:39:30 UTC
(In reply to comment #0)
> Compiling the attached module, with gfortran 4.6 trunk results in the following
> error message:
> 
> ==============
> gfortran test_2.f90
> test_2.f90:6.52:
> 
>   procedure(fun_interface), pointer, pass :: fun_ptr
>                                                     1
> Error: Non-polymorphic passed-object dummy argument of 'fun_ptr' at (1)
> 
> ==============
> 
> potential problem 1 : the error message appears incorrect because the target of
> the passed-object dummy argument isn't polymorphic.

No, the error message is perfectly fine. The Fortran 2008 standard clearly demands:

C456 The passed-object dummy argument shall be a scalar, nonpointer, nonallocatable dummy data object with the same declared type as the type being defined; all of its length type parameters shall be assumed; it shall be polymorphic (4.3.1.3) if and only if the type being defined is extensible (4.5.7). It shall not have the VALUE attribute.


> potential problem 2: if the error message is correct and if the type of the
> passed-object dummy argument in the sample code is changed from a declaration
> of "type" to "class", the module compiles but hangs when the passed-object
> dummy argument is referenced. 

After changing the PASS arg from TYPE to CLASS, the module compiles fine for me without any hanging (on x86_64-unknown-linux-gnu at r165600).
Comment 2 janus 2010-10-18 20:08:52 UTC
(In reply to comment #1)
> > potential problem 2: if the error message is correct and if the type of the
> > passed-object dummy argument in the sample code is changed from a declaration
> > of "type" to "class", the module compiles but hangs when the passed-object
> > dummy argument is referenced. 
> 
> After changing the PASS arg from TYPE to CLASS, the module compiles fine for me
> without any hanging (on x86_64-unknown-linux-gnu at r165600).

Ok, one has to be a little careful at this point: When changing both TYPE declarations into CLASS (inside 'fun_interface' and 'fun1'), the program compiles ok and apparently gives the correct output (assuming that the undefined variable 'pi' is zero, contrary to its suggestive name):

  fun1(pi)   id =            1
   1.0000000 

However, when changing only the TYPE declaration in 'fun_interface', but not the one in 'fun1', the program compiles but gives bogus results:

  fun1(pi)   id =      6295264
   1.0000000

This is due to the fact that the resulting program is invalid, which gfortran currently fails to detect.

In summary: The only bug that gfortran exhibits in the context of this PR is the fact that it does not reject the invalid procedure pointer assignment in the following program:


  implicit none
  
  type test_type
    integer :: id
    procedure(fun_interface), pointer, pass :: fun_ptr
  end type test_type
  
  abstract interface
    function fun_interface(t,x) result(res)
      import :: test_type
      real, intent(in) :: x
      class(test_type) :: t
      real :: res
    end function fun_interface
  end interface  
  
  type(test_type),dimension(1) :: funs

  funs(1)%id = 1
  funs(1)%fun_ptr => fun1                    !!! invalid !!!
  print *, " fun1(pi) ",funs(1)%fun_ptr(0.)

contains

  function fun1 (t,x) result (res)
    real, intent(in) :: x
    type(test_type) :: t
    real :: res
    print *," id = ", t%id
   res=cos(x)
  end function fun1
 
end
Comment 3 janus 2010-10-18 21:29:31 UTC
(In reply to comment #1)
> > potential problem 2: if the error message is correct and if the type of the
> > passed-object dummy argument in the sample code is changed from a declaration
> > of "type" to "class", the module compiles but hangs when the passed-object
> > dummy argument is referenced. 
> 
> After changing the PASS arg from TYPE to CLASS, the module compiles fine for me
> without any hanging (on x86_64-unknown-linux-gnu at r165600).

I can confirm the runtime hanging on Mac OS. It happens for the original test case as well as for this reduction:


  implicit none
  
  type test_type
	procedure(fun1), pointer, pass :: fun_ptr
  end type test_type
  
  type(test_type) :: funs

  funs%fun_ptr => fun1
  print *, " fun1(pi) ",funs%fun_ptr(0.)

contains

  real function fun1 (t,x)
    real, intent(in) :: x
    class(test_type) :: t
    print *," in fun1 "
    fun1 = cos(x)
  end function fun1
 
end


The reason seems to be the "recursive I/O" in the program, i.e. the fact that the call to 'fun_ptr'/'fun1' happens inside a PRINT statement, but 'fun1' itself contains another PRINT statement. I think I've seen this kind of behavior before on Darwin, though I'm not sure if the Fortran standard allows it or whether gfortran should actually reject it.
Comment 4 Dominique d'Humieres 2010-10-18 21:31:54 UTC
Beware the INVALID recursive IOs: they hang on darwin!-(see pr 30617).
Comment 5 janus 2010-10-20 13:11:39 UTC
Mine. The accepts-invalid problem in comment #2 is fixed by the following patch:

Index: gcc/fortran/interface.c
===================================================================
--- gcc/fortran/interface.c	(revision 165712)
+++ gcc/fortran/interface.c	(working copy)
@@ -1056,7 +1056,7 @@ gfc_compare_interfaces (gfc_symbol *s1, gfc_symbol
 	  }
 
 	/* Check type and rank.  */
-	if (!compare_type_rank (f1->sym, f2->sym))
+	if (!compare_type_rank (f2->sym, f1->sym))
 	  {
 	    if (errmsg != NULL)
 	      snprintf (errmsg, err_len, "Type/rank mismatch in argument '%s'",
Comment 6 janus 2010-10-21 07:51:37 UTC
Here is a variant of the test case in comment #3 which uses plain procedure pointers instead of PPCs (and avoids recursive I/O):


  implicit none
  
  type test_type
    integer :: id = 1
  end type
  
  abstract interface
    real function fun_interface(t,x)
      import :: test_type
      real, intent(in) :: x
      class(test_type) :: t
    end function
  end interface  
  
  type(test_type) :: funs
  real :: r
  procedure(fun_interface), pointer :: pp

  pp => fun1
  r = pp(funs,0.)
  print *, " pp(0) ", r 

contains

  real function fun1 (t,x)
    real, intent(in) :: x
    type(test_type) :: t
    print *," id = ", t%id
    fun1 = cos(x)
  end function
 
end
Comment 7 janus 2010-10-21 07:54:43 UTC
And here is yet another variant, which uses a procedure as actual argument to another procedure (instead of procedure pointers). Same symptoms (accepts-invalid).


module m

  type test_type
    integer :: id = 1
  end type

contains

  real function fun1 (t,x)
    real, intent(in) :: x
    type(test_type) :: t
    print *," id = ", t%id
    fun1 = cos(x)
  end function

end module


  use m
  implicit none

  call test(fun1)

contains

  subroutine test(proc)
    interface
      real function proc(t,x)
	import :: test_type
	real, intent(in) :: x
	class(test_type) :: t
      end function
    end interface
    type(test_type) :: funs
    real :: r
    r = proc(funs,0.)
    print *, " proc(0) ",r
  end subroutine
 
end
Comment 8 janus 2010-10-21 07:59:37 UTC
Note: Both of the test cases in comment #6 and #7 are invalid but accepted by current trunk builds (as well as 4.5). However, they are rejected with the patch in comment #5, which I will commit as obvious shortly.
Comment 9 janus 2010-10-21 09:25:24 UTC
Author: janus
Date: Thu Oct 21 09:25:17 2010
New Revision: 165755

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=165755
Log:
2010-10-21  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/46067
	* interface.c (gfc_compare_interfaces): Switch arguments of type
	comparison (important for polymorphic variables).


2010-10-21  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/46067
	* gfortran.dg/dummy_procedure_4.f90: New.
	* gfortran.dg/proc_ptr_30.f90: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/dummy_procedure_4.f90
    trunk/gcc/testsuite/gfortran.dg/proc_ptr_30.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/interface.c
    trunk/gcc/testsuite/ChangeLog
Comment 10 janus 2010-10-21 09:27:45 UTC
The accepts-invalid problem from comment #2 has been fixed on trunk by r165755. The recursive I/O is being tracked by PR30617. So I think we can close this one.