This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
Correct OPf_SPECIAL/OP_UNSTACK comment
[perl5.git] / regexec.c
index 77e5b55..e74ca18 100644 (file)
--- a/regexec.c
+++ b/regexec.c
@@ -536,12 +536,10 @@ S_isFOO_utf8_lc(pTHX_ const U8 classnum, const U8* character)
         case _CC_ENUM_BLANK:     return is_HORIZWS_high(character);
         case _CC_ENUM_XDIGIT:    return is_XDIGIT_high(character);
         case _CC_ENUM_VERTSPACE: return is_VERTWS_high(character);
-        default:                 return 0;  /* Things like CNTRL are always
-                                               below 256 */
+        default:                 break;
     }
 
-    assert(0); /* NOTREACHED */
-    return FALSE;
+    return FALSE; /* Things like CNTRL are always below 256 */
 }
 
 /*
@@ -705,6 +703,7 @@ Perl_re_intuit_start(pTHX_
        goto fail;
     }
 
+    RX_MATCH_UTF8_set(rx,utf8_target);
     reginfo->is_utf8_target = cBOOL(utf8_target);
     reginfo->info_aux = NULL;
     reginfo->strbeg = strbeg;
@@ -774,7 +773,7 @@ Perl_re_intuit_start(pTHX_
              * be too fiddly (e.g. REXEC_IGNOREPOS).
              */
             if (   strpos != strbeg
-                && (prog->intflags & (PREGf_ANCH_BOL|PREGf_ANCH_SBOL)))
+                && (prog->intflags & PREGf_ANCH_SBOL))
             {
                DEBUG_EXECUTE_r(PerlIO_printf(Perl_debug_log,
                                 "  Not at start...\n"));
@@ -898,7 +897,7 @@ Perl_re_intuit_start(pTHX_
 
 
         /* If the regex is absolutely anchored to either the start of the
-         * string (BOL,SBOL) or to pos() (ANCH_GPOS), then
+         * string (SBOL) or to pos() (ANCH_GPOS), then
          * check_offset_max represents an upper bound on the string where
          * the substr could start. For the ANCH_GPOS case, we assume that
          * the caller of intuit will have already set strpos to
@@ -1502,6 +1501,10 @@ STMT_START {
     }                                                                               \
 } STMT_END
 
+#define DUMP_EXEC_POS(li,s,doutf8)                          \
+    dump_exec_pos(li,s,(reginfo->strend),(reginfo->strbeg), \
+                startpos, doutf8)
+
 #define REXEC_FBC_EXACTISH_SCAN(COND)                     \
 STMT_START {                                              \
     while (s <= e) {                                      \
@@ -1529,34 +1532,30 @@ STMT_START {                                          \
     }                                                 \
 } STMT_END
 
-#define REXEC_FBC_UTF8_CLASS_SCAN(COND)               \
-REXEC_FBC_UTF8_SCAN(                                  \
-    if (COND) {                                       \
-       if (tmp && (reginfo->intuit || regtry(reginfo, &s))) \
-           goto got_it;                              \
-       else                                          \
-           tmp = doevery;                            \
-    }                                                 \
-    else                                              \
-       tmp = 1;                                      \
+#define REXEC_FBC_UTF8_CLASS_SCAN(COND)                        \
+REXEC_FBC_UTF8_SCAN( /* Loops while (s < strend) */            \
+    if (COND) {                                                \
+       if (tmp && (reginfo->intuit || regtry(reginfo, &s)))   \
+           goto got_it;                                       \
+       else                                                   \
+           tmp = doevery;                                     \
+    }                                                          \
+    else                                                       \
+       tmp = 1;                                               \
 )
 
-#define REXEC_FBC_CLASS_SCAN(COND)                    \
-REXEC_FBC_SCAN(                                       \
-    if (COND) {                                       \
-       if (tmp && (reginfo->intuit || regtry(reginfo, &s)))  \
-           goto got_it;                              \
-       else                                          \
-           tmp = doevery;                            \
-    }                                                 \
-    else                                              \
-       tmp = 1;                                      \
+#define REXEC_FBC_CLASS_SCAN(COND)                             \
+REXEC_FBC_SCAN( /* Loops while (s < strend) */                 \
+    if (COND) {                                                \
+       if (tmp && (reginfo->intuit || regtry(reginfo, &s)))   \
+           goto got_it;                                       \
+       else                                                   \
+           tmp = doevery;                                     \
+    }                                                          \
+    else                                                       \
+       tmp = 1;                                               \
 )
 
-#define REXEC_FBC_TRYIT                       \
-if ((reginfo->intuit || regtry(reginfo, &s))) \
-    goto got_it
-
 #define REXEC_FBC_CSCAN(CONDUTF8,COND)                         \
     if (utf8_target) {                                         \
        REXEC_FBC_UTF8_CLASS_SCAN(CONDUTF8);                   \
@@ -1564,97 +1563,152 @@ if ((reginfo->intuit || regtry(reginfo, &s))) \
     else {                                                     \
        REXEC_FBC_CLASS_SCAN(COND);                            \
     }
-    
-#define DUMP_EXEC_POS(li,s,doutf8)                          \
-    dump_exec_pos(li,s,(reginfo->strend),(reginfo->strbeg), \
-                startpos, doutf8)
-
 
+/* The three macros below are slightly different versions of the same logic.
+ *
+ * The first is for /a and /aa when the target string is UTF-8.  This can only
+ * match ascii, but it must advance based on UTF-8.   The other two handle the
+ * non-UTF-8 and the more generic UTF-8 cases.   In all three, we are looking
+ * for the boundary (or non-boundary) between a word and non-word character.
+ * The utf8 and non-utf8 cases have the same logic, but the details must be
+ * different.  Find the "wordness" of the character just prior to this one, and
+ * compare it with the wordness of this one.  If they differ, we have a
+ * boundary.  At the beginning of the string, pretend that the previous
+ * character was a new-line.
+ *
+ * All these macros uncleanly have side-effects with each other and outside
+ * variables.  So far it's been too much trouble to clean-up
+ *
+ * TEST_NON_UTF8 is the macro or function to call to test if its byte input is
+ *               a word character or not.
+ * IF_SUCCESS    is code to do if it finds that we are at a boundary between
+ *               word/non-word
+ * IF_FAIL       is code to do if we aren't at a boundary between word/non-word
+ *
+ * Exactly one of the two IF_FOO parameters is a no-op, depending on whether we
+ * are looking for a boundary or for a non-boundary.  If we are looking for a
+ * boundary, we want IF_FAIL to be the no-op, and for IF_SUCCESS to go out and
+ * see if this tentative match actually works, and if so, to quit the loop
+ * here.  And vice-versa if we are looking for a non-boundary.
+ *
+ * 'tmp' below in the next three macros in the REXEC_FBC_SCAN and
+ * REXEC_FBC_UTF8_SCAN loops is a loop invariant, a bool giving the return of
+ * TEST_NON_UTF8(s-1).  To see this, note that that's what it is defined to be
+ * at entry to the loop, and to get to the IF_FAIL branch, tmp must equal
+ * TEST_NON_UTF8(s), and in the opposite branch, IF_SUCCESS, tmp is that
+ * complement.  But in that branch we complement tmp, meaning that at the
+ * bottom of the loop tmp is always going to be equal to TEST_NON_UTF8(s),
+ * which means at the top of the loop in the next iteration, it is
+ * TEST_NON_UTF8(s-1) */
 #define FBC_UTF8_A(TEST_NON_UTF8, IF_SUCCESS, IF_FAIL)                         \
-       tmp = (s != reginfo->strbeg) ? UCHARAT(s - 1) : '\n';                  \
-       tmp = TEST_NON_UTF8(tmp);                                              \
-       REXEC_FBC_UTF8_SCAN(                                                   \
-           if (tmp == ! TEST_NON_UTF8((U8) *s)) {                             \
-               tmp = !tmp;                                                    \
-               IF_SUCCESS;                                                    \
-           }                                                                  \
-           else {                                                             \
-               IF_FAIL;                                                       \
-           }                                                                  \
-       );                                                                     \
-
-#define FBC_UTF8(TEST1_UTF8, TEST2_UTF8, IF_SUCCESS, IF_FAIL)                  \
-       if (s == reginfo->strbeg) {                                            \
-           tmp = '\n';                                                        \
-       }                                                                      \
-       else {                                                                 \
-           U8 * const r = reghop3((U8*)s, -1, (U8*)reginfo->strbeg);          \
-           tmp = utf8n_to_uvchr(r, (U8*) reginfo->strend - r,                 \
+    tmp = (s != reginfo->strbeg) ? UCHARAT(s - 1) : '\n';                      \
+    tmp = TEST_NON_UTF8(tmp);                                                  \
+    REXEC_FBC_UTF8_SCAN( /* advances s while s < strend */                     \
+        if (tmp == ! TEST_NON_UTF8((U8) *s)) {                                 \
+            tmp = !tmp;                                                        \
+            IF_SUCCESS; /* Is a boundary if values for s-1 and s differ */     \
+        }                                                                      \
+        else {                                                                 \
+            IF_FAIL;                                                           \
+        }                                                                      \
+    );                                                                         \
+
+/* Like FBC_UTF8_A, but TEST_UV is a macro which takes a UV as its input, and
+ * TEST_UTF8 is a macro that for the same input code points returns identically
+ * to TEST_UV, but takes a pointer to a UTF-8 encoded string instead */
+#define FBC_UTF8(TEST_UV, TEST_UTF8, IF_SUCCESS, IF_FAIL)                      \
+    if (s == reginfo->strbeg) {                                                \
+        tmp = '\n';                                                            \
+    }                                                                          \
+    else { /* Back-up to the start of the previous character */                \
+        U8 * const r = reghop3((U8*)s, -1, (U8*)reginfo->strbeg);              \
+        tmp = utf8n_to_uvchr(r, (U8*) reginfo->strend - r,                     \
                                                        0, UTF8_ALLOW_DEFAULT); \
-       }                                                                      \
-       tmp = TEST1_UTF8;                                                      \
-       LOAD_UTF8_CHARCLASS_ALNUM();                                           \
-       REXEC_FBC_UTF8_SCAN(                                                   \
-           if (tmp == ! (TEST2_UTF8)) {                                       \
-               tmp = !tmp;                                                    \
-               IF_SUCCESS;                                                    \
-           }                                                                  \
-           else {                                                             \
-               IF_FAIL;                                                       \
-           }                                                                  \
-       );                                                                     \
+    }                                                                          \
+    tmp = TEST_UV(tmp);                                                        \
+    LOAD_UTF8_CHARCLASS_ALNUM();                                               \
+    REXEC_FBC_UTF8_SCAN( /* advances s while s < strend */                     \
+        if (tmp == ! (TEST_UTF8((U8 *) s))) {                                  \
+            tmp = !tmp;                                                        \
+            IF_SUCCESS;                                                        \
+        }                                                                      \
+        else {                                                                 \
+            IF_FAIL;                                                           \
+        }                                                                      \
+    );
 
-/* The only difference between the BOUND and NBOUND cases is that
- * REXEC_FBC_TRYIT is called when matched in BOUND, and when non-matched in
- * NBOUND.  This is accomplished by passing it in either the if or else clause,
- * with the other one being empty */
-#define FBC_BOUND(TEST_NON_UTF8, TEST1_UTF8, TEST2_UTF8) \
-    FBC_BOUND_COMMON(FBC_UTF8(TEST1_UTF8, TEST2_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER), TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER)
-
-#define FBC_BOUND_A(TEST_NON_UTF8, TEST1_UTF8, TEST2_UTF8) \
-    FBC_BOUND_COMMON(FBC_UTF8_A(TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER), TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER)
-
-#define FBC_NBOUND(TEST_NON_UTF8, TEST1_UTF8, TEST2_UTF8) \
-    FBC_BOUND_COMMON(FBC_UTF8(TEST1_UTF8, TEST2_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT), TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT)
-
-#define FBC_NBOUND_A(TEST_NON_UTF8, TEST1_UTF8, TEST2_UTF8) \
-    FBC_BOUND_COMMON(FBC_UTF8_A(TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT), TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT)
-
-
-/* Common to the BOUND and NBOUND cases.  Unfortunately the UTF8 tests need to
- * be passed in completely with the variable name being tested, which isn't
- * such a clean interface, but this is easier to read than it was before.  We
- * are looking for the boundary (or non-boundary between a word and non-word
- * character.  The utf8 and non-utf8 cases have the same logic, but the details
- * must be different.  Find the "wordness" of the character just prior to this
- * one, and compare it with the wordness of this one.  If they differ, we have
- * a boundary.  At the beginning of the string, pretend that the previous
- * character was a new-line */
+/* Like the above two macros.  UTF8_CODE is the complete code for handling
+ * UTF-8.  Common to the BOUND and NBOUND cases, set-up by the FBC_BOUND, etc
+ * macros below */
 #define FBC_BOUND_COMMON(UTF8_CODE, TEST_NON_UTF8, IF_SUCCESS, IF_FAIL)        \
     if (utf8_target) {                                                         \
-               UTF8_CODE                                                      \
+        UTF8_CODE                                                              \
     }                                                                          \
     else {  /* Not utf8 */                                                     \
        tmp = (s != reginfo->strbeg) ? UCHARAT(s - 1) : '\n';                  \
        tmp = TEST_NON_UTF8(tmp);                                              \
-       REXEC_FBC_SCAN(                                                        \
+       REXEC_FBC_SCAN( /* advances s while s < strend */                      \
            if (tmp == ! TEST_NON_UTF8((U8) *s)) {                             \
-               tmp = !tmp;                                                    \
                IF_SUCCESS;                                                    \
+               tmp = !tmp;                                                    \
            }                                                                  \
            else {                                                             \
                IF_FAIL;                                                       \
            }                                                                  \
        );                                                                     \
     }                                                                          \
-    if ((!prog->minlen && tmp) && (reginfo->intuit || regtry(reginfo, &s)))    \
-       goto got_it;
+    /* Here, things have been set up by the previous code so that tmp is the   \
+     * return of TEST_NON_UTF(s-1) or TEST_UTF8(s-1) (depending on the         \
+     * utf8ness of the target).  We also have to check if this matches against \
+     * the EOS, which we treat as a \n (which is the same value in both UTF-8  \
+     * or non-UTF8, so can use the non-utf8 test condition even for a UTF-8    \
+     * string */                                                               \
+    if (tmp == ! TEST_NON_UTF8('\n')) {                                        \
+        IF_SUCCESS;                                                            \
+    }                                                                          \
+    else {                                                                     \
+        IF_FAIL;                                                               \
+    }
+
+/* This is the macro to use when we want to see if something that looks like it
+ * could match, actually does, and if so exits the loop */
+#define REXEC_FBC_TRYIT                            \
+    if ((reginfo->intuit || regtry(reginfo, &s)))  \
+        goto got_it
+
+/* The only difference between the BOUND and NBOUND cases is that
+ * REXEC_FBC_TRYIT is called when matched in BOUND, and when non-matched in
+ * NBOUND.  This is accomplished by passing it as either the if or else clause,
+ * with the other one being empty (PLACEHOLDER is defined as empty).
+ *
+ * The TEST_FOO parameters are for operating on different forms of input, but
+ * all should be ones that return identically for the same underlying code
+ * points */
+#define FBC_BOUND(TEST_NON_UTF8, TEST_UV, TEST_UTF8)                           \
+    FBC_BOUND_COMMON(                                                          \
+          FBC_UTF8(TEST_UV, TEST_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER),          \
+          TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER)
+
+#define FBC_BOUND_A(TEST_NON_UTF8, TEST_UV, TEST_UTF8)                         \
+    FBC_BOUND_COMMON(                                                          \
+            FBC_UTF8_A(TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER),           \
+            TEST_NON_UTF8, REXEC_FBC_TRYIT, PLACEHOLDER)
+
+#define FBC_NBOUND(TEST_NON_UTF8, TEST_UV, TEST_UTF8)                          \
+    FBC_BOUND_COMMON(                                                          \
+          FBC_UTF8(TEST_UV, TEST_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT),          \
+          TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT)
+
+#define FBC_NBOUND_A(TEST_NON_UTF8, TEST_UV, TEST_UTF8)                        \
+    FBC_BOUND_COMMON(                                                          \
+            FBC_UTF8_A(TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT),           \
+            TEST_NON_UTF8, PLACEHOLDER, REXEC_FBC_TRYIT)
+
 
 /* We know what class REx starts with.  Try to find this position... */
 /* if reginfo->intuit, its a dryrun */
 /* annoyingly all the vars in this routine have different names from their counterparts
    in regmatch. /grrr */
-
 STATIC char *
 S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s, 
     const char *strend, regmatch_info *reginfo)
@@ -1843,45 +1897,30 @@ S_find_byclass(pTHX_ regexp * prog, const regnode *c, char *s,
         }
         break;
     }
+
     case BOUNDL:
-        FBC_BOUND(isWORDCHAR_LC,
-                  isWORDCHAR_LC_uvchr(tmp),
-                  isWORDCHAR_LC_utf8((U8*)s));
+        FBC_BOUND(isWORDCHAR_LC, isWORDCHAR_LC_uvchr, isWORDCHAR_LC_utf8);
         break;
     case NBOUNDL:
-        FBC_NBOUND(isWORDCHAR_LC,
-                   isWORDCHAR_LC_uvchr(tmp),
-                   isWORDCHAR_LC_utf8((U8*)s));
+        FBC_NBOUND(isWORDCHAR_LC, isWORDCHAR_LC_uvchr, isWORDCHAR_LC_utf8);
         break;
     case BOUND:
-        FBC_BOUND(isWORDCHAR,
-                  isWORDCHAR_uni(tmp),
-                  cBOOL(swash_fetch(PL_utf8_swash_ptrs[_CC_WORDCHAR], (U8*)s, utf8_target)));
+        FBC_BOUND(isWORDCHAR, isWORDCHAR_uni, isWORDCHAR_utf8);
         break;
     case BOUNDA:
-        FBC_BOUND_A(isWORDCHAR_A,
-                    isWORDCHAR_A(tmp),
-                    isWORDCHAR_A((U8*)s));
+        FBC_BOUND_A(isWORDCHAR_A, isWORDCHAR_A, isWORDCHAR_A);
         break;
     case NBOUND:
-        FBC_NBOUND(isWORDCHAR,
-                   isWORDCHAR_uni(tmp),
-                   cBOOL(swash_fetch(PL_utf8_swash_ptrs[_CC_WORDCHAR], (U8*)s, utf8_target)));
+        FBC_NBOUND(isWORDCHAR, isWORDCHAR_uni, isWORDCHAR_utf8);
         break;
     case NBOUNDA:
-        FBC_NBOUND_A(isWORDCHAR_A,
-                     isWORDCHAR_A(tmp),
-                     isWORDCHAR_A((U8*)s));
+        FBC_NBOUND_A(isWORDCHAR_A, isWORDCHAR_A, isWORDCHAR_A);
         break;
     case BOUNDU:
-        FBC_BOUND(isWORDCHAR_L1,
-                  isWORDCHAR_uni(tmp),
-                  cBOOL(swash_fetch(PL_utf8_swash_ptrs[_CC_WORDCHAR], (U8*)s, utf8_target)));
+        FBC_BOUND(isWORDCHAR_L1, isWORDCHAR_uni, isWORDCHAR_utf8);
         break;
     case NBOUNDU:
-        FBC_NBOUND(isWORDCHAR_L1,
-                   isWORDCHAR_uni(tmp),
-                   cBOOL(swash_fetch(PL_utf8_swash_ptrs[_CC_WORDCHAR], (U8*)s, utf8_target)));
+        FBC_NBOUND(isWORDCHAR_L1, isWORDCHAR_uni, isWORDCHAR_utf8);
         break;
     case LNBREAK:
         REXEC_FBC_CSCAN(is_LNBREAK_utf8_safe(s, strend),
@@ -2579,6 +2618,7 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, char *strend,
     }
 
     RX_MATCH_TAINTED_off(rx);
+    RX_MATCH_UTF8_set(rx, utf8_target);
 
     reginfo->prog = rx;         /* Yes, sorry that this is confusing.  */
     reginfo->intuit = 0;
@@ -2599,7 +2639,6 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, char *strend,
            magic belonging to this SV.
            Not newSVsv, either, as it does not COW.
         */
-        assert(!IS_PADGV(sv));
         reginfo->sv = newSV(0);
         SvSetSV_nosteal(reginfo->sv, sv);
         SAVEFREESV(reginfo->sv);
@@ -2677,7 +2716,7 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, char *strend,
     }
 
     /* Simplest case:  anchored match need be tried only once. */
-    /*  [unless only anchor is BOL and multiline is set] */
+    /*  [unless only anchor is MBOL - implying multiline is set] */
     if (prog->intflags & (PREGf_ANCH & ~PREGf_ANCH_GPOS)) {
        if (s == startpos && regtry(reginfo, &s))
            goto got_it;
@@ -2931,7 +2970,7 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, char *strend,
        }
        DEBUG_EXECUTE_r({
            SV * const prop = sv_newmortal();
-            regprop(prog, prop, c, reginfo);
+            regprop(prog, prop, c, reginfo, NULL);
            {
                RE_PV_QUOTED_DECL(quoted,utf8_target,PERL_DEBUG_PAD_ZERO(1),
                    s,strend-s,60);
@@ -3037,7 +3076,8 @@ Perl_regexec_flags(pTHX_ REGEXP * const rx, char *stringarg, char *strend,
                  * and replaced it with this one. Yves */
                DEBUG_EXECUTE_r(
                    PerlIO_printf(Perl_debug_log,
-                       "String does not contain required substring, cannot match.\n"
+                       "%sString does not contain required substring, cannot match.%s\n",
+                        PL_colors[4], PL_colors[5]
                    ));
                goto phooey;
            }
@@ -3099,8 +3139,6 @@ got_it:
     if (RXp_PAREN_NAMES(prog)) 
         (void)hv_iterinit(RXp_PAREN_NAMES(prog));
 
-    RX_MATCH_UTF8_set(rx, utf8_target);
-
     /* make sure $`, $&, $', and $digit will work later */
     if ( !(flags & REXEC_NOT_FIRST) )
         S_reg_set_capture_string(aTHX_ rx,
@@ -3596,8 +3634,8 @@ S_setup_EXACTISH_ST_c1_c2(pTHX_ const regnode * const text_node, int *c1p,
 
     const bool utf8_target = reginfo->is_utf8_target;
 
-    UV c1 = CHRTEST_NOT_A_CP_1;
-    UV c2 = CHRTEST_NOT_A_CP_2;
+    UV c1 = (UV)CHRTEST_NOT_A_CP_1;
+    UV c2 = (UV)CHRTEST_NOT_A_CP_2;
     bool use_chrtest_void = FALSE;
     const bool is_utf8_pat = reginfo->is_utf8_pat;
 
@@ -3953,7 +3991,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
            SV * const prop = sv_newmortal();
            regnode *rnext=regnext(scan);
            DUMP_EXEC_POS( locinput, scan, utf8_target );
-            regprop(rex, prop, scan, reginfo);
+            regprop(rex, prop, scan, reginfo, NULL);
             
            PerlIO_printf(Perl_debug_log,
                    "%3"IVdf":%*s%s(%"IVdf")\n",
@@ -3975,8 +4013,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
         assert(nextchr < 256 && (nextchr >= 0 || nextchr == NEXTCHR_EOS));
 
        switch (state_num) {
-       case BOL:  /*  /^../   */
-       case SBOL: /*  /^../s  */
+       case SBOL: /*  /^../ and /\A../  */
            if (locinput == reginfo->strbeg)
                break;
            sayNO;
@@ -3999,21 +4036,22 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
            st->u.keeper.val = rex->offs[0].start;
            rex->offs[0].start = locinput - reginfo->strbeg;
            PUSH_STATE_GOTO(KEEPS_next, next, locinput);
-           assert(0); /*NOTREACHED*/
+            /* NOTREACHED */
+           assert(0);
+
        case KEEPS_next_fail:
            /* rollback the start point change */
            rex->offs[0].start = st->u.keeper.val;
            sayNO_SILENT;
-           assert(0); /*NOTREACHED*/
+            /* NOTREACHED */
+           assert(0);
 
        case MEOL: /* /..$/m  */
            if (!NEXTCHR_IS_EOS && nextchr != '\n')
                sayNO;
            break;
 
-       case EOL: /* /..$/  */
-            /* FALLTHROUGH */
-       case SEOL: /* /..$/s  */
+       case SEOL: /* /..$/  */
            if (!NEXTCHR_IS_EOS && nextchr != '\n')
                sayNO;
            if (reginfo->strend - locinput > 1)
@@ -4055,7 +4093,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                               REPORT_CODE_OFF+depth*2, "", PL_colors[4], PL_colors[5])
                 );
                 sayNO_SILENT;
-                assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+                assert(0);
             }
             /* FALLTHROUGH */
        case TRIE:  /* (ab|cd)  */
@@ -4242,7 +4281,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                );
                goto trie_first_try; /* jump into the fail handler */
            }}
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case TRIE_next_fail: /* we failed - try next alternative */
         {
@@ -4356,7 +4396,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
 
            if (ST.accepted > 1 || has_cutgroup) {
                PUSH_STATE_GOTO(TRIE_next, scan, (char*)uc);
-               assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+               assert(0);
            }
            /* only one choice left - just continue */
            DEBUG_EXECUTE_r({
@@ -4380,7 +4421,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
 
            locinput = (char*)uc;
            continue; /* execute rest of RE */
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
         }
 #undef  ST
 
@@ -5147,9 +5189,6 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
        case TAIL: /* placeholder while compiling (A|B|C) */
            break;
 
-       case BACK: /* ??? doesn't appear to be used ??? */
-           break;
-
 #undef  ST
 #define ST st->u.eval
        {
@@ -5189,7 +5228,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
             /* and then jump to the code we share with EVAL */
             goto eval_recurse_doit;
 
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case EVAL:  /*   /(?{A})B/   /(??{A})B/  and /(?(?{A})X|Y)B/   */        
             if (cur_eval && cur_eval->locinput==locinput) {
@@ -5278,7 +5318,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                        assert(o->op_targ == OP_LEAVE);
                        o = cUNOPo->op_first;
                        assert(o->op_type == OP_ENTER);
-                       o = o->op_sibling;
+                       o = OP_SIBLING(o);
                    }
 
                    if (o->op_type != OP_STUB) {
@@ -5405,7 +5445,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                        re_sv = rex->engine->op_comp(aTHX_ &ret, 1, NULL,
                                    rex->engine, NULL, NULL,
                                     /* copy /msix etc to inner pattern */
-                                    scan->flags,
+                                    ARG2L(scan),
                                     pm_flags);
 
                        if (!(SvFLAGS(ret)
@@ -5470,7 +5510,8 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                cur_eval = st;
                /* now continue from first node in postoned RE */
                PUSH_YES_STATE_GOTO(EVAL_AB, startpoint, locinput);
-               assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+               assert(0);
        }
 
        case EVAL_AB: /* cleanup after a successful (??{A})B */
@@ -5579,7 +5620,7 @@ S_regmatch(pTHX_ regmatch_info *reginfo, char *startpos, regnode *prog)
                 }
             }
            goto fake_end;
-           /*NOTREACHED*/          
+           /* NOTREACHED */
 
        case GROUPP:  /*  (?(1))  */
            n = ARG(scan);  /* which paren pair */
@@ -5729,19 +5770,22 @@ NULL
            ST.lastloc = NULL;  /* this will be updated by WHILEM */
 
            PUSH_YES_STATE_GOTO(CURLYX_end, PREVOPER(next), locinput);
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
        }
 
        case CURLYX_end: /* just finished matching all of A*B */
            cur_curlyx = ST.prev_curlyx;
            sayYES;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case CURLYX_end_fail: /* just failed to match all of A*B */
            regcpblow(ST.cp);
            cur_curlyx = ST.prev_curlyx;
            sayNO;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
 
 #undef ST
@@ -5751,11 +5795,14 @@ NULL
        {
            /* see the discussion above about CURLYX/WHILEM */
            I32 n;
-           int min = ARG1(cur_curlyx->u.curlyx.me);
-           int max = ARG2(cur_curlyx->u.curlyx.me);
-           regnode *A = NEXTOPER(cur_curlyx->u.curlyx.me) + EXTRA_STEP_2ARGS;
+           int min, max;
+           regnode *A;
 
            assert(cur_curlyx); /* keep Coverity happy */
+
+           min = ARG1(cur_curlyx->u.curlyx.me);
+           max = ARG2(cur_curlyx->u.curlyx.me);
+           A = NEXTOPER(cur_curlyx->u.curlyx.me) + EXTRA_STEP_2ARGS;
            n = ++cur_curlyx->u.curlyx.count; /* how many A's matched */
            ST.save_lastloc = cur_curlyx->u.curlyx.lastloc;
            ST.cache_offset = 0;
@@ -5776,7 +5823,8 @@ NULL
                REGCP_SET(ST.lastcp);
 
                PUSH_STATE_GOTO(WHILEM_A_pre, A, locinput);
-               assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+               assert(0);
            }
 
            /* If degenerate A matches "", assume A done. */
@@ -5888,7 +5936,8 @@ NULL
                REGCP_SET(ST.lastcp);
                PUSH_YES_STATE_GOTO(WHILEM_B_min, ST.save_curlyx->u.curlyx.B,
                                     locinput);
-               assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+               assert(0);
            }
 
            /* Prefer A over B for maximal matching. */
@@ -5899,24 +5948,28 @@ NULL
                cur_curlyx->u.curlyx.lastloc = locinput;
                REGCP_SET(ST.lastcp);
                PUSH_STATE_GOTO(WHILEM_A_max, A, locinput);
-               assert(0); /* NOTREACHED */
+                /* NOTREACHED */
+               assert(0);
            }
            goto do_whilem_B_max;
        }
-       assert(0); /* NOTREACHED */
+        /* NOTREACHED */
+       assert(0);
 
        case WHILEM_B_min: /* just matched B in a minimal match */
        case WHILEM_B_max: /* just matched B in a maximal match */
            cur_curlyx = ST.save_curlyx;
            sayYES;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case WHILEM_B_max_fail: /* just failed to match B in a maximal match */
            cur_curlyx = ST.save_curlyx;
            cur_curlyx->u.curlyx.lastloc = ST.save_lastloc;
            cur_curlyx->u.curlyx.count--;
            CACHEsayNO;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case WHILEM_A_min_fail: /* just failed to match A in a minimal match */
            /* FALLTHROUGH */
@@ -5926,7 +5979,8 @@ NULL
            cur_curlyx->u.curlyx.lastloc = ST.save_lastloc;
            cur_curlyx->u.curlyx.count--;
            CACHEsayNO;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case WHILEM_A_max_fail: /* just failed to match A in a maximal match */
            REGCP_UNWIND(ST.lastcp);
@@ -5952,7 +6006,8 @@ NULL
            cur_curlyx = cur_curlyx->u.curlyx.prev_curlyx;
            PUSH_YES_STATE_GOTO(WHILEM_B_max, ST.save_curlyx->u.curlyx.B,
                                 locinput);
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case WHILEM_B_min_fail: /* just failed to match B in a minimal match */
            cur_curlyx = ST.save_curlyx;
@@ -5986,7 +6041,8 @@ NULL
            PUSH_STATE_GOTO(WHILEM_A_min,
                /*A*/ NEXTOPER(ST.save_curlyx->u.curlyx.me) + EXTRA_STEP_2ARGS,
                 locinput);
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
 #undef  ST
 #define ST st->u.branch
@@ -6011,13 +6067,15 @@ NULL
            } else {
                PUSH_STATE_GOTO(BRANCH_next, scan, locinput);
            }
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
         case CUTGROUP:  /*  /(*THEN)/  */
             sv_yes_mark = st->u.mark.mark_name = scan->flags ? NULL :
                 MUTABLE_SV(rexi->data->data[ ARG( scan ) ]);
             PUSH_STATE_GOTO(CUTGROUP_next, next, locinput);
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case CUTGROUP_next_fail:
             do_cutgroup = 1;
@@ -6025,11 +6083,13 @@ NULL
             if (st->u.mark.mark_name)
                 sv_commit = st->u.mark.mark_name;
             sayNO;         
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case BRANCH_next:
             sayYES;
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
        case BRANCH_next_fail: /* that branch failed; try the next, if any */
            if (do_cutgroup) {
@@ -6051,7 +6111,8 @@ NULL
                sayNO_SILENT;
             }
            continue; /* execute next BRANCH[J] op */
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
     
        case MINMOD: /* next op will be non-greedy, e.g. A*?  */
            minmod = 1;
@@ -6095,7 +6156,8 @@ NULL
 
          curlym_do_A: /* execute the A in /A{m,n}B/  */
            PUSH_YES_STATE_GOTO(CURLYM_A, ST.A, locinput); /* match A */
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case CURLYM_A: /* we've just matched an A */
            ST.count++;
@@ -6145,6 +6207,7 @@ NULL
                /* calculate c1 and c2 for possible match of 1st char
                 * following curly */
                ST.c1 = ST.c2 = CHRTEST_VOID;
+                assert(ST.B);
                if (HAS_TEXT(ST.B) || JUMPABLE(ST.B)) {
                    regnode *text_node = ST.B;
                    if (! HAS_TEXT(text_node))
@@ -6230,7 +6293,8 @@ NULL
            }
            
            PUSH_STATE_GOTO(CURLYM_B, ST.B, locinput); /* match B */
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case CURLYM_B_fail: /* just failed to match a B */
            REGCP_UNWIND(ST.cp);
@@ -6408,8 +6472,8 @@ NULL
                REGCP_SET(ST.cp);
                goto curly_try_B_max;
            }
