https://gcc.gnu.org/bugzilla/show_bug.cgi?id=90329
--- Comment #31 from Jakub Jelinek <jakub at gcc dot gnu.org> --- (In reply to Thomas Koenig from comment #30) > Hi Jakub, > > > Untested workaround that isn't a too big hammer. This should just avoid > > tail calls in functions where the hidden string arguments for > > character(len=constant) dummy arguments are passed partially or fully on the > > stack and the callee needs to pass anything on the stack and thus might > > clobber that. > > Thanks for taking this on! > > Two remarks: It should be possible to have this workaround in place > only when there is no explicit interface for the called routine. > No need to penalize modern, correct Fortran for this. First of all, the thing is that we don't have just caller and callee to consider in this case, but 3 functions, some C/C++ function (C caller below) calls incorrectly prototyped (or for C unprototyped) Fortran function (Fortran caller bellow) and that function calls some other function in a position where tail call is considered (callee bellow). I don't see how having a properly interfaced callee (and it doesn't matter if that one is implemented in Fortran or C or C++ or any other language) matters to whether we need to do this workaround or not. The bug is in the incorrect prototype visible in the C caller and the incorrect (insufficient number) of arguments in that call. Even if the callee function has proper interface, if we tail call it, we will clobber the argument area of the Fortran caller in the C caller. And it doesn't really matter what arguments the callee has, it could very well be: subroutine foo (a, b, c, d, e, f) character(len=1) :: a integer(kind=8) :: b, c, d, e, f interface subroutine bar (g, h, i, j, k, l, m) integer(kind=8) :: g, h, i, j, k, l, m end subroutine bar end interface call bar (b, c, d, e, f, 2, 3) end subroutine foo Here if we tail call bar from foo, which we generally on x86_64 can, because the caller has 6 normal arguments + 1 artificial hidden string length, and the callee has 7 normal arguments, in both cases 6 go in registers, the 7th in a stack slot, then the argument stack area is equal size (for tail call it is enough if the callee stack area is smaller or equal than caller's). > And I would like to have the Fortran part behind an option, so > people could disable this pessimization if they start using the > correct prototypes. Agreed, just no idea how to call that option and how much to express in the option name that it is a workaround for undefined behavior. > Ideally, the compiler could warn about this. It already does so > if you use -flto, but without LTO, the warning would have to > be emitted from the C compiler, and I see no even halfway sane > way of doing it. This can be diagnosed only with LTO (but it already is I think) or perhaps with some debug info parsing and analysis tool that would inspect debug info of the whole app and all libraries and complain. It is the same thing as extern int baz (int x, int y); int foo (int x, int y) { return baz (x + y, 0); } in one C TU and extern int foo (int x); int bar (void) { return foo (10); } in another one, we don't diagnose that without LTO either and can't.