Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

<locale>: Repair std::collate<unsigned short> #5361

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

muellerj2
Copy link
Contributor

This repairs collate<unsigned short> by adding two missing unsigned short specializations for _LStrcoll and _LStrxfrm when wchar_t is a native type. Fixes #5236.

There are similar specializations for a few functions in <xlocale>. I guess _LStrcoll and _LStrxfrm were missed because they are located in a different header.

Since collate is the only user of these functions, I also moved them from <xlocinfo> to <locale> just above collate.

As for why this also fixes collate<wchar_t> = collate<unsigned short> under non-native wchar_t when linking to the DLL, this is because the the locale facets are constructed in the DLL here:

STL/stl/src/wlocale.cpp

Lines 58 to 88 in f2a2933

// moved from locale to ease subsetting
using _Tu1 = ctype<unsigned short>;
using _Tu2 = num_get<unsigned short>;
using _Tu3 = num_put<unsigned short>;
using _Tu4 = numpunct<unsigned short>;
using _Tu5 = collate<unsigned short>;
using _Tu6 = messages<unsigned short>;
using _Tu7 = money_get<unsigned short>;
using _Tu8 = money_put<unsigned short>;
using _Tu9 = moneypunct<unsigned short, false>;
using _Tu10 = moneypunct<unsigned short, true>;
using _Tu11 = time_get<unsigned short>;
using _Tu12 = time_put<unsigned short>;
using _Tu13 = codecvt<unsigned short, char, _Mbstatet>;
void __CLRCALL_OR_CDECL locale::_Locimp::_Makeushloc(const _Locinfo& lobj, locale::category cat, _Locimp* ptrimp,
const locale* ptrloc) { // setup wide part of a new locale
ADDFAC(_Tu1, cat, ptrimp, ptrloc);
ADDFAC(_Tu2, cat, ptrimp, ptrloc);
ADDFAC(_Tu3, cat, ptrimp, ptrloc);
ADDFAC(_Tu4, cat, ptrimp, ptrloc);
ADDFAC(_Tu5, cat, ptrimp, ptrloc);
ADDFAC(_Tu6, cat, ptrimp, ptrloc);
ADDFAC(_Tu7, cat, ptrimp, ptrloc);
ADDFAC(_Tu8, cat, ptrimp, ptrloc);
ADDFAC(_Tu9, cat, ptrimp, ptrloc);
ADDFAC(_Tu10, cat, ptrimp, ptrloc);
ADDFAC(_Tu11, cat, ptrimp, ptrloc);
ADDFAC(_Tu12, cat, ptrimp, ptrloc);
ADDFAC(_Tu13, cat, ptrimp, ptrloc);
}

Thus, collate's virtual functions originate from the DLL as well. These virtual functions call _LStrcoll and _LStrxfrm, but the specializations for unsigned short were missing since the DLL is built with native wchar_t.

The setup of the new test is a bit wild, but it's the best I could come up with:

  • Since we should test this under native wchar_t, we have to make collate<unsigned short> well-defined by setting _ENFORCE_LOCALE_SPECIALIZATIONS to 0.
  • We have to skip collate::transform() tests when there is IDL mismatch between TU and linked DLL.
  • When linking to the DLL, we have to define collate<unsigned short>::id. I tried defining __FORCE_INSTANCE instead (which is used to the same effect during the DLL build), but this results in several warnings-turned-errors in other facets. So it's either this or suppressing more warnings in STL headers.

@muellerj2 muellerj2 requested a review from a team as a code owner March 25, 2025 18:48
@StephanTLavavej StephanTLavavej added the bug Something isn't working label Mar 25, 2025
@StephanTLavavej StephanTLavavej self-assigned this Mar 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
Status: Initial Review
Development

Successfully merging this pull request may close these issues.

<locale>: std::collate<wchar_t> does not respect collation order when compiled with /MD(d) /Zc:wchar_t-
2 participants