[PATCH] D16467: [libcxx] re.results.form: Format out-of-range subexpression references as null

Duncan P. N. Exon Smith via cfe-commits cfe-commits at lists.llvm.org
Fri Jan 22 09:17:44 PST 2016


dexonsmith created this revision.
dexonsmith added reviewers: EricWF, mclow.lists.
dexonsmith added a subscriber: cfe-commits.

Rather than crashing in match_results::format() when a reference to a
marked subexpression is out of range, format the subexpression as
empty (i.e., replace it with an empty string).

The standard doesn't require that marked subexpression references are
valid (the only preconditions are that ready() == true and that Out is
an output iterator), so the implementation shouldn't segfault on
out-of-range marked subexpressions.  The most user-friendly behaviour
(and the easiest to implement) is to treat them as "null" sub-matches.
Another option that I rejected is to leave them un-substituted.

I'm not sure about my choice of where to put the tests.  I considered
duplicating them across all four form*.pass.cpp, but thought I'd get
some feedback first.

http://reviews.llvm.org/D16467

Files:
  include/regex
  test/std/re/re.results/re.results.form/form1.pass.cpp

Index: test/std/re/re.results/re.results.form/form1.pass.cpp
===================================================================
--- test/std/re/re.results/re.results.form/form1.pass.cpp
+++ test/std/re/re.results/re.results.form/form1.pass.cpp
@@ -38,6 +38,31 @@
     {
         std::match_results<const char*> m;
         const char s[] = "abcdefghijk";
+        assert(std::regex_search(s, m, std::regex("cd((e)fg)hi",
+                                                  std::regex_constants::nosubs)));
+
+        char out[100] = {0};
+        const char fmt[] = "prefix: $`, match: $&, suffix: $', m[1]: $1, m[2]: $2";
+        char* r = m.format(output_iterator<char*>(out),
+                    fmt, fmt + std::char_traits<char>::length(fmt)).base();
+        assert(r == out + 54);
+        assert(std::string(out) == "prefix: ab, match: cdefghi, suffix: jk, m[1]: , m[2]: ");
+    }
+    {
+        std::match_results<const char*> m;
+        const char s[] = "abcdefghijk";
+        assert(std::regex_search(s, m, std::regex("cdefghi")));
+
+        char out[100] = {0};
+        const char fmt[] = "prefix: $`, match: $&, suffix: $', m[1]: $1, m[2]: $2";
+        char* r = m.format(output_iterator<char*>(out),
+                    fmt, fmt + std::char_traits<char>::length(fmt)).base();
+        assert(r == out + 54);
+        assert(std::string(out) == "prefix: ab, match: cdefghi, suffix: jk, m[1]: , m[2]: ");
+    }
+    {
+        std::match_results<const char*> m;
+        const char s[] = "abcdefghijk";
         assert(std::regex_search(s, m, std::regex("cd((e)fg)hi")));
 
         char out[100] = {0};
@@ -61,6 +86,33 @@
         assert(r == out + 34);
         assert(std::string(out) == "match: cdefghi, m[1]: efg, m[2]: e");
     }
+    {
+        std::match_results<const char*> m;
+        const char s[] = "abcdefghijk";
+        assert(std::regex_search(s, m, std::regex("cd((e)fg)hi",
+                                                  std::regex_constants::nosubs)));
+
+        char out[100] = {0};
+        const char fmt[] = "match: &, m[1]: \\1, m[2]: \\2";
+        char* r = m.format(output_iterator<char*>(out),
+                    fmt, fmt + std::char_traits<char>::length(fmt),
+                    std::regex_constants::format_sed).base();
+        assert(r == out + 30);
+        assert(std::string(out) == "match: cdefghi, m[1]: , m[2]: ");
+    }
+    {
+        std::match_results<const char*> m;
+        const char s[] = "abcdefghijk";
+        assert(std::regex_search(s, m, std::regex("cdefghi")));
+
+        char out[100] = {0};
+        const char fmt[] = "match: &, m[1]: \\1, m[2]: \\2";
+        char* r = m.format(output_iterator<char*>(out),
+                    fmt, fmt + std::char_traits<char>::length(fmt),
+                    std::regex_constants::format_sed).base();
+        assert(r == out + 30);
+        assert(std::string(out) == "match: cdefghi, m[1]: , m[2]: ");
+    }
 
     {
         std::match_results<const wchar_t*> m;
Index: include/regex
===================================================================
--- include/regex
+++ include/regex
@@ -5387,8 +5387,10 @@
                 if ('0' <= *__fmt_first && *__fmt_first <= '9')
                 {
                     size_t __i = *__fmt_first - '0';
-                    __out = _VSTD::copy(__matches_[__i].first,
-                                       __matches_[__i].second, __out);
+                    if (__i < __matches_.size()) {
+                        __out = _VSTD::copy(__matches_[__i].first,
+                                            __matches_[__i].second, __out);
+                    }
                 }
                 else
                 {
@@ -5439,8 +5441,10 @@
                             ++__fmt_first;
                             __i = 10 * __i + *__fmt_first - '0';
                         }
-                        __out = _VSTD::copy(__matches_[__i].first,
-                                           __matches_[__i].second, __out);
+                        if (__i < __matches_.size()) {
+                            __out = _VSTD::copy(__matches_[__i].first,
+                                                __matches_[__i].second, __out);
+                        }
                     }
                     else
                     {


-------------- next part --------------
A non-text attachment was scrubbed...
Name: D16467.45692.patch
Type: text/x-patch
Size: 4314 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20160122/fbab720d/attachment.bin>


More information about the cfe-commits mailing list