Bug 45521 - [F08] GENERIC resolution with ALLOCATABLE/POINTER and PROCEDURE
Summary: [F08] GENERIC resolution with ALLOCATABLE/POINTER and PROCEDURE
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: fortran (show other bugs)
Version: 4.8.0
: P3 normal
Target Milestone: 9.0
Assignee: janus
URL:
Keywords:
: 51736 (view as bug list)
Depends on:
Blocks: F2008
  Show dependency treegraph
 
Reported: 2010-09-03 15:04 UTC by Tobias Burnus
Modified: 2018-08-04 15:39 UTC (History)
3 users (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-04-19 00:00:00


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2010-09-03 15:04:19 UTC
As the introduction of Fortran 2008 mentions:
- ALLOCATABLE and POINTER attributes are used in generic resolution.
- Procedureness of a dummy argument is used in generic resolution.

Or as "The new features of Fortran 2008" puts it:
"A pair of specific procedures in a generic interface are permitted to be distinguishable by virtue of a pointer argument without intent in of one corresponding to an allocatable argument of the other or a data argument of one corresponding to a procedure argument of the other."


Fortran 2008's "12.4.3.4.5 Restrictions on generic declarations" has"

"Two dummy arguments are distinguishable if
- one is a procedure and the other is a data object,
- they are both data objects or known to be functions, and neither is TKR compatible with the other,
- one has the ALLOCATABLE attribute and the other has the POINTER attribute, or
- one is a function with nonzero rank and the other is not known to be a function."

Interpretation request F08/0001 / 10-145 changes this ("EDITS to 10-007")"

'[286:4] In 12.4.3.4.5p3, after "the other has the POINTER attribute",
Insert "and not the INTENT(IN) attribute".'
Cf. http://j3-fortran.org/doc/meeting/193/10-199.txt

Fortran 2003 just had ("16.2.3 Restrictions on generic declarations"):

"Two dummy arguments are distinguishable if neither is a subroutine and neither is TKR compatible (5.1.1.2) with the other."
Comment 1 Tobias Burnus 2012-01-02 22:38:29 UTC
*** Bug 51736 has been marked as a duplicate of this bug. ***
Comment 2 janus 2012-04-18 19:16:59 UTC
(In reply to comment #1)
> *** Bug 51736 has been marked as a duplicate of this bug. ***

carrying over test case:

module a
  interface testAlloc
    module procedure::testAlloc1
    module procedure::testAlloc2
  end interface
contains
  function testAlloc1(obj)
    integer,allocatable,intent(in)::obj(:)
    logical testAlloc1
    testAlloc1=allocated(obj)
  end function
  function testAlloc2(obj)
    integer,pointer,intent(in)::obj(:)
    logical testAlloc2
    testAlloc2=associated(obj)
  end function
end module

program test
  use a
  integer,pointer::a1(:)=>null()
  integer,allocatable::a2(:)
  write(*,*),testAlloc(a1),testAlloc(a2)
end program


With current trunk one gets:

    module procedure::testAlloc2
                                1   
Error: Ambiguous interfaces 'testalloc2' and 'testalloc1' in generic interface 'testalloc' at (1)
Comment 3 janus 2012-04-18 19:38:10 UTC
To implement this, we'll presumably need to modify 'gfc_compare_interfaces' in interface.c (for the case of generic_flag=1 and strict_flag=0). Possibly the changes should go directly into 'generic_correspondence'.
Comment 4 janus 2012-04-19 12:45:28 UTC
Here is a preliminary patch which makes gfortran accept the code in comment #2:

Index: gcc/fortran/interface.c
===================================================================
--- gcc/fortran/interface.c	(revision 186485)
+++ gcc/fortran/interface.c	(working copy)
@@ -955,7 +955,9 @@ generic_correspondence (gfc_formal_arglist *f1, gf
 	goto next;
 
       if (f2 != NULL && (compare_type_rank (f1->sym, f2->sym)
-			 || compare_type_rank (f2->sym, f1->sym)))
+			 || compare_type_rank (f2->sym, f1->sym))
+	  && !((f1->sym->attr.allocatable && f2->sym->attr.pointer)
+	       || (f2->sym->attr.allocatable && f1->sym->attr.pointer)))
 	goto next;
 
       /* Now search for a disambiguating keyword argument starting at
@@ -966,7 +968,9 @@ generic_correspondence (gfc_formal_arglist *f1, gf
 	    continue;
 
 	  sym = find_keyword_arg (g->sym->name, f2_save);
-	  if (sym == NULL || !compare_type_rank (g->sym, sym))
+	  if (sym == NULL || !compare_type_rank (g->sym, sym)
+	      || (sym->attr.allocatable && g->sym->attr.pointer)
+	      || (sym->attr.pointer && g->sym->attr.allocatable))
 	    return 1;
 	}
Comment 5 janus 2012-04-19 12:53:05 UTC
(In reply to comment #4)
> Here is a preliminary patch which makes gfortran accept the code in comment #2:

Of course we need to do more. As quoted in comment #0:

"Two dummy arguments are distinguishable if
- one is a procedure and the other is a data object,
- they are both data objects or known to be functions, and neither is TKR
compatible with the other,
- one has the ALLOCATABLE attribute and the other has the POINTER attribute, or
- one is a function with nonzero rank and the other is not known to be a
function."

The patch above only handles the third item, and the second item works already.
Items #1 and #4 are still missing (I think).
Comment 6 janus 2012-04-19 13:04:18 UTC
(In reply to comment #5)
> "Two dummy arguments are distinguishable if
> - one is a procedure and the other is a data object,

Here is a test case for this item:


module m
  interface testIF
    module procedure :: test1
    module procedure :: test2
  end interface
contains
  real function test1 (obj)
    real :: obj
    test1 = obj
  end function
  real function test2 (obj)
    procedure(real) :: pr
    test2 = pr(0.)
  end function
end module

program test
  use m
  print *,testIF(2.0),testIF(cos)
end program



... which is currently rejected with:


    module procedure :: test2
                             1
Error: Ambiguous interfaces 'test2' and 'test1' in generic interface 'testif' at (1)
Comment 7 Tobias Burnus 2012-04-19 13:15:27 UTC
(In reply to comment #4)
> Here is a preliminary patch which makes gfortran accept the code in
> comment #2:

Don't forget to add -std=f2003 diagnostic - either by simply marking it as ambiguous or fancier by telling that it is invalid but would be valid in Fortran 2008.
Comment 8 Mianzhi Wang 2012-04-19 13:20:57 UTC
if replace the input argument for test2() with pr, the program will 
compile but gives seg fault at run time.



于 2012年04月19日 09:04, janus at gcc dot gnu.org 写道:
> http://gcc.gnu.org/bugzilla/show_bug.cgi?id=45521
>
> --- Comment #6 from janus at gcc dot gnu.org 2012-04-19 13:04:18 UTC ---
> (In reply to comment #5)
>> "Two dummy arguments are distinguishable if
>> - one is a procedure and the other is a data object,
> Here is a test case for this item:
>
>
> module m
>    interface testIF
>      module procedure :: test1
>      module procedure :: test2
>    end interface
> contains
>    real function test1 (obj)
>      real :: obj
>      test1 = obj
>    end function
>    real function test2 (obj)
>      procedure(real) :: pr
>      test2 = pr(0.)
>    end function
> end module
>
> program test
>    use m
>    print *,testIF(2.0),testIF(cos)
> end program
>
>
>
> ... which is currently rejected with:
>
>
>      module procedure :: test2
>                               1
> Error: Ambiguous interfaces 'test2' and 'test1' in generic interface 'testif'
> at (1)
>
Comment 9 Mianzhi Wang 2012-04-19 13:22:24 UTC
if replace the input argument for test2() with pr, the program will compile but gives seg fault at run time.
Comment 10 janus 2012-04-19 13:36:46 UTC
(In reply to comment #6)
> (In reply to comment #5)
> > "Two dummy arguments are distinguishable if
> > - one is a procedure and the other is a data object,
> 
> Here is a test case for this item:

Sorry, I messed up the declaration of 'test2' (by not using 'implicit none'). Therefore gfortran is correct in rejecting it. It should have been:


module m
  implicit none
  interface testIF
    module procedure test1
    module procedure test2
  end interface
contains
  real function test1 (obj)
    real :: obj
    test1 = obj
  end function
  real function test2 (pr)
    procedure(real) :: pr
    test2 = pr(0.)
  end function
end module

program test
  use m
  implicit none
  intrinsic :: cos
  print *,testIF(2.0)
  print *,testIF(cos)
end program


This is actually accepted by all gfortran versions I tried (4.3,4.6,4.7,trunk). However, it yields a segfault at runtime (-fdump-tree-original shows that 'test2' is used in both calls).
Comment 11 janus 2012-04-20 12:29:34 UTC
(In reply to comment #10)
> However, it yields a segfault at runtime (-fdump-tree-original shows that
> 'test2' is used in both calls).

Related to this, it also shows that the specific call

  print *,test2(2.0)

is not being rejected, while

  print *,test1(cos)

is. For for former, we clearly need to add a check in 'compare_parameter' to reject it (which should also solve the segfault in comment #10 by selecting the correct specific function for the generic call).
Comment 12 janus 2012-04-20 12:58:24 UTC
(In reply to comment #11)
> For for former, we clearly need to add a check in 'compare_parameter' to
> reject it


Something like:

Index: gcc/fortran/interface.c
===================================================================
--- gcc/fortran/interface.c	(revision 186596)
+++ gcc/fortran/interface.c	(working copy)
@@ -1663,6 +1667,13 @@ compare_parameter (gfc_symbol *formal, gfc_expr *a
        the module variables are generated.  */
     gfc_find_derived_vtab (actual->ts.u.derived);
 
+  if (formal->attr.flavor == FL_PROCEDURE && actual->ts.type != BT_PROCEDURE)
+    {
+      if (where)
+	gfc_error ("Procedure argument expected at %L", &actual->where);
+      return 0;
+    }
+  
   if (actual->ts.type == BT_PROCEDURE)
     {
       char err[200];


This correctly rejects the invalid code in comment #11 and makes the valid code in comment #10 give the expected output (without segfaulting).
Comment 13 janus 2012-04-25 12:29:55 UTC
(In reply to comment #12)
> > For for former, we clearly need to add a check in 'compare_parameter' to
> > reject it

Actually, we do have a check for this already, which is just not working in some cases. Therefore the patch in comment #12 is not the right thing to do. Here is a better one (which is actually free of testsuite regressions):

Index: gcc/fortran/interface.c
===================================================================
--- gcc/fortran/interface.c	(revision 186596)
+++ gcc/fortran/interface.c	(working copy)
@@ -2393,9 +2397,8 @@ compare_actual_formal (gfc_actual_arglist **ap, gf
 
       /* Satisfy 12.4.1.2 by ensuring that a procedure actual argument is
 	 provided for a procedure formal argument.  */
-      if (a->expr->ts.type != BT_PROCEDURE && !gfc_is_proc_ptr_comp (a->expr, NULL)
-	  && a->expr->expr_type == EXPR_VARIABLE
-	  && f->sym->attr.flavor == FL_PROCEDURE)
+      if (f->sym->attr.flavor == FL_PROCEDURE
+	  && gfc_expr_attr (a->expr).flavor != FL_PROCEDURE)
 	{
 	  if (where)
 	    gfc_error ("Expected a procedure for argument '%s' at %L",



Cleanup side note: A lot of the stuff in 'compare_actual_formal' could probably be moved into 'compare_parameter'. It does not really make a difference, but the distinction of what goes where seems completely arbitrary right now.
Comment 14 janus 2012-10-06 12:20:17 UTC
Author: janus
Date: Sat Oct  6 12:20:09 2012
New Revision: 192157

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

	PR fortran/45521
	* interface.c (generic_correspondence): Implement additional
	distinguishability criteria of F08.
	(compare_actual_formal): Reject data object as actual argument for
	procedure formal argument.

2012-10-06  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/45521
	* gfortran.dg/generic_25.f90: New.
	* gfortran.dg/generic_26.f90: New.
	* gfortran.dg/generic_27.f90: New.

Added:
    trunk/gcc/testsuite/gfortran.dg/generic_25.f90
    trunk/gcc/testsuite/gfortran.dg/generic_26.f90
    trunk/gcc/testsuite/gfortran.dg/generic_27.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/interface.c
    trunk/gcc/testsuite/ChangeLog
Comment 15 janus 2012-10-06 12:35:26 UTC
(In reply to comment #0)
> Fortran 2008's "12.4.3.4.5 Restrictions on generic declarations" has"
> 
> "Two dummy arguments are distinguishable if
> - one is a procedure and the other is a data object,
> - they are both data objects or known to be functions, and neither is TKR
> compatible with the other,
> - one has the ALLOCATABLE attribute and the other has the POINTER attribute, or
> - one is a function with nonzero rank and the other is not known to be a
> function."

r192157 implements item 3 and contains a bugfix for item 1, so that items 1-3 should be handled correctly.

About item 4 I'm not completely sure, but possibly we still miss that.



> Interpretation request F08/0001 / 10-145 changes this ("EDITS to 10-007")"
> 
> '[286:4] In 12.4.3.4.5p3, after "the other has the POINTER attribute",
> Insert "and not the INTENT(IN) attribute".'
> Cf. http://j3-fortran.org/doc/meeting/193/10-199.txt

Unfortunately this was forgotten in the above commit. To do!
Comment 16 janus 2016-12-04 17:18:16 UTC
(In reply to janus from comment #15)
> > Interpretation request F08/0001 / 10-145 changes this ("EDITS to 10-007")"
> > 
> > '[286:4] In 12.4.3.4.5p3, after "the other has the POINTER attribute",
> > Insert "and not the INTENT(IN) attribute".'
> > Cf. http://j3-fortran.org/doc/meeting/193/10-199.txt
> 
> Unfortunately this was forgotten in the above commit. To do!

That is, we need to reject this example, because both interfaces are compatible with the call (i.e. they are not distinguishable):

  INTERFACE gen
    SUBROUTINE suba(a)
      REAL,ALLOCATABLE :: a(:)
    END SUBROUTINE
    SUBROUTINE subp(p)
      REAL,POINTER,INTENT(IN) :: p(:)
    END SUBROUTINE
  END INTERFACE
  REAL,ALLOCATABLE,TARGET :: x(:)
  ALLOCATE(x(100))
  CALL gen(x)
end

For the explanation see the link above.
Comment 17 janus 2018-06-08 10:32:40 UTC
Another case that is not yet working is when polymorphic arguments are involved:


  type :: t
  end type

  interface test
    procedure testAlloc
    procedure testPtr
  end interface

contains

  logical function testAlloc(obj)
    class(t), allocatable :: obj
    testAlloc = .true.
  end function

  logical function testPtr(obj)
    class(t), pointer :: obj
    testPtr = .false.
  end function

end


Using type(t) instead of class(t), this case is correctly accepted, but in the above form gfortran wrongly complains:

Error: Ambiguous interfaces in generic interface 'test' for ‘testalloc’ at (1) and ‘testptr’ at (2)
Comment 18 Dominique d'Humieres 2018-06-08 10:45:38 UTC
Related to pr86006.
Comment 19 janus 2018-06-08 11:15:06 UTC
There seem to be additional issues with ASSIGNMENT interfaces:


  type :: t
  end type

  interface test           ! accepted
    procedure testAlloc
    procedure testPtr
  end interface

  interface assignment(=)  ! rejected as ambiguous
    procedure testAlloc
    procedure testPtr
  end interface

contains

  subroutine testAlloc(obj, val)
    type(t), allocatable, intent(out) :: obj
    integer, intent(in) :: val
  end subroutine

  subroutine testPtr(obj, val)
    type(t), pointer, intent(out) :: obj
    integer, intent(in) :: val
  end subroutine

end



Error: Ambiguous interfaces in intrinsic assignment operator for ‘testalloc’ at (1) and ‘testptr’ at (2)
Comment 20 janus 2018-06-11 18:45:32 UTC
Author: janus
Date: Mon Jun 11 18:44:38 2018
New Revision: 261448

URL: https://gcc.gnu.org/viewcvs?rev=261448&root=gcc&view=rev
Log:
2018-06-11  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/45521
	* interface.c (compare_ptr_alloc): New function.
	(generic_correspondence): Call it.


2018-06-11  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/45521
	* gfortran.dg/generic_32.f90: New test.
	* gfortran.dg/generic_33.f90: New test.

Added:
    trunk/gcc/testsuite/gfortran.dg/generic_32.f90
    trunk/gcc/testsuite/gfortran.dg/generic_33.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/interface.c
    trunk/gcc/testsuite/ChangeLog
Comment 21 janus 2018-06-11 18:47:15 UTC
r261448 fixed comments 16 and 17.

Still open: Comment 19.
Comment 22 janus 2018-08-04 15:37:55 UTC
Author: janus
Date: Sat Aug  4 15:37:23 2018
New Revision: 263308

URL: https://gcc.gnu.org/viewcvs?rev=263308&root=gcc&view=rev
Log:
2018-08-04  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/45521
	* interface.c (gfc_compare_interfaces): Apply additional
	distinguishability criteria of F08 to operator interfaces.


2018-08-04  Janus Weil  <janus@gcc.gnu.org>

	PR fortran/45521
	* gfortran.dg/interface_assignment_6.f90: New test case.

Added:
    trunk/gcc/testsuite/gfortran.dg/interface_assignment_6.f90
Modified:
    trunk/gcc/fortran/ChangeLog
    trunk/gcc/fortran/interface.c
    trunk/gcc/testsuite/ChangeLog
Comment 23 janus 2018-08-04 15:39:01 UTC
(In reply to janus from comment #21)
> Still open: Comment 19.

Fixed with r263308. Closing for good.