re PR libstdc++/71500 (regex::icase only works on first character in a range)
authorTim Shen <timshen@google.com>
Mon, 11 Sep 2017 19:02:34 +0000 (19:02 +0000)
committerTim Shen <timshen@gcc.gnu.org>
Mon, 11 Sep 2017 19:02:34 +0000 (19:02 +0000)
PR libstdc++/71500
* include/bits/regex_executor.tcc: Support icase in regex_tratis<...>
for back reference matches.
* testsuite/28_regex/regression.cc: Test case.

From-SVN: r251982

libstdc++-v3/ChangeLog
libstdc++-v3/include/bits/regex_executor.tcc
libstdc++-v3/testsuite/28_regex/regression.cc

index 33b9cdb20e00396c98c7cdd1a527ff5f2681e0e3..7163c6427b4851148a66cae9f3a70a93380efc58 100644 (file)
@@ -1,3 +1,10 @@
+2017-09-11  Tim Shen  <timshen@google.com>
+
+       PR libstdc++/71500
+       * include/bits/regex_executor.tcc: Support icase in regex_tratis<...>
+       for back reference matches.
+       * testsuite/28_regex/regression.cc: Test case.
+
 2017-09-11  Jonathan Wakely  <jwakely@redhat.com>
 
        * testsuite/21_strings/basic_string/lwg2946.cc: Adjust for
index 226e05856e151e76b59658cf8c419b09a34034c8..f6149fecf9d81585b04a720271cb8ef2b34870a9 100644 (file)
@@ -335,6 +335,54 @@ namespace __detail
          _M_states._M_queue(__state._M_next, _M_cur_results);
     }
 
+  template<typename _BiIter, typename _TraitsT>
+    struct _Backref_matcher
+    {
+      _Backref_matcher(bool __icase, const _TraitsT& __traits)
+      : _M_traits(__traits) { }
+
+      bool
+      _M_apply(_BiIter __expected_begin,
+              _BiIter __expected_end, _BiIter __actual_begin,
+              _BiIter __actual_end)
+      {
+       return _M_traits.transform(__expected_begin, __expected_end)
+           == _M_traits.transform(__actual_begin, __actual_end);
+      }
+
+      const _TraitsT& _M_traits;
+    };
+
+  template<typename _BiIter, typename _CharT>
+    struct _Backref_matcher<_BiIter, std::regex_traits<_CharT>>
+    {
+      using _TraitsT = std::regex_traits<_CharT>;
+      _Backref_matcher(bool __icase, const _TraitsT& __traits)
+      : _M_icase(__icase), _M_traits(__traits) { }
+
+      bool
+      _M_apply(_BiIter __expected_begin,
+              _BiIter __expected_end, _BiIter __actual_begin,
+              _BiIter __actual_end)
+      {
+       if (!_M_icase)
+         return std::equal(__expected_begin, __expected_end,
+                           __actual_begin, __actual_end);
+       typedef std::ctype<_CharT> __ctype_type;
+       const auto& __fctyp = use_facet<__ctype_type>(_M_traits.getloc());
+       return std::equal(__expected_begin, __expected_end,
+                         __actual_begin, __actual_end,
+                         [this, &__fctyp](_CharT __lhs, _CharT __rhs)
+                         {
+                           return __fctyp.tolower(__lhs)
+                               == __fctyp.tolower(__rhs);
+                         });
+      }
+
+      bool _M_icase;
+      const _TraitsT& _M_traits;
+    };
+
   // First fetch the matched result from _M_cur_results as __submatch;
   // then compare it with
   // (_M_current, _M_current + (__submatch.second - __submatch.first)).
@@ -355,9 +403,10 @@ namespace __detail
           __last != _M_end && __tmp != __submatch.second;
           ++__tmp)
        ++__last;
-      if (_M_re._M_automaton->_M_traits.transform(__submatch.first,
-                                                 __submatch.second)
-         == _M_re._M_automaton->_M_traits.transform(_M_current, __last))
+      if (_Backref_matcher<_BiIter, _TraitsT>(
+             _M_re.flags() & regex_constants::icase,
+             _M_re._M_automaton->_M_traits)._M_apply(
+                 __submatch.first, __submatch.second, _M_current, __last))
        {
          if (__last != _M_current)
            {
index ee4d3e1e6f8761470b94e2b98ad959d1b6176473..3fa9022eac4691ebe8a59d2df652a9ae2f25d6ee 100644 (file)
@@ -93,6 +93,17 @@ test06()
   }
 }
 
+// PR libstdc++/71500
+void
+test07()
+{
+  bool test [[gnu::unused]] = true;
+
+  VERIFY(regex_match_debug("abc abc", regex("([a-z]+) \\1", regex::icase)));
+  VERIFY(regex_match_debug("Abc abc", regex("([a-z]+) \\1", regex::icase)));
+  VERIFY(regex_match_debug("abc Abc", regex("([a-z]+) \\1", regex::icase)));
+}
+
 int
 main()
 {
@@ -102,6 +113,7 @@ main()
   test04();
   test05();
   test06();
+  test07();
   return 0;
 }