diff --git a/stl/CMakeLists.txt b/stl/CMakeLists.txt index ac17fb0a55f..10d21b3173c 100644 --- a/stl/CMakeLists.txt +++ b/stl/CMakeLists.txt @@ -213,6 +213,7 @@ set(IMPLIB_SOURCES ${CMAKE_CURRENT_LIST_DIR}/src/locale0_implib.cpp ${CMAKE_CURRENT_LIST_DIR}/src/nothrow.cpp ${CMAKE_CURRENT_LIST_DIR}/src/print.cpp + ${CMAKE_CURRENT_LIST_DIR}/src/regex.cpp ${CMAKE_CURRENT_LIST_DIR}/src/sharedmutex.cpp ${CMAKE_CURRENT_LIST_DIR}/src/stacktrace.cpp ${CMAKE_CURRENT_LIST_DIR}/src/syserror_import_lib.cpp diff --git a/stl/inc/locale b/stl/inc/locale index cc08f4d4eee..7e75f4d7634 100644 --- a/stl/inc/locale +++ b/stl/inc/locale @@ -94,6 +94,9 @@ inline size_t __CRTDECL _LStrxfrm(_Out_writes_(_Last1 - _First1) _Post_readable_ } #endif // defined(_CRTBLD) +template +class _Regex_traits; + _EXPORT_STD template class collate : public locale::facet { // facet for ordering sequences of elements public: @@ -189,6 +192,8 @@ protected: private: _Locinfo::_Collvec _Coll; // used by _LStrcoll and _XStrxfrm + + friend _Regex_traits<_Elem>; }; #ifdef __clang__ diff --git a/stl/inc/regex b/stl/inc/regex index b63f7e83066..cdfefd0cddf 100644 --- a/stl/inc/regex +++ b/stl/inc/regex @@ -53,6 +53,17 @@ _STL_DISABLE_CLANG_WARNINGS #endif // ^^^ !defined(_DEBUG) ^^^ #endif // !defined(_ENHANCED_REGEX_VISUALIZER) +#if defined(_CPPRTTI) && !defined(_M_CEE_PURE) +extern "C" { +_STD size_t __stdcall __std_regex_transform_primary_char( + _Out_writes_(_Last1 - _First1) _Post_readable_size_(return) char* _First1, char* _Last1, + _In_reads_(_Last2 - _First2) const char* _First2, const char* _Last2, _In_opt_ const _Collvec*) noexcept; +_STD size_t __stdcall __std_regex_transform_primary_wchar_t( + _Out_writes_(_Last1 - _First1) _Post_readable_size_(return) wchar_t* _First1, wchar_t* _Last1, + _In_reads_(_Last2 - _First2) const wchar_t* _First2, const wchar_t* _Last2, _In_opt_ const _Collvec*) noexcept; +} // extern "C" +#endif // ^^^ defined(_CPPRTTI) && !defined(_M_CEE_PURE) ^^^ + _STD_BEGIN enum _Meta_type : int { // meta character representations for parser @@ -267,6 +278,20 @@ struct _Regex_traits_base { // base of all regular expression traits using char_class_type = ctype_base::mask; }; +#if defined(_CPPRTTI) && !defined(_M_CEE_PURE) +inline size_t _Regex_transform_primary(_Out_writes_(_Last1 - _First1) _Post_readable_size_(return) char* _First1, + char* _Last1, _In_reads_(_Last2 - _First2) const char* _First2, const char* _Last2, + _In_opt_ const _Locinfo::_Collvec* _Vector) noexcept { + return __std_regex_transform_primary_char(_First1, _Last1, _First2, _Last2, _Vector); +} + +inline size_t _Regex_transform_primary(_Out_writes_(_Last1 - _First1) _Post_readable_size_(return) wchar_t* _First1, + wchar_t* _Last1, _In_reads_(_Last2 - _First2) const wchar_t* _First2, const wchar_t* _Last2, + _In_opt_ const _Locinfo::_Collvec* _Vector) noexcept { + return __std_regex_transform_primary_wchar_t(_First1, _Last1, _First2, _Last2, _Vector); +} +#endif // ^^^ defined(_CPPRTTI) && !defined(_M_CEE_PURE) ^^^ + template class _Regex_traits : public _Regex_traits_base { // base class for regular expression traits public: @@ -312,13 +337,38 @@ public: string_type transform_primary(_FwdIt _First, _FwdIt _Last) const { // apply locale-specific case-insensitive transformation string_type _Res; - - if (_First != _Last) { // non-empty string, transform it - vector<_Elem> _Temp(_First, _Last); - - _Getctype()->tolower(_Temp.data(), _Temp.data() + _Temp.size()); - _Res = _Getcoll()->transform(_Temp.data(), _Temp.data() + _Temp.size()); +#if defined(_CPPRTTI) && !defined(_M_CEE_PURE) + if (_First != _Last) { + const collate<_Elem>* _Coll = _Getcoll(); + const auto& _Coll_type = typeid(*_Coll); + // TRANSITION, ABI: GH-5394: locale creates collate objects of type collate, not collate_byname. + // Depending on the resolution of LWG-2338, comparison to typeid(collate) might also become + // required by the standard. + if (_Coll_type == typeid(collate_byname<_Elem>) || _Coll_type == typeid(collate<_Elem>)) { + // non-empty string with known collate facet, transform it + const string_type _Src(_First, _Last); + const auto _Src_first = _Src.data(); + const auto _Src_last = _Src_first + _Src.size(); + + size_t _Count = _Src.size(); + while (_Res.size() < _Count) { + _Res.resize(_Count); + _Count = _STD _Regex_transform_primary( + &_Res[0], &_Res[0] + _Count, _Src_first, _Src_last, &_Coll->_Coll); + + if (_Count == static_cast(-1)) { + // return empty string in case of error + _Count = 0; + break; + } + } + _Res.resize(_Count); + } } +#else // ^^^ defined(_CPPRTTI) && !defined(_M_CEE_PURE) / !defined(_CPPRTTI) || defined(_M_CEE_PURE) vvv + (void) _First; + (void) _Last; +#endif // ^^^ !defined(_CPPRTTI) || defined(_M_CEE_PURE) ^^^ return _Res; } @@ -4211,26 +4261,30 @@ _Prs_ret _Parser<_FwdIt, _Elem, _RxTraits>::_Do_ex_class2( _Elem* const _Coll_elem_first = &_Coll_elem.front(); const _Elem* const _Coll_elem_last = _Coll_elem_first + _Size; + + if (_Size == 1 && _End_arg == _Meta_dot) { + // process single-element collating elements like individual characters + _Val = *_Coll_elem_first; + return _Prs_chr; + } + + if (_Flags & regex_constants::icase) { + for (auto _Current = _Coll_elem_first; _Current != _Coll_elem_last; ++_Current) { + *_Current = _Traits.translate_nocase(*_Current); + } + } else if (_Flags & regex_constants::collate) { + for (auto _Current = _Coll_elem_first; _Current != _Coll_elem_last; ++_Current) { + *_Current = _Traits.translate(*_Current); + } + } + if (_End_arg == _Meta_equal) { // process equivalence _Nfa._Add_equiv2(_Coll_elem_first, _Coll_elem_last); return _Prs_set; } else { // process collating element - if (_Size == 1) { - _Val = *_Coll_elem_first; - return _Prs_chr; - } // Character ranges with multi-character bounds cannot be represented in NFA nodes yet (see GH-5391). // Provisionally treat multi-character collating elements as character sets. - if (_Flags & regex_constants::icase) { - for (auto _Current = _Coll_elem_first; _Current != _Coll_elem_last; ++_Current) { - *_Current = _Traits.translate_nocase(*_Current); - } - } else if (_Flags & regex_constants::collate) { - for (auto _Current = _Coll_elem_first; _Current != _Coll_elem_last; ++_Current) { - *_Current = _Traits.translate(*_Current); - } - } _Nfa._Add_coll2(_Coll_elem_first, _Coll_elem_last); return _Prs_set; } diff --git a/stl/inc/yvals.h b/stl/inc/yvals.h index f6c6d4a2288..0ac04d6b4a4 100644 --- a/stl/inc/yvals.h +++ b/stl/inc/yvals.h @@ -3,7 +3,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// This header is used to compile the import library (via locale0_implib.cpp => locale0.cpp => xfacet => yvals.h). +// This header is used to compile the import library +// (via locale0_implib.cpp => locale0.cpp => xfacet => yvals.h and regex.cpp => awint.hpp => yvals.h). // MAJOR LIMITATIONS apply to what can be included here! // Before editing this file, read: /docs/import_library.md diff --git a/stl/msbuild/stl_base/stl.files.settings.targets b/stl/msbuild/stl_base/stl.files.settings.targets index 9b7db156955..0669a4c0a59 100644 --- a/stl/msbuild/stl_base/stl.files.settings.targets +++ b/stl/msbuild/stl_base/stl.files.settings.targets @@ -158,6 +158,7 @@ SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception $(CrtRoot)\github\stl\src\locale0_implib.cpp; $(CrtRoot)\github\stl\src\nothrow.cpp; $(CrtRoot)\github\stl\src\print.cpp; + $(CrtRoot)\github\stl\src\regex.cpp; $(CrtRoot)\github\stl\src\sharedmutex.cpp; $(CrtRoot)\github\stl\src\stacktrace.cpp; $(CrtRoot)\github\stl\src\syserror_import_lib.cpp; diff --git a/stl/src/awint.hpp b/stl/src/awint.hpp index 797801b7a98..da88c79bc7d 100644 --- a/stl/src/awint.hpp +++ b/stl/src/awint.hpp @@ -2,6 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // Internal definitions for A&W Win32 wrapper routines. + +// This file is compiled into the import library (via regex.cpp => awint.hpp). +// MAJOR LIMITATIONS apply to what can be included here! +// Before editing this file, read: /docs/import_library.md + #pragma once #include diff --git a/stl/src/regex.cpp b/stl/src/regex.cpp new file mode 100644 index 00000000000..6ecd7744cd7 --- /dev/null +++ b/stl/src/regex.cpp @@ -0,0 +1,128 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +// This file is compiled into the import library. +// MAJOR LIMITATIONS apply to what can be included here! +// Before editing this file, read: /docs/import_library.md + +#include <__msvc_xlocinfo_types.hpp> +#include +#include +#include +#include +#include + +#include + +#undef _ENFORCE_ONLY_CORE_HEADERS +#include "awint.hpp" + +extern "C" { + +// derived from xstrxfrm.cpp +size_t __stdcall __std_regex_transform_primary_char( + _Out_writes_(end1 - string1) _Post_readable_size_(return) char* string1, char* end1, + _In_reads_(end2 - string2) const char* string2, const char* end2, _In_opt_ const _Collvec* ploc) noexcept { + size_t n1 = end1 - string1; + size_t n2 = end2 - string2; + size_t retval = static_cast(-1); + UINT codepage; + const wchar_t* locale_name; + + if (ploc == nullptr) { + locale_name = ___lc_locale_name_func()[LC_COLLATE]; + codepage = ___lc_collate_cp_func(); + } else { + locale_name = ploc->_LocaleName; + codepage = ploc->_Page; + } + + if (locale_name == nullptr && codepage == CP_ACP) { + if (n2 <= n1) { + memcpy(string1, string2, n2); + } + retval = n2; + } else { + // Inquire size of dst string in BYTES + const int dstlen = __crtLCMapStringA(locale_name, + LCMAP_SORTKEY | LINGUISTIC_IGNORECASE | LINGUISTIC_IGNOREDIACRITIC | NORM_IGNOREKANATYPE | NORM_IGNOREWIDTH, + string2, static_cast(n2), nullptr, 0, codepage, TRUE); + + if (dstlen != 0) { + retval = dstlen; + + // if not enough room, return amount needed + if (dstlen <= static_cast(n1)) { + // Map src string to dst string + __crtLCMapStringA(locale_name, + LCMAP_SORTKEY | LINGUISTIC_IGNORECASE | LINGUISTIC_IGNOREDIACRITIC | NORM_IGNOREKANATYPE + | NORM_IGNOREWIDTH, + string2, static_cast(n2), string1, static_cast(n1), codepage, TRUE); + } + } + } + + return retval; +} + +// derived from xwcsxfrm.cpp +size_t __stdcall __std_regex_transform_primary_wchar_t( + _Out_writes_(end1 - string1) _Post_readable_size_(return) wchar_t* string1, wchar_t* end1, + _In_reads_(end2 - string2) const wchar_t* string2, const wchar_t* end2, _In_opt_ const _Collvec* ploc) noexcept { + size_t n1 = end1 - string1; + size_t n2 = end2 - string2; + size_t size = static_cast(-1); + const wchar_t* locale_name; + + if (ploc == nullptr) { + locale_name = ___lc_locale_name_func()[LC_COLLATE]; + } else { + locale_name = ploc->_LocaleName; + } + + if (locale_name == nullptr) { + if (n2 <= n1) { + memcpy(string1, string2, n2 * sizeof(wchar_t)); + } + size = n2; + } else { + // When using LCMAP_SORTKEY, LCMapStringW handles BYTES not wide + // chars. We use a byte buffer to hold bytes and then convert the + // byte string to a wide char string and return this so it can be + // compared using wcscmp(). User's buffer is n1 wide chars, so + // use an internal buffer of n1 bytes. + + auto bbuffer = _malloc_crt_t(unsigned char, n1); + + if (bbuffer) { +#pragma warning(push) +#pragma warning(disable : 6386) // PREfast doesn't understand LCMAP_SORTKEY + size = __crtLCMapStringW(locale_name, + LCMAP_SORTKEY | LINGUISTIC_IGNORECASE | LINGUISTIC_IGNOREDIACRITIC | NORM_IGNOREKANATYPE + | NORM_IGNOREWIDTH, + string2, static_cast(n2), reinterpret_cast(bbuffer.get()), static_cast(n1)); +#pragma warning(pop) + + if (size == 0) { + // buffer not big enough, get size required. + size = __crtLCMapStringW(locale_name, + LCMAP_SORTKEY | LINGUISTIC_IGNORECASE | LINGUISTIC_IGNOREDIACRITIC | NORM_IGNOREKANATYPE + | NORM_IGNOREWIDTH, + string2, static_cast(n2), nullptr, 0); + + if (size == 0) { + size = static_cast(-1); // default error + } + } else { + // string successfully mapped, convert to wide char + + for (size_t i = 0; i < size; ++i) { + string1[i] = static_cast(bbuffer.get()[i]); + } + } + } + } + + return size; +} +} // extern "C" diff --git a/tests/libcxx/expected_results.txt b/tests/libcxx/expected_results.txt index 64b389eaf67..c0fff7a9161 100644 --- a/tests/libcxx/expected_results.txt +++ b/tests/libcxx/expected_results.txt @@ -830,7 +830,6 @@ std/re/re.alg/re.alg.search/basic.pass.cpp FAIL std/re/re.alg/re.alg.search/ecma.pass.cpp FAIL std/re/re.alg/re.alg.search/extended.pass.cpp FAIL std/re/re.traits/lookup_collatename.pass.cpp FAIL -std/re/re.traits/transform_primary.pass.cpp FAIL # Not analyzed, likely STL bugs. Various assertions. std/numerics/complex.number/complex.ops/complex_divide_complex.pass.cpp FAIL diff --git a/tests/std/tests/GH_005204_regex_collating_ranges/test.cpp b/tests/std/tests/GH_005204_regex_collating_ranges/test.cpp index b24141a9fc3..687812ce480 100644 --- a/tests/std/tests/GH_005204_regex_collating_ranges/test.cpp +++ b/tests/std/tests/GH_005204_regex_collating_ranges/test.cpp @@ -535,31 +535,98 @@ void test_gh_994() { gh_994_should_throw("[a-[.cs.]]", error_range); gh_994_should_throw("[[.cs.]-[.dzs.]]", error_range); -#ifndef SKIP_COLLATE_TESTS +#ifndef _M_CEE_PURE g_regexTester.should_throw("[[=a=]-c]", error_range); g_regexTester.should_throw("[c-[=z=]]", error_range); g_regexTester.should_throw("[[=a=]-[=z=]]", error_range); g_regexTester.should_match("a", "[[=a=]]"); - g_regexTester.should_match("A", "[[=a=]]"); + g_regexTester.should_not_match("A", "[[=a=]]"); g_regexTester.should_not_match("b", "[[=a=]]"); g_regexTester.should_not_match("B", "[[=a=]]"); - g_regexTester.should_match("z", "[[=Z=]]"); + g_regexTester.should_not_match("z", "[[=Z=]]"); g_regexTester.should_match("Z", "[[=Z=]]"); g_regexTester.should_not_match("b", "[[=Z=]]"); g_regexTester.should_not_match("B", "[[=Z=]]"); + g_regexTester.should_match("a", "[[=a=]]", icase); + g_regexTester.should_match("A", "[[=a=]]", icase); + g_regexTester.should_not_match("b", "[[=a=]]", icase); + g_regexTester.should_not_match("B", "[[=a=]]", icase); + g_regexTester.should_match("z", "[[=Z=]]", icase); + g_regexTester.should_match("Z", "[[=Z=]]", icase); + g_regexTester.should_not_match("b", "[[=Z=]]", icase); + g_regexTester.should_not_match("B", "[[=Z=]]", icase); + g_regexTester.should_match("ab", "[[=a=]]b"); - g_regexTester.should_match("Ab", "[[=a=]]b"); + g_regexTester.should_not_match("Ab", "[[=a=]]b"); g_regexTester.should_not_match("Ab", "[[=a=]]B"); g_regexTester.should_not_match("b", "[[=a=]]b"); g_regexTester.should_not_match("aab", "[[=a=]]b"); g_regexTester.should_not_match("B", "[[=a=]]b"); - - g_regexTester.should_match("AaAaaAaab", "[[=a=]]*b"); + g_regexTester.should_not_match("ab", "[[=A=]]b"); + g_regexTester.should_match("Ab", "[[=A=]]b"); + g_regexTester.should_not_match("Ab", "[[=A=]]B"); + g_regexTester.should_not_match("b", "[[=A=]]b"); + g_regexTester.should_not_match("AAb", "[[=A=]]b"); + g_regexTester.should_not_match("B", "[[=A=]]b"); + + g_regexTester.should_match("ab", "[[=a=]]b", icase); + g_regexTester.should_match("Ab", "[[=a=]]b", icase); + g_regexTester.should_match("Ab", "[[=a=]]B", icase); + g_regexTester.should_not_match("b", "[[=a=]]b", icase); + g_regexTester.should_not_match("aab", "[[=a=]]b", icase); + g_regexTester.should_not_match("B", "[[=a=]]b", icase); + g_regexTester.should_match("ab", "[[=A=]]b", icase); + g_regexTester.should_match("Ab", "[[=A=]]b", icase); + g_regexTester.should_match("Ab", "[[=A=]]B", icase); + g_regexTester.should_not_match("b", "[[=A=]]b", icase); + g_regexTester.should_not_match("AAb", "[[=A=]]b", icase); + g_regexTester.should_not_match("B", "[[=A=]]b", icase); + + g_regexTester.should_not_match("AaAaaAaab", "[[=a=]]*b"); g_regexTester.should_not_match("AaAaaAaab", "[[=a=]]*c"); - g_regexTester.should_match("AaAabcaAaad", "[[=a=]bc]*d"); -#endif // !defined(SKIP_COLLATE_TESTS) + g_regexTester.should_not_match("AaAabcaAaad", "[[=a=]bc]*d"); + g_regexTester.should_match("AaAaaAaab", "[[=a=]]*b", icase); + g_regexTester.should_not_match("AaAaaAaab", "[[=a=]]*c", icase); + g_regexTester.should_match("AaAabcaAaad", "[[=a=]bc]*d", icase); +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ +} + +void test_gh_5435() { + // GH-5435: : Equivalence classes have unexpected behavior with std::wregex +#ifndef _M_CEE_PURE + { + test_wregex_locale eq_a_regex(&g_regexTester, L"^[[=a=]]*b$", "en-US"); + eq_a_regex.should_search_match(L"A\u00c0ab", L"A\u00c0ab"); // U+00C0 LATIN CAPITAL LETTER A WITH GRAVE + eq_a_regex.should_search_fail(L"Ab\u00c0ab"); // U+00C0 LATIN CAPITAL LETTER A WITH GRAVE + eq_a_regex.should_search_match(L"A\u00e0ab", L"A\u00e0ab"); // U+00E0 LATIN SMALL LETTER A WITH GRAVE + eq_a_regex.should_search_match(L"A\u00c1ab", L"A\u00c1ab"); // U+00C1 LATIN CAPITAL LETTER A WITH ACUTE + eq_a_regex.should_search_match(L"A\u00e1ab", L"A\u00e1ab"); // U+00E1 LATIN SMALL LETTER A WITH ACUTE + eq_a_regex.should_search_match(L"A\u00c2ab", L"A\u00c2ab"); // U+00C2 LATIN CAPITAL LETTER A WITH CIRCUMFLEX + eq_a_regex.should_search_match(L"A\u00e2ab", L"A\u00e2ab"); // U+00E2 LATIN SMALL LETTER A WITH CIRCUMFLEX + eq_a_regex.should_search_match(L"A\u00c3ab", L"A\u00c3ab"); // U+00C3 LATIN CAPITAL LETTER A WITH TILDE + eq_a_regex.should_search_match(L"A\u00e3ab", L"A\u00e3ab"); // U+00E3 LATIN SMALL LETTER A WITH TILDE + eq_a_regex.should_search_match(L"A\u00c4ab", L"A\u00c4ab"); // U+00C4 LATIN CAPITAL LETTER A WITH DIAERESIS + eq_a_regex.should_search_match(L"A\u00e4ab", L"A\u00e4ab"); // U+00E4 LATIN SMALL LETTER A WITH DIAERESIS + eq_a_regex.should_search_match(L"A\u00c5ab", L"A\u00c5ab"); // U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE + eq_a_regex.should_search_match(L"A\u00e5ab", L"A\u00e5ab"); // U+00E5 LATIN SMALL LETTER A WITH RING ABOVE + } + { + test_wregex_locale eq_e_regex(&g_regexTester, L"^[[=e=]]*b$", "en-US"); + eq_e_regex.should_search_match(L"e\u00c8Eb", L"e\u00c8Eb"); // U+00C8 LATIN CAPITAL LETTER E WITH GRAVE + eq_e_regex.should_search_fail(L"eb\u00c8Eb"); // U+00C8 LATIN CAPITAL LETTER E WITH GRAVE + eq_e_regex.should_search_match(L"e\u00e8Eb", L"e\u00e8Eb"); // U+00E8 LATIN SMALL LETTER E WITH GRAVE + eq_e_regex.should_search_match(L"e\u00c9Eb", L"e\u00c9Eb"); // U+00C9 LATIN CAPITAL LETTER E WITH ACUTE + eq_e_regex.should_search_match(L"e\u00e9Eb", L"e\u00e9Eb"); // U+00E9 LATIN SMALL LETTER E WITH ACUTE + eq_e_regex.should_search_match(L"e\u00caEb", L"e\u00caEb"); // U+00CA LATIN CAPITAL LETTER E WITH CIRCUMFLEX + eq_e_regex.should_search_match(L"e\u00eaEb", L"e\u00eaEb"); // U+00EA LATIN SMALL LETTER E WITH CIRCUMFLEX + eq_e_regex.should_search_match(L"e\u00cbEb", L"e\u00cbEb"); // U+00CB LATIN CAPITAL LETTER E WITH DIAERESIS + eq_e_regex.should_search_match(L"e\u00ebEb", L"e\u00ebEb"); // U+00EB LATIN SMALL LETTER E WITH DIAERESIS + eq_e_regex.should_search_fail(L"e\u00ccEb"); // U+00CC LATIN CAPITAL LETTER I WITH GRAVE + eq_e_regex.should_search_fail(L"e\u00ecEb"); // U+00EC LATIN SMALL LETTER I WITH GRAVE + } +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ } void test_gh_5437_ECMAScript_or_collate(syntax_option_type ECMAScript_or_collate) { @@ -592,6 +659,7 @@ void test_gh_5437() { int main() { test_collating_ranges_german(); test_gh_994(); + test_gh_5435(); test_gh_5437(); return g_regexTester.result(); diff --git a/tests/std/tests/VSO_0000000_regex_use/test.cpp b/tests/std/tests/VSO_0000000_regex_use/test.cpp index d7a4dc65f38..3d6fe5380a7 100644 --- a/tests/std/tests/VSO_0000000_regex_use/test.cpp +++ b/tests/std/tests/VSO_0000000_regex_use/test.cpp @@ -764,9 +764,11 @@ void test_gh_4995() { g_regexTester.should_throw("[[:digit:]-e]", error_range); g_regexTester.should_throw("[e-[:digit:]]", error_range); g_regexTester.should_throw("[[:alpha:]-[:digit:]]", error_range); +#ifndef _M_CEE_PURE g_regexTester.should_throw("[[=a=]-e]", error_range, ECMAScript | regex::collate); g_regexTester.should_throw("[e-[=a=]]", error_range, ECMAScript | regex::collate); g_regexTester.should_throw("[[=a=]-[=b=]]", error_range, ECMAScript | regex::collate); +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ // Test valid cases: g_regexTester.should_not_match("b", R"([\d-])"); diff --git a/tests/tr1/tests/regex1/test.cpp b/tests/tr1/tests/regex1/test.cpp index a9f4689b176..2aaf0ea2e7e 100644 --- a/tests/tr1/tests/regex1/test.cpp +++ b/tests/tr1/tests/regex1/test.cpp @@ -173,9 +173,11 @@ static void test_traits() { // test template regex_traits CHECKSTRING(v0.transform(carr, carr + xlen(carr)), v0.transform(carr, carr + xlen(carr))); CHECK(v0.transform(carr, carr + xlen(carr)) != v0.transform(carr0, carr0 + xlen(carr0))); CHECK(v0.transform(carr, carr + xlen(carr)) < v0.transform(carr1, carr1 + xlen(carr1))); +#ifndef _M_CEE_PURE CHECK(v0.transform_primary(carr, carr + xlen(carr)) == v0.transform_primary(carr, carr + xlen(carr))); - CHECK(v0.transform_primary(carr, carr + xlen(carr)) == v0.transform_primary(carr0, carr0 + xlen(carr0))); + CHECK(v0.transform_primary(carr, carr + xlen(carr)) != v0.transform_primary(carr0, carr0 + xlen(carr0))); CHECK(v0.transform_primary(carr0, carr0 + xlen(carr0)) < v0.transform_primary(carr1, carr1 + xlen(carr1))); +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ for (size_t i = 0; i < sizeof(class_names) / sizeof(*class_names); ++i) { CHECK(v0.lookup_classname(class_names[i], class_names[i] + xlen(class_names[i])) != 0); diff --git a/tests/tr1/tests/regex2/test.cpp b/tests/tr1/tests/regex2/test.cpp index 44cb5632126..d52371192de 100644 --- a/tests/tr1/tests/regex2/test.cpp +++ b/tests/tr1/tests/regex2/test.cpp @@ -588,8 +588,10 @@ static const regex_test tests[] = { {__LINE__, T("[[:xdigit:]]"), T("g"), "0", ALL}, {__LINE__, T("[[:xdigit:]]"), T("1"), "1 0 1", ALL}, {__LINE__, T("[[:xdigit:]]"), T(" "), "0", ALL}, - {__LINE__, T("[[=x=]]"), T("X"), "1 0 1", ALL}, +#ifndef _M_CEE_PURE + {__LINE__, T("[[=x=]]"), T("X"), "0", ALL}, {__LINE__, T("[[=x=]]"), T("x"), "1 0 1", ALL}, +#endif // ^^^ !defined(_M_CEE_PURE) ^^^ // character class ranges {__LINE__, T("[-]"), T("-"), "1 0 1", ALL},