Commit f553cc2db2 for perl

commit f553cc2db21c4db18c006e20854be745bca85175
Author: Yves Orton <demerphq@gmail.com>
Date:   Tue Oct 27 21:37:23 2026 +0100

    regcomp: name ANYOF properties

    Name the auxiliary data, outside-bitmap flags, regex-set inversion list,
    excluded byte, first byte, and UTF-8 string length stored by ANYOF
    nodes. This separates the meanings of shared node storage without
    changing their layout or matching behavior.

diff --git a/regcomp.c b/regcomp.c
index a385ee6fb2..28c4471675 100644
--- a/regcomp.c
+++ b/regcomp.c
@@ -8964,7 +8964,7 @@ redo_curchar:
                     {
                         vFAIL("Expecting interpolated extended charclass");
                     }
-                    resultant_invlist = (SV *) ARGp(REGNODE_p(node));
+                    resultant_invlist = REGEX_SET_INVLIST(REGNODE_p(node));
                     current = invlist_clone(resultant_invlist, NULL);
                     SvREFCNT_dec(resultant_invlist);

@@ -12637,7 +12637,7 @@ Perl_set_ANYOF_arg(pTHX_ RExC_state_t* const pRExC_state,
              *  1)  there is no list of code points matched outside the bitmap
              */
             if (! cp_list) {
-                ARG1u_SET(node, ANYOF_MATCHES_NONE_OUTSIDE_BITMAP_VALUE);
+                ANYOF_MATCHES_NONE_OUTSIDE_BITMAP_SET(node);
                 return;
             }

@@ -12646,7 +12646,7 @@ Perl_set_ANYOF_arg(pTHX_ RExC_state_t* const pRExC_state,
                 && invlist_highest_range_start(cp_list)
                                                        <= NUM_ANYOF_CODE_POINTS)
             {
-                ARG1u_SET(node, ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_VALUE);
+                ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_SET(node);
                 return;
             }

@@ -12719,7 +12719,7 @@ Perl_set_ANYOF_arg(pTHX_ RExC_state_t* const pRExC_state,
             /* Here, the existence and contents of both compile-time lists
              * are identical between the new and existing data.  Re-use the
              * existing one */
-            ARG1u_SET(node, i);
+            ANYOF_AUX_DATA_SLOT_SET(node, i);
             return;
         } /* end of loop through existing classes */
     }
@@ -12751,7 +12751,7 @@ Perl_set_ANYOF_arg(pTHX_ RExC_state_t* const pRExC_state,
     rv = newRV_noinc(MUTABLE_SV(av));
     n = reg_add_data(pRExC_state, STR_WITH_LEN("s"));
     RExC_rxi->data->data[n] = (void*)rv;
-    ARG1u_SET(node, n);
+    ANYOF_AUX_DATA_SLOT_SET(node, n);
 }
 #endif /* PERL_RE_BUILD_AUX */

@@ -12809,7 +12809,7 @@ Perl_get_re_gclass_aux_data(pTHX_ const regexp *prog, const regnode* node, bool
     const struct reg_data * const data = prog ? progi->data : NULL;

     if (data && data->count) {
-        const U32 n = ARG1u(node);
+        const U32 n = ANYOF_AUX_DATA_SLOT(node);

         if (data->what[n] == 's') {
             SV * const rv = MUTABLE_SV(data->data[n]);
diff --git a/regcomp.h b/regcomp.h
index 2cb0d6a35c..acdb828550 100644
--- a/regcomp.h
+++ b/regcomp.h
@@ -612,6 +612,28 @@ struct regnode_ssc {
     ARG2u_SET((p), (val));                                                    \
 } STMT_END

+#define ANYOF_AUX_DATA_SLOT(p)                                                \
+    (assert(ANYOF_HAS_AUX(p)), PREVENT_LVALUE(ARG1u(p)))
+#define ANYOF_AUX_DATA_SLOT_SET(p, val) STMT_START {                          \
+    assert(((val) & ANYOF_ONLY_HAS_BITMAP_MASK) !=                            \
+        ANYOF_ONLY_HAS_BITMAP_MASK);                                          \
+    ARG1u_SET((p), (val));                                                    \
+} STMT_END
+
+#define NEXACTb_BYTE(p)                                                       \
+    (assert(OP(p) == NEXACTb), PREVENT_LVALUE(ARG1u(p)))
+#define NEXACTb_BYTE_SET(p, val) STMT_START {                                 \
+    assert(OP(p) == NEXACTb);                                                 \
+    ARG1u_SET((p), (val));                                                    \
+} STMT_END
+
+#define REGEX_SET_INVLIST(p)                                                  \
+    (assert(OP(p) == REGEX_SET), ARGp(p))
+#define REGEX_SET_INVLIST_SET(p, val) STMT_START {                            \
+    assert(OP(p) == REGEX_SET);                                               \
+    ARGp_SET((p), (val));                                                     \
+} STMT_END
+
 #define REGNODE_NEXT_OFFSET(p)                                                \
     (PREVENT_LVALUE((REGNODE_OFF_BY_ARG(OP(p)) ? ARG1u(p) : NEXT_OFF(p))))
 #define REGNODE_NEXT_OFFSET_SET(p, val) STMT_START {                          \