-           assert(0); /* NOTREACHED */
-
+            /* NOTREACHED */
+           assert(0);
 
        case CURLY_B_min_known_fail:
            /* failed to find B in a non-greedy match where c1,c2 valid */
@@ -6484,8 +6548,8 @@ NULL
                }
                PUSH_STATE_GOTO(CURLY_B_min_known, ST.B, locinput);
            }
-           assert(0); /* NOTREACHED */
-
+            /* NOTREACHED */
+           assert(0);
 
        case CURLY_B_min_fail:
            /* failed to find B in a non-greedy match where c1,c2 invalid */
@@ -6517,8 +6581,8 @@ NULL
                }
            }
             sayNO;
-           assert(0); /* NOTREACHED */
-
+            /* NOTREACHED */
+           assert(0);
 
        curly_try_B_max:
            /* a successful greedy match: now try to match B */
@@ -6548,7 +6612,8 @@ NULL
                 if (ST.c1 == CHRTEST_VOID || could_match) {
                    CURLY_SETPAREN(ST.paren, ST.count);
                    PUSH_STATE_GOTO(CURLY_B_max, ST.B, locinput);
-                   assert(0); /* NOTREACHED */
+                    /* NOTREACHED */
+                   assert(0);
                }
            }
            /* FALLTHROUGH */
