Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-09-02 Thread Tobias Burnus

Mikael Morin wrote:

On 29/08/2012 21:53, Tobias Burnus wrote:

a) The main patch, which implements the wrapper.
   I am asking for approval for that patch.

A few more nitpicks below.


I would like to include the patch (c) as modifying the vtable changes
the ABI. Bumping the .mod version is a reliable way to force
recompilation. The alternative is to wait until the final FINAL patch
before bumping the .mod version (and disable the "_final" generation).

I don't like bumping the module version, for something not
module-related (vtypes are output as normal types in the module files),
but I guess it is the most user-friendly thing to do.


I also do not like it - but it might otherwise lead to segfaults at run 
time (or the wrong procedure being called), which is even uglier.



Is the patch (a) OK for the trunk? With which version of (c)?

(I am slightly inclined to do the .mod bump now. As a follow up, one can
also commit Janus' proc-pointer patch,
http://gcc.gnu.org/ml/fortran/2012-04/msg00033.html, though I think
someone has still to review it.)

I am inclined to disable finalization completely (thus defer .mod bump),
because the new code is hardly tested and doesn't provide (yet) new
benefits such as reduced memory leaks as it is disabled.
We could do the bump now, but I'm afraid that we discover a bug when
finalization gets completely implemented, and we have to bump again to
fix it (though I don't see what kind of bug it could be).


I concur.


I think Janus' patch is a much less serious problem in the sense that
people trying to link codes compiled with patched and non-patched
compiler will get a link error.  I don't think it's worth a .mod bump.


Well, the idea was: If we do bump the .mod for this patch, having around 
that time Janus' patch (which also breaks the ABI) makes sense. I concur 
that his ABI breakage is less severe.



For (a), I noticed a few indenting issues (8+ spaces) and (mostly
wording) nits below to be fixed.  Then OK.


Fixed.


+/* Returns true if any of its nonpointer nonallocatable components or
+   their nonpointer nonallocatable subcomponents has a finalization
+   subroutine.  */
+
+static bool
+has_finalizer_component (gfc_symbol *derived)

Rename to has_finalizable_component ?


I prefer finalizer because also allocatable components are finalizable 
but they are excluded by this check.



+/* Call DEALLOCATE for the passed component if it is allocatable, if it is
+   neither allocatable nor a pointer but has a finalizer, call it. If it
+   is a nonpointer component with allocatable or finalizes components, walk

s/finalizes/finalizable/ ?


Actually: with allocatable components or has finalizers.


+   them. Either of the is required; other nonallocatables and pointers aren't

s/the/them/ ?

done.


+   handled gracefully.
+   Note: The DEALLOCATE handling takes care of finalizers, coarray
+   deregistering and allocatable components of the allocatable.  */

"coarray deregistering and allocatable components" is confusing.

Note: If the component is allocatable, the DEALLOCATE handling takes
care of calling the appropriate finalizer(s), of coarray deregistering,
and of deallocating allocatable (sub)components.


Done.


+/* Generate the wrapper finalization/polymorphic freeing subroutine for the

Difficult to read.
"Generate the finalization/polymorphic freeing wrapper subroutine..." or
something ?


Done.


+  /* We now create a wrapper, which does the following:
+ 1. It calls the suitable finalization subroutine for this type

s/It calls/Call/ ? (to be in line with the other verbs).

+ 2. In a loop over all noninherited allocatable components and noninherited

s/In a loop/Loop/


Done.


Thanks for the review. I have no committed it as Rev. 190869

Tobias


Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-09-01 Thread Mikael Morin
On 29/08/2012 21:53, Tobias Burnus wrote:
> Dear all,
> 
> that's the revised version of patch at
> http://gcc.gnu.org/ml/fortran/2012-08/msg00095.html, taking the review
> comments into account.
> 
> Reminder: This patch only generates the finalization wrapper, which is
> in the virtual table. It does not add the required calls; hence, it
> still doesn't allow to use finalization.
> 
> 
> The patch consists of three parts:
> 
> a) The main patch, which implements the wrapper.
>   I am asking for approval for that patch.
A few more nitpicks below.

> 
> b) A patch which removes the gfc_error "not yet implemented"
>   I suggest to only remove the error after finalization calls have been
> added
Sensible. By the way some (testsuite) parts of b) should be part of a).

> 
> c) A patch which bumps the .mod version
>- or alternatively -
>a patch which disables the _final generation in the vtable.
> 
> I have build and regtested (on x86-64-linux) the patch with (a) and
> (a)+(b) applied.
> 
> 
> I would like to include the patch (c) as modifying the vtable changes
> the ABI. Bumping the .mod version is a reliable way to force
> recompilation. The alternative is to wait until the final FINAL patch
> before bumping the .mod version (and disable the "_final" generation).
I don't like bumping the module version, for something not
module-related (vtypes are output as normal types in the module files),
but I guess it is the most user-friendly thing to do.

> 
> One possibility, if deemed useful, is to combine the .mod version bump
> with backward compatible reading of .mod files, i.e., only error out
> when BT_CLASS is encountered in an old .mod file.
Let's keep things simple, let's not do that.

> 
> 
> Is the patch (a) OK for the trunk? With which version of (c)?
> 
> (I am slightly inclined to do the .mod bump now. As a follow up, one can
> also commit Janus' proc-pointer patch,
> http://gcc.gnu.org/ml/fortran/2012-04/msg00033.html, though I think
> someone has still to review it.)
I am inclined to disable finalization completely (thus defer .mod bump),
because the new code is hardly tested and doesn't provide (yet) new
benefits such as reduced memory leaks as it is disabled.
We could do the bump now, but I'm afraid that we discover a bug when
finalization gets completely implemented, and we have to bump again to
fix it (though I don't see what kind of bug it could be).

I think Janus' patch is a much less serious problem in the sense that
people trying to link codes compiled with patched and non-patched
compiler will get a link error.  I don't think it's worth a .mod bump.
Unless I miss something.

For (a), I noticed a few indenting issues (8+ spaces) and (mostly
wording) nits below to be fixed.  Then OK.



> diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
> index 21a91ba..9d58aab 100644
> --- a/gcc/fortran/class.c
> +++ b/gcc/fortran/class.c
> @@ -689,6 +694,702 @@ copy_vtab_proc_comps (gfc_symbol *declared, gfc_symbol 
> *vtype)
>  }
>  
>  
> +/* Returns true if any of its nonpointer nonallocatable components or
> +   their nonpointer nonallocatable subcomponents has a finalization
> +   subroutine.  */
> +
> +static bool
> +has_finalizer_component (gfc_symbol *derived)
Rename to has_finalizable_component ?

> +{
> +   gfc_component *c;
> +
> +  for (c = derived->components; c; c = c->next)
> +{
> +  if (c->ts.type == BT_DERIVED && c->ts.u.derived->f2k_derived
> +   && c->ts.u.derived->f2k_derived->finalizers)
> + return true;
> +
> +  if (c->ts.type == BT_DERIVED
> +   && !c->attr.pointer && !c->attr.allocatable
> +   && has_finalizer_component (c->ts.u.derived))
> + return true;
> +}
> +  return false;
> +}
> +
> +
> +/* Call DEALLOCATE for the passed component if it is allocatable, if it is
> +   neither allocatable nor a pointer but has a finalizer, call it. If it
> +   is a nonpointer component with allocatable or finalizes components, walk
s/finalizes/finalizable/ ?
> +   them. Either of the is required; other nonallocatables and pointers aren't
s/the/them/ ?
> +   handled gracefully.
> +   Note: The DEALLOCATE handling takes care of finalizers, coarray
> +   deregistering and allocatable components of the allocatable.  */
"coarray deregistering and allocatable components" is confusing.

Note: If the component is allocatable, the DEALLOCATE handling takes
care of calling the appropriate finalizer(s), of coarray deregistering,
and of deallocating allocatable (sub)components.

> +
> +static void
> +finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
> + gfc_expr *stat, gfc_code **code)

