Bug 53694 - [OOP] GENERIC type-bound procs should be available without part-ref syntax
[OOP] GENERIC type-bound procs should be available without part-ref syntax
Status: NEW
Product: gcc
Classification: Unclassified
Component: fortran
4.8.0
: P3 normal
: ---
Assigned To: Not yet assigned to anyone
: rejects-valid
Depends on:
Blocks:
  Show dependency treegraph
 
Reported: 2012-06-16 08:45 UTC by Tobias Burnus
Modified: 2012-09-21 18:50 UTC (History)
1 user (show)

See Also:
Host:
Target:
Build:
Known to work:
Known to fail:
Last reconfirmed: 2012-06-17 00:00:00


Attachments
test.f90 (1.38 KB, text/plain)
2012-06-16 08:45 UTC, Tobias Burnus
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Tobias Burnus 2012-06-16 08:45:29 UTC
Created attachment 27629 [details]
test.f90

If "sqrt" is a generic type-bound procedure, not only something like
  a%sqrt()  or  a%sqrt(b)   [for pass and nopass, respectively]
should work but also a simple:
  sqrt(a)   or  sqrt(a, b)

That is: The generic enter the normal generic namespace with the exception that
  use, only: type
also imports the generic name for that type.

See also: https://groups.google.com/forum/#!msg/comp.lang.fortran/YDt3j0--1Do


It is not obvious from the standard that this holds, but it is analog to ASSIGNMENT(=) and OPERATOR(...) which also act that way. [Which is supported in gfortran.]  Additionally, the following statement (F2008,4.5.7.3 Type-bound procedure overriding) wouldn't make sense with a different interpretation of the standard:

"If a generic binding specied in a type denition has the same generic-spec as an inherited binding, it extends the generic interface and shall satisfy the requirements specied in 12.4.3.4.5."
Comment 1 janus 2012-06-17 08:52:44 UTC
(In reply to comment #0)
> See also: https://groups.google.com/forum/#!msg/comp.lang.fortran/YDt3j0--1Do

Note: That link does not seem to work.
Comment 2 janus 2012-06-17 17:19:57 UTC
(In reply to comment #0)
> It is not obvious from the standard that this holds, but it is analog to
> ASSIGNMENT(=) and OPERATOR(...) which also act that way. [Which is supported in
> gfortran.]

It is correct that gfortran supports this for ASSIGNMENTs and OPERATORs. However, there are problems, cf. PR 41951 comment 6 to 10.

The two PRs might be fixable in one go.
Comment 3 Tobias Burnus 2012-06-17 19:06:58 UTC
(In reply to comment #1)
> (In reply to comment #0)
> > See also: https://groups.google.com/forum/#!msg/comp.lang.fortran/YDt3j0--1Do
> Note: That link does not seem to work.

Try:

http://www.rhinocerus.net/forum/lang-fortran/708232-there-way-do-following.html
Comment 4 janus 2012-06-17 22:03:05 UTC
Slightly compactified test case:


module type_mod
  implicit none

  type field
     real :: var(1:3)
   contains
     procedure :: scalar_equals_field
     generic :: assignment (=) => scalar_equals_field
     procedure, nopass :: field_sqrt
     generic :: sqrt => field_sqrt
  end type

contains

  elemental pure subroutine scalar_equals_field (A, b)
    class(field), intent(out) :: A
    real, intent(in) :: b
    A%var(:) = b
  end subroutine

  elemental pure function field_sqrt (A) result (B)
    class(field), intent(in) :: A
    type(field) :: B
    B%var(:) = sqrt (A%var(:))
  end function

end module


program test
  use type_mod, only : field
  implicit none
  type(field) :: a

  a = 4.0
  print *, sqrt(a)

end program
Comment 5 janus 2012-06-19 09:52:42 UTC
(In reply to comment #3)
> > > See also: https://groups.google.com/forum/#!msg/comp.lang.fortran/YDt3j0--1Do
> > Note: That link does not seem to work.
> 
> Try:
> 
> http://www.rhinocerus.net/forum/lang-fortran/708232-there-way-do-following.html

The correct google groups link would be:

https://groups.google.com/forum/#!topic/comp.lang.fortran/YDt3j0--1Do


Btw, I'm not completely convinced yet that the code in comment #0 (and #4) is really legal. No one in the c.l.f. thread has brought up a quote from the standard which clearly shows that referencing a type-bound generic is legal without part-ref syntax.


For me, to most convincing reference up to now is this quote from F08:12.4.3.4.5 (though it still sounds a bit 'cloudy' to me):

NOTE 12.10
In most scoping units, the possible sources of procedures with a particular generic identifier are the accessible interface blocks and the generic bindings other than names for the accessible objects in that scoping unit.
Comment 6 janus 2012-06-19 10:46:56 UTC
(In reply to comment #5)
> Btw, I'm not completely convinced yet that the code in comment #0 (and #4) is
> really legal.

In any case, here is a simple draft patch, which makes the code in comment 4 work (at least when the ONLY clause in the USE statement is removed):


Index: gcc/fortran/decl.c
===================================================================
--- gcc/fortran/decl.c	(revision 188334)
+++ gcc/fortran/decl.c	(working copy)
@@ -8374,12 +8374,20 @@ gfc_match_generic (void)
 	  {
 	    const bool is_op = (op_type == INTERFACE_USER_OP);
 	    gfc_symtree* st;
+	    gfc_symbol *gensym;
 
 	    st = gfc_new_symtree (is_op ? &ns->tb_uop_root : &ns->tb_sym_root,
 				  name);
 	    gcc_assert (st);
 	    st->n.tb = tb;
 
+	    /* Create non-typebound generic symbol.  */
+	    if (gfc_get_symbol (name, NULL, &gensym))
+	      return MATCH_ERROR;
+	    if (!gensym->attr.generic
+		&& gfc_add_generic (&gensym->attr, gensym->name, NULL) == FAILURE)
+	      return MATCH_ERROR;
+	    
 	    break;
 	  }
 	  
Index: gcc/fortran/resolve.c
===================================================================
--- gcc/fortran/resolve.c	(revision 188335)
+++ gcc/fortran/resolve.c	(working copy)
@@ -11125,6 +11125,26 @@ specific_found:
 	    return FAILURE;
 	  }
 
+	/* Add target to (non-typebound) generic symbol.  */
+	if (!p->u.generic->is_operator)
+	  {
+	    gfc_symbol *gensym;
+	    if (gfc_get_symbol (name, NULL, &gensym))
+	      return FAILURE;
+	    if (gensym)
+	      {
+		gfc_interface *head, *intr;
+		head = gensym->generic;
+		intr = gfc_get_interface ();
+		intr->sym = target->specific->u.specific->n.sym;
+		intr->where = gfc_current_locus;
+		intr->sym->declared_at = gfc_current_locus;
+		intr->next = head;
+		gensym->generic = intr;
+		gfc_commit_symbol (gensym);
+	      }
+	  }
+
 	/* Check those already resolved on this type directly.  */
 	for (g = p->u.generic; g; g = g->next)
 	  if (g != target && g->specific
Comment 7 janus 2012-06-19 21:56:09 UTC
One problem with the patch in comment #6 is that it produces double error messages for type-bound generics, e.g. on typebound_generic_{1,10,11}.
Comment 8 Tobias Burnus 2012-06-21 14:39:32 UTC
Actually, I am no longer sure that this PR is valid - nor is Richard Maine in c.l.f. Janus seems to have the same doubts, if I read comment 5 correctly.

The standard seems to make a distinction between 'generic type-bound procedure' and 'generic procedure name'.