From 3366a4740876b62c7e40f1ab74d3ed65bd698606 Mon Sep 17 00:00:00 2001 From: Tim Shen Date: Mon, 11 Sep 2017 19:02:34 +0000 Subject: [PATCH] re PR libstdc++/71500 (regex::icase only works on first character in a range) 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 | 7 +++ libstdc++-v3/include/bits/regex_executor.tcc | 55 ++++++++++++++++++- libstdc++-v3/testsuite/28_regex/regression.cc | 12 ++++ 3 files changed, 71 insertions(+), 3 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 33b9cdb20e0..7163c6427b4 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2017-09-11 Tim Shen + + 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 * testsuite/21_strings/basic_string/lwg2946.cc: Adjust for 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 + 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 + 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) { diff --git a/libstdc++-v3/testsuite/28_regex/regression.cc b/libstdc++-v3/testsuite/28_regex/regression.cc index ee4d3e1e6f8..3fa9022eac4 100644 --- a/libstdc++-v3/testsuite/28_regex/regression.cc +++ b/libstdc++-v3/testsuite/28_regex/regression.cc @@ -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; } -- 2.30.2