After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 598481 - Fortran extends keyword not supported
Fortran extends keyword not supported
Status: RESOLVED FIXED
Product: doxygen
Classification: Other
Component: general
unspecified
Other Linux
: Normal normal
: ---
Assigned To: Dimitri van Heesch
Dimitri van Heesch
Depends on: 636946
Blocks:
 
 
Reported: 2009-10-14 18:57 UTC by raphael
Modified: 2011-03-28 14:18 UTC
See Also:
GNOME target: ---
GNOME version: ---


Attachments
Mother class (701 bytes, text/plain)
2009-10-15 09:49 UTC, raphael
  Details
Children class (383 bytes, text/plain)
2009-10-15 09:51 UTC, raphael
  Details
Doxyfile example (8.95 KB, text/plain)
2009-10-15 09:52 UTC, raphael
  Details
Test case (295 bytes, text/plain)
2010-12-05 22:46 UTC, Alexis Rohou
  Details
Proposed patch to fix this bug (751 bytes, patch)
2010-12-21 23:47 UTC, Alexis Rohou
none Details | Review
patch, please test (13.19 KB, patch)
2010-12-25 17:10 UTC, Daniel Franke
none Details | Review
Test case with procedure pointer components and abstract interfaces (1.12 KB, text/plain)
2010-12-26 16:09 UTC, Alexis Rohou
  Details
Updated patch. (14.15 KB, patch)
2010-12-26 17:15 UTC, Daniel Franke
none Details | Review

Description raphael 2009-10-14 18:57:59 UTC
It seems that the keyword extends can make doxygen crash (segfault) or print a warning.
This keyword belongs to the 2003 norm.
It is an extension of a type (class).


For instance: file.f90
----------------------------
implicit none

! Mother class
type mother
...
end type mother

! Children class that inherit from Mother 
type,extends(mother) :: children
...
end type children
----------------------------

doxygen behavior (not sure)
1.6.1 gives a crash
1.5.x just print a warning
Comment 1 raphael 2009-10-15 09:49:36 UTC
Created attachment 145494 [details]
Mother class
Comment 2 raphael 2009-10-15 09:51:29 UTC
Created attachment 145495 [details]
Children class
Comment 3 raphael 2009-10-15 09:52:39 UTC
Created attachment 145496 [details]
Doxyfile example
Comment 4 Alexis Rohou 2010-12-05 22:45:19 UTC
I also see this behaviour. 

Revision 749 (checked out 5-dec-2010) gives:
********************************************************************
Error in file /tmp/test.f90 line: 19, state: 17
********************************************************************
Segmentation fault
Comment 5 Alexis Rohou 2010-12-05 22:46:17 UTC
Created attachment 175891 [details]
Test case
Comment 6 Alexis Rohou 2010-12-21 23:47:21 UTC
Created attachment 176871 [details] [review]
Proposed patch to fix this bug

With this patch, doxygen does not choke on the EXTENDS attribute anymore. 

However, it does not do anything clever with this attribute either.
Comment 7 Daniel Franke 2010-12-24 14:08:41 UTC
Confirmed. I intend to fully implement this after the next svn update.