@@ -6667,7 +6732,8 @@ NULL
            
            /* execute body of (?...A) */
            PUSH_YES_STATE_GOTO(IFMATCH_A, NEXTOPER(NEXTOPER(scan)), newstart);
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
         }
 
        case IFMATCH_A_fail: /* body of (?...A) failed */
@@ -6707,7 +6773,8 @@ NULL
            if (!scan->flags)
                sv_yes_mark = sv_commit = MUTABLE_SV(rexi->data->data[ ARG( scan ) ]);
            PUSH_STATE_GOTO(COMMIT_next, next, locinput);
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
        case COMMIT_next_fail:
            no_final = 1;    
@@ -6715,7 +6782,8 @@ NULL
 
        case OPFAIL:   /* (*FAIL)  */
            sayNO;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
 
 #define ST st->u.mark
         case MARKPOINT: /*  (*MARK:foo)  */
@@ -6725,12 +6793,14 @@ NULL
             mark_state = st;
             ST.mark_loc = locinput;
             PUSH_YES_STATE_GOTO(MARKPOINT_next, next, locinput);
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case MARKPOINT_next:
             mark_state = ST.prev_mark;
             sayYES;
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case MARKPOINT_next_fail:
             if (popmark && sv_eq(ST.mark_name,popmark)) 
