diff --git a/stl/inc/regex b/stl/inc/regex index b2023ebd87c..672414f2a8b 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -1202,16 +1202,17 @@ _INLINE_VAR constexpr unsigned int _Bmp_size = (_Bmp_max + _Bmp_chrs - 1U) / _B _INLINE_VAR constexpr unsigned int _ARRAY_THRESHOLD = 4U; enum _Node_flags : int { // flags for nfa nodes with special properties - _Fl_none = 0x000, - _Fl_negate = 0x001, - _Fl_greedy = 0x002, - _Fl_longest = 0x008, // TRANSITION, ABI: 0x004 is unused; the parser previously marked some nodes with it - _Fl_class_negated_w = 0x100, - _Fl_class_negated_s = 0x200, - _Fl_class_negated_d = 0x400, - _Fl_begin_needs_w = 0x100, - _Fl_begin_needs_s = 0x200, - _Fl_begin_needs_d = 0x400 + _Fl_none = 0x000, + _Fl_negate = 0x001, + _Fl_greedy = 0x002, + _Fl_longest = 0x008, // TRANSITION, ABI: 0x004 is unused; the parser previously marked some nodes with it + _Fl_class_negated_w = 0x100, + _Fl_class_negated_s = 0x200, + _Fl_class_negated_d = 0x400, + _Fl_class_cl_all_bits = 0x800, // TRANSITION, ABI: GH-5242 + _Fl_begin_needs_w = 0x100, + _Fl_begin_needs_s = 0x200, + _Fl_begin_needs_d = 0x400 }; _BITMASK_OPS(_EMPTY_ARGUMENT, _Node_flags) @@ -2961,11 +2962,19 @@ template void _Builder<_FwdIt, _Elem, _RxTraits>::_Add_named_class( typename _RxTraits::char_class_type _Cl, const _Rx_char_class_kind _Kind) { // add contents of named class to bracket expression + using _Char_class_type = typename _RxTraits::char_class_type; _Node_class<_Elem, _RxTraits>* _Node = static_cast<_Node_class<_Elem, _RxTraits>*>(_Current); _Add_elts(_Node, _Cl, _Kind != _Rx_char_class_kind::_Positive); if (_Bmp_max <= _STD _Max_limit()) { if (_Kind == _Rx_char_class_kind::_Positive) { - _Node->_Classes = static_cast(_Node->_Classes | _Cl); + auto _Cl_all_bits_set = static_cast<_Char_class_type>(-1); + if ((_Node->_Classes != _Cl_all_bits_set && _Cl != _Cl_all_bits_set) + || _Node->_Classes == _Char_class_type{}) { + _Node->_Classes = static_cast<_Char_class_type>(_Node->_Classes | _Cl); + } else if (_Node->_Classes != _Cl) { + _Node->_Classes = static_cast<_Char_class_type>(_Node->_Classes & _Cl); + _Node->_Flags |= _Fl_class_cl_all_bits; + } } else { auto _Node_flag = static_cast<_Node_flags>(_Kind); _Node->_Flags |= _Node_flag; @@ -3514,6 +3523,9 @@ bool _Matcher<_BidIt, _Elem, _RxTraits, _It>::_Do_class(_Node_base* _Nx) { // ap _Found = true; } else if (_Node->_Classes != typename _RxTraits::char_class_type{} && _Traits.isctype(_Ch, _Node->_Classes)) { _Found = true; + } else if ((_Node->_Flags & _Fl_class_cl_all_bits) + && _Traits.isctype(_Ch, static_cast(-1))) { + _Found = true; } else if (_Node->_Equiv && _STD _Lookup_equiv2(_Ch, _Node->_Equiv, _Traits)) { _Found = true; } else if ((_Node->_Flags & _Fl_class_negated_w) @@ -3890,6 +3902,9 @@ _BidIt _Matcher<_BidIt, _Elem, _RxTraits, _It>::_Skip(_BidIt _First_arg, _BidIt } else if (_Node->_Classes != typename _RxTraits::char_class_type{} && _Traits.isctype(_Ch, _Node->_Classes)) { _Found = true; + } else if ((_Node->_Flags & _Fl_class_cl_all_bits) + && _Traits.isctype(_Ch, static_cast(-1))) { + _Found = true; } else if (_Node->_Equiv && _STD _Lookup_equiv2(_Ch, _Node->_Equiv, _Traits)) { _Found = true; } else if ((_Node->_Flags & _Fl_class_negated_w) diff --git a/tests/std/tests/VSO_0000000_regex_use/test.cpp b/tests/std/tests/VSO_0000000_regex_use/test.cpp index 4f7f3b1e855..d7a4dc65f38 100644 --- a/tests/std/tests/VSO_0000000_regex_use/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_use/test.cpp @@ -1275,6 +1275,50 @@ void test_gh_5214() { } } +void test_gh_5243() { + // GH-5243: : wregex with regular expression [\w\s] fails to match some spaces + for (wstring pattern : {LR"([\w])", LR"([\w\w])"}) { + const test_wregex word_regex(&g_regexTester, pattern); + word_regex.should_search_match(L"a", L"a"); + word_regex.should_search_match(L"2", L"2"); + word_regex.should_search_match(L"_", L"_"); + word_regex.should_search_match(L"\u00e4", L"\u00e4"); // U+00E4 LATIN SMALL LETTER A WITH DIAERESIS + word_regex.should_search_match(L"\u0662", L"\u0662"); // U+0662 ARABIC-INDIC DIGIT TWO + word_regex.should_search_fail(L" "); + word_regex.should_search_fail(L"\u2028"); // U+2028 LINE SEPARATOR + word_regex.should_search_fail(L"."); + word_regex.should_search_fail(L"-"); + word_regex.should_search_fail(L"\u203d"); // U+203D INTERROBANG + } + { + const test_wregex space_regex(&g_regexTester, LR"([\s])"); + space_regex.should_search_fail(L"a"); + space_regex.should_search_fail(L"2"); + space_regex.should_search_fail(L"_"); + space_regex.should_search_fail(L"\u00e4"); // U+00E4 LATIN SMALL LETTER A WITH DIAERESIS + space_regex.should_search_fail(L"\u0662"); // U+0662 ARABIC-INDIC DIGIT TWO + space_regex.should_search_match(L" ", L" "); + space_regex.should_search_match(L"\u2028", L"\u2028"); // U+2028 LINE SEPARATOR + space_regex.should_search_fail(L"."); + space_regex.should_search_fail(L"-"); + space_regex.should_search_fail(L"\u203d"); // U+203D INTERROBANG + } + for (wstring pattern : {LR"([\w\s])", LR"([\s\w])"}) { + const test_wregex word_or_space_regex(&g_regexTester, pattern); + word_or_space_regex.should_search_match(L"a", L"a"); + word_or_space_regex.should_search_match(L"2", L"2"); + word_or_space_regex.should_search_match(L"_", L"_"); + word_or_space_regex.should_search_match(L"\u00e4", L"\u00e4"); // U+00E4 LATIN SMALL LETTER A WITH DIAERESIS + word_or_space_regex.should_search_match(L"\u0662", L"\u0662"); // U+0662 ARABIC-INDIC DIGIT TWO + word_or_space_regex.should_search_match(L" ", L" "); + word_or_space_regex.should_search_match(L"\u2028", L"\u2028"); // U+2028 LINE SEPARATOR + word_or_space_regex.should_search_fail(L"."); + word_or_space_regex.should_search_fail(L"-"); + word_or_space_regex.should_search_fail(L"\u203d"); // U+203D INTERROBANG + } +} + + void test_gh_5245() { // GH-5245: : Successful negative lookahead assertions // sometimes mistakenly assign matches to capture groups @@ -1660,6 +1704,7 @@ int main() { test_gh_5167(); test_gh_5192(); test_gh_5214(); + test_gh_5243(); test_gh_5245(); test_gh_5253(); test_gh_5362();