Hi Chris!
Am 10.11.25 um 00:45 schrieb Christopher Albert:
Thanks, Harald!
On Sun, 9 Nov 2025 22:57:29 +0100
Harald Anlauf <[email protected]> wrote:
Am 08.11.25 um 18:03 schrieb Jerry D:
On 11/7/25 8:30 PM, Christopher Albert wrote:
Derived types with recursive allocatable components and FINAL
procedures trigger an ICE in gimplify_call_expr because the
finalizer wrapper's result
symbol references itself (final->result = final), creating a
cycle. This patch creates a separate __result_<typename> symbol to
break the cycle.
Self-assignment (a = a) with such types causes use-after-free
because the left-hand side is finalized before copying, destroying
the source. The patch
adds detection using gfc_dep_compare_expr at compile time and
pointer comparison at runtime to skip finalization when lhs == rhs.
Test pr112459.f90 now expects 6 _final calls instead of 12 because
separate
result symbols eliminate double-counting in tree dumps.
--- snip ---
Applies and test OK here. I want to see if any one else has any
comments.
Jerry
Albert,
I did see the patch with commit messages inlined, not attached.
Hope this did not lead me to wrong observations.
I attach now an updated patch (still not used to the process).
The commit message is not properly formed here; there should not
be <TAB><SPACE><SPACE> for continuation lines, just <TAB>.
Trying to push would lead to a rejection by the filters.
Thanks for pointing that out, this is fixed.
Regarding the run-time testcases: while writing to stdout and
checking the output with a pattern works, also please consider
the alternative
"if (result /= expected) stop n"
where you think it is appropriate (e.g. the total finalization count)
and where it may make the testcase easier to read for others.
(Not critical, though).
I modified testcase finalizer_self_assign.f90 slightly by replacing
the self-assignment
a = a
by
a = (a)
and get a runtime failure:
ERROR: a%next deallocated
ERROR STOP 1
with a traceback from the ERROR STOP. That case might need a
different treatment, maybe a temporary, to be able keep the nested
components. Can you have a further look?
If you do not find a simple fix, we might proceed and track this
issue either in the existing PR or move it to a different one.
(NAG and Intel seem to get this variant right.)
Found a simple fix, should work now. Hope this is clean enough.
Hmm, this works for scalar instances, but does not get the bounds
right for arrays.
Example: add to test_self_assign of finalizer_self_assign.f90:
block
type(node_t), allocatable :: b(:), c(:)
allocate (b(5:5))
b = (b)
print *, lbound (b) ! Should print: 1
end block
This now prints:
5
Interestingly, NAG prints the same!
Only Intel (ifx) gets it right:
1
This is because lbound (b,1) = 5, but lbound ((b),1) = 1;
see F2023:10.2.1.3 and the description of LBOUND.
(The parentheses enforce the resetting of the bounds).
@Jerry: we could proceed with the current patch, maybe add a TODO
for the array assignment case and let Chris check if he finds a
separate solution for the rank /= 0 version.
Thanks,
Harald
Thanks,
Harald
Best,
Chris