@@ -6751,7 +6821,8 @@ NULL
             sv_yes_mark = mark_state ? 
                 mark_state->u.mark.mark_name : NULL;
             sayNO;
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 
         case SKIP:  /*  (*SKIP)  */
             if (scan->flags) {
@@ -6796,7 +6867,8 @@ NULL
             } 
             no_final = 1; 
             sayNO;
-            assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+            assert(0);
 #undef ST
 
         case LNBREAK: /* \R */
@@ -6830,7 +6902,8 @@ NULL
         /* switch break jumps here */
        scan = next; /* prepare to execute the next op and ... */
        continue;    /* ... jump back to the top, reusing st */
-       assert(0); /* NOTREACHED */
+        /* NOTREACHED */
+       assert(0);
 
       push_yes_state:
        /* push a state that backtracks on success */
@@ -6873,7 +6946,8 @@ NULL
            locinput = pushinput;
            st = newst;
            continue;
-           assert(0); /* NOTREACHED */
+            /* NOTREACHED */
+           assert(0);
        }
     }
 
@@ -6882,7 +6956,7 @@ NULL
     * the terminating point.
     */
     Perl_croak(aTHX_ "corrupted regexp pointers");
-    /*NOTREACHED*/
+    /* NOTREACHED */
     sayNO;
 
 yes:
