PR libstdc++/85831 define move constructors and operators for exceptions

PR libstdc++/85831
	* config/abi/pre/gnu.ver: Export move constructors and move
	assignment operators for std::logic_error and std::runtime_error.
	* include/std/stdexcept: Use _GLIBCXX_NOTHROW instead of
	_GLIBCXX_USE_NOEXCEPT.
	(logic_error, runtime_error): Declare move constructors and move
	assignment operators. When not declared already, define copy
	constructors and copy assignment operators as explicit-defaulted.
	(domain_error, invalid_argument, length_error, out_of_range)
	(overflow_error, underflow_error): Define move constructors and move
	assignment operators as explicitly-defaulted.
	* libsupc++/exception.h (exception): Likewise.
	* src/c++11/cow-stdexcept.cc (logic_error, runtime_error): Define
	move constructors and move assignment operators as defaulted.
	* testsuite/19_diagnostics/stdexcept.cc: Check that constructors and
	assignment operators are defined.

From-SVN: r262456
This commit is contained in:
Jonathan Wakely 2018-07-05 22:29:51 +01:00 committed by Jonathan Wakely
parent 1c1d2d8ca7
commit d04dbb8ad3
6 changed files with 115 additions and 22 deletions

View File

@ -1,5 +1,22 @@
2018-07-05 Jonathan Wakely <jwakely@redhat.com>
PR libstdc++/85831
* config/abi/pre/gnu.ver: Export move constructors and move
assignment operators for std::logic_error and std::runtime_error.
* include/std/stdexcept: Use _GLIBCXX_NOTHROW instead of
_GLIBCXX_USE_NOEXCEPT.
(logic_error, runtime_error): Declare move constructors and move
assignment operators. When not declared already, define copy
constructors and copy assignment operators as explicit-defaulted.
(domain_error, invalid_argument, length_error, out_of_range)
(overflow_error, underflow_error): Define move constructors and move
assignment operators as explicitly-defaulted.
* libsupc++/exception.h (exception): Likewise.
* src/c++11/cow-stdexcept.cc (logic_error, runtime_error): Define
move constructors and move assignment operators as defaulted.
* testsuite/19_diagnostics/stdexcept.cc: Check that constructors and
assignment operators are defined.
* testsuite/21_strings/basic_string/cons/char/deduction.cc: XFAIL for
COW strings.
* testsuite/21_strings/basic_string/cons/wchar_t/deduction.cc:

View File

@ -2014,6 +2014,13 @@ GLIBCXX_3.4.26 {
# std::basic_string::insert(const_iterator, initializer_list)
_ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE6insertEN9__gnu_cxx17__normal_iteratorIPK[cw]S4_EESt16initializer_listI[cw]E;
# std::logic_error move operations
_ZNSt11logic_errorC[12]EOS_;
_ZNSt11logic_erroraSEOS_;
# std::runtime_error move operations
_ZNSt13runtime_errorC[12]EOS_;
_ZNSt13runtime_erroraSEOS_;
} GLIBCXX_3.4.25;
# Symbols in the support library (libsupc++) have their own tag.

View File

