From fe22bdabd4ca51c036e5e2ab89f56ffe32f4cac9 Mon Sep 17 00:00:00 2001 From: Josef Melcr Date: Mon, 8 Dec 2025 09:21:38 +0100 Subject: [PATCH] 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 --- 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 3c21e174943..1a7d49922e0 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 49f0e58fa1e..816fc53c28a 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; } -- 2.47.3