Besides EXTENDS, we'd need PROCEDURE pointers (#636946), [generic] type bound procedures, the DEFERRED attribute, "TYPE, ABSTRACT" for abstract base classes - anything else?
Comment 8 Alexis Rohou 2010-12-24 17:13:19 UTC
Looking forward to it! Don't have any more suggestions atm.
Comment 9 Daniel Franke 2010-12-24 20:30:15 UTC
(In reply to comment #7)
> Besides EXTENDS, we'd need PROCEDURE pointers (#636946), [generic] type bound
> procedures, the DEFERRED attribute, "TYPE, ABSTRACT" for abstract base classes
> - anything else?

To answer myself: at least polymorphic entities, i.e. CLASS(xyz) and unlimited polymorphic entities, CLASS(*).

Question to Alexis and Raphael: while procedure pointer components are obviously variables ("attributes" in the doxygen sense) and should be listed as such, type bound procedures (TBP) are more like member functions and should, imo, be listed as such. However, member functions do generally not have an initializer, so if the TBP has one, it doesn't show up in the docs. Letting a TBP be a variable (attribute), its initializer is shown. What would be your preference?
Comment 10 Alexis Rohou 2010-12-25 00:49:17 UTC
(In reply to comment #9)
> > - anything else?
> 
> To answer myself: at least polymorphic entities, i.e. CLASS(xyz) and unlimited
> polymorphic entities, CLASS(*).

Yes, obviously these would be good too - I thought you were asking about type declarations specifically.

> type bound procedures (TBP) are more like member functions and should,
> imo, be listed as such. 

Sounds like the right choice.

> However, member functions do generally not have an
> initializer, so if the TBP has one, it doesn't show up in the docs. 

Afraid you lost me there - I am not aware of how a TBP could have an initializer, or even what you really mean by that. I'd be interested in seeing an example.
Comment 11 Alexis Rohou 2010-12-25 00:57:07 UTC
(In reply to comment #9)
> (In reply to comment #7)
> > Besides EXTENDS, we'd need PROCEDURE pointers (#636946), [generic] type bound
> > procedures, the DEFERRED attribute, "TYPE, ABSTRACT" for abstract base classes
> > - anything else?
> 
> To answer myself: at least polymorphic entities, i.e. CLASS(xyz) and unlimited
> polymorphic entities, CLASS(*).

Something else which would be nice to see documented a bit better: ABSTRACT interfaces. At the moment, they are made to look like regular interface but maybe there's a better way to document them? At least indicate that they are abstract, to avoid possible confusion?
Comment 12 Daniel Franke 2010-12-25 01:11:57 UTC
(In reply to comment #10)
> > type bound procedures (TBP) are more like member functions and should,
> > imo, be listed as such. 
> 
> Sounds like the right choice.
> 
> > However, member functions do generally not have an
> > initializer, so if the TBP has one, it doesn't show up in the docs. 
> 
> Afraid you lost me there - I am not aware of how a TBP could have an
> initializer, or even what you really mean by that. I'd be interested in seeing
> an example.

MODULE
  TYPE:: mytype
    REAL :: dummy
  CONTAINS
    PROCEDURE :: write => write_mytype
  END TYPE
CONTAINS
  SUBROUTINE write_mytype (this, unit)
    CLASS(mytype) :: this
    INTEGER, OPTIONAL :: unit
     :
  END SUBROUTINE
END MODULE

Here, the "=> write_mytype" would be the initializer of the TBP "write". I think.


(In reply to comment #11)
> Something else which would be nice to see documented a bit better: ABSTRACT
> interfaces. At the moment, they are made to look like regular interface but
> maybe there's a better way to document them? At least indicate that they are
> abstract, to avoid possible confusion?

Yes, I'd like to see that as well. However, I'm happy I know my way around the fortran scanner by now. The internals of doxygen still elude me. Dimitri would be the right one for this (see also bug 637610).


While at it: does it make sense to resolve procedure pointer interfaces and show the type not as declared, but slightly more readable? Think:

MODULE m
  TYPE :: t
    INTEGER, POINTER :: dummy
  CONTAINS
    final :: ctor
  END TYPE
CONTAINS
  SUBROUTINE ctor (this)
    TYPE(t) :: this
     :
  END SUBROUTINE
END MODULE

One could now document "ctor" as a FINAL component (aka destructor) of TYPE(t) and CTOR as subroutine of M. However, one could also resolve the procedure and directly hook the destructor into the type, and remove it from the module?!

Also, PROECURE(interface) could be resolved to show the actual interface, not the way the procedure pointer was declared?! I.e.

   Public Member Functions
   procedure(iface), pass        name

vs.

   Public Member Functions
   subroutine name(...)

where (...) is copied over from the interface.
Comment 13 Alexis Rohou 2010-12-25 02:59:37 UTC
(In reply to comment #12)
> Here, the "=> write_mytype" would be the initializer of the TBP "write". I
> think.

OK I see what you mean - I hadn't seen this being called an initializer before. Other name for this: (specific) binding (not that I really know the name for this - I had to look it up, e.g.: http://publib.boulder.ibm.com/infocenter/cellcomp/v9v111/index.jsp?topic=/com.ibm.xlf111.cell.doc/xlflr/typeboundproceduresIn your example above, clicking on 'iface' (which is in brackets) would take the user to the documentation for the interface, w.htm)

So, now back to your original question, here's my suggestion: do you think it would be possible to have TBPs treated as member functions which are (something like) INTERFACEs? That way, doxygen would know to link to the actual function like it does for regular interfaces. In fact in my mind, they are very much like interfaces to MODULE PROCEDURES - do you know what I mean?


(In reply to comment #12)
> While at it: does it make sense to resolve procedure pointer interfaces and
> show the type not as declared, but slightly more readable? Think:
> 
> MODULE m
>   TYPE :: t
>     INTEGER, POINTER :: dummy
>   CONTAINS
>     final :: ctor
>   END TYPE
> CONTAINS
>   SUBROUTINE ctor (this)
>     TYPE(t) :: this
>      :
>   END SUBROUTINE
> END MODULE
> 
> One could now document "ctor" as a FINAL component (aka destructor) of TYPE(t)
> and CTOR as subroutine of M. However, one could also resolve the procedure and
> directly hook the destructor into the type, and remove it from the module?!

I don't think removing it from the module would be a good idea, since it may be used for other purposes. For example if there is another derived type (call it s) which has a component of type t, it could be that the destructor for s calls the ctor routine directly  & explicitely and in that case, the code would be better documented if ctor had been left in the module documentation.

E.g:

MODULE m
   TYPE :: t
     INTEGER, POINTER :: dummy
   CONTAINS
     final :: ctor
   END TYPE
   TYPE :: s
     TYPE(t) :: x
     INTEGER :: dummy
   CONTAINS
     final :: s_final
   END TYPE
 CONTAINS
   SUBROUTINE ctor (this)
     TYPE(t) :: this
      :
   END SUBROUTINE
   SUBROUTINE s_final(this)
     TYPE(s) :: this
       :
     CALL ctor(this%x)
   END SUBROUTINE
END MODULE

So I say stick with the first option:
> One could now document "ctor" as a FINAL component (aka destructor) of TYPE(t)
> and CTOR as subroutine of M. 



> Also, PROECURE(interface) could be resolved to show the actual interface, not
> the way the procedure pointer was declared?! I.e.
> 
>    Public Member Functions
>    procedure(iface), pass        name
> 
> vs.
> 
>    Public Member Functions
>    subroutine name(...)
> 
> where (...) is copied over from the interface.

I think I would be in favour of doxygen documenting the way the procedure pointer was declared, with a click-through to the actual (abstract) interface, to avoid confusion as to how the code was actually written. In your second suggestion above, could the reader be fooled into thinking the developper had written explicit interfaces into the type declaration, for example?

The way it is done at the moment in SVN r750 / 20101224 is quite good already. I would just make sure that procedure pointers are listed as member functions rather than attributes, and that clicking on the 'iface' in brackets (in your example) would take one to the interface declaration.

HTH
Comment 14 Daniel Franke 2010-12-25 12:57:07 UTC
(In reply to comment #13)
> So, now back to your original question, here's my suggestion: do you think it
> would be possible to have TBPs treated as member functions which are 
> (something like) INTERFACEs? That way, doxygen would know to link to the 
> actual function like it does for regular interfaces. In fact in my mind, they 
> are very much like interfaces to MODULE PROCEDURES - do you know what I mean?

I think I get the idea, but I have no idea how to achieve that yet. Will see what I can find.


> I think I would be in favour of doxygen documenting the way the procedure
> pointer was declared, with a click-through to the actual (abstract) interface,
> to avoid confusion as to how the code was actually written. In your second
> suggestion above, could the reader be fooled into thinking the developper had
> written explicit interfaces into the type declaration, for example?

As the original code has to be valid Fortran to begin with, probably not ;)

 
> The way it is done at the moment in SVN r750 / 20101224 is quite good already.
> I would just make sure that procedure pointers are listed as member functions
> rather than attributes, and that clicking on the 'iface' in brackets (in your
> example) would take one to the interface declaration.

TBP as member functions, ok. However, procedure pointers _components_ should be attributes, one may change them at runtime.


Btw, I have the actual extension part ready, inheritance and collaboration diagrams work. Now the above needs to be taken into account, GENERIC to be done.
Comment 15 Daniel Franke 2010-12-25 17:10:34 UTC
Created attachment 177047 [details] [review]
patch, please test

This patch adds support for Fortran-OO features to doxygen, namely:
 - type-extension (EXTENDS)
 - abstract types
 - type bound procedures
 - final procedures
 - generic procedures
 - additional fixes for procedure pointers
 - ATTRIBUTES: deferred, non_overridable
 - polymorphic entities (CLASS)

Further:
 - it fixes some issues with procedure pointer components
 - USE statements are not allowed in types

It's not perfect, but a good start. Comments welcome.
Comment 16 Alexis Rohou 2010-12-26 16:09:00 UTC
Created attachment 177073 [details]
Test case with procedure pointer components and abstract interfaces
Comment 17 Alexis Rohou 2010-12-26 16:18:46 UTC
I feel the code snippet just attached could be documented better:
- the abstract interfaces are both called "PURE REAL" in the module documentation page
- in the "MOD_INTERPOL::INTERPOLATION_SCHEME Type Reference" page, it would be really helpful if clicking on the procedure pointer components could take the user to the definition of the abstract interface:
PROCEDURE(INTERPOLATION_FUNCTION), 
(click here----^                 pointer, nopass 	INTERPOLATION_FUNCTION
to go to abstract
interface definition)

I'll let you know if I find other potential improvements.
Thanks again!
Comment 18 Daniel Franke 2010-12-26 17:15:58 UTC
Created attachment 177074 [details] [review]
Updated patch.

(In reply to comment #17)
> I feel the code snippet just attached could be documented better:
> - the abstract interfaces are both called "PURE REAL" in the module
> documentation page

Meh! Seems I managed to test with SUBROUTINEs only, but not FUNCTIONs.
The required change is a simple one, updated patch attached.

It also allows the click-through to the interface.
Comment 19 Alexis Rohou 2010-12-26 17:19:03 UTC
Daniel,

I notice that interfaces defined in modules end up listed in the "Class list" page. Is this intentional? I can't think why it makes sense, but maybe there's a good reason?

For exanple, with the code below, the "Class list" then include TEST_MODULE::NICE_GUY (as expected) and TEST_MODULE::CREATE (this is what I don't understand).

MODULE TEST_MODULE
  TYPE NICE_GUY
    REAL :: DUMMY
  END TYPE NICE_GUY

  INTERFACE CREATE
    MODULE PROCEDURE NICE_GUY_CREATE
  END INTERFACE

  CONTAINS

    SUBROUTINE NICE_GUY_CREATE(SELF)
       TYPE(NICE_GUY) :: SELF
       SELF%DUMMY = 3.14
    END SUBROUTINE
END MODULE
Comment 20 Alexis Rohou 2010-12-26 17:23:47 UTC
(In reply to comment #18)
> The required change is a simple one, updated patch attached.
> 
> It also allows the click-through to the interface.

I can confirm you fixed the behaviour. The click through to the interface reference is great too. Thanks!
Comment 21 Alexis Rohou 2010-12-26 17:32:49 UTC
Hello again,

A couple of suggested improvements (hope you don't mind this bug getting overloaded with not-directly-related requests):
1. In the interface reference page, would it be possible to indicate if the interface is ABSTRACT?
2. In the module reference page, would it be possible for derived type subroutine and function arguments to have a link to click-through to the type reference page?

Let me know if you would prefer separate bug reports for future suggestions if I think of more.
Comment 22 Daniel Franke 2010-12-26 17:38:07 UTC
(In reply to comment #19)
> I notice that interfaces defined in modules end up listed in the "Class list"
> page. Is this intentional? I can't think why it makes sense, but maybe there's
> a good reason?

My assumption is that any of the other supported languages provides a type
thingy called interface (Java comes to mind). Then, internally, the same
interface abstraction is used to represent a Fortran interface. Hence
INTERFACEs show up as a type. Which is suboptimal.

Technically, I think for Fortran we'd need an own section "Interfaces".
However, this would be beyond (a) this PR and (b) my knowledge of the internals
of doxygen. INTERFACE handling certainly needs to be improved, but that's
something for later, probably someone else.


(In reply to comment #21)
> 1. In the interface reference page, would it be possible to indicate if the
> interface is ABSTRACT?

See above.


> 2. In the module reference page, would it be possible for derived type
> subroutine and function arguments to have a link to click-through to the type
> reference page?

If I understand you correctly, this would be some layout-changing doxygen internal thing. No idea. I can make the Fortran reader sit and beg, but anything else is still a mystery to me.


> Let me know if you would prefer separate bug reports for future suggestions if
> I think of more.

Anything not OO-related, further enhancements, change requests should go into a report of their own. Each one, preferably.

Thanks.
Comment 23 Dimitri van Heesch 2011-01-04 08:51:15 UTC
Hi Daniel,

I'll include your last patch in the next subversion update.
Comment 24 albert 2011-03-01 19:35:26 UTC
The extends keyword looks like to work in the documentation part of the code but not in the source browser (in Doxyfile SOURCE_BROWSER = YES).
The following code:
module test
type t1
  integer :: a
end type t1
type, extends(t1):: t11
  integer :: b
end type t11
end module

gives the following error message:
********************************************************************
Error in file /cygdrive/c/Users/user/AppData/Local/Temp/dg/extends.f90 line: 10, state: 17
********************************************************************

When removing the extends no error message is given.
Comment 25 Daniel Franke 2011-03-01 20:15:04 UTC
(In reply to comment #24)
> The extends keyword looks like to work in the documentation part of the code
> but not in the source browser (in Doxyfile SOURCE_BROWSER = YES).

I expect that SOURCE_BROWSER is handled by fortrancode.l - if yes, then EXTENDS is not the only construct that need to be added ...
Comment 26 albert 2011-03-01 20:34:20 UTC
It is indeed in fortrancode.l
Don't know why the error line I submitted in my report about the error is there (probably a wrong cut and paste).
Currently I don't get this error message anymore but the message:
WARNING: fortrancode.l: stack empty!--(end of buffer or a NUL)

Strangely enough I don't get this message in all cases when the extends keyword is used.

Yes I do agree probably a few other constructs should be added to the fortrancode.l as well.
Comment 27 Dimitri van Heesch 2011-03-28 14:18:58 UTC
This bug was previously marked ASSIGNED, which means it should be fixed in
doxygen version 1.7.4. Please verify if this is indeed the case. Reopen the
bug if you think it is not fixed and please include any additional information
that you think can be relevant.