https://gcc.gnu.org/g:fe22bdabd4ca51c036e5e2ab89f56ffe32f4cac9

commit r16-5959-gfe22bdabd4ca51c036e5e2ab89f56ffe32f4cac9
Author: Josef Melcr <[email protected]>
Date:   Mon Dec 8 09:21:38 2025 +0100

    ipa/122798: Adjust local and address_taken flags for callback clones.
    
    Hi,
    previously, clones of callback functions had their local flag set.
    Because callback edges are direct rather than indirect, GCC falsely
    assumes that their callsites are available and that it can change their
    ABI, leading to segfaults.  This patch fixes that.  Additionally, this
    patch fixes a check in redirect_callee for clearing the address_taken
    flag.
    
            PR ipa/122798
    
    gcc/ChangeLog:
    
            * cgraph.cc (cgraph_edge::redirect_callee): Use
            iterate_referring instead of referred_to_p.
            * cgraphclones.cc (set_new_clone_decl_and_node_flags): Set local
            to true iff the node does not have its address taken.
    
    Signed-off-by: Josef Melcr <[email protected]>

Diff:
---
 gcc/cgraph.cc       | 6 +++++-
 gcc/cgraphclones.cc | 4 +++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/gcc/cgraph.cc b/gcc/cgraph.cc
index 3c21e1749430..1a7d49922e09 100644
--- a/gcc/cgraph.cc
+++ b/gcc/cgraph.cc
@@ -1696,8 +1696,12 @@ cgraph_edge::redirect_callee (cgraph_node *n)
       old_ref->remove_reference ();
       ipa_ref *new_ref = caller->create_reference (n, IPA_REF_ADDR, call_stmt);
       new_ref->lto_stmt_uid = lto_stmt_uid;
-      if (!old_callee->referred_to_p ())
+      /* If the last reference to OLD_CALLEE has been redirected, unset
+        address_taken.  old_ref is only used as a placeholder when looking for
+        a different reference.  */
+      if (!old_callee->iterate_referring (0, old_ref))
        old_callee->address_taken = 0;
+      n->mark_address_taken ();
     }
 
   if (!inline_failed)
diff --git a/gcc/cgraphclones.cc b/gcc/cgraphclones.cc
index 49f0e58fa1ef..816fc53c28a1 100644
--- a/gcc/cgraphclones.cc
+++ b/gcc/cgraphclones.cc
@@ -176,7 +176,9 @@ set_new_clone_decl_and_node_flags (cgraph_node *new_node)
   DECL_IS_REPLACEABLE_OPERATOR (new_node->decl) = 0;
 
   new_node->externally_visible = 0;
-  new_node->local = 1;
+  /* Clones of callbacks might have their address taken, and thus cannot be
+     local.  */
+  new_node->local = !new_node->address_taken;
   new_node->lowered = true;
   new_node->semantic_interposition = 0;
 }

Reply via email to