[...]

> +
> +
> +/* Generate the wrapper finalization/polymorphic freeing subroutine for the
Difficult to read.
"Generate the finalization/polymorphic freeing wrapper subroutine..." or
something ?

> +   derived type "derived". The function first calls the approriate FINAL
> +   subroutine, then it DEALLOCATEs (finalizes/frees) the 

Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-29 Thread Tobias Burnus

Dear all,

that's the revised version of patch at 
http://gcc.gnu.org/ml/fortran/2012-08/msg00095.html, taking the review 
comments into account.


Reminder: This patch only generates the finalization wrapper, which is 
in the virtual table. It does not add the required calls; hence, it 
still doesn't allow to use finalization.



The patch consists of three parts:

a) The main patch, which implements the wrapper.
  I am asking for approval for that patch.

b) A patch which removes the gfc_error "not yet implemented"
  I suggest to only remove the error after finalization calls have been 
added


c) A patch which bumps the .mod version
   - or alternatively -
   a patch which disables the _final generation in the vtable.

I have build and regtested (on x86-64-linux) the patch with (a) and 
(a)+(b) applied.



I would like to include the patch (c) as modifying the vtable changes 
the ABI. Bumping the .mod version is a reliable way to force 
recompilation. The alternative is to wait until the final FINAL patch 
before bumping the .mod version (and disable the "_final" generation).


One possibility, if deemed useful, is to combine the .mod version bump 
with backward compatible reading of .mod files, i.e., only error out 
when BT_CLASS is encountered in an old .mod file.



Is the patch (a) OK for the trunk? With which version of (c)?

(I am slightly inclined to do the .mod bump now. As a follow up, one can 
also commit Janus' proc-pointer patch, 
http://gcc.gnu.org/ml/fortran/2012-04/msg00033.html, though I think 
someone has still to review it.)


Tobias

PS: When doing the ABI change, I am going to document it in the release 
notes / wiki.
2012-08-29  Alessandro Fanfarillo  
Tobias Burnus  

	PR fortran/37336
	* gfortran.h (symbol_attribute): Add artificial.
	* module.c (mio_symbol_attribute): Handle attr.artificial
	* class.c (gfc_build_class_symbol): Defer creation of the vtab
	if the DT has finalizers, mark generated symbols as
	attr.artificial.
	(has_finalizer_component, finalize_component,
	finalization_scalarizer, generate_finalization_wrapper):
	New static functions.
	(gfc_find_derived_vtab): Add _final component and call
	generate_finalization_wrapper.
* dump-parse-tree.c (show_f2k_derived): Use resolved
	proc_tree->n.sym rather than unresolved proc_sym.
	(show_attr): Handle attr.artificial.
	* resolve.c (gfc_resolve_finalizers): Ensure that the vtab exists.
	(resolve_fl_derived): Resolve finalizers before
	generating the vtab.
	(resolve_symbol): Also allow assumed-rank arrays with CONTIGUOUS;
	skip artificial symbols.
	(resolve_fl_derived0): Skip artificial symbols.

2012-08-29  Tobias Burnus  

	PR fortran/51632
	* gfortran.dg/coarray_class_1.f90: New.

diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index 21a91ba..9d58aab 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -34,7 +34,7 @@ along with GCC; see the file COPYING3.  If not see
  declared type of the class variable and its attributes
  (pointer/allocatable/dimension/...).
 * _vptr: A pointer to the vtable entry (see below) of the dynamic type.
-
+
For each derived type we set up a "vtable" entry, i.e. a structure with the
following fields:
 * _hash: A hash value serving as a unique identifier for this type.
@@ -42,6 +42,9 @@ along with GCC; see the file COPYING3.  If not see
 * _extends:  A pointer to the vtable entry of the parent derived type.
 * _def_init: A pointer to a default initialized variable of this type.
 * _copy: A procedure pointer to a copying procedure.
+* _final:A procedure pointer to a wrapper function, which frees
+		 allocatable components and calls FINAL subroutines.
+
After these follow procedure pointer components for the specific
type-bound procedures.  */
 