@ -55,8 +55,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
__cow_string();
__cow_string(const std::string&);
__cow_string(const char*, size_t);
__cow_string(const __cow_string&) _GLIBCXX_USE_NOEXCEPT;
__cow_string& operator=(const __cow_string&) _GLIBCXX_USE_NOEXCEPT;
__cow_string(const __cow_string&) _GLIBCXX_NOTHROW;
__cow_string& operator=(const __cow_string&) _GLIBCXX_NOTHROW;
~__cow_string();
#if __cplusplus >= 201103L
__cow_string(__cow_string&&) noexcept;
@ -83,7 +83,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
char _M_bytes[sizeof(__str)];
};
__sso_string() _GLIBCXX_USE_NOEXCEPT;
__sso_string() _GLIBCXX_NOTHROW;
__sso_string(const std::string&);
__sso_string(const char*, size_t);
__sso_string(const __sso_string&);
@ -122,19 +122,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
explicit
logic_error(const char*) _GLIBCXX_TXN_SAFE;
logic_error(logic_error&&) noexcept;
logic_error& operator=(logic_error&&) noexcept;
#endif
#if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_DEFINE_STDEXCEPT_COPY_OPS
logic_error(const logic_error&) _GLIBCXX_USE_NOEXCEPT;
logic_error& operator=(const logic_error&) _GLIBCXX_USE_NOEXCEPT;
logic_error(const logic_error&) _GLIBCXX_NOTHROW;
logic_error& operator=(const logic_error&) _GLIBCXX_NOTHROW;
#elif __cplusplus >= 201103L
logic_error(const logic_error&) = default;
logic_error& operator=(const logic_error&) = default;
#endif
virtual ~logic_error() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
virtual ~logic_error() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW;
/** Returns a C-style character string describing the general cause of
* the current error (the same string passed to the ctor). */
virtual const char*
what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW;
# ifdef _GLIBCXX_TM_TS_INTERNAL
friend void*
@ -152,8 +158,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit domain_error(const char*) _GLIBCXX_TXN_SAFE;
domain_error(const domain_error&) = default;
domain_error& operator=(const domain_error&) = default;
domain_error(domain_error&&) = default;
domain_error& operator=(domain_error&&) = default;
#endif
virtual ~domain_error() _GLIBCXX_USE_NOEXCEPT;
virtual ~domain_error() _GLIBCXX_NOTHROW;
};
/** Thrown to report invalid arguments to functions. */
@ -165,8 +173,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit invalid_argument(const char*) _GLIBCXX_TXN_SAFE;
invalid_argument(const invalid_argument&) = default;
invalid_argument& operator=(const invalid_argument&) = default;
invalid_argument(invalid_argument&&) = default;
invalid_argument& operator=(invalid_argument&&) = default;
#endif
virtual ~invalid_argument() _GLIBCXX_USE_NOEXCEPT;
virtual ~invalid_argument() _GLIBCXX_NOTHROW;
};
/** Thrown when an object is constructed that would exceed its maximum
@ -179,8 +189,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit length_error(const char*) _GLIBCXX_TXN_SAFE;
length_error(const length_error&) = default;
length_error& operator=(const length_error&) = default;
length_error(length_error&&) = default;
length_error& operator=(length_error&&) = default;
#endif
virtual ~length_error() _GLIBCXX_USE_NOEXCEPT;
virtual ~length_error() _GLIBCXX_NOTHROW;
};
/** This represents an argument whose value is not within the expected
@ -193,8 +205,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit out_of_range(const char*) _GLIBCXX_TXN_SAFE;
out_of_range(const out_of_range&) = default;
out_of_range& operator=(const out_of_range&) = default;
out_of_range(out_of_range&&) = default;
out_of_range& operator=(out_of_range&&) = default;
#endif
virtual ~out_of_range() _GLIBCXX_USE_NOEXCEPT;
virtual ~out_of_range() _GLIBCXX_NOTHROW;
};
/** Runtime errors represent problems outside the scope of a program;
@ -214,19 +228,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#if __cplusplus >= 201103L
explicit
runtime_error(const char*) _GLIBCXX_TXN_SAFE;
runtime_error(runtime_error&&) noexcept;
runtime_error& operator=(runtime_error&&) noexcept;
#endif
#if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_DEFINE_STDEXCEPT_COPY_OPS
runtime_error(const runtime_error&) _GLIBCXX_USE_NOEXCEPT;
runtime_error& operator=(const runtime_error&) _GLIBCXX_USE_NOEXCEPT;
runtime_error(const runtime_error&) _GLIBCXX_NOTHROW;
runtime_error& operator=(const runtime_error&) _GLIBCXX_NOTHROW;
#elif __cplusplus >= 201103L
runtime_error(const runtime_error&) = default;
runtime_error& operator=(const runtime_error&) = default;
#endif
virtual ~runtime_error() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
virtual ~runtime_error() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW;
/** Returns a C-style character string describing the general cause of
* the current error (the same string passed to the ctor). */
virtual const char*
what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW;
# ifdef _GLIBCXX_TM_TS_INTERNAL
friend void*
@ -243,8 +263,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit range_error(const char*) _GLIBCXX_TXN_SAFE;
range_error(const range_error&) = default;
range_error& operator=(const range_error&) = default;
range_error(range_error&&) = default;
range_error& operator=(range_error&&) = default;
#endif
virtual ~range_error() _GLIBCXX_USE_NOEXCEPT;
virtual ~range_error() _GLIBCXX_NOTHROW;
};
/** Thrown to indicate arithmetic overflow. */
@ -256,8 +278,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit overflow_error(const char*) _GLIBCXX_TXN_SAFE;
overflow_error(const overflow_error&) = default;
overflow_error& operator=(const overflow_error&) = default;
overflow_error(overflow_error&&) = default;
overflow_error& operator=(overflow_error&&) = default;
#endif
virtual ~overflow_error() _GLIBCXX_USE_NOEXCEPT;
virtual ~overflow_error() _GLIBCXX_NOTHROW;
};
/** Thrown to indicate arithmetic underflow. */
@ -269,8 +293,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
explicit underflow_error(const char*) _GLIBCXX_TXN_SAFE;
underflow_error(const underflow_error&) = default;
underflow_error& operator=(const underflow_error&) = default;
underflow_error(underflow_error&&) = default;
underflow_error& operator=(underflow_error&&) = default;
#endif
virtual ~underflow_error() _GLIBCXX_USE_NOEXCEPT;
virtual ~underflow_error() _GLIBCXX_NOTHROW;
};
// @} group exceptions

