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.

Reply via email to