@@ -572,7 +575,9 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
   if (gfc_add_component (fclass, "_vptr", &c) == FAILURE)
 	return FAILURE;
   c->ts.type = BT_DERIVED;
-  if (delayed_vtab)
+  if (delayed_vtab
+	  || (ts->u.derived->f2k_derived
+	  && ts->u.derived->f2k_derived->finalizers))
 	c->ts.u.derived = NULL;
   else
 	{
@@ -689,6 +694,702 @@ copy_vtab_proc_comps (gfc_symbol *declared, gfc_symbol *vtype)
 }
 
 
+/* Returns true if any of its nonpointer nonallocatable components or
+   their nonpointer nonallocatable subcomponents has a finalization
+   subroutine.  */
+
+static bool
+has_finalizer_component (gfc_symbol *derived)
+{
+   gfc_component *c;
+
+  for (c = derived->components; c; c = c->next)
+{
+  if (c->ts.type == BT_DERIVED && c->ts.u.derived->f2k_derived
+	  && c->ts.u.derived->f2k_derived->finalizers)
+	return true;
+
+  if (c->ts.type == BT_DERIVED
+	  && !c->attr.pointer && !c->attr.allocatable
+	  && has_finalizer_component (c->ts.u.derived))
+	return true;
+}
+  return false;
+}
+
+
+/* Call DEALLOCATE for the passed component if it is allocatable, if i

Re: [EXTERNAL] Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-27 Thread Mikael Morin
On 27/08/2012 20:20, Rouson, Damian wrote:
> Hi Mikael,
> 
> Is this patch approved?
There are a few overlooks to be fixed and the components walking code
that I would like to see shared.
Then I think it can go in. But there is no big stopper.

Mikael


Re: [EXTERNAL] Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-27 Thread Rouson, Damian
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
>




Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-25 Thread Mikael Morin
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


Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-25 Thread Tobias Burnus

Mikael Morin wrote:

What if only comp's subcomponents are finalizable, the finalization
wrapper should still be called, shouldn't it?

Well, that's handled in the "else" branch. There, I walk all
subcomponents. I do not need to walk them in case there is a finalizer
as the called finalization wrapper will handle them.

Actually, I don't understand why you walk twice over the subcomponents:
in the else branch here and in the finalizer.


Well, I only walk once per component. However, I could unconditionally 
call this function – and move some of the checks from the main program here.



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.




As said above, I don't understand why you would walk over the components
twice


I don't. I touch every ((sub)sub)component only once; I only do a deep 
walk until there is either no component or a pointer or an allocatable 
or a finalizable component. I do acknowledge that I repeat some of the 
logic by handling the outer component in the wrapper and the inner 
(sub)subcomponents in the final_components.



+  else if (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
+   && CLASS_DATA (comp)->attr.allocatable)
+alloc_comp = true;

Shouldn't one assume without condition that there are allocatable or
finalizable subcomponents when there is a polymorphic component?

Well, we do not deallocate/finalize polymorphic POINTER components.

Indeed, then I prefer having !CLASS_DATA(comp)->attr.pointer.


Okay, that's equivalent; though, I have to admit that I prefer the 
current version, which I regard as cleaner.


 * * *

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
}

in class.c

Another is the version which gets set in parse.c.

However, I do not understand what you mean by:


If performance is a problem, the function could use the flag as a
backend.  As long as the field is used and set in a single place, I
don't mind.  I don't have a strong opinion either, there is already a
full bag of flags; one more wouldn't make things dramatically worse.



Tobias


Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-25 Thread Mikael Morin
On 25/08/2012 17:21, Tobias Burnus wrote:
> (And nonallocatble, nonpointer
> components do not exist.)
I missed that indeed.

>> What if only comp's subcomponents are finalizable, the finalization
>> wrapper should still be called, shouldn't it?
> 
> Well, that's handled in the "else" branch. There, I walk all
> subcomponents. I do not need to walk them in case there is a finalizer
> as the called finalization wrapper will handle them.
Actually, I don't understand why you walk twice over the subcomponents:
in the else branch here and in the finalizer.

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

As said above, I don't understand why you would walk over the components
twice

>>> >+  else if (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
>>> >+   && CLASS_DATA (comp)->attr.allocatable)
>>> >+alloc_comp = true;
>> Shouldn't one assume without condition that there are allocatable or
>> finalizable subcomponents when there is a polymorphic component?
> 
> Well, we do not deallocate/finalize polymorphic POINTER components.
Indeed, then I prefer having !CLASS_DATA(comp)->attr.pointer.


>>> >diff --git a/gcc/fortran/parse.c b/gcc/fortran/parse.c
>>> >index 44b1900..4cafefe 100644
>>> >--- a/gcc/fortran/parse.c
>>> >+++ b/gcc/fortran/parse.c
>>> >@@ -2250,6 +2250,16 @@ endType:
>>> >sym->attr.lock_comp = 1;
>>> >  }
>>> >  >+  /* Look for finalizers.  */
>>> >+  if (c->attr.final_comp
>> c->attr.final_comp is never set.
>>
>> I would like to avoid if possible yet another symbol attribute set in
>> three different functions in three different files and used all over the
>> place.  What about using a function "calculating" the predicate this
>> time?
> 
> Maybe, however, one has then to call the function a lot of times: In
> generate_finalization_wrapper for the whole type, then for the new added
> components, and then for each component in finalize_component. With the
> current code, the latter has a complexity of approx. O(n lg n), but one
> might be able to improve it a bit by restructuring the code. (On the
> other hand, "n" is probably not excessively large.)
> 
If performance is a problem, the function could use the flag as a
backend.  As long as the field is used and set in a single place, I
don't mind.  I don't have a strong opinion either, there is already a
full bag of flags; one more wouldn't make things dramatically worse.

Mikael


Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-25 Thread Tobias Burnus

Dear Mikael, dear all,

Mikael Morin wrote:

the patch mixes deallocation and finalization, which are treated
separately in the standard.


First, I want to remark that the standard - in many cases - does not 
require memory freeing ("deallocation"), it "merely" makes it possible 
that one does not leak memory with allocatables. The actually freeing of 
the memory is just a matter of the qualify of the implementation.


Secondly, for a polymorphic type, one does not know at compile time 
whether it has allocatable components or not - nor whether it has a 
finalizer or not. Hence, I do not see another possibility to have a 
common _free/_final entry point in the vtable. As there has to be a 
common entry point, I think it makes sense to have a single finalization 
wrapper which handles both. (I had also initially thought, that one 
could handle those two cases separately, but now I don't see it anymore.)



  1. some weird cases are not correctly covered (polymorphic components,
multiple level of finalizable and/or non-finalizable components, of
inheritance, ...)


I do believe that polymorphic components are correctly handled: If they 
are a POINTER, they are untouched but if they are ALLOCATABLE, one calls 
DEALLOCATE for the component, which should handle the 
finalization/deallocation correctly. (And nonallocatble, nonpointer 
components do not exist.)



I would like to point out that forcing the wrapper's array argument to
be contiguous will lead to poor code as repacking will be needed with
inherited types to call the parent's wrapper (and the parent's parent's,
etc...).


I think that's unavoidable with the current array descriptor, which 
assumes that the stride is always a multiple of the size of the type. I 
concur that with the new array descriptor, one restrict the 
copy-in/copy-out to calling explict-shape/assumed-size finalizers, which 
probably do not occur in practice.




>+finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
>+  e = gfc_copy_expr (expr);
>+  e->ref = gfc_get_ref ();
You should walk to the end of the reference chain.  Otherwise you are
overwriting it here.


I will do this.


>+  if (comp->attr.allocatable
>+  || (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
>+ && CLASS_DATA (comp)->attr.allocatable))
>+{

>+}
>+  else if (comp->ts.type == BT_DERIVED
>+   && comp->ts.u.derived->f2k_derived
>+   && comp->ts.u.derived->f2k_derived->finalizers)

What about polymorphic components?


I have to admit that the code is a bit implicit: polymorphic components 
are either ALLOCATABLE - and hence handled in the "if" block, or they 
are pointers - in which case this function is not called at all.



What if only comp's subcomponents are finalizable, the finalization
wrapper should still be called, shouldn't it?


Well, that's handled in the "else" branch. There, I walk all 
subcomponents. I do not need to walk them in case there is a finalizer 
as the called finalization wrapper will handle them.



>+  else
>+{
>+  gfc_component *c;
>+
>+  gcc_assert ((comp->attr.alloc_comp || comp->attr.final_comp)
>+ && comp->ts.type != BT_CLASS);
>+  for (c = comp->ts.u.derived->components; c; c = c->next)
>+   if ((comp->ts.type != BT_CLASS && !comp->attr.pointer
>+&& (comp->attr.alloc_comp || comp->attr.allocatable
>+|| comp->attr.final_comp))
>+   || ((comp->ts.type == BT_CLASS && CLASS_DATA (comp)
>+&& CLASS_DATA (comp)->attr.allocatable)))
>+ finalize_component (e, comp->ts.u.derived, comp, stat, code);
>+}

This doesn't work, you use comp instead of c.


I hate copy-and-paste bugs. Thanks.


If there is a polymorphic component whose declared type is not
finalizable, but whose actual type is, the finalization wrapper should
still be called.


But it will, as written above, polymorphic components are allocatable 
(or they are pointers and won't get finalized).



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



>+  block->symtree = gfc_find_symtree (sub_ns->sym_root, "c_f_pointer");

This is useless...


I concur.


>+  bool alloc_comp = false;

This is misnamed, it should be final_comp or something.


I concur, its use became extended during the development of the patch.




>+  for (comp = vtab->ts.u.derived->components; comp; comp = comp->next)
>+   if (comp->name[0] == '_' && comp->name[1] == 'f')

I have no strong opinion about it, but slightly prefer strcmp (

Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-25 Thread Mikael Morin

On 19/08/2012 19:50, Tobias Burnus wrote:
> Dear all,
> 
> attached is a slightly updated patch:
> 
> * Call finalizers of nonallocatable, nonpointer components
> * Generate FINAL wrapper for abstract types which have a finalizer. (The
> allocatable components are deallocated in the first type (abstract or
> not) which has a finalizer, i.e. abstract + finalizer or first
> nonabstract type.)
> 
> I had to disable some resolve warning; I did so by introducing an
> attr.artificial. I used it to also fix PR 51632, where we errored out
> for __def_init and __copy where there were coarray components.
> 
> Build and regtested on x86-64-linux.
> OK for the trunk?
> 
> Tobias

Hello,

some general comment:

the patch mixes deallocation and finalization, which are treated
separately in the standard.  I don' know at this point whether it will
make our life really tougher or not, but I think it makes the code
slightly more difficult to read.

I have a mixed general feeling about the patch that
 1. some weird cases are not correctly covered (polymorphic components,
multiple level of finalizable and/or non-finalizable components, of
inheritance, ...)
 2. some of the above "incorrectnesses" may actually cancel each other;
the patch is implemented differently than how I thought it would be. I
may be missing the point after all.

I would like to point out that forcing the wrapper's array argument to
be contiguous will lead to poor code as repacking will be needed with
inherited types to call the parent's wrapper (and the parent's parent's,
etc...).

More specific comments below.

Mikael


> 2012-08-19  Alessandro Fanfarillo  
> Tobias Burnus  
> 
>   PR fortran/37336
>   * gfortran.h (symbol_attribute): Add artifical and final_comp.
>   * parse.c (parse_derived): Set final_comp.
>   * module.c (mio_symbol_attribute): Handle final.comp.
>   * class.c (gfc_build_class_symbol): Defer creation of the vtab
>   if the DT has finalizers, mark generated symbols as
>   attr.artificial.
>   (finalize_component, finalization_scalarizer,
>   generate_finalization_wrapper): New static functions.
>   (gfc_find_derived_vtab): Add _final component and call
>   generate_finalization_wrapper.
> * dump-parse-tree.c (show_f2k_derived): Use resolved
>   proc_tree->n.sym rather than unresolved proc_sym.
>   * resolve.c (gfc_resolve_finalizers): Remove not-implemented
>   error and ensure that the vtab exists.
>   (resolve_fl_derived): Resolve finalizers before
>   generating the vtab.
>   (resolve_symbol): Also allow assumed-rank arrays with CONTIGUOUS;
>   skip artificial symbols.
>   (resolve_fl_derived0): Skip artificial symbols.
> 
> 2012-08-19  Alessandro Fanfarillo  
> Tobias Burnus  
> 
>   PR fortran/51632
>   * gfortran.dg/coarray_class_1.f90: New.
> 
>   PR fortran/37336
>   * gfortran.dg/coarray_poly_3.f90: Update dg-error.
>   * gfortran.dg/auto_dealloc_2.f90: Update scan-tree-dump-times.
>   * gfortran.dg/class_19.f03: Ditto.
>   * gfortran.dg/finalize_4.f03: Remove dg-excess-errors
>   for not implemented.
>   * gfortran.dg/finalize_5.f03: Ditto.
>   * gfortran.dg/finalize_7.f03: Ditto.
> 
> diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
> index 21a91ba..122cc43 100644
> --- a/gcc/fortran/class.c
> +++ b/gcc/fortran/class.c
> @@ -689,6 +694,672 @@ copy_vtab_proc_comps (gfc_symbol *declared, gfc_symbol 
> *vtype)
>  }
>  
>  
> +/* Call DEALLOCATE for the passed component if it is allocatable, if it is
> +   neither allocatable nor a pointer but has a finalizer, call it. If it
> +   is a nonpointer component with allocatable or finalizes components, walk
> +   them. Either of the is required; other nonallocatables and pointers aren't
> +   handled gracefully.
> +   Note: The DEALLOCATE handling takes care of finalizers, coarray
> +   deregistering and allocatable components of the allocatable.  */
> +
> +void
> +finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
> + gfc_expr *stat, gfc_code **code)
> +{
> +  gfc_expr *e;
> +  e = gfc_copy_expr (expr);
> +  e->ref = gfc_get_ref ();
You should walk to the end of the reference chain.  Otherwise you are
overwriting it here.  Unless you avoid recursing, in which case you can
assert it was NULL.

> +  e->ref->type = REF_COMPONENT;
> +  e->ref->u.c.sym = derived;
> +  e->ref->u.c.component = comp;
> +  e->ts = comp->ts;
> +
> +  if (comp->attr.dimension
> +  || (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
> +   && CLASS_DATA (comp)->attr.dimension))
> +{
> +  e->ref->next = gfc_get_ref ();
> +  e->ref->next->type = REF_ARRAY;
> +  e->ref->next->u.ar.type = AR_FULL;
> +  e->ref->next->u.ar.dimen = 0;
> +  e->ref->next->u.ar.as = comp->ts.type == BT_CLASS ? CLASS_DATA 
> (comp)->as
> + : comp->as;
> +  e-

Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-24 Thread Tobias Burnus

Dear Alessandro,

Alessandro Fanfarillo wrote:

there are some problems with the final-wrapper-v2.diff patch; I get
Internal Error at (1):
gfc_code2string(): Bad code
for every test case that I use; in attachment final2.f90.


Fixed by the patch below. However, note that the current patch only 
implement the wrapper function - it doesn't handle calling the wrapper 
function. That's requires a follow up patch. (That was the reason that I 
did not do extensive test.)


The patch is a complete module.c patch, not incrementally based on the 
previous patch.


Tobias
diff --git a/gcc/fortran/module.c b/gcc/fortran/module.c
index a4ff199..3e636cd 100644
--- a/gcc/fortran/module.c
+++ b/gcc/fortran/module.c
@@ -1840,17 +1840,18 @@ typedef enum
   AB_ELEMENTAL, AB_PURE, AB_RECURSIVE, AB_GENERIC, AB_ALWAYS_EXPLICIT,
   AB_CRAY_POINTER, AB_CRAY_POINTEE, AB_THREADPRIVATE,
   AB_ALLOC_COMP, AB_POINTER_COMP, AB_PROC_POINTER_COMP, AB_PRIVATE_COMP,
-  AB_VALUE, AB_VOLATILE, AB_PROTECTED, AB_LOCK_COMP,
+  AB_VALUE, AB_VOLATILE, AB_PROTECTED, AB_LOCK_COMP, AB_FINAL_COMP,
   AB_IS_BIND_C, AB_IS_C_INTEROP, AB_IS_ISO_C, AB_ABSTRACT, AB_ZERO_COMP,
   AB_IS_CLASS, AB_PROCEDURE, AB_PROC_POINTER, AB_ASYNCHRONOUS, AB_CODIMENSION,
   AB_COARRAY_COMP, AB_VTYPE, AB_VTAB, AB_CONTIGUOUS, AB_CLASS_POINTER,
-  AB_IMPLICIT_PURE
+  AB_IMPLICIT_PURE, AB_ARTIFICIAL
 }
 ab_attribute;
 
 static const mstring attr_bits[] =
 {
 minit ("ALLOCATABLE", AB_ALLOCATABLE),
+minit ("ARTIFICIAL", AB_ARTIFICIAL),
 minit ("ASYNCHRONOUS", AB_ASYNCHRONOUS),
 minit ("DIMENSION", AB_DIMENSION),
 minit ("CODIMENSION", AB_CODIMENSION),
@@ -1883,6 +1884,7 @@ static const mstring attr_bits[] =
 minit ("VALUE", AB_VALUE),
 minit ("ALLOC_COMP", AB_ALLOC_COMP),
 minit ("COARRAY_COMP", AB_COARRAY_COMP),
+minit ("FINAL_COMP", AB_FINAL_COMP),
 minit ("LOCK_COMP", AB_LOCK_COMP),
 minit ("POINTER_COMP", AB_POINTER_COMP),
 minit ("PROC_POINTER_COMP", AB_PROC_POINTER_COMP),
@@ -1975,6 +1977,8 @@ mio_symbol_attribute (symbol_attribute *attr)
 {
   if (attr->allocatable)
 	MIO_NAME (ab_attribute) (AB_ALLOCATABLE, attr_bits);
+  if (attr->artificial)
+	MIO_NAME (ab_attribute) (AB_ARTIFICIAL, attr_bits);
   if (attr->asynchronous)
 	MIO_NAME (ab_attribute) (AB_ASYNCHRONOUS, attr_bits);
   if (attr->dimension)
@@ -2057,6 +2061,8 @@ mio_symbol_attribute (symbol_attribute *attr)
 	MIO_NAME (ab_attribute) (AB_PRIVATE_COMP, attr_bits);
   if (attr->coarray_comp)
 	MIO_NAME (ab_attribute) (AB_COARRAY_COMP, attr_bits);
+  if (attr->final_comp)
+	MIO_NAME (ab_attribute) (AB_FINAL_COMP, attr_bits);
   if (attr->lock_comp)
 	MIO_NAME (ab_attribute) (AB_LOCK_COMP, attr_bits);
   if (attr->zero_comp)
@@ -2090,6 +2096,9 @@ mio_symbol_attribute (symbol_attribute *attr)
 	case AB_ALLOCATABLE:
 	  attr->allocatable = 1;
 	  break;
+	case AB_ARTIFICIAL:
+	  attr->artificial = 1;
+	  break;
 	case AB_ASYNCHRONOUS:
 	  attr->asynchronous = 1;
 	  break;
@@ -2198,6 +2207,9 @@ mio_symbol_attribute (symbol_attribute *attr)
 	case AB_COARRAY_COMP:
 	  attr->coarray_comp = 1;
 	  break;
+	case AB_FINAL_COMP:
+	  attr->final_comp = 1;
+	  break;
 	case AB_LOCK_COMP:
 	  attr->lock_comp = 1;
 	  break;


Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-24 Thread Alessandro Fanfarillo
Dear Tobias,

there are some problems with the final-wrapper-v2.diff patch; I get
the following error

final2.f90:71.15:

end module test
   1
Internal Error at (1):
gfc_code2string(): Bad code

for every test case that I use; in attachment final2.f90.

Regards

Alessandro

2012/8/19 Tobias Burnus :
> Dear all,
>
> attached is a slightly updated patch:
>
> * Call finalizers of nonallocatable, nonpointer components
> * Generate FINAL wrapper for abstract types which have a finalizer. (The
> allocatable components are deallocated in the first type (abstract or not)
> which has a finalizer, i.e. abstract + finalizer or first nonabstract type.)
>
> I had to disable some resolve warning; I did so by introducing an
> attr.artificial. I used it to also fix PR 51632, where we errored out for
> __def_init and __copy where there were coarray components.
>
> Build and regtested on x86-64-linux.
> OK for the trunk?
>
> Tobias



--


final2.f90
Description: Binary data


Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-22 Thread Tobias Burnus

* PING *

On August 19, 2012, Tobias Burnus wrote:

Dear all,

attached is a slightly updated patch:

* Call finalizers of nonallocatable, nonpointer components
* Generate FINAL wrapper for abstract types which have a finalizer. 
(The allocatable components are deallocated in the first type 
(abstract or not) which has a finalizer, i.e. abstract + finalizer or 
first nonabstract type.)


I had to disable some resolve warning; I did so by introducing an 
attr.artificial. I used it to also fix PR 51632, where we errored out 
for __def_init and __copy where there were coarray components.


Build and regtested on x86-64-linux.
OK for the trunk?

Tobias


Re: [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-19 Thread Tobias Burnus

Dear all,

attached is a slightly updated patch:

* Call finalizers of nonallocatable, nonpointer components
* Generate FINAL wrapper for abstract types which have a finalizer. (The 
allocatable components are deallocated in the first type (abstract or 
not) which has a finalizer, i.e. abstract + finalizer or first 
nonabstract type.)


I had to disable some resolve warning; I did so by introducing an 
attr.artificial. I used it to also fix PR 51632, where we errored out 
for __def_init and __copy where there were coarray components.


Build and regtested on x86-64-linux.
OK for the trunk?

Tobias
2012-08-19  Alessandro Fanfarillo  
Tobias Burnus  

	PR fortran/37336
	* gfortran.h (symbol_attribute): Add artifical and final_comp.
	* parse.c (parse_derived): Set final_comp.
	* module.c (mio_symbol_attribute): Handle final.comp.
	* class.c (gfc_build_class_symbol): Defer creation of the vtab
	if the DT has finalizers, mark generated symbols as
	attr.artificial.
	(finalize_component, finalization_scalarizer,
	generate_finalization_wrapper): New static functions.
	(gfc_find_derived_vtab): Add _final component and call
	generate_finalization_wrapper.
* dump-parse-tree.c (show_f2k_derived): Use resolved
	proc_tree->n.sym rather than unresolved proc_sym.
	* resolve.c (gfc_resolve_finalizers): Remove not-implemented
	error and ensure that the vtab exists.
	(resolve_fl_derived): Resolve finalizers before
	generating the vtab.
	(resolve_symbol): Also allow assumed-rank arrays with CONTIGUOUS;
	skip artificial symbols.
	(resolve_fl_derived0): Skip artificial symbols.

2012-08-19  Alessandro Fanfarillo  
Tobias Burnus  

	PR fortran/51632
	* gfortran.dg/coarray_class_1.f90: New.

	PR fortran/37336
	* gfortran.dg/coarray_poly_3.f90: Update dg-error.
 	* gfortran.dg/auto_dealloc_2.f90: Update scan-tree-dump-times.
	* gfortran.dg/class_19.f03: Ditto.
	* gfortran.dg/finalize_4.f03: Remove dg-excess-errors
	for not implemented.
	* gfortran.dg/finalize_5.f03: Ditto.
	* gfortran.dg/finalize_7.f03: Ditto.

diff --git a/gcc/fortran/class.c b/gcc/fortran/class.c
index 21a91ba..122cc43 100644
--- a/gcc/fortran/class.c
+++ b/gcc/fortran/class.c
@@ -34,7 +34,7 @@ along with GCC; see the file COPYING3.  If not see
  declared type of the class variable and its attributes
  (pointer/allocatable/dimension/...).
 * _vptr: A pointer to the vtable entry (see below) of the dynamic type.
-
+
For each derived type we set up a "vtable" entry, i.e. a structure with the
following fields:
 * _hash: A hash value serving as a unique identifier for this type.
@@ -42,6 +42,9 @@ along with GCC; see the file COPYING3.  If not see
 * _extends:  A pointer to the vtable entry of the parent derived type.
 * _def_init: A pointer to a default initialized variable of this type.
 * _copy: A procedure pointer to a copying procedure.
+* _final:A procedure pointer to a wrapper function, which frees
+		 allocatable components and calls FINAL subroutines.
+
After these follow procedure pointer components for the specific
type-bound procedures.  */
 
@@ -572,7 +575,9 @@ gfc_build_class_symbol (gfc_typespec *ts, symbol_attribute *attr,
   if (gfc_add_component (fclass, "_vptr", &c) == FAILURE)
 	return FAILURE;
   c->ts.type = BT_DERIVED;
-  if (delayed_vtab)
+  if (delayed_vtab
+	  || (ts->u.derived->f2k_derived
+	  && ts->u.derived->f2k_derived->finalizers))
 	c->ts.u.derived = NULL;
   else
 	{
@@ -689,6 +694,672 @@ copy_vtab_proc_comps (gfc_symbol *declared, gfc_symbol *vtype)
 }
 
 
+/* Call DEALLOCATE for the passed component if it is allocatable, if it is
+   neither allocatable nor a pointer but has a finalizer, call it. If it
+   is a nonpointer component with allocatable or finalizes components, walk
+   them. Either of the is required; other nonallocatables and pointers aren't
+   handled gracefully.
+   Note: The DEALLOCATE handling takes care of finalizers, coarray
+   deregistering and allocatable components of the allocatable.  */
+
+void
+finalize_component (gfc_expr *expr, gfc_symbol *derived, gfc_component *comp,
+		gfc_expr *stat, gfc_code **code)
+{
+  gfc_expr *e;
+  e = gfc_copy_expr (expr);
+  e->ref = gfc_get_ref ();
+  e->ref->type = REF_COMPONENT;
+  e->ref->u.c.sym = derived;
+  e->ref->u.c.component = comp;
+  e->ts = comp->ts;
+
+  if (comp->attr.dimension
+  || (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
+	  && CLASS_DATA (comp)->attr.dimension))
+{
+  e->ref->next = gfc_get_ref ();
+  e->ref->next->type = REF_ARRAY;
+  e->ref->next->u.ar.type = AR_FULL;
+  e->ref->next->u.ar.dimen = 0;
+  e->ref->next->u.ar.as = comp->ts.type == BT_CLASS ? CLASS_DATA (comp)->as
+			: comp->as;
+  e->rank = e->ref->next->u.ar.as->rank;
+}
+
+  if (comp->attr.allocatable
+  || (comp->ts.type == BT_CLASS && CLASS_DATA (comp)
+	  && CLASS_DATA (comp)->attr.allocatable))

Re: [EXTERNAL] [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-13 Thread Tobias Burnus

Hi Damian, dear all,

Rouson, Damian wrote:

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.


I believe that's already covered by (3) which invokes (1) for the parent 
type – and handles the parent's components via (2). (Besides, in the 
standard is not much more than (1)–(3); thus, if it weren't implied by 
those, it likely wouldn't be part of the standard at all.)



In ForTrilnos, we need for this to happen even when the parent is abstract
but has a finalizable component.


I think that's (mostly) handled via the current wrapper subroutine (i.e. 
the finalizer of an allocatable component, which has been added in an 
abstract type, is finalized).


However, I think there are two issues with the current patch:

(a) If an abstract type has itself finalizer, it is currently not 
called. (Only its components are finalized)
(b) The current patch doesn't finalize nonallocatable [nonpointer] 
components, but those might also have a finalizer.


Thanks for your comments.

Tobias


On 8/13/12 1:05 PM, "Tobias Burnus"  wrote:

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


Re: [EXTERNAL] [Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-13 Thread Rouson, Damian
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/

[Fortran] PR37336 - FIINAL patch [1/n]: Implement the finalization wrapper subroutine

2012-08-13 Thread Tobias Burnus

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/msg00033.html (I think is okay, 
but I believe it has not yet been reviewed.)


Tobias

PS: I used the following test case to test whether the wrapper 
generation and scalarization works; it properly prints 11,22,33,44,55,66 
and also the dump looks okay for various versions.


The scalarization code should work relatively well; there is only one 
call to an external function: For SIZE gfortran - for what ever reason - 
doesn't generate inline code, but calls libgfortran.



But now the test code:

module m
type tt
end type tt

type t
! type(tt), allocatable :: comp1
integer :: val
contains
final bar1
end type t

type t1t
! type(tt), allocatable :: comp1
integer :: val
!contains
! final bar1
end type t1t

type, extends(t) :: t2
type(tt), allocatable :: comp2
contains