Commit dd069ec447 for perl

commit dd069ec447d3595b4560fd08e5481dec9b14102b
Author: Paul Evans <leonerd@leonerd.org.uk>
Date:   Fri Oct 9 11:21:32 2026 +0100

    Give mgv2_copy() a flags argument to control strength of MgAUXSV copy

    There are existing uses of (currently v1) magic that have different
    behaviours on copying, so it would be useful to be able to reüse this
    function in those situations too.

diff --git a/embed.fnc b/embed.fnc
index 25034b90c4..22990f7aa3 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -5248,7 +5248,8 @@ Tp	|bool	|translate_substr_offsets				\
 p	|void	|mg_free_struct |NN SV *sv				\
 				|NN MAGIC *mg
 p	|void	|mgv2_copy	|NN const MAGIC *smg			\
-				|NN MAGIC *dmg
+				|NN MAGIC *dmg				\
+				|U32 flags
 p	|MAGIC *|sv_magicv2_attach					\
 				|NN SV *sv				\
 				|NN const struct MagicFunctions *funcs	\
diff --git a/embed.h b/embed.h
index 8bb2d22f46..68aeb583db 100644
--- a/embed.h
+++ b/embed.h
@@ -1521,7 +1521,7 @@
 #   endif
 #   if defined(PERL_IN_MG_C) || defined(PERL_IN_SV_C)
 #     define mg_free_struct(a,b)                Perl_mg_free_struct(aTHX_ a,b)
-#     define mgv2_copy(a,b)                     Perl_mgv2_copy(aTHX_ a,b)
+#     define mgv2_copy(a,b,c)                   Perl_mgv2_copy(aTHX_ a,b,c)
 #     define sv_magicv2_attach(a,b,c)           Perl_sv_magicv2_attach(aTHX_ a,b,c)
 #   endif
 #   if defined(PERL_IN_MRO_C)
diff --git a/mg.c b/mg.c
index 63f6dcef1e..14a8c8e62b 100644
--- a/mg.c
+++ b/mg.c
@@ -806,7 +806,7 @@ Perl_mg_propagate(pTHX_ SV *ssv, SV *dsv)
         MAGIC *dmg = NULL;
         if (funcs->flags & MGv2f_SCALARVALUE_AUTOPROPAGATE) {
             dmg = sv_magicv2_attach(dsv, MgFUNCS(smg), MgFLAGS(smg));
-            mgv2_copy(smg, dmg);
+            mgv2_copy(smg, dmg, MGv2f_COPY_DEFAULT);
         }

         if (funcs->propagate)
@@ -1054,7 +1054,7 @@ Perl_magicv2_localize_copy(pTHX_ SV *nsv, SV *osv, MAGIC *omg)
     PERL_UNUSED_ARG(osv);

     MAGIC *nmg = sv_magicv2_attach(nsv, MgFUNCS(omg), MgFLAGS(omg));
-    mgv2_copy(omg, nmg);
+    mgv2_copy(omg, nmg, MGv2f_COPY_DEFAULT);

     return nmg;
 }
diff --git a/mg.h b/mg.h
index 85e2fd0ceb..9987dfeead 100644
--- a/mg.h
+++ b/mg.h
@@ -457,6 +457,15 @@ L</MgKEYIV> or L</MgKEYSV> fields, and wish to manage their own storage.
 */
 #define MgUSERSTRUCT(mg, type)  ((type)(((char *)(mg)) + MgSIZEOF(mg)))

+#ifdef PERL_CORE
+/* Flags used by mgv2_copy() */
+enum {
+    MGv2f_COPY_DEFAULT      = 0,      /* MgAUXSV is copied with same strength as original */
+    MGv2f_COPY_AUXSV_INC    = (1<<0), /* MgAUXSV is copied strongly with inc refcount */
+    MGv2f_COPY_AUXSV_WEAKLY = (1<<1), /* MgAUXSV is copied weakly */
+};
+#endif
+
 /*
  * ex: set ts=8 sts=4 sw=4 et:
  */
diff --git a/proto.h b/proto.h
index 712761f9f6..d2be87bfdf 100644
--- a/proto.h
+++ b/proto.h
@@ -13429,7 +13429,7 @@ Perl_mg_free_struct(pTHX_ SV *sv, MAGIC *mg)
     } STMT_END

 PERL_CALLCONV void
-Perl_mgv2_copy(pTHX_ const MAGIC *smg, MAGIC *dmg)
+Perl_mgv2_copy(pTHX_ const MAGIC *smg, MAGIC *dmg, U32 flags)
         Perl_attribute_nonnull_aTHX
         Perl_attribute_nonnull(pTHX_1)
         Perl_attribute_nonnull(pTHX_2)
diff --git a/sv.c b/sv.c
index 556b4636f3..754617b79e 100644
--- a/sv.c
+++ b/sv.c
@@ -6758,13 +6758,12 @@ bad_shape:
 }

 void
-Perl_mgv2_copy(pTHX_ const MAGIC *smg, MAGIC *dmg)
+Perl_mgv2_copy(pTHX_ const MAGIC *smg, MAGIC *dmg, U32 flags)
 {
     PERL_ARGS_ASSERT_MGV2_COPY;

     MgFLAGS(dmg) = MgFLAGS(smg);
     MgPRIV(dmg)  = MgPRIV(smg);
-    MgAUXSV_set(dmg, MgAUXSV(smg));

     void *sptr = MgPTR(smg);
     STRLEN slen = MgPTRLEN(smg);
@@ -6775,11 +6774,23 @@ Perl_mgv2_copy(pTHX_ const MAGIC *smg, MAGIC *dmg)
     else if(slen)
         MgPTRLEN_set(dmg, slen);

-    if(!MgWEAK_AUXSV(smg))
-        MgWEAK_AUXSV_off(dmg);
+    switch (flags & (MGv2f_COPY_AUXSV_INC|MGv2f_COPY_AUXSV_WEAKLY)) {
+        case 0: /* default */
+            if (!MgWEAK_AUXSV(smg))
+                MgWEAK_AUXSV_off(dmg);
+            MgAUXSV_set(dmg, MgAUXSV(smg));
+            if (MgAUXSV(dmg) && !MgWEAK_AUXSV(dmg))
+                SvREFCNT_inc_void_NN(MgAUXSV(dmg));
+            break;
+
+        case MGv2f_COPY_AUXSV_INC:
+            MgAUXSV_set_inc(dmg, MgAUXSV(smg));
+            break;

-    if(MgAUXSV(dmg) && !MgWEAK_AUXSV(dmg))
-        SvREFCNT_inc_void_NN(MgAUXSV(dmg));
+        case MGv2f_COPY_AUXSV_WEAKLY:
+            MgAUXSV_set_weak(dmg, MgAUXSV(smg));
+            break;
+    }

     switch(MgFLAGS(smg) & MGv2f_WITH_MASK) {
         case 0: