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

Strengthen exception specification for some facet base types #3855

Merged
merged 1 commit into from
Jul 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 11 additions & 5 deletions stl/inc/xlocale
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public:
_Atomic_counter_t _Myrefs; // the reference count

protected:
explicit __CLR_OR_THIS_CALL facet(size_t _Initrefs = 0)
explicit __CLR_OR_THIS_CALL facet(size_t _Initrefs = 0) noexcept // strengthened
: _Myrefs(static_cast<_Atomic_counter_t>(_Initrefs)) // non-atomic initialization
{}

Expand Down Expand Up @@ -618,7 +618,9 @@ inline unsigned short* __CRTDECL _Maklocstr(const char* _Ptr, unsigned short*, c
}
#endif // defined(_NATIVE_WCHAR_T_DEFINED) && !_ENFORCE_FACET_SPECIALIZATIONS

_EXPORT_STD extern "C++" class _CRTIMP2_PURE_IMPORT codecvt_base : public locale::facet { // base class for codecvt
_EXPORT_STD extern "C++" class _CRTIMP2_PURE_IMPORT codecvt_base // base class for codecvt
: public locale::facet // TRANSITION, ABI, shouldn't be derived from locale::facet
{
public:
enum { // constants for different parse states
ok,
Expand All @@ -628,7 +630,8 @@ public:
};
using result = int;

__CLR_OR_THIS_CALL codecvt_base(size_t _Refs = 0) : locale::facet(_Refs) {}
__CLR_OR_THIS_CALL codecvt_base(size_t _Refs = 0) noexcept // strengthened
: locale::facet(_Refs) {}

bool __CLR_OR_THIS_CALL always_noconv() const noexcept {
// return true if conversions never change input (from codecvt)
Expand Down Expand Up @@ -2361,7 +2364,9 @@ protected:
#define _UP _UPPER // 'A'-'Z'
#define _XD _HEX // '0'-'9', 'A'-'F', 'a'-'f'

_EXPORT_STD extern "C++" struct _CRTIMP2_PURE_IMPORT ctype_base : locale::facet { // base for ctype
_EXPORT_STD extern "C++" struct _CRTIMP2_PURE_IMPORT ctype_base // base for ctype
: locale::facet // TRANSITION, ABI, shouldn't be derived from locale::facet
{
enum { // constants for character classifications
alnum = _DI | _LO | _UP | _XA,
alpha = _LO | _UP | _XA,
Expand All @@ -2378,7 +2383,8 @@ _EXPORT_STD extern "C++" struct _CRTIMP2_PURE_IMPORT ctype_base : locale::facet
};
using mask = short; // to match <ctype.h>

__CLR_OR_THIS_CALL ctype_base(size_t _Refs = 0) : locale::facet(_Refs) {}
__CLR_OR_THIS_CALL ctype_base(size_t _Refs = 0) noexcept // strengthened
: locale::facet(_Refs) {}

__CLR_OR_THIS_CALL ~ctype_base() noexcept override {}
};
Expand Down
8 changes: 6 additions & 2 deletions stl/inc/xlocmes
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,14 @@ _STL_DISABLE_CLANG_WARNINGS
#undef new

_STD_BEGIN
_EXPORT_STD struct messages_base : locale::facet { // base class for messages
_EXPORT_STD struct messages_base // base class for messages
: locale::facet // TRANSITION, ABI, shouldn't be derived from locale::facet
{
using catalog = int;

explicit messages_base(size_t _Refs = 0) : locale::facet(_Refs) {}
messages_base() noexcept // strengthened
: messages_base(0) {}
explicit messages_base(size_t _Refs) noexcept : locale::facet(_Refs) {}
};

_EXPORT_STD template <class _Elem>
Expand Down
7 changes: 5 additions & 2 deletions stl/inc/xlocmon
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ _STL_DISABLE_CLANG_WARNINGS
#undef new

_STD_BEGIN
_EXPORT_STD struct money_base : locale::facet { // ultimate base class for moneypunct
_EXPORT_STD struct money_base // ultimate base class for moneypunct
: locale::facet // TRANSITION, ABI, shouldn't be derived from locale::facet
{
enum { // constants for different format codes
symbol = '$',
sign = '+',
Expand All @@ -33,7 +35,8 @@ _EXPORT_STD struct money_base : locale::facet { // ultimate base class for money
char field[4];
};

money_base(size_t _Refs = 0) : locale::facet(_Refs) {}
money_base(size_t _Refs = 0) noexcept // strengthened
: locale::facet(_Refs) {}
};

template <class _Elem>
Expand Down
7 changes: 5 additions & 2 deletions stl/inc/xloctime
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,9 @@ ios_base::iostate _Getint_v2(_InIt& _First, _InIt& _Last, int _Lo, int _Hi, int&
return _State;
}

_EXPORT_STD extern "C++" struct _CRTIMP2_PURE_IMPORT time_base : locale::facet { // base class for time_get
_EXPORT_STD extern "C++" struct _CRTIMP2_PURE_IMPORT time_base // base class for time_get
: locale::facet // TRANSITION, ABI, shouldn't be derived from locale::facet
{
enum dateorder { // constants for different orders of date components
no_order,
dmy,
Expand All @@ -95,7 +97,8 @@ _EXPORT_STD extern "C++" struct _CRTIMP2_PURE_IMPORT time_base : locale::facet {
ydm
};

__CLR_OR_THIS_CALL time_base(size_t _Refs = 0) : locale::facet(_Refs) {}
__CLR_OR_THIS_CALL time_base(size_t _Refs = 0) noexcept // strengthened
: locale::facet(_Refs) {}

__CLR_OR_THIS_CALL ~time_base() noexcept override {}
};
Expand Down
27 changes: 27 additions & 0 deletions tests/std/tests/Dev09_056375_locale_cleanup/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,33 @@ using namespace std;
STATIC_ASSERT(noexcept(locale{} == locale{}));
STATIC_ASSERT(noexcept(locale{} != locale{}));

STATIC_ASSERT(is_nothrow_default_constructible_v<ctype_base>); // strengthened
STATIC_ASSERT(is_nothrow_default_constructible_v<codecvt_base>); // strengthened
STATIC_ASSERT(is_nothrow_default_constructible_v<time_base>); // strengthened
STATIC_ASSERT(is_nothrow_default_constructible_v<money_base>); // strengthened
STATIC_ASSERT(is_nothrow_default_constructible_v<messages_base>); // strengthened

// Test that *_base classes are implicitly default constructible.

template <class T>
void parameter_taker(const T&); // not defined

template <class T, class = void>
constexpr bool is_implicitly_default_constructible = false;

template <class T>
constexpr bool is_implicitly_default_constructible<T, void_t<decltype(parameter_taker<T>({}))>> = true;

STATIC_ASSERT(is_implicitly_default_constructible<ctype_base>);
STATIC_ASSERT(is_implicitly_default_constructible<codecvt_base>);
STATIC_ASSERT(is_implicitly_default_constructible<time_base>);
STATIC_ASSERT(is_implicitly_default_constructible<money_base>);
STATIC_ASSERT(is_implicitly_default_constructible<messages_base>);

STATIC_ASSERT(!is_implicitly_default_constructible<locale::facet>);
STATIC_ASSERT(!is_implicitly_default_constructible<ctype<char>>);
STATIC_ASSERT(!is_implicitly_default_constructible<ctype<wchar_t>>);

void test_dll() {
puts("Calling dll");
#ifdef _M_CEE
Expand Down