This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
regcomp.c: Consolidate checks for warnings fatality
[perl5.git] / regcomp.c
index 6e790d5..a3f7194 100644 (file)
--- a/regcomp.c
+++ b/regcomp.c
@@ -810,6 +810,9 @@ static const scan_data_t zero_scan_data = {
 #define TO_OUTPUT_WARNINGS(loc)                                         \
   (PASS2 && RExC_copy_start_in_constructed)
 
+#define UPDATE_WARNINGS_LOC(loc)  NOOP
+
+/* 'warns' is the output of the packWARNx macro used in 'code' */
 #define _WARN_HELPER(loc, warns, code)                                  \
     STMT_START {                                                        \
         if (! RExC_copy_start_in_constructed) {                         \
@@ -818,7 +821,10 @@ static const scan_data_t zero_scan_data = {
                               __FILE__, __LINE__, loc);                 \
         }                                                               \
         if (TO_OUTPUT_WARNINGS(loc)) {                                  \
+            if (ckDEAD(warns))                                          \
+                PREPARE_TO_DIE;                                         \
             code;                                                       \
+            UPDATE_WARNINGS_LOC(loc);                                   \
         }                                                               \
     } STMT_END
 
@@ -5221,15 +5227,13 @@ S_study_chunk(pTHX_ RExC_state_t *pRExC_state, regnode **scanp,
                     && maxcount <= REG_INFTY/3) /* Complement check for big
                                                    count */
                {
-                   /* Fatal warnings may leak the regexp without this: */
-                   SAVEFREESV(RExC_rx_sv);
-                   Perl_ck_warner(aTHX_ packWARN(WARN_REGEXP),
-                       "Quantifier unexpected on zero-length expression "
-                       "in regex m/%" UTF8f "/",
-                        UTF8fARG(UTF, RExC_precomp_end - RExC_precomp,
-                                 RExC_precomp));
-                   (void)ReREFCNT_inc(RExC_rx_sv);
-               }
+                   _WARN_HELPER(RExC_precomp_end, packWARN(WARN_REGEXP),
+                        Perl_ck_warner(aTHX_ packWARN(WARN_REGEXP),
+                            "Quantifier unexpected on zero-length expression "
+                            "in regex m/%" UTF8f "/",
+                            UTF8fARG(UTF, RExC_precomp_end - RExC_precomp,
+                                 RExC_precomp)));
+                }
 
                min += minnext * mincount;
                is_inf_internal |= deltanext == SSize_t_MAX
@@ -12285,14 +12289,12 @@ S_regpiece(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
     }
   nest_check:
     if (!SIZE_ONLY && !(flags&(HASWIDTH|POSTPONED)) && max > REG_INFTY/3) {
-       SAVEFREESV(RExC_rx_sv); /* in case of fatal warnings */
        ckWARN2reg(RExC_parse,
                   "%" UTF8f " matches null string many times",
                   UTF8fARG(UTF, (RExC_parse >= origparse
                                  ? RExC_parse - origparse
                                  : 0),
                   origparse));
-       (void)ReREFCNT_inc(RExC_rx_sv);
     }
 
     if (*RExC_parse == '?') {
@@ -13794,6 +13796,7 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
                                                   to exact spot of failure */
                                vFAIL(error_msg);
                            }
+                            UPDATE_WARNINGS_LOC(p - 1);
                             ender = result;
                            if (ender > 0xff) {
                                REQUIRE_UTF8(flagp);
@@ -13821,6 +13824,7 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
                                                   to exact spot of failure */
                                vFAIL(error_msg);
                            }
