[libstdc++/71500] make back reference work with icase

Jonathan Wakely jwakely@redhat.com
Fri Sep 15 15:39:00 GMT 2017


On 04/09/17 03:31 -0700, Tim Shen via libstdc++ wrote:
>This fixes the follow-up comments in 71500.
>
>Back-reference matching is different from other matching, as the
>content the back-reference refers to is at "run-time", aka during
>regex_match(), not regex() compilation.
>
>For compilation we do have an abstraction layer to catch all
>comparison customizations, namely _M_translator in regex_compiler.h.
>Until this patch, we don't have an abstraction for "run-time"
>matching. I believe that back-reference is the only place that needs
>run-time matching, so I just build a _Backref_matcher in
>regex_executot.tcc.
>
>Tested on x86_64-linux-gnu.
>
>Thanks!
>
>-- 
>Regards,
>Tim Shen

>commit a97b7fecd319e031ffc489a956b8cf3dc63eeb26
>Author: Tim Shen <timshen@google.com>
>Date:   Mon Sep 4 03:19:35 2017 -0700
>
>            PR libstdc++/71500
>            * include/bits/regex_executor.tcc: Support icase in
>            regex_tratis<...> for back reference matches.
>            * testsuite/28_regex/regression.cc: Test case.
>
>diff --git a/libstdc++-v3/include/bits/regex_executor.tcc b/libstdc++-v3/include/bits/regex_executor.tcc
>index 226e05856e1..f6149fecf9d 100644
>--- a/libstdc++-v3/include/bits/regex_executor.tcc
>+++ b/libstdc++-v3/include/bits/regex_executor.tcc
>@@ -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);

This is only valid in C++14 and higher, because the 4-argument version
of std::equal isn't present in C++11.

>+	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,

Same here.

>+			  [this, &__fctyp](_CharT __lhs, _CharT __rhs)
>+			  {
>+			    return __fctyp.tolower(__lhs)
>+				== __fctyp.tolower(__rhs);
>+			  });

We need to rewrite this to check the lengths are equal first, and then
call the 3-argument version of std::equal.

Alternatively, we could move the implementation of the C++14
std::equal overloads to __equal and make that available for C++11.
I'll try that.




More information about the Libstdc++ mailing list