https://gcc.gnu.org/bugzilla/show_bug.cgi?id=119376
--- Comment #29 from GCC Commits <cvs-commit at gcc dot gnu.org> --- The master branch has been updated by Jakub Jelinek <ja...@gcc.gnu.org>: https://gcc.gnu.org/g:634215cdc3c569f9a9a247dcd4d9a4d6ce68ad57 commit r15-9145-g634215cdc3c569f9a9a247dcd4d9a4d6ce68ad57 Author: Jakub Jelinek <ja...@redhat.com> Date: Wed Apr 2 10:51:42 2025 +0200 tailc: Don't fail musttail calls if they use or could use local arguments, instead warn [PR119376] As discussed here and in bugzilla, [[clang::musttail]] attribute in clang not just strongly asks for tail call or error, but changes behavior. To quote: https://clang.llvm.org/docs/AttributeReference.html#musttail "The lifetimes of all local variables and function parameters end immediately before the call to the function. This means that it is undefined behaviour to pass a pointer or reference to a local variable to the called function, which is not the case without the attribute. Clang will emit a warning in common cases where this happens." The GCC behavior was just to error if we can't prove the musttail callee could not have dereferenced escaped pointers to local vars or parameters of the caller. That is still the case for variables with non-trivial destruction (even in clang), like vars with C++ non-trivial destructors or variables with cleanup attribute. The following patch changes the behavior to match that of clang, for all of [[clang::musttail]], [[gnu::musttail]] and __attribute__((musttail)). clang 20 actually added warning for some cases of it in https://github.com/llvm/llvm-project/pull/109255 but it is under -Wreturn-stack-address warning. Now, gcc doesn't have that warning, but -Wreturn-local-addr instead, and IMHO it is better to have this under new warnings, because this isn't about returning local address, but about passing it to a musttail call, or maybe escaping to a musttail call. And perhaps users will appreciate they can control it separately as well. The patch introduces 2 new warnings. -Wmusttail-local-addr which is turn on by default and warns for the always dumb cases of passing an address of a local variable or parameter to musttail call's argument. And then -Wmaybe-musttail-local-addr which is only diagnosed if -Wmusttail-local-addr was not diagnosed and diagnoses at most one (so that we don't emit 100s of warnings for one call if 100s of vars can escape) case where an address of a local var could have escaped to the musttail call. This is less severe, the code doesn't have to be obviously wrong, so the warning is only enabled in -Wextra. And I've adjusted also the documentation for this change and addition of new warnings. 2025-04-02 Jakub Jelinek <ja...@redhat.com> PR ipa/119376 * common.opt (Wmusttail-local-addr, Wmaybe-musttail-local-addr): New. * tree-tailcall.cc (suitable_for_tail_call_opt_p): Don't fail for TREE_ADDRESSABLE PARM_DECLs for musttail calls if diag_musttail. Emit -Wmusttail-local-addr warnings. (maybe_error_musttail): Use gimple_location instead of directly accessing location member. (find_tail_calls): For musttail calls if diag_musttail, don't fail if address of local could escape to the call, instead emit -Wmaybe-musttail-local-addr warnings. Emit -Wmaybe-musttail-local-addr warnings also for address taken parameters. * common.opt.urls: Regenerate. * doc/extend.texi (musttail statement attribute): Clarify local variables without non-trivial destruction are considered out of scope before the tail call instruction. * doc/invoke.texi (-Wno-musttail-local-addr, -Wmaybe-musttail-local-addr): Document. * c-c++-common/musttail8.c: Expect a warning rather than error in one case. (f4): Add int * argument. * c-c++-common/musttail15.c: Don't disallow for C++98. * c-c++-common/musttail16.c: Likewise. * c-c++-common/musttail17.c: Likewise. * c-c++-common/musttail18.c: Likewise. * c-c++-common/musttail19.c: Likewise. Expect a warning rather than error in one case. (f4): Add int * argument. * c-c++-common/musttail20.c: Don't disallow for C++98. * c-c++-common/musttail21.c: Likewise. * c-c++-common/musttail28.c: New test. * c-c++-common/musttail29.c: New test. * c-c++-common/musttail30.c: New test. * c-c++-common/musttail31.c: New test. * g++.dg/ext/musttail1.C: New test. * g++.dg/ext/musttail2.C: New test. * g++.dg/ext/musttail3.C: New test.