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

Reply via email to