+                            UPDATE_WARNINGS_LOC(p - 1);
                             ender = result;
 
                             if (ender < 0x100) {
@@ -13838,6 +13842,7 @@ S_regatom(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth)
                    case 'c':
                        p++;
                        ender = grok_bslash_c(*p, TO_OUTPUT_WARNINGS(p));
+                        UPDATE_WARNINGS_LOC(p);
                         p++;
                        break;
                     case '8': case '9': /* must be a backreference */
@@ -16349,8 +16354,8 @@ S_output_or_return_posix_warnings(pTHX_ RExC_state_t *pRExC_state, AV* posix_war
                                                array is mortal, but is a
                                                fail-safe */
                 (void) sv_2mortal(msg);
-                if (PASS2) {
-                    SAVEFREESV(RExC_rx_sv);
+                if (ckDEAD(packWARN(WARN_REGEXP))) {
+                    PREPARE_TO_DIE;
                 }
             }
             Perl_warner(aTHX_ packWARN(WARN_REGEXP), "%s",
@@ -16358,6 +16363,10 @@ S_output_or_return_posix_warnings(pTHX_ RExC_state_t *pRExC_state, AV* posix_war
             SvREFCNT_dec_NN(msg);
         }
     }
+
+    if (! return_posix_warnings) {
+        UPDATE_WARNINGS_LOC(RExC_parse);
+    }
 }
 
 STATIC AV *
@@ -16574,6 +16583,7 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
                        one.  */
     U8 anyof_flags = 0;   /* flag bits if the node is an ANYOF-type */
     U32 posixl = 0;       /* bit field of posix classes matched under /l */
+    bool use_anyofd = FALSE; /* ? Is this to be an ANYOFD node */
 
     GET_RE_DEBUG_FLAGS_DECL;
 
@@ -16619,7 +16629,6 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
                                                 NULL,
                                                 TRUE /* checking only */);
         if (PASS2 && maybe_class >= OOB_NAMEDCLASS && do_posix_warnings) {
-            SAVEFREESV(RExC_rx_sv);
             ckWARN4reg(not_posix_region_end,
                     "POSIX syntax [%c %c] belongs inside character classes%s",
                     *RExC_parse, *RExC_parse,
@@ -16629,7 +16638,6 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
                         : " (but this one isn't fully valid)")
                     : ""
                     );
-            (void)ReREFCNT_inc(RExC_rx_sv);
         }
     }
 
@@ -17121,6 +17129,7 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
                    if (! valid) {
                        vFAIL(error_msg);
                    }
+                    UPDATE_WARNINGS_LOC(RExC_parse - 1);
                }
                 non_portable_endpoint++;
                break;
@@ -17139,11 +17148,13 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
                     if (! valid) {
                        vFAIL(error_msg);
                    }
+                    UPDATE_WARNINGS_LOC(RExC_parse - 1);
                }
                 non_portable_endpoint++;
                break;
            case 'c':
                value = grok_bslash_c(*RExC_parse, TO_OUTPUT_WARNINGS(RExC_parse));
+                UPDATE_WARNINGS_LOC(RExC_parse);
                RExC_parse++;
                 non_portable_endpoint++;
                break;
@@ -17166,11 +17177,9 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
                                  && isDIGIT(*RExC_parse)
                                  && ckWARN(WARN_REGEXP))
                         {
-                            SAVEFREESV(RExC_rx_sv);
                             reg_warn_non_literal_string(
                                  RExC_parse + 1,
                                  form_short_octal_warning(RExC_parse, numlen));
-                            (void)ReREFCNT_inc(RExC_rx_sv);
                         }
                     }
                     non_portable_endpoint++;
@@ -17184,11 +17193,9 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
                                (int)value);
                     }
                     else {
-                        SAVEFREESV(RExC_rx_sv);
                         ckWARN2reg(RExC_parse,
                             "Unrecognized escape \\%c in character class passed through",
                             (int)value);
-                        (void)ReREFCNT_inc(RExC_rx_sv);
                     }
                }
                break;
