Commit 9f2e27e801 for perl
commit 9f2e27e801d2895e24ceb8dda686d58e8628b736
Author: Paul Evans <leonerd@leonerd.org.uk>
Date: Wed Oct 7 17:22:31 2026 +0100
Add sv_magicv2_remove_by_shape()
diff --git a/embed.fnc b/embed.fnc
index 5c2bc6cc67..2058bb2433 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -4549,6 +4549,9 @@ p |void |parser_free_nexttoke_ops \
RTi |bool |should_warn_nl |NN const char *pv
Mp |bool |sv_has_valuemagic \
|NN const SV *sv
+Adpx |void |sv_magicv2_remove_by_shape \
+ |NN SV *sv \
+ |enum MagicShape shape
# if defined(PERL_DEBUG_READONLY_OPS)
ep |void |Slab_to_ro |NN OPSLAB *slab
ep |void |Slab_to_rw |NN OPSLAB * const slab
diff --git a/embed.h b/embed.h
index adce942b91..9dec7aa656 100644
--- a/embed.h
+++ b/embed.h
@@ -979,6 +979,7 @@
# define sv_setsv_cow(a,b) Perl_sv_setsv_cow(aTHX_ a,b)
# endif
# if defined(PERL_CORE)
+# define sv_magicv2_remove_by_shape(a,b) Perl_sv_magicv2_remove_by_shape(aTHX_ a,b)
# define PerlLIO_dup2_cloexec(a,b) Perl_PerlLIO_dup2_cloexec(aTHX_ a,b)
# define PerlLIO_dup_cloexec(a) Perl_PerlLIO_dup_cloexec(aTHX_ a)
# define PerlLIO_open3_cloexec(a,b,c) Perl_PerlLIO_open3_cloexec(aTHX_ a,b,c)
diff --git a/proto.h b/proto.h
index b6ee43aecb..7ad89638c6 100644
--- a/proto.h
+++ b/proto.h
@@ -11234,6 +11234,15 @@ Perl_sv_has_valuemagic(pTHX_ const SV *sv)
PERL_UNUSED_CONTEXT_FOR_ARGS_ASSERT; \
} STMT_END
+PERL_CALLCONV void
+Perl_sv_magicv2_remove_by_shape(pTHX_ SV *sv, enum MagicShape shape)
+ Perl_attribute_nonnull_aTHX
+ Perl_attribute_nonnull(pTHX_1);
+# define PERL_ARGS_ASSERT_SV_MAGICV2_REMOVE_BY_SHAPE \
+ STMT_START { Perl_assert_aTHX; assert(sv); \
+ PERL_UNUSED_CONTEXT_FOR_ARGS_ASSERT; \
+ } STMT_END
+
# if defined(PERL_DEBUG_READONLY_OPS)
PERL_CALLCONV void
Perl_Slab_to_ro(pTHX_ OPSLAB *slab)
diff --git a/sv.c b/sv.c
index 5fc3cc13eb..556b4636f3 100644
--- a/sv.c
+++ b/sv.c
@@ -7043,6 +7043,30 @@ Perl_sv_magicv2_remove_by_funcs(pTHX_ SV *sv, const struct MagicFunctions *funcs
S_sv_magicv2_remove(aTHX_ sv, &S_filter_mgv2_by_funcs, funcs);
}
+static bool
+S_filter_mgv2_by_shape(pTHX_ MAGIC *mg, const void *key)
+{
+ return MgFUNCS(mg)->shape == PTR2IV(key);
+}
+
+/*
+=for apidoc sv_magicv2_remove_by_shape
+
+Removes every magic attachment on the SV whose functions structure has the
+given shape. This is equivalent to calling C<sv_magicv2_remove> on each of
+them in turn, invoking any C<free> trigger functions and decrementing any
+associated SV refcounts.
+
+=cut
+*/
+
+void
+Perl_sv_magicv2_remove_by_shape(pTHX_ SV *sv, enum MagicShape shape)
+{
+ PERL_ARGS_ASSERT_SV_MAGICV2_REMOVE_BY_SHAPE;
+ S_sv_magicv2_remove(aTHX_ sv, &S_filter_mgv2_by_shape, INT2PTR(void *,shape));
+}
+
#if defined(PERL_USE_VALUEMAGIC)
static bool