@@ -717,6 +739,10 @@ struct regnode_ssc {
 } STMT_END

 #define IS_LOOKBEHIND(p) (LOOKBEHIND_MAX_CHARS(p) != 0)
+#define ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_SET(p)                               \
+    ARG1u_SET((p), ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_VALUE)
+#define ANYOF_MATCHES_NONE_OUTSIDE_BITMAP_SET(p)                              \
+    ARG1u_SET((p), ANYOF_MATCHES_NONE_OUTSIDE_BITMAP_VALUE)

 /* the following define was set to 0xde in 075abff3
  * as part of some linting logic. I have set it to 0
diff --git a/regcomp_debug.c b/regcomp_debug.c
index f0ebf0da9b..04db7354c3 100644
--- a/regcomp_debug.c
+++ b/regcomp_debug.c
@@ -970,14 +970,16 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o, const regmatch_
         if (op == ANYOFHs) {
             sv_catpvf(sv, " (Leading UTF-8 bytes = %s",
                 byte_dump_string_((U8 *) ((struct regnode_anyofhs *) o)->string,
-                FLAGS(o), 1));
+                STR_LEN_U8(o), 1));
         }
         else if (REGNODE_TYPE(op) != ANYOF) {
-            U8 lowest = (op != ANYOFHr)
-                         ? FLAGS(o)
-                         : LOWEST_ANYOF_HRx_BYTE(FLAGS(o));
+            U8 lowest = op == ANYOFHr
+                         ? LOWEST_ANYOF_HRx_BYTE(ANYOF_FLAGS(o))
+                         : (op == ANYOFH || op == ANYOFR)
+                           ? ANYOF_FLAGS(o)
+                           : FIRST_BYTE(o);
             U8 highest = (op == ANYOFHr)
-                         ? HIGHEST_ANYOF_HRx_BYTE(FLAGS(o))
+                         ? HIGHEST_ANYOF_HRx_BYTE(ANYOF_FLAGS(o))
                          : (op == ANYOFH || op == ANYOFR)
                            ? 0xFF
                            : lowest;
@@ -1010,7 +1012,7 @@ Perl_regprop(pTHX_ const regexp *prog, SV *sv, const regnode *o, const regmatch_
     }
     else if (op == NEXACTb) {
         sv_catpvf(sv, "[%s%c%s]",
-                       PL_colors[0], (int) ARG1u(o), PL_colors[1]);
+                       PL_colors[0], (int) NEXACTb_BYTE(o), PL_colors[1]);
     }
     else if (k == ANYOFHbbm) {
         SV * cp_list = get_ANYOFHbbm_contents(o);
diff --git a/regcomp_study.c b/regcomp_study.c
index e525048e1e..6706d67547 100644
--- a/regcomp_study.c
+++ b/regcomp_study.c
@@ -379,7 +379,7 @@ Perl_ssc_init(pTHX_ const RExC_state_t *pRExC_state, regnode_ssc *ssc)

     Zero(ssc, 1, regnode_ssc);
     set_ANYOF_SYNTHETIC(ssc);
-    ARG1u_SET(ssc, ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_VALUE);
+    ANYOF_MATCHES_ALL_OUTSIDE_BITMAP_SET(ssc);
     ssc_anything(ssc);

     /* If any portion of the regex is to operate under locale rules that aren't
@@ -456,7 +456,7 @@ S_get_ANYOF_cp_list_for_ssc(pTHX_ const RExC_state_t *pRExC_state,
         invlist = add_range_to_invlist_(invlist, NUM_ANYOF_CODE_POINTS, UV_MAX);
     }
     else if (ANYOF_HAS_AUX(node)) {
-        const U32 n = ARG1u(node);
+        const U32 n = ANYOF_AUX_DATA_SLOT(node);
         SV * const rv = MUTABLE_SV(RExC_rxi->data->data[n]);
         AV * const av = AV_FROM_REF(rv);
         SV **const ary = AvARRAY(av);
@@ -3156,7 +3156,7 @@ Perl_study_chunk(pTHX_
                   {
                     SV* Nb_invlist = new_invlist_(2);
                     Nb_invlist = add_cp_to_invlist(Nb_invlist,
-                                                   (U8) ARG1u(scan));
+                                                   (U8) NEXACTb_BYTE(scan));
                     if (flags & SCF_DO_STCLASS_OR) {
                         ssc_union(data->start_class, Nb_invlist, true);
                     }
diff --git a/regexec.c b/regexec.c
index a02c653278..116021a9be 100644
--- a/regexec.c
+++ b/regexec.c
@@ -2669,13 +2669,13 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
       case NEXACTb_tb_pb:
       case NEXACTb_tb_p8:
         REXEC_FBC_NON_UTF8_FIND_NEXT_SCAN(
-           find_span_end((U8 *) s, (U8 *) strend, (U8) ARG1u(c)));
+           find_span_end((U8 *) s, (U8 *) strend, (U8) NEXACTb_BYTE(c)));
         break;

       case NEXACTb_t8_pb:
       case NEXACTb_t8_p8:
         REXEC_FBC_UTF8_CLASS_SCAN(
-           ! (UTF8SKIP(s) == 1 && (U8) *s == (U8) ARG1u(c)));
+           ! (UTF8SKIP(s) == 1 && (U8) *s == (U8) NEXACTb_BYTE(c)));
         break;

       /* These nodes all require at least one code point to be in UTF-8 to
@@ -2711,7 +2711,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
       case ANYOFHb_t8_p8:
         {
             /* We know what the first byte of any matched string should be. */
