commit c8457910bf92772e60f77935f687dad1b4cf2b6a
Author: Torvald Riegel <triegel@redhat.com>
Date: Wed Dec 23 18:19:32 2015 +0100
v2 changes
new file mode 100644
@@ -0,0 +1,89 @@
+// Tests that the exceptions declared by the TM TS (N4514) as transaction_safe
+// are indeed that. Thus, this also tests the transactional clones in
+// libstdc++ and libsupc++.
+
+// { dg-do run }
+
+#include <iostream>
+#include <exception>
+#include <stdexcept>
+#include <string>
+
+using namespace std;
+
+template<typename T> void thrower(const T& t)
+{
+ try
+ {
+ atomic_commit
+ {
+ throw t;
+ }
+ }
+ catch (T ex)
+ {
+ if (ex != t) abort ();
+ }
+}
+
+template<typename T> void thrower1(const string& what)
+{
+ try
+ {
+ atomic_commit
+ {
+ throw T ();
+ }
+ }
+ catch (T ex)
+ {
+ if (what != ex.what()) abort ();
+ }
+}
+
+template<typename T> void thrower2(const string& what)
+{
+ try
+ {
+ atomic_commit
+ {
+ throw T (what);
+ }
+ }
+ catch (T ex)
+ {
+ if (what != ex.what()) abort ();
+ }
+}
+
+
+int main ()
+{
+ thrower<unsigned int> (23);
+ thrower<int> (23);
+ thrower<unsigned short> (23);
+ thrower<short> (23);
+ thrower<unsigned char> (23);
+ thrower<char> (23);
+ thrower<unsigned long int> (42);
+ thrower<long int> (42);
+ thrower<unsigned long long int> (42);
+ thrower<long long int> (42);
+ thrower<double> (23.42);
+ thrower<long double> (23.42);
+ thrower<float> (23.42);
+ thrower<void*> (0);
+ thrower<void**> (0);
+ thrower1<exception> ("std::exception");
+ thrower1<bad_exception> ("std::bad_exception");
+ thrower2<logic_error> ("test");
+ thrower2<domain_error> ("test");
+ thrower2<invalid_argument> ("test");
+ thrower2<length_error> ("test");
+ thrower2<out_of_range> ("test");
+ thrower2<runtime_error> ("test");
+ thrower2<range_error> ("test");
+ thrower2<overflow_error> ("test");
+ thrower2<underflow_error> ("test");
+ return 0;
+}
@@ -1881,6 +1881,31 @@ GLIBCXX_3.4.22 {
_ZGTtNSt11logic_errorC[12]ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
_ZGTtNKSt11logic_error4whatEv;
_ZGTtNSt11logic_errorD[012]Ev;
+ _ZGTtNSt12domain_errorC[12]EPKc;
+ _ZGTtNSt12domain_errorC[12]ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
+ _ZGTtNSt12domain_errorD[012]Ev;
+ _ZGTtNSt16invalid_argumentC[12]EPKc;
+ _ZGTtNSt16invalid_argumentC[12]ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
+ _ZGTtNSt16invalid_argumentD[012]Ev;
+ _ZGTtNSt12length_errorC[12]EPKc;
+ _ZGTtNSt12length_errorC[12]ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
+ _ZGTtNSt12length_errorD[012]Ev;
+ _ZGTtNSt12out_of_rangeC[12]EPKc;
+ _ZGTtNSt12out_of_rangeC[12]ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
+ _ZGTtNSt12out_of_rangeD[012]Ev;
+ _ZGTtNSt13runtime_errorC[12]EPKc;
+ _ZGTtNSt13runtime_errorC[12]ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
+ _ZGTtNKSt13runtime_error4whatEv;
+ _ZGTtNSt13runtime_errorD[012]Ev;
+ _ZGTtNSt11range_errorC[12]EPKc;
+ _ZGTtNSt11range_errorC[12]ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
+ _ZGTtNSt11range_errorD[012]Ev;
+ _ZGTtNSt14overflow_errorC[12]EPKc;
+ _ZGTtNSt14overflow_errorC[12]ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
+ _ZGTtNSt14overflow_errorD[012]Ev;
+ _ZGTtNSt15underflow_errorC[12]EPKc;
+ _ZGTtNSt15underflow_errorC[12]ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE;
+ _ZGTtNSt15underflow_errorD[012]Ev;
} GLIBCXX_3.4.21;
@@ -146,9 +146,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class domain_error : public logic_error
{
public:
- explicit domain_error(const string& __arg);
+ explicit domain_error(const string& __arg) _GLIBCXX_TXN_SAFE;
#if __cplusplus >= 201103L
- explicit domain_error(const char*);
+ explicit domain_error(const char*) _GLIBCXX_TXN_SAFE;
#endif
virtual ~domain_error() _GLIBCXX_USE_NOEXCEPT;
};
@@ -157,9 +157,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class invalid_argument : public logic_error
{
public:
- explicit invalid_argument(const string& __arg);
+ explicit invalid_argument(const string& __arg) _GLIBCXX_TXN_SAFE;
#if __cplusplus >= 201103L
- explicit invalid_argument(const char*);
+ explicit invalid_argument(const char*) _GLIBCXX_TXN_SAFE;
#endif
virtual ~invalid_argument() _GLIBCXX_USE_NOEXCEPT;
};
@@ -169,9 +169,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class length_error : public logic_error
{
public:
- explicit length_error(const string& __arg);
+ explicit length_error(const string& __arg) _GLIBCXX_TXN_SAFE;
#if __cplusplus >= 201103L
- explicit length_error(const char*);
+ explicit length_error(const char*) _GLIBCXX_TXN_SAFE;
#endif
virtual ~length_error() _GLIBCXX_USE_NOEXCEPT;
};
@@ -181,9 +181,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class out_of_range : public logic_error
{
public:
- explicit out_of_range(const string& __arg);
+ explicit out_of_range(const string& __arg) _GLIBCXX_TXN_SAFE;
#if __cplusplus >= 201103L
- explicit out_of_range(const char*);
+ explicit out_of_range(const char*) _GLIBCXX_TXN_SAFE;
#endif
virtual ~out_of_range() _GLIBCXX_USE_NOEXCEPT;
};
@@ -200,11 +200,11 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
public:
/** Takes a character string describing the error. */
explicit
- runtime_error(const string& __arg);
+ runtime_error(const string& __arg) _GLIBCXX_TXN_SAFE;
#if __cplusplus >= 201103L
explicit
- runtime_error(const char*);
+ runtime_error(const char*) _GLIBCXX_TXN_SAFE;
#endif
#if _GLIBCXX_USE_CXX11_ABI || _GLIBCXX_DEFINE_STDEXCEPT_COPY_OPS
@@ -212,21 +212,25 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
runtime_error& operator=(const runtime_error&) _GLIBCXX_USE_NOEXCEPT;
#endif
- virtual ~runtime_error() _GLIBCXX_USE_NOEXCEPT;
+ virtual ~runtime_error() _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
/** 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_USE_NOEXCEPT;
+ what() const _GLIBCXX_TXN_SAFE_DYN _GLIBCXX_USE_NOEXCEPT;
+# ifdef _GLIBCXX_TM_TS_INTERNAL
+ friend void*
+ ::_txnal_runtime_error_get_msg(void* e);
+# endif
};
/** Thrown to indicate range errors in internal computations. */
class range_error : public runtime_error
{
public:
- explicit range_error(const string& __arg);
+ explicit range_error(const string& __arg) _GLIBCXX_TXN_SAFE;
#if __cplusplus >= 201103L
- explicit range_error(const char*);
+ explicit range_error(const char*) _GLIBCXX_TXN_SAFE;
#endif
virtual ~range_error() _GLIBCXX_USE_NOEXCEPT;
};
@@ -235,9 +239,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class overflow_error : public runtime_error
{
public:
- explicit overflow_error(const string& __arg);
+ explicit overflow_error(const string& __arg) _GLIBCXX_TXN_SAFE;
#if __cplusplus >= 201103L
- explicit overflow_error(const char*);
+ explicit overflow_error(const char*) _GLIBCXX_TXN_SAFE;
#endif
virtual ~overflow_error() _GLIBCXX_USE_NOEXCEPT;
};
@@ -246,9 +250,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
class underflow_error : public runtime_error
{
public:
- explicit underflow_error(const string& __arg);
+ explicit underflow_error(const string& __arg) _GLIBCXX_TXN_SAFE;
#if __cplusplus >= 201103L
- explicit underflow_error(const char*);
+ explicit underflow_error(const char*) _GLIBCXX_TXN_SAFE;
#endif
virtual ~underflow_error() _GLIBCXX_USE_NOEXCEPT;
};
@@ -38,6 +38,8 @@ void
_txnal_cow_string_D1_commit(void* that);
void*
_txnal_logic_error_get_msg(void* e);
+void*
+_txnal_runtime_error_get_msg(void* e);
// All exception classes still use the classic COW std::string.
#define _GLIBCXX_USE_CXX11_ABI 0
@@ -244,8 +246,8 @@ _txnal_cow_string_C1_for_exceptions(void* that, const char* s, void *exc)
// transactional clone of global new[]; if this throws, it will do so in a
// transaction-compatible way.
// The allocation belongs to this exception, so tell the runtime about it.
- // TODO associate exception
-// void *prev = _ITM_setAssociatedException(exc);
+ // TODO Once this is supported, link the following allocation to this
+ // exception: void *prev = _ITM_setAssociatedException(exc);
bs_type::_Rep *rep;
try
{
@@ -254,12 +256,14 @@ _txnal_cow_string_C1_for_exceptions(void* that, const char* s, void *exc)
catch (...)
{
// Pop the association with this exception.
-// _ITM_setAssociatedException(prev);
+ // TODO Once this is supported, link the following allocation to this
+ // exception: _ITM_setAssociatedException(prev);
// We do not need to instrument a rethrow.
throw;
}
// Pop the association with this exception.
-// _ITM_setAssociatedException(prev);
+ // TODO Once this is supported, link the following allocation to this
+ // exception: _ITM_setAssociatedException(prev);
// Now initialize the rest of the string and copy the C string. The memory
// will be freshly allocated, so nontransactional accesses are sufficient,
@@ -332,45 +336,78 @@ _txnal_logic_error_get_msg(void* e)
return &le->_M_msg;
}
-extern "C" {
-
-void
-_ZGTtNSt11logic_errorC1EPKc (std::logic_error* that, const char* s)
+void*
+_txnal_runtime_error_get_msg(void* e)
{
- // This will use the singleton _Rep for an empty string and just point
- // to it instead of allocating memory. Thus, we can use it as source, copy
- // it into the object we are constructing, and then construct the COW string
- // in the latter manually.
- std::logic_error le("");
- _ITM_memcpyRnWt(that, &le, sizeof(std::logic_error));
- _txnal_cow_string_C1_for_exceptions(_txnal_logic_error_get_msg(that),
- s, that);
+ std::runtime_error* le = (std::runtime_error*) e;
+ return &le->_M_msg;
}
-void
-_ZGTtNSt11logic_errorC2EPKc (std::logic_error*, const char*)
- __attribute__((alias ("_ZGTtNSt11logic_errorC1EPKc")));
-void
-_ZGTtNSt11logic_errorC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE(
- std::logic_error* that, const std::__sso_string& s)
-{
- std::logic_error le("");
- _ITM_memcpyRnWt(that, &le, sizeof(std::logic_error));
- // This constructor is only declared transaction-safe if the C++11 ABI is
- // used for std::string yet logic_error used a COW string internally. A
- // user must not call this constructor otherwise; although we can still
- // compile and provide it, calling it would result in undefined behavior,
- // which is in this case not initializing the message.
+// The constructors are only declared transaction-safe if the C++11 ABI is
+// used for std::string and the exception classes use a COW string internally.
+// A user must not call these constructors otherwise; if they do, it will
+// result in undefined behavior, which is in this case not initializing this
+// string.
#if _GLIBCXX_USE_DUAL_ABI
- // Get the C string from the SSO string.
- _txnal_cow_string_C1_for_exceptions(_txnal_logic_error_get_msg(that),
- _txnal_sso_string_c_str(&s), that);
+#define CTORDTORSTRINGCSTR(s) _txnal_sso_string_c_str((s))
+#else
+#define CTORDTORSTRINGCSTR(s) ""
#endif
+
+// This macro defines transaction constructors and destructors for a specific
+// exception class. NAME is the variable part of the mangled name, CLASS is
+// the class name, and BASE must be logic_error or runtime_error (which is
+// then used to call the proper friend function that can return a pointer to
+// the _M_msg member declared by the given (base) class).
+#define CTORDTOR(NAME, CLASS, BASE) \
+void \
+_ZGTtNSt##NAME##C1EPKc (CLASS* that, const char* s) \
+{ \
+ /* This will use the singleton _Rep for an empty string and just \
+ point to it instead of allocating memory. Thus, we can use it as \
+ source, copy it into the object we are constructing, and then \
+ construct the COW string in the latter manually. */ \
+ CLASS e(""); \
+ _ITM_memcpyRnWt(that, &e, sizeof(CLASS)); \
+ _txnal_cow_string_C1_for_exceptions(_txnal_##BASE##_get_msg(that), \
+ s, that); \
+} \
+void \
+_ZGTtNSt##NAME##C2EPKc (CLASS*, const char*) \
+ __attribute__((alias ("_ZGTtNSt" #NAME "C1EPKc"))); \
+void \
+_ZGTtNSt##NAME##C1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE( \
+ CLASS* that, const std::__sso_string& s) \
+{ \
+ CLASS e(""); \
+ _ITM_memcpyRnWt(that, &e, sizeof(CLASS)); \
+ /* Get the C string from the SSO string. */ \
+ _txnal_cow_string_C1_for_exceptions(_txnal_##BASE##_get_msg(that), \
+ CTORDTORSTRINGCSTR(&s), that); \
+} \
+void \
+_ZGTtNSt##NAME##C2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE( \
+ CLASS*, const std::__sso_string&) __attribute__((alias \
+("_ZGTtNSt" #NAME \
+ "C1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE"))); \
+void \
+_ZGTtNSt##NAME##D1Ev(CLASS* that) \
+{ _txnal_cow_string_D1(_txnal_##BASE##_get_msg(that)); } \
+void \
+_ZGTtNSt##NAME##D2Ev(CLASS*) \
+__attribute__((alias ("_ZGTtNSt" #NAME "D1Ev"))); \
+void \
+_ZGTtNSt##NAME##D0Ev(CLASS* that) \
+{ \
+ _ZGTtNSt##NAME##D1Ev(that); \
+ _ZGTtdlPv(that); \
}
-void
-_ZGTtNSt11logic_errorC2ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE(
- std::logic_error*, const std::__sso_string&) __attribute__((alias
-("_ZGTtNSt11logic_errorC1ERKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE")));
+
+// Now create all transactional constructors and destructors, as well as the
+// two virtual what() functions.
+extern "C" {
+
+CTORDTOR(11logic_error, std::logic_error, logic_error)
const char*
_ZGTtNKSt11logic_error4whatEv(const std::logic_error* that)
@@ -379,19 +416,23 @@ _ZGTtNKSt11logic_error4whatEv(const std::logic_error* that)
const_cast<std::logic_error*>(that)));
}
-void
-_ZGTtNSt11logic_errorD1Ev(std::logic_error* that)
-{
- _txnal_cow_string_D1(_txnal_logic_error_get_msg(that));
-}
-void
-_ZGTtNSt11logic_errorD2Ev(std::logic_error*)
-__attribute__((alias ("_ZGTtNSt11logic_errorD1Ev")));
-void
-_ZGTtNSt11logic_errorD0Ev(std::logic_error* that)
+CTORDTOR(12domain_error, std::domain_error, logic_error)
+CTORDTOR(16invalid_argument, std::invalid_argument, logic_error)
+CTORDTOR(12length_error, std::length_error, logic_error)
+CTORDTOR(12out_of_range, std::out_of_range, logic_error)
+
+
+CTORDTOR(13runtime_error, std::runtime_error, runtime_error)
+
+const char*
+_ZGTtNKSt13runtime_error4whatEv(const std::runtime_error* that)
{
- _ZGTtNSt11logic_errorD1Ev(that);
- _ZGTtdlPv(that);
+ return _txnal_cow_string_c_str(_txnal_runtime_error_get_msg(
+ const_cast<std::runtime_error*>(that)));
}
+CTORDTOR(11range_error, std::range_error, runtime_error)
+CTORDTOR(14overflow_error, std::overflow_error, runtime_error)
+CTORDTOR(15underflow_error, std::underflow_error, runtime_error)
+
}