Skip to content

Commit 77f93aa

Browse files
authored
Merge pull request #1 from frederick-vs-ja/fix-issue-5780-keeping-abi
Keep ABI for `_Locinfo`
2 parents cb5ad5b + 7cb20fb commit 77f93aa

File tree

3 files changed

+44
-19
lines changed

3 files changed

+44
-19
lines changed

stl/inc/xlocinfo

Lines changed: 35 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,28 @@ private:
134134
void* _Timeptr; // pointer to time information
135135
};
136136

137+
template <class _Elem>
138+
_Elem* _Ntcts_dup_dbg(const _Elem* const _Ptr) noexcept {
139+
_STL_INTERNAL_STATIC_ASSERT(_Is_any_of_v<_Elem, char, wchar_t, unsigned short>);
140+
141+
auto _Iter = _Ptr;
142+
while (*_Iter != _Elem{}) {
143+
++_Iter;
144+
}
145+
const size_t _Count = static_cast<size_t>(_Iter - _Ptr + 1) * sizeof(_Elem);
146+
147+
#ifdef _DEBUG
148+
const auto _Result = static_cast<_Elem*>(_CSTD _malloc_dbg(_Count, _CRT_BLOCK, __FILE__, __LINE__));
149+
#else
150+
const auto _Result = static_cast<_Elem*>(_CSTD malloc(_Count));
151+
#endif
152+
if (_Result) {
153+
_CSTD memcpy(_Result, _Ptr, _Count);
154+
}
155+
156+
return _Result;
157+
}
158+
137159
extern "C++" template <class _Elem>
138160
class _CRTIMP2_PURE_IMPORT _Yarn { // wrap a NTCTS
139161
public:
@@ -156,26 +178,22 @@ public:
156178
_Tidy();
157179

158180
if (_Right) { // new is not empty, copy it
159-
const _Elem* _Ptr = _Right;
160-
while (*_Ptr != _Elem{}) {
161-
++_Ptr;
162-
}
181+
_Myptr = _STD _Ntcts_dup_dbg(_Right);
182+
}
183+
}
163184

164-
const auto _Count = (++_Ptr - _Right) * sizeof(_Elem);
185+
return *this;
186+
}
165187

166-
#ifdef _DEBUG
167-
_Myptr = static_cast<_Elem*>(_malloc_dbg(_Count, _CRT_BLOCK, __FILE__, __LINE__));
168-
#else
169-
_Myptr = static_cast<_Elem*>(_CSTD malloc(_Count));
170-
#endif
188+
template <class _Elem2 = _Elem, enable_if_t<is_same_v<_Elem2, char>, int> = 0>
189+
void _From_wide(const wchar_t* const _Right) noexcept {
190+
if (reinterpret_cast<wchar_t*>(_Myptr) != _Right) { // new value, discard old and copy new
191+
_Tidy();
171192

172-
if (_Myptr) {
173-
_CSTD memcpy(_Myptr, _Right, _Count);
174-
}
193+
if (_Right) { // new is not empty, copy it
194+
_Myptr = reinterpret_cast<char*>(_STD _Ntcts_dup_dbg(_Right));
175195
}
176196
}
177-
178-
return *this;
179197
}
180198

181199
__CLR_OR_THIS_CALL ~_Yarn() noexcept {
@@ -382,7 +400,8 @@ private:
382400
_Yarn<char> _Months; // month names
383401
_Yarn<wchar_t> _W_Days; // wide weekday names
384402
_Yarn<wchar_t> _W_Months; // wide month names
385-
_Yarn<wchar_t> _Oldlocname; // old locale name to revert to on destruction
403+
// TRANSITION, ABI, `_Oldlocname._Myptr` is reinterpreted as `wchar_t*`. `wchar` should be wrapped instead.
404+
_Yarn<char> _Oldlocname; // old locale name to revert to on destruction
386405
_Yarn<char> _Newlocname; // new locale name for this object
387406
};
388407
_STD_END

stl/src/locale.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ void __CLRCALL_PURE_OR_CDECL locale::_Locimp::_Locimp_Addfac(
137137

138138
void __CLRCALL_PURE_OR_CDECL _Locinfo::_Locinfo_ctor(
139139
_Locinfo* pLocinfo, int cat, const char* locname) { // capture a named locale
140-
pLocinfo->_Oldlocname = _wsetlocale(LC_ALL, nullptr);
140+
pLocinfo->_Oldlocname._From_wide(_wsetlocale(LC_ALL, nullptr));
141141
_Locinfo_Addcats(pLocinfo, cat, locname);
142142
}
143143

stl/src/locale0.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,7 @@ void __CLRCALL_PURE_OR_CDECL locale::_Locimp::_Locimp_dtor(_Locimp* _This) { //
222222

223223
void __CLRCALL_PURE_OR_CDECL _Locinfo::_Locinfo_ctor(
224224
_Locinfo* pLocinfo, const char* locname) { // switch to a named locale
225-
pLocinfo->_Oldlocname = _wsetlocale(LC_ALL, nullptr);
225+
pLocinfo->_Oldlocname._From_wide(_wsetlocale(LC_ALL, nullptr));
226226

227227
if (locname != nullptr) {
228228
locname = setlocale(LC_ALL, locname);
@@ -232,7 +232,13 @@ void __CLRCALL_PURE_OR_CDECL _Locinfo::_Locinfo_ctor(
232232
}
233233

234234
void __CLRCALL_PURE_OR_CDECL _Locinfo::_Locinfo_dtor(_Locinfo* pLocinfo) { // destroy a _Locinfo object, revert locale
235-
_wsetlocale(LC_ALL, pLocinfo->_Oldlocname._C_str());
235+
if (pLocinfo->_Oldlocname._Empty()) {
236+
// `pLocinfo->_Oldlocname._C_str()` points to a single `char` of value 0 in this case,
237+
// so reinterpret_cast is not reliable.
238+
_wsetlocale(LC_ALL, L"");
239+
} else {
240+
_wsetlocale(LC_ALL, reinterpret_cast<const wchar_t*>(pLocinfo->_Oldlocname._C_str()));
241+
}
236242
}
237243
_STD_END
238244

0 commit comments

Comments
 (0)