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."
*** Bug 51736 has been marked as a duplicate of this bug. ***
(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)
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'.
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; }
(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).
(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)
(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.
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) >
if replace the input argument for test2() with pr, the program will compile but gives seg fault at run time.
(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).
(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).
(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).
(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.
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
(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!
(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.
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)
Related to pr86006.
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)
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
r261448 fixed comments 16 and 17. Still open: Comment 19.
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
(In reply to janus from comment #21) > Still open: Comment 19. Fixed with r263308. Closing for good.