Re: [Patch,Fortran] PR39427/37829 - implement F2003's constructors
Bravo! Thanks for all the hard work, Tobias. Although I realize many people will (correctly) label the constructor capability as syntactic sugar, it supports an idiom that is common across OOP languages as you point out. Common idioms have expressive power. Damian On 11/6/11 6:29 AM, "Tobias Burnus" wrote: >Dear all, > >this patch fixes as collateral effect PR 37829 (alias PR 45190) where >C_PTR/C_FUNPTR occurred when use associating a module using them, if one >additionally uses iso_fc_binding directly. > >The main part of this patch, however, is for PR 39427 (alias 45190): >Allowing generic functions to have the same name as a derived type, >which is a Fortran 2003 feature. In expressions, the generic functions >have a higher precedence then the structure constructor. Note that the >functions are not required to return the derived type. > >This feature allows one to create something which looks similar to >constructors in other OOP languages, except that static constructor >functions do not exist. > >This patch implements them by creating for each derived type two symbols >(symtrees): One for the derived type and one for the generic function, >which links to the derived type. To distinguish them, the derived type >starts with a capital letter in the symtree. In order to facilitate the >error-message handling, the symbol itself remains in lower case. > >The main challenges were to ensure that one gets the derived type when >needed and to store them properly in the module. The most time consuming >part was to find all the places one had to change that issues with >module reading could turn up much later; for instance at resolution time >of a scope which had read that module. In total, it took 18 months >between the first draft patch (cf. PR39427 comment 6, 12-14) and the >final patch. Although, the patch looked almost working by then, it took >many, many, many hours to fix the issues. Also the RFC patch, posted 6 >days ago, had more issues than I had hoped for. > >The attached patch had been build on x86-64-linux and successfully >regtested (gfortran and libgomp). (A full bootstrap of an almost-ready >version was done as well; I had to rebuild because I found some >left-over commented code blocks.) > >Additionally, I tried the previous patches with several programs to >reduce the likelihood that it breaks real-world code. In particular, the >very latest version of the patch was used to compile FLEUR, Elk, Octopus >and the Polyhedron benchmark. Yesterday evening's version was used to >compile the Exciting code (which includes the sensitive FoX Fortran XML >library), CP2K, PSBLAS and FGSL. With a slightly older version, I also >successfully compiled Tonto, Quantum Espresso and Abinit. > >OK for the trunk? > >Tobias > >PS: I have also included a patch for the website, i.e. >http://gcc.gnu.org/gcc-4.7/changes.html#fortran > >PPS: As mentioned in the attachment, the patch includes the tree-walking >patch, which was posted before. It's a really an independent bug, even >if it only exposed with the constructor patch. I can either commit it >before or as part of this patch. See also >http://gcc.gnu.org/ml/fortran/2011-11/msg00026.html
Re: [EXTERNAL] [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine
Hi Tobias, Thanks for your work on this. This is a big step. I would add to your list the following: (4) If the entity is of extended type and the parent type has a component that is finalizable, the parent component's component is finalized. In ForTrilnos, we need for this to happen even when the parent is abstract but has a finalizable component. So far, the IBM, NAG, and Cray compilers support this use case and we've had enough dialogue with committee members that I'm confident it's required by the standard, although I can't cite the specific part of the standard that requires it. Please copy my staff member Karla Morris on any replies. Thanks again! Damian On 8/13/12 1:05 PM, "Tobias Burnus" wrote: >Dear all, > >Attached is the first part of a patch which will implement finalization >support and polymorphic freeing in gfortran. > > >It addresses two needs: > >a) For polymorphic ("CLASS") variables, allocatable components have to >be freed; however, at compile time only the allocatable components of >the declared type are known and the dynamic type might have more > >b) Fortran 2003 allows finalization subroutines ("FINAL", destructors), >which can be elemental, scalar or for a given rank (any array type is >allowed). Those should be called for DEALLOCATE, leaving the scope >(unless saved), intrinsic assignment and with intent(out). > > >The finalization is done as follows (F2008, "4.5.6.2 The finalization >process") > >"(1) If the dynamic type of the entity has a final subroutine whose >dummy argument has the same kind type parameters and rank as the entity >being finalized, it is called with the entity as an actual argument. >Otherwise, if there is an elemental final subroutine whose dummy >argument has the same kind type parameters as the entity being >finalized, it is called with the entity as an actual argument. >Otherwise, no subroutine is called at this point. > >"(2) All finalizable components that appear in the type definition are >finalized in a processor-dependent order. If the entity being finalized >is an array, each finalizable component of each element of that entity >is finalized separately. > >"(3) If the entity is of extended type and the parent type is >finalizable, the parent component is finalized." > > >The idea is to create a wrapper function which handles those steps - and >attach a reference to the dynamic type (i.e. add it via proc-pointer to >the vtable). Additionally, the wrapper can be directly called for TYPE. > > >The attached patch implements the generation of the wrapper subroutine; >it does not yet implement the actual calls. The wrapper is generated on >Fortran AST level and creates code similar to > >subroutine final_wrapper_for_type_t (array) >type(t), intent(inout) :: array(..) >integer, pointer :: ptr >integer(c_intptr_t) :: i, addr > >select case (rank (array)) >case (3) >call final_rank3 (array) >case default: >do i = 0, size (array)-1 >addr = transfer (c_loc (array), addr) + i * STORAGE_SIZE (array) >call c_f_pointer (transfer (addr, c_ptr), ptr) >call elemental_final (ptr) >end do >end select > >! For all noninherited allocatable components, call >! DEALLOCATE(array(:)%comp, stat=ignore) >! scalarized as above > >call final_wrapper_of_parent (array(...)%parent) >end subroutine final_wrapper_for_type_t > > >Note 1: The call to the parent type requires packing support for >assumed-rank arrays, which has not yet been implemented (also required >for TS29113, though not for this usage). That is, without further >patches, the wrapper will only work for scalars or if the parent has no >wrapper subroutine. > >Note 2: The next step will be to add the calls to the wrapper, starting >with an explicit DEALLOCATE. > > >I intent to commit the patch, when approved, without allowing FINAL at >resolution time; that way there is no false impression that finalization >actually works. > >Build and regtested on x86-64-gnu-linux. >OK for the trunk? > >* * * > >Note: The patch will break gfortran's OOP ABI. It does so by adding >"_final" to the virtual table (vtab). > >I think breaking the ABI for this functionality is unavoidable. The ABI >change only affects code which uses the CLASS (polymorphic variables) >and the issue only raises if one mixes old with new code for the same >derived type. However, if one does so (e.g. by incomplete >recompilation), segfaults and similar issues will occur. Hence, I am >considering to bump the .mod version; that will effectively force a >recompilation and thus avoid the issue. The down side is that it will >also break packages (e.g. of Linux distributions) which ship .mod files >(sorry!). What do you think? > >I think it could then be combined with Janus' proc-pointer patch, which >changes the assembler name of (non-Bind(C)) procedure pointers, declared >at module level. Again, by forcing recompilation, the .mod version bump >should ensure that users don't see the ABI breakage. His patch is at >http://gcc.gnu.org/ml/fortran/2012-04/
Re: [EXTERNAL] Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine
Hi Mikael, Is this patch approved? I realize it's not the final step (no pun intended), but I will be very excited to see this hit the trunk. Supporting FINAL will have broad impact on my work and the work of others writing modern Fortran libraries and applications. Damian On 8/25/12 1:42 PM, "Mikael Morin" wrote: >On 25/08/2012 22:06, Tobias Burnus wrote: > If comp has finalizable subcomponents, it has a finalization > wrapper, which is (or should be) caught above, so this branch > is (or should be) unreachable. I probably miss something, but I don't see why this branch should be unreachable. One has: if (component is allocatable) call DEALLOCATE(comp) ! which might invoke finalizers else if (component itself has a finalizer) call FINAL_WRAPPER else for all nonpointer subcomponents which are allocatables, have finalizers or have allocatable/finalizable components, call finalize_component. end if >>> I expected something like: if (allocatable) call deallocate (comp) >>> else if (finalizer or subcomponents have a finalizer) call >>> FINAL_WRAPPER >> >> Well, the question is whether one wants to call a finalize wrapper >> for a simple "comp%alloctable_int(10)" or not. In the current scheme, >> I tried to avoid calling a finalizer wrapper for simple allocatable >> components. >> >> Thus, one has the choice: a) Directly call DEALLOCATE for alloctable >> components of subcomponents b) Always call the finalizer wrapper >> also for nonalloctable TYPEs (with finalizable/allocatable >> components) >> >> (a) is more direct and possibly a bit faster while (b) makes the >> wrapper function a tad smaller. >OK, this is a deliberate choice of implementation to avoid call >overhead. I slightly prefer (b), but we can keep (a). >I'm fine with (a) if the code walking the components is shared - which >avoids c vs. comp issues by the way ;-) . > >> * * * >> >> Regarding the flag or nonflag final_comp, I have to admit that I >> still do not completely understand how you would implement it. >> >> One option would be something like the following >> >> bool has_final_comp(derived) { for (comp = derived->components; comp; >> comp = comp->next) { if (comp->attr.pointer) continue; if >> (comp->f2k_derived->finalizers || comp->ts.type == BT_CLASS) return >> true; if (comp->ts.type == BT_DERIVED && >> has_final_comp(comp->ts.u.derived)) return true; } return false } >This was my initial proposition. The benefit is it is very clear how it >works compared to manual setting the flag here and there. >As you raised a performance issue, I proposed something like this: > >bool has_final_comp(derived) { > bool retval = false; > > if (derived->cache.final_comp_set) >return derived->cache.final_comp; > > for (comp = derived->components; comp; comp = comp->next) > { > if (comp->attr.pointer) > continue; >if (comp->f2k_derived->finalizers || comp->ts.type == BT_CLASS) > { >retval = true; >break; > } >if (comp->ts.type == BT_DERIVED >&& has_final_comp(comp->ts.u.derived)) > { >retval = true; >break; > } > } > derived->cache.final_comp_set = 1; > derived->cache.final_comp = retval; > return retval; >} > >It's no big deal anyway. >I dream of a compiler where all the non-standard symbol attribute flags, >expression rank and typespec, etc, would be implemented like this... No >need for resolution, etc; it would just work everywhere. >I know the story, patches welcome; they may come, one day... > >Mikael >