New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fortran extends keyword not supported (Origin: bugzilla #598481) #3561

Closed
doxygen opened this Issue Jul 2, 2018 · 0 comments

Comments

Projects
None yet
1 participant
@doxygen
Owner

doxygen commented Jul 2, 2018

status RESOLVED severity normal in component general for ---
Reported in version unspecified on platform Other
Assigned to: Dimitri van Heesch

Original attachment names and IDs:

On 2009-10-14 18:57:59 +0000, raphael wrote:

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

On 2009-10-15 09:49:36 +0000, raphael wrote:

Created attachment 145494
Mother class

On 2009-10-15 09:51:29 +0000, raphael wrote:

Created attachment 145495
Children class

On 2009-10-15 09:52:39 +0000, raphael wrote:

Created attachment 145496
Doxyfile example

On 2010-12-05 22:45:19 +0000, Alexis Rohou wrote:

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

On 2010-12-05 22:46:17 +0000, Alexis Rohou wrote:

Created attachment 175891
Test case

On 2010-12-21 23:47:21 +0000, Alexis Rohou wrote:

Created attachment 176871
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.

On 2010-12-24 14:08:41 +0000, Daniel Franke wrote:

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?

On 2010-12-24 17:13:19 +0000, Alexis Rohou wrote:

Looking forward to it! Don't have any more suggestions atm.

On 2010-12-24 20:30:15 +0000, Daniel Franke wrote:

(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?

On 2010-12-25 00:49:17 +0000, Alexis Rohou wrote:

(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.

On 2010-12-25 00:57:07 +0000, Alexis Rohou wrote:

(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?

On 2010-12-25 01:11:57 +0000, Daniel Franke wrote:

(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.

On 2010-12-25 02:59:37 +0000, Alexis Rohou wrote:

(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

On 2010-12-25 12:57:07 +0000, Daniel Franke wrote:

(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.

On 2010-12-25 17:10:34 +0000, Daniel Franke wrote:

Created attachment 177047
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.

On 2010-12-26 16:09:00 +0000, Alexis Rohou wrote:

Created attachment 177073
Test case with procedure pointer components and abstract interfaces

On 2010-12-26 16:18:46 +0000, Alexis Rohou wrote:

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!

On 2010-12-26 17:15:58 +0000, Daniel Franke wrote:

Created attachment 177074
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.

On 2010-12-26 17:19:03 +0000, Alexis Rohou wrote:

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

On 2010-12-26 17:23:47 +0000, Alexis Rohou wrote:

(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!

On 2010-12-26 17:32:49 +0000, Alexis Rohou wrote:

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.

On 2010-12-26 17:38:07 +0000, Daniel Franke wrote:

(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.

  1. 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.

On 2011-01-04 08:51:15 +0000, Dimitri van Heesch wrote:

Hi Daniel,

I'll include your last patch in the next subversion update.

On 2011-03-01 19:35:26 +0000, albert wrote:

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.

On 2011-03-01 20:15:04 +0000, Daniel Franke wrote:

(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 ...

On 2011-03-01 20:34:20 +0000, albert wrote:

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.

On 2011-03-28 14:18:58 +0000, Dimitri van Heesch wrote:

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.

@doxygen doxygen closed this Jul 2, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment