From: Tim Shen Date: Thu, 27 Oct 2016 21:40:34 +0000 (+0000) Subject: [libcxx] Make regex_match backtrack when search fails X-Git-Tag: llvmorg-4.0.0-rc1~6084 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e776667441686a82f394fac401a9822bc7d63f6c;p=platform%2Fupstream%2Fllvm.git [libcxx] Make regex_match backtrack when search fails Summary: Fixes PR19851. alg.re.match/ecma.pass.cpp still XFAILS on linux, but after commenting out locale-related tests, it passes. I don't have a freebsd machine to produce a full pass. Reviewers: mclow.lists Subscribers: cfe-commits, emaste Differential Revision: https://reviews.llvm.org/D26026 llvm-svn: 285352 --- diff --git a/libcxx/include/regex b/libcxx/include/regex index 975f640..baff5d3 100644 --- a/libcxx/include/regex +++ b/libcxx/include/regex @@ -865,7 +865,8 @@ enum match_flag_type format_sed = 1 << 8, format_no_copy = 1 << 9, format_first_only = 1 << 10, - __no_update_pos = 1 << 11 + __no_update_pos = 1 << 11, + __full_match = 1 << 12 }; inline _LIBCPP_INLINE_VISIBILITY @@ -2984,10 +2985,12 @@ __lookahead<_CharT, _Traits>::__exec(__state& __s) const { match_results __m; __m.__init(1 + __exp_.mark_count(), __s.__current_, __s.__last_); - bool __matched = __exp_.__match_at_start_ecma(__s.__current_, __s.__last_, - __m, - __s.__flags_ | regex_constants::match_continuous, - __s.__at_first_ && __s.__current_ == __s.__first_); + bool __matched = __exp_.__match_at_start_ecma( + __s.__current_, __s.__last_, + __m, + (__s.__flags_ | regex_constants::match_continuous) & + ~regex_constants::__full_match, + __s.__at_first_ && __s.__current_ == __s.__first_); if (__matched != __invert_) { __s.__do_ = __state::__accept_but_not_consume; @@ -5555,12 +5558,18 @@ basic_regex<_CharT, _Traits>::__match_at_start_ecma( switch (__s.__do_) { case __state::__end_state: - if (__flags & regex_constants::match_not_null && + if ((__flags & regex_constants::match_not_null) && __s.__current_ == __first) { __states.pop_back(); break; } + if ((__flags & regex_constants::__full_match) && + __s.__current_ != __last) + { + __states.pop_back(); + break; + } __m.__matches_[0].first = __first; __m.__matches_[0].second = _VSTD::next(__first, __s.__current_ - __first); __m.__matches_[0].matched = true; @@ -5624,12 +5633,18 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_nosubs( switch (__s.__do_) { case __state::__end_state: - if (__flags & regex_constants::match_not_null && + if ((__flags & regex_constants::match_not_null) && __s.__current_ == __first) { __states.pop_back(); break; } + if ((__flags & regex_constants::__full_match) && + __s.__current_ != __last) + { + __states.pop_back(); + break; + } if (!__matched || __highest_j < __s.__current_ - __s.__first_) __highest_j = __s.__current_ - __s.__first_; __matched = true; @@ -5715,12 +5730,18 @@ basic_regex<_CharT, _Traits>::__match_at_start_posix_subs( switch (__s.__do_) { case __state::__end_state: - if (__flags & regex_constants::match_not_null && + if ((__flags & regex_constants::match_not_null) && __s.__current_ == __first) { __states.pop_back(); break; } + if ((__flags & regex_constants::__full_match) && + __s.__current_ != __last) + { + __states.pop_back(); + break; + } if (!__matched || __highest_j < __s.__current_ - __s.__first_) { __highest_j = __s.__current_ - __s.__first_; @@ -5951,8 +5972,10 @@ regex_match(_BidirectionalIterator __first, _BidirectionalIterator __last, const basic_regex<_CharT, _Traits>& __e, regex_constants::match_flag_type __flags = regex_constants::match_default) { - bool __r = _VSTD::regex_search(__first, __last, __m, __e, - __flags | regex_constants::match_continuous); + bool __r = _VSTD::regex_search( + __first, __last, __m, __e, + __flags | regex_constants::match_continuous | + regex_constants::__full_match); if (__r) { __r = !__m.suffix().matched; diff --git a/libcxx/test/std/re/re.alg/re.alg.match/ecma.pass.cpp b/libcxx/test/std/re/re.alg/re.alg.match/ecma.pass.cpp index a4568f6..bbe57ad 100644 --- a/libcxx/test/std/re/re.alg/re.alg.match/ecma.pass.cpp +++ b/libcxx/test/std/re/re.alg/re.alg.match/ecma.pass.cpp @@ -371,16 +371,37 @@ int main() } { std::cmatch m; + // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2273 const char s[] = "tournament"; - assert(!std::regex_match(s, m, std::regex("tour|to|tournament"))); - assert(m.size() == 0); + assert(std::regex_match(s, m, std::regex("tour|to|tournament"))); + assert(m.size() == 1); + assert(!m.prefix().matched); + assert(m.prefix().first == s); + assert(m.prefix().second == m[0].first); + assert(!m.suffix().matched); + assert(m.suffix().first == m[0].second); + assert(m.suffix().second == m[0].second); + assert(m.length(0) == std::char_traits::length(s)); + assert(m.position(0) == 0); + assert(m.str(0) == s); } { std::cmatch m; + // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2273 const char s[] = "tournamenttotour"; - assert(!std::regex_match(s, m, std::regex("(tour|to|tournament)+", - std::regex_constants::nosubs))); - assert(m.size() == 0); + assert( + std::regex_match(s, m, std::regex("(tour|to|tournament)+", + std::regex_constants::nosubs))); + assert(m.size() == 1); + assert(!m.prefix().matched); + assert(m.prefix().first == s); + assert(m.prefix().second == m[0].first); + assert(!m.suffix().matched); + assert(m.suffix().first == m[0].second); + assert(m.suffix().second == m[0].second); + assert(m.length(0) == std::char_traits::length(s)); + assert(m.position(0) == 0); + assert(m.str(0) == s); } { std::cmatch m; @@ -1036,16 +1057,37 @@ int main() } { std::wcmatch m; + // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2273 const wchar_t s[] = L"tournament"; - assert(!std::regex_match(s, m, std::wregex(L"tour|to|tournament"))); - assert(m.size() == 0); + assert(std::regex_match(s, m, std::wregex(L"tour|to|tournament"))); + assert(m.size() == 1); + assert(!m.prefix().matched); + assert(m.prefix().first == s); + assert(m.prefix().second == m[0].first); + assert(!m.suffix().matched); + assert(m.suffix().first == m[0].second); + assert(m.suffix().second == m[0].second); + assert(m.length(0) == std::char_traits::length(s)); + assert(m.position(0) == 0); + assert(m.str(0) == s); } { std::wcmatch m; + // http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#2273 const wchar_t s[] = L"tournamenttotour"; - assert(!std::regex_match(s, m, std::wregex(L"(tour|to|tournament)+", - std::regex_constants::nosubs))); - assert(m.size() == 0); + assert( + std::regex_match(s, m, std::wregex(L"(tour|to|tournament)+", + std::regex_constants::nosubs))); + assert(m.size() == 1); + assert(!m.prefix().matched); + assert(m.prefix().first == s); + assert(m.prefix().second == m[0].first); + assert(!m.suffix().matched); + assert(m.suffix().first == m[0].second); + assert(m.suffix().second == m[0].second); + assert(m.length(0) == std::char_traits::length(s)); + assert(m.position(0) == 0); + assert(m.str(0) == s); } { std::wcmatch m;