@@ -17214,11 +17221,9 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
                             UTF8fARG(UTF, w, rangebegin));
                     }
                     else {
-                        SAVEFREESV(RExC_rx_sv); /* in case of fatal warnings */
                         ckWARN2reg(RExC_parse,
                             "False [] range \"%" UTF8f "\"",
                             UTF8fARG(UTF, w, rangebegin));
-                        (void)ReREFCNT_inc(RExC_rx_sv);
                         cp_list = add_cp_to_invlist(cp_list, '-');
                         cp_foldable_list = add_cp_to_invlist(cp_foldable_list,
                                                              prevvalue);
@@ -18025,11 +18030,6 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
 
     /****** !SIZE_ONLY (Pass 2) AFTER HERE *********/
 
-    ANYOF_FLAGS(REGNODE_p(ret)) = anyof_flags;
-    if (posixl) {
-        ANYOF_POSIXL_SET_TO_BITMAP(REGNODE_p(ret), posixl);
-    }
-
     /* If folding, we calculate all characters that could fold to or from the
      * ones already on the list */
     if (cp_foldable_list) {
@@ -18243,7 +18243,7 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
                 _invlist_subtract(only_non_utf8_list, cp_list,
                                   &only_non_utf8_list);
                 if (_invlist_len(only_non_utf8_list) != 0) {
-                    ANYOF_FLAGS(REGNODE_p(ret)) |= ANYOF_SHARED_d_MATCHES_ALL_NON_UTF8_NON_ASCII_non_d_WARN_SUPER;
+                    anyof_flags |= ANYOF_SHARED_d_MATCHES_ALL_NON_UTF8_NON_ASCII_non_d_WARN_SUPER;
                 }
                 SvREFCNT_dec_NN(only_non_utf8_list);
             }
@@ -18328,7 +18328,7 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
         }
 
         if (warn_super) {
-            ANYOF_FLAGS(REGNODE_p(ret))
+            anyof_flags
              |= ANYOF_SHARED_d_MATCHES_ALL_NON_UTF8_NON_ASCII_non_d_WARN_SUPER;
 
             /* Because an ANYOF node is the only one that warns, this node
@@ -18366,24 +18366,24 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
             }
         }
         if (only_utf8_locale_list) {
-            ANYOF_FLAGS(REGNODE_p(ret))
-                 |=  ANYOFL_FOLD
-                    |ANYOFL_SHARED_UTF8_LOCALE_fold_HAS_MATCHES_nonfold_REQD;
+            anyof_flags
+                 |= ANYOFL_FOLD
+                 |  ANYOFL_SHARED_UTF8_LOCALE_fold_HAS_MATCHES_nonfold_REQD;
         }
         else if (cp_list) { /* Look to see if a 0-255 code point is in list */
             UV start, end;
             invlist_iterinit(cp_list);
             if (invlist_iternext(cp_list, &start, &end) && start < 256) {
-                ANYOF_FLAGS(REGNODE_p(ret)) |= ANYOFL_FOLD;
+                anyof_flags |= ANYOFL_FOLD;
             }
             invlist_iterfinish(cp_list);
         }
     }
     else if (   DEPENDS_SEMANTICS
              && (    has_upper_latin1_only_utf8_matches
-                 || (ANYOF_FLAGS(REGNODE_p(ret)) & ANYOF_SHARED_d_MATCHES_ALL_NON_UTF8_NON_ASCII_non_d_WARN_SUPER)))
+                 || (anyof_flags & ANYOF_SHARED_d_MATCHES_ALL_NON_UTF8_NON_ASCII_non_d_WARN_SUPER)))
     {
-        OP(REGNODE_p(ret)) = ANYOFD;
+        use_anyofd = TRUE;
         optimizable = FALSE;
     }
 
@@ -18394,8 +18394,8 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
      * */
     if (     cp_list
         &&   invert
-        &&   OP(REGNODE_p(ret)) != ANYOFD
-        && ! (ANYOF_FLAGS(REGNODE_p(ret)) & (ANYOF_LOCALE_FLAGS))
+        && ! use_anyofd
+        && ! (anyof_flags & (ANYOF_LOCALE_FLAGS))
        && ! HAS_NONLOCALE_RUNTIME_PROPERTY_DEFINITION)
     {
         _invlist_invert(cp_list);
@@ -18715,6 +18715,16 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
         }
     }
 
+    /* It's going to be an ANYOF node. */
+    OP(REGNODE_p(ret)) = (use_anyofd)
+         ? ANYOFD
+         : ((posixl)
+            ? ANYOFPOSIXL
+            : ((LOC)
+               ? ANYOFL
+               : ANYOF));
+    ANYOF_FLAGS(REGNODE_p(ret)) = anyof_flags;
+
     /* Here, <cp_list> contains all the code points we can determine at
      * compile time that match under all conditions.  Go through it, and
      * for things that belong in the bitmap, put them there, and delete from
@@ -18723,6 +18733,10 @@ S_regclass(pTHX_ RExC_state_t *pRExC_state, I32 *flagp, U32 depth,
 
     populate_ANYOF_from_invlist(REGNODE_p(ret), &cp_list);
 
+    if (posixl) {
+        ANYOF_POSIXL_SET_TO_BITMAP(REGNODE_p(ret), posixl);
+    }
+
     if (invert) {
         ANYOF_FLAGS(REGNODE_p(ret)) |= ANYOF_INVERT;
     }