@@ -7509,7 +7583,8 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
 
     default:
         Perl_croak(aTHX_ "panic: regrepeat() called with unrecognized node type %d='%s'", OP(p), PL_reg_name[OP(p)]);
-        assert(0); /* NOTREACHED */
+        /* NOTREACHED */
+        assert(0);
 
     }
 
@@ -7523,7 +7598,7 @@ S_regrepeat(pTHX_ regexp *prog, char **startposp, const regnode *p,
        GET_RE_DEBUG_FLAGS_DECL;
        DEBUG_EXECUTE_r({
            SV * const prop = sv_newmortal();
-            regprop(prog, prop, p, reginfo);
+            regprop(prog, prop, p, reginfo, NULL);
            PerlIO_printf(Perl_debug_log,
                        "%*s  %s can match %"IVdf" times out of %"IVdf"...\n",
                        REPORT_CODE_OFF + depth*2, "", SvPVX_const(prop),(IV)c,(IV)max);
@@ -7549,121 +7624,9 @@ Perl_regclass_swash(pTHX_ const regexp *prog, const regnode* node, bool doinit,
         *altsvp = NULL;
     }
 
-    return newSVsv(_get_regclass_nonbitmap_data(prog, node, doinit, listsvp, NULL));
+    return newSVsv(_get_regclass_nonbitmap_data(prog, node, doinit, listsvp, NULL, NULL));
 }
 
-SV *
-Perl__get_regclass_nonbitmap_data(pTHX_ const regexp *prog,
-                                        const regnode* node,
-                                        bool doinit,
-                                        SV** listsvp,
-                                        SV** only_utf8_locale_ptr)
-{
-    /* For internal core use only.
-     * Returns the swash for the input 'node' in the regex 'prog'.
-     * If <doinit> is 'true', will attempt to create the swash if not already
-     *   done.
-     * If <listsvp> is non-null, will return the printable contents of the
-     *    swash.  This can be used to get debugging information even before the
-     *    swash exists, by calling this function with 'doinit' set to false, in
-     *    which case the components that will be used to eventually create the
-     *    swash are returned  (in a printable form).
-     * Tied intimately to how regcomp.c sets up the data structure */
-
-    SV *sw  = NULL;
-    SV *si  = NULL;         /* Input swash initialization string */
-    SV*  invlist = NULL;
-
-    RXi_GET_DECL(prog,progi);
-    const struct reg_data * const data = prog ? progi->data : NULL;
-
-    PERL_ARGS_ASSERT__GET_REGCLASS_NONBITMAP_DATA;
-
-    assert(ANYOF_FLAGS(node)
-                        & (ANYOF_UTF8|ANYOF_NONBITMAP_NON_UTF8|ANYOF_LOC_FOLD));
-
-    if (data && data->count) {
-       const U32 n = ARG(node);
-
-       if (data->what[n] == 's') {
-           SV * const rv = MUTABLE_SV(data->data[n]);
-           AV * const av = MUTABLE_AV(SvRV(rv));
-           SV **const ary = AvARRAY(av);
-           U8 swash_init_flags = _CORE_SWASH_INIT_ACCEPT_INVLIST;
-       
-           si = *ary;  /* ary[0] = the string to initialize the swash with */
-
-           /* Elements 3 and 4 are either both present or both absent. [3] is
-            * any inversion list generated at compile time; [4] indicates if
-            * that inversion list has any user-defined properties in it. */
-            if (av_tindex(av) >= 2) {
-                if (only_utf8_locale_ptr
-                    && ary[2]
-                    && ary[2] != &PL_sv_undef)
-                {
-                    *only_utf8_locale_ptr = ary[2];
-                }
-                else {
-                    assert(only_utf8_locale_ptr);
-                    *only_utf8_locale_ptr = NULL;
-                }
-
-                if (av_tindex(av) >= 3) {
-                    invlist = ary[3];
-                    if (SvUV(ary[4])) {
-                        swash_init_flags |= _CORE_SWASH_INIT_USER_DEFINED_PROPERTY;
-                    }
-                }
-                else {
-                    invlist = NULL;
-                }
-           }
-
-           /* Element [1] is reserved for the set-up swash.  If already there,
-            * return it; if not, create it and store it there */
-           if (ary[1] && SvROK(ary[1])) {
-               sw = ary[1];
-           }
-           else if (doinit && ((si && si != &PL_sv_undef)
-                                 || (invlist && invlist != &PL_sv_undef))) {
-               assert(si);
-               sw = _core_swash_init("utf8", /* the utf8 package */
-                                     "", /* nameless */
-                                     si,
-                                     1, /* binary */
-                                     0, /* not from tr/// */
-                                     invlist,
-                                     &swash_init_flags);
-               (void)av_store(av, 1, sw);
-           }
-       }
-    }
-       
-    /* If requested, return a printable version of what this swash matches */
-    if (listsvp) {
-       SV* matches_string = newSVpvs("");
-
-        /* The swash should be used, if possible, to get the data, as it
-         * contains the resolved data.  But this function can be called at
-         * compile-time, before everything gets resolved, in which case we
-         * return the currently best available information, which is the string
-         * that will eventually be used to do that resolving, 'si' */
-       if ((! sw || (invlist = _get_swash_invlist(sw)) == NULL)
-            && (si && si != &PL_sv_undef))
-        {
-           sv_catsv(matches_string, si);
-       }
-
-       /* Add the inversion list to whatever we have.  This may have come from
-        * the swash, or from an input parameter */
-       if (invlist) {
-           sv_catsv(matches_string, _invlist_contents(invlist));
-       }
-       *listsvp = matches_string;
-    }
-
-    return sw;
-}
 #endif /* !defined(PERL_IN_XSUB_RE) || defined(PLUGGABLE_RE_EXTENSION) */
 
 /*
@@ -7706,22 +7669,25 @@ S_reginclass(pTHX_ regexp * const prog, const regnode * const n, const U8* const
     }
 
     /* If this character is potentially in the bitmap, check it */
-    if (c < 256) {
+    if (c < NUM_ANYOF_CODE_POINTS) {
        if (ANYOF_BITMAP_TEST(n, c))
            match = TRUE;
-       else if (flags & ANYOF_NON_UTF8_NON_ASCII_ALL
-               && ! utf8_target
-               && ! isASCII(c))
+       else if ((flags & ANYOF_MATCHES_ALL_NON_UTF8_NON_ASCII)
+                 && ! utf8_target
+                 && ! isASCII(c))
        {
            match = TRUE;
        }
        else if (flags & ANYOF_LOCALE_FLAGS) {
-           if (flags & ANYOF_LOC_FOLD) {
-                if (ANYOF_BITMAP_TEST(n, PL_fold_locale[c])) {
-                    match = TRUE;
-                }
+           if ((flags & ANYOF_LOC_FOLD)
+                && c < 256
+               && ANYOF_BITMAP_TEST(n, PL_fold_locale[c]))
+            {
+                match = TRUE;
             }
-           if (! match && ANYOF_POSIXL_TEST_ANY_SET(n)) {
+            else if (ANYOF_POSIXL_TEST_ANY_SET(n)
+                     && c < 256
+            ) {
 
                 /* The data structure is arranged so bits 0, 2, 4, ... are set
                  * if the class includes the Posix character class given by
@@ -7774,18 +7740,20 @@ S_reginclass(pTHX_ regexp * const prog, const regnode * const n, const U8* const
     /* If the bitmap didn't (or couldn't) match, and something outside the
      * bitmap could match, try that. */
     if (!match) {
-       if (c >= 256 && (flags & ANYOF_ABOVE_LATIN1_ALL)) {
-           match = TRUE;       /* Everything above 255 matches */
+       if (c >= NUM_ANYOF_CODE_POINTS
+            && (flags & ANYOF_MATCHES_ALL_ABOVE_BITMAP))
+        {
+           match = TRUE;       /* Everything above the bitmap matches */
        }
-       else if ((flags & ANYOF_NONBITMAP_NON_UTF8)
-                 || (utf8_target && (flags & ANYOF_UTF8))
+       else if ((flags & ANYOF_HAS_NONBITMAP_NON_UTF8_MATCHES)
+                 || (utf8_target && (flags & ANYOF_HAS_UTF8_NONBITMAP_MATCHES))
                   || ((flags & ANYOF_LOC_FOLD)
                        && IN_UTF8_CTYPE_LOCALE
-                       && ARG(n) != ANYOF_NONBITMAP_EMPTY))
+                       && ARG(n) != ANYOF_ONLY_HAS_BITMAP))
         {
             SV* only_utf8_locale = NULL;
            SV * const sw = _get_regclass_nonbitmap_data(prog, n, TRUE, 0,
-                                                            &only_utf8_locale);
+                                                       &only_utf8_locale, NULL);
            if (sw) {
                 U8 utf8_buffer[2];
                U8 * utf8_p;