-            U8 first_byte = FLAGS(c);
+            U8 first_byte = FIRST_BYTE(c);

             anyofh_list = GET_ANYOFH_INVLIST(prog, c);
             REXEC_FBC_FIND_NEXT_UTF8_BYTE_SCAN(first_byte,
@@ -2726,7 +2726,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
       case ANYOFHbbm_t8_p8:
         {
             /* We know what the first byte of any matched string should be. */
-            U8 first_byte = FLAGS(c);
+            U8 first_byte = FIRST_BYTE(c);

             /* And a bitmap defines all the legal 2nd byte matches */
             REXEC_FBC_FIND_NEXT_UTF8_BYTE_SCAN(first_byte,
@@ -2755,7 +2755,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
         REXEC_FBC_FIND_NEXT_UTF8_STRING_SCAN(
                         ((struct regnode_anyofhs *) c)->string,
                         /* Note FLAGS is the string length in this regnode */
-                        ((struct regnode_anyofhs *) c)->string + FLAGS(c),
+                        ((struct regnode_anyofhs *) c)->string + STR_LEN_U8(c),
                         invlist_contains_cp_(anyofh_list,
                                              utf8_to_uv_or_die((U8 *) s,
                                                                (U8 *) strend,
@@ -2787,7 +2787,7 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
       case ANYOFRb_t8_pb:
       case ANYOFRb_t8_p8:
         {   /* We know what the first byte of any matched string should be */
-            U8 first_byte = FLAGS(c);
+            U8 first_byte = FIRST_BYTE(c);

             REXEC_FBC_FIND_NEXT_UTF8_BYTE_SCAN(first_byte,
                                 withinCOUNT(utf8_to_uv_or_die((U8 *) s,
@@ -8369,7 +8369,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)

         case NEXACTb: /*  /[^x]/ : single excluded byte  */
             if (   NEXTCHR_IS_EOS
-                || (U8) ARG1u(scan) == UCHARAT(locinput)
+                || (U8) NEXACTb_BYTE(scan) == UCHARAT(locinput)
                 || locinput >= loceol)
             {
                 sayNO;
@@ -8440,8 +8440,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
         case ANYOFHs:
             if (   ! utf8_target
                 ||   NEXTCHR_IS_EOS
-                ||   loceol - locinput < FLAGS(scan)
-                ||   memNE(locinput, ((struct regnode_anyofhs *) scan)->string, FLAGS(scan))
+                ||   loceol - locinput < STR_LEN_U8(scan)
+                ||   memNE(locinput, ((struct regnode_anyofhs *) scan)->string, STR_LEN_U8(scan))
                 || ! (anyofh_list = GET_ANYOFH_INVLIST(rex, scan))
                 || ! invlist_contains_cp_(anyofh_list,
                                           utf8_to_uv_or_die((U8 *) locinput,
@@ -11419,7 +11419,7 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,

       case NEXACTb_t8:
         {
-          const U8 nchar = (U8) ARG1u(p);
+          const U8 nchar = (U8) NEXACTb_BYTE(p);
           while (     hardcount < max
                  &&   scan < this_eol
                  &&  (UTF8SKIP(scan) != 1 || (U8) *scan != nchar))
@@ -11432,7 +11432,7 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,

       case NEXACTb_tb:
         {
-          char * found = (char *) memchr(scan, (U8) ARG1u(p),
+          char * found = (char *) memchr(scan, (U8) NEXACTb_BYTE(p),
                                          this_eol - scan);
           scan = found ? found : this_eol;
         }
@@ -11509,8 +11509,8 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
       case ANYOFHs_t8:
         anyofh_list = GET_ANYOFH_INVLIST(prog, p);
         while (   hardcount < max
-               && scan + FLAGS(p) < this_eol
-               && memEQ(scan, ((struct regnode_anyofhs *) p)->string, FLAGS(p))
+               && scan + STR_LEN_U8(p) < this_eol
+               && memEQ(scan, ((struct regnode_anyofhs *) p)->string, STR_LEN_U8(p))
                && invlist_contains_cp_(anyofh_list,
                                        utf8_to_uv_or_die((U8 *) scan,
                                                          (U8 *) this_eol,
@@ -11884,7 +11884,7 @@ S_reginclass(pTHX_ regexp * const prog, const regnode * const n, const U8* const
         {
             /* In this case, the ARG is set up so that the final bit indicates
              * whether it matches or not */
-            match = ARG1u(n) & 1;
+            match = ANYOF_MATCHES_ALL_OUTSIDE_BITMAP(n);
         }
         else
             /* Here, the main way it could match is if the code point is