GNOME Bugzilla – Bug 598481
Fortran extends keyword not supported
Last modified: 2011-03-28 14:18:58 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
Created attachment 145494 [details] Mother class
Created attachment 145495 [details] Children class
Created attachment 145496 [details] Doxyfile example
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
Created attachment 175891 [details] Test case
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.
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?
Looking forward to it! Don't have any more suggestions atm.
(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?
(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.
(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?
(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.
(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
(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.
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.
Created attachment 177073 [details] Test case with procedure pointer components and abstract interfaces
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!
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.
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
(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!
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.
(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.
Hi Daniel, I'll include your last patch in the next subversion update.
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.
(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 ...
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.
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.