diff --git a/stl/inc/xlocale b/stl/inc/xlocale index 5a70bb2cb4..c2b2decbad 100644 --- a/stl/inc/xlocale +++ b/stl/inc/xlocale @@ -280,6 +280,7 @@ public: locale(const locale& _Loc, const locale& _Other, category _Cat) : _Ptr(_Locimp::_New_Locimp(*_Loc._Ptr)) { // construct a locale by copying named facets if (_Cat != none) { // worth adding, do it + _STL_ASSERT((_Cat & all) == _Cat, "the bitmask value specifying category must be valid"); _Facet_guard _Guard{_Ptr}; _BEGIN_LOCINFO(_Lobj) _Locimp::_Makeloc(_Lobj, _Cat, _Ptr, &_Other); @@ -294,6 +295,7 @@ public: private: void _Construct(const string& _Str, category _Cat) { + _STL_ASSERT((_Cat & all) == _Cat, "the bitmask value specifying category must be valid"); // construct a locale with named facets bool _Bad = false; _Init(); diff --git a/tests/std/tests/Dev09_056375_locale_cleanup/test.cpp b/tests/std/tests/Dev09_056375_locale_cleanup/test.cpp index 7a7cd8f9bf..5f3c899806 100644 --- a/tests/std/tests/Dev09_056375_locale_cleanup/test.cpp +++ b/tests/std/tests/Dev09_056375_locale_cleanup/test.cpp @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#define _SILENCE_CXX20_CODECVT_FACETS_DEPRECATION_WARNING + #include #include #include @@ -11,8 +13,8 @@ using namespace std; #define STATIC_ASSERT(...) static_assert(__VA_ARGS__, #__VA_ARGS__) -STATIC_ASSERT(noexcept(locale{} == locale{})); -STATIC_ASSERT(noexcept(locale{} != locale{})); +STATIC_ASSERT(noexcept(locale{} == locale{})); // strengthened +STATIC_ASSERT(noexcept(locale{} != locale{})); // strengthened void test_dll() { puts("Calling dll"); @@ -50,8 +52,131 @@ void test_exe_part2() { assert(!isspace(L'Z', locale())); } +#ifndef _M_CEE_PURE +locale make_unnamed_locale() { + locale result{locale{"C"}, &use_facet>(locale{"C"})}; + assert(result.name() == "*"); + return result; +} + +template +void test_locale_name_with_facet_pointer_one() { + { + locale result{locale{"C"}, static_cast(nullptr)}; + assert(result.name() == "C"); + } + { + locale result{make_unnamed_locale(), static_cast(nullptr)}; + assert(result.name() == "*"); + } + { + locale le{"C"}; + locale result{le, &use_facet(le)}; + assert(result.name() == "*"); + } + { + locale lunnamed{make_unnamed_locale()}; + locale result{lunnamed, &use_facet(lunnamed)}; + assert(result.name() == "*"); + } +} + +void test_locale_name_with_facet_pointer_all() { + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); +#ifdef __cpp_char8_t + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); +#endif // __cpp_char8_t + test_locale_name_with_facet_pointer_one>(); + + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); + + test_locale_name_with_facet_pointer_one>(); + test_locale_name_with_facet_pointer_one>(); +} + +void test_locale_name_with_another_locale_and_cats() { + locale lc{"C"}; + locale lunnamed{make_unnamed_locale()}; + { + locale result{lc, lc, locale::none}; + assert(result.name() != "*"); + } + { + locale result{lc, lunnamed, locale::none}; + assert(result.name() != "*"); + } + { + locale result{lunnamed, lc, locale::none}; + assert(result.name() == "*"); + } + { + locale result{lunnamed, lunnamed, locale::none}; + assert(result.name() == "*"); + } + + constexpr int cats_masks_count = 6; // collate | ctype | monetary | numeric | time | messages + for (int precats = 1; precats < (1 << cats_masks_count); ++precats) { + const locale::category cats = ((precats & (1 << 0)) != 0 ? locale::collate : locale::none) + | ((precats & (1 << 1)) != 0 ? locale::ctype : locale::none) + | ((precats & (1 << 2)) != 0 ? locale::monetary : locale::none) + | ((precats & (1 << 3)) != 0 ? locale::numeric : locale::none) + | ((precats & (1 << 4)) != 0 ? locale::time : locale::none) + | ((precats & (1 << 5)) != 0 ? locale::messages : locale::none); + { + locale result{lc, lc, cats}; + assert(result.name() != "*"); + } + { + locale result{lc, lunnamed, cats}; + assert(result.name() == "*"); + } + { + locale result{lunnamed, lc, cats}; + assert(result.name() == "*"); + } + { + locale result{lunnamed, lunnamed, cats}; + assert(result.name() == "*"); + } + } +} +#endif // _M_CEE_PURE + int main() { test_exe_part1(); test_dll(); test_exe_part2(); + +#ifndef _M_CEE_PURE + // test coverage for LWG-2295 + test_locale_name_with_facet_pointer_all(); + test_locale_name_with_another_locale_and_cats(); +#endif // _M_CEE_PURE }