View File

@ -60,17 +60,19 @@ namespace std
class exception
{
public:
exception() _GLIBCXX_USE_NOEXCEPT { }
virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
exception() _GLIBCXX_NOTHROW { }
virtual ~exception() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW;
#if __cplusplus >= 201103L
exception(const exception&) = default;
exception& operator=(const exception&) = default;
exception(exception&&) = default;
exception& operator=(exception&&) = default;
#endif
/** Returns a C-style character string describing the general cause
* of the current error. */
virtual const char*
what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_NOTHROW;
};
} // namespace std

View File

@ -53,7 +53,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
{
_GLIBCXX_BEGIN_NAMESPACE_VERSION
// Copy constructors and assignment operators defined using COW std::string
// Copy/move constructors and assignment operators defined using COW string.
// These operations are noexcept even though copying a COW string is not,
// but we know that the string member in an exception has not been "leaked"
// so copying is a simple reference count increment.
logic_error::logic_error(const logic_error& e) noexcept
: exception(e), _M_msg(e._M_msg) { }
@ -61,6 +64,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
logic_error& logic_error::operator=(const logic_error& e) noexcept
{ _M_msg = e._M_msg; return *this; }
logic_error::logic_error(logic_error&& e) noexcept = default;
logic_error&
logic_error::operator=(logic_error&& e) noexcept = default;
runtime_error::runtime_error(const runtime_error& e) noexcept
: exception(e), _M_msg(e._M_msg) { }
@ -68,6 +76,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
runtime_error::operator=(const runtime_error& e) noexcept
{ _M_msg = e._M_msg; return *this; }
runtime_error::runtime_error(runtime_error&& e) noexcept = default;
runtime_error&
runtime_error::operator=(runtime_error&& e) noexcept = default;
// New C++11 constructors:
logic_error::logic_error(const char* __arg)

View File

@ -219,9 +219,37 @@ void test02()
}
}
void test03()
{
std::logic_error le1("");
// Copy constructor:
std::logic_error le2(le1);
// Copy assignment operator:
le1 = le2;
#if __cplusplus >= 201103L
// Move constructor:
std::logic_error le3 = std::move(le1);
// Move assignment operator:
le1 = std::move(le3);
#endif
std::runtime_error re1("");
// Copy constructor:
std::runtime_error re2(re1);
// Copy assignment operator:
re1 = re2;
#if __cplusplus >= 201103L
// Move constructor:
std::runtime_error re3 = std::move(re1);
// Move assignment operator:
re1 = std::move(re3);
#endif
}
int main(void)
{
test01();
test02();
test03();
return 0;
}