git: 17a7ea7e3e39 - stable/14 - libcxxrt: Update to upstream 698997bfde1f

From: Ed Maste <emaste_at_FreeBSD.org>
Date: Tue, 29 Oct 2024 22:17:49 UTC
The branch stable/14 has been updated by emaste:

URL: https://cgit.FreeBSD.org/src/commit/?id=17a7ea7e3e39cdfb1b367b27c7b38fb0ea6c0806

commit 17a7ea7e3e39cdfb1b367b27c7b38fb0ea6c0806
Author:     Ed Maste <emaste@FreeBSD.org>
AuthorDate: 2024-10-22 23:40:09 +0000
Commit:     Ed Maste <emaste@FreeBSD.org>
CommitDate: 2024-10-29 22:17:05 +0000

    libcxxrt: Update to upstream 698997bfde1f
    
    Interesting fixes:
    
    045c52c Mark __cxa_allocate_exception, __cxa_free_exception and
            __cxa_init_primary_exception noexcept.
    8a2f123 Define _LIBCXXRT_NOEXCEPT in cxxabi.h and use it instead of
            throw()
    9529236 Fix memory corruption in cpp_demangle_read_sname()
    8f5c74e Add test cases, fix more bugs, and improve perf
    391a3dc Add a simple implementation of __cxa_call_terminate
    40e4fa2 mark std::terminate as noreturn and noexcept
    5eede09 Print diagnostics in default std::terminate handler
    
    Reviewed by:    dim
    Sponsored by:   The FreeBSD Foundation
    Differential Revision: https://reviews.freebsd.org/D47238
    
    (cherry picked from commit 13da1af1cd677b7901d3bf4b9dbe3290b94130d5)
---
 contrib/libcxxrt/atomic.h            |   2 +-
 contrib/libcxxrt/cxxabi.h            |  17 +++-
 contrib/libcxxrt/exception.cc        | 174 ++++++++++++++++++-----------------
 contrib/libcxxrt/libelftc_dem_gnu3.c |  92 +++++++++---------
 contrib/libcxxrt/memory.cc           |  14 ++-
 contrib/libcxxrt/noexception.cc      |   4 +-
 contrib/libcxxrt/stdexcept.cc        |  40 ++++----
 contrib/libcxxrt/stdexcept.h         |  42 +++++----
 8 files changed, 196 insertions(+), 189 deletions(-)

diff --git a/contrib/libcxxrt/atomic.h b/contrib/libcxxrt/atomic.h
index 701d05337cf1..0768c08038df 100644
--- a/contrib/libcxxrt/atomic.h
+++ b/contrib/libcxxrt/atomic.h
@@ -56,7 +56,7 @@ namespace
 		/**
 		 * Constructor, takes a value.
 		 */
-		atomic(T init) : val(init) {}
+		constexpr atomic(T init) : val(init) {}
 
 		/**
 		 * Atomically load with the specified memory order.
diff --git a/contrib/libcxxrt/cxxabi.h b/contrib/libcxxrt/cxxabi.h
index ef4076a08a0a..2bf7f99b5245 100644
--- a/contrib/libcxxrt/cxxabi.h
+++ b/contrib/libcxxrt/cxxabi.h
@@ -41,8 +41,15 @@ namespace std
  */
 
 #ifdef __cplusplus
+#if __cplusplus < 201103L
+#define _LIBCXXRT_NOEXCEPT throw()
+#else
+#define _LIBCXXRT_NOEXCEPT noexcept
+#endif
 namespace __cxxabiv1 {
 extern "C" {
+#else
+#define _LIBCXXRT_NOEXCEPT
 #endif
 /**
  * Function type to call when an unexpected exception is encountered.
@@ -76,7 +83,7 @@ typedef void (*terminate_handler)();
  */
 struct __cxa_exception
 {
-#if __LP64__
+#ifdef __LP64__
 	/**
 	 * Now _Unwind_Exception is marked with __attribute__((aligned)), which
 	 * implies __cxa_exception is also aligned.  Insert padding in the
@@ -154,7 +161,7 @@ struct __cxa_exception
 	 * need to adjust the thrown pointer to make it all work correctly.
 	 */
 	void *adjustedPtr;
-#if !__LP64__
+#ifndef __LP64__
 	/**
 	 * Reference count.  Used to support the C++11 exception_ptr class.  This
 	 * is prepended to the structure in 64-bit mode and squeezed in to the
@@ -204,12 +211,12 @@ __cxa_eh_globals *__cxa_get_globals_fast(void);
 std::type_info * __cxa_current_exception_type();
 
 
-void *__cxa_allocate_exception(size_t thrown_size) throw();
+void *__cxa_allocate_exception(size_t thrown_size) _LIBCXXRT_NOEXCEPT;
 
-void __cxa_free_exception(void* thrown_exception) throw();
+void __cxa_free_exception(void* thrown_exception) _LIBCXXRT_NOEXCEPT;
 
 __cxa_exception *__cxa_init_primary_exception(
-		void *object, std::type_info* tinfo, void (*dest)(void *)) throw();
+		void *object, std::type_info* tinfo, void (*dest)(void *)) _LIBCXXRT_NOEXCEPT;
 
 /**
  * Throws an exception returned by __cxa_current_primary_exception().  This
diff --git a/contrib/libcxxrt/exception.cc b/contrib/libcxxrt/exception.cc
index b56333e979a2..c87fe5ac4468 100644
--- a/contrib/libcxxrt/exception.cc
+++ b/contrib/libcxxrt/exception.cc
@@ -121,7 +121,7 @@ static inline _Unwind_Reason_Code continueUnwinding(struct _Unwind_Exception *ex
 }
 
 
-extern "C" void __cxa_free_exception(void *thrown_exception) throw();
+extern "C" void __cxa_free_exception(void *thrown_exception) _LIBCXXRT_NOEXCEPT;
 extern "C" void __cxa_free_dependent_exception(void *thrown_exception);
 extern "C" void* __dynamic_cast(const void *sub,
                                 const __class_type_info *src,
@@ -198,7 +198,7 @@ struct __cxa_thread_info
  */
 struct __cxa_dependent_exception
 {
-#if __LP64__
+#ifdef __LP64__
 	void *reserve;
 	void *primaryException;
 #endif
@@ -217,7 +217,7 @@ struct __cxa_dependent_exception
 	const char *languageSpecificData;
 	void *catchTemp;
 	void *adjustedPtr;
-#if !__LP64__
+#ifndef __LP64__
 	void *primaryException;
 #endif
 	_Unwind_Exception unwindHeader;
@@ -241,8 +241,8 @@ namespace std
 	class exception
 	{
 		public:
-			virtual ~exception() throw();
-			virtual const char* what() const throw();
+			virtual ~exception() _LIBCXXRT_NOEXCEPT;
+			virtual const char* what() const _LIBCXXRT_NOEXCEPT;
 	};
 
 }
@@ -296,15 +296,80 @@ namespace std
 {
 	// Forward declaration of standard library terminate() function used to
 	// abort execution.
-	void terminate(void);
+	[[noreturn]] void terminate(void) _LIBCXXRT_NOEXCEPT;
 }
 
 using namespace ABI_NAMESPACE;
 
+#ifdef LIBCXXRT_NO_DEFAULT_TERMINATE_DIAGNOSTICS
+/** The global termination handler. */
+static atomic<terminate_handler> terminateHandler = abort;
+#else
+/**
+ * Callback function used with _Unwind_Backtrace().
+ *
+ * Prints a stack trace.  Used only for debugging help.
+ *
+ * Note: As of FreeBSD 8.1, dladdr() still doesn't work properly, so this only
+ * correctly prints function names from public, relocatable, symbols.
+ */
+static _Unwind_Reason_Code trace(struct _Unwind_Context *context, void *c)
+{
+	Dl_info myinfo;
+	int mylookup =
+		dladdr(reinterpret_cast<void *>(__cxa_current_exception_type), &myinfo);
+	void *ip = reinterpret_cast<void*>(_Unwind_GetIP(context));
+	Dl_info info;
+	if (dladdr(ip, &info) != 0)
+	{
+		if (mylookup == 0 || strcmp(info.dli_fname, myinfo.dli_fname) != 0)
+		{
+			printf("%p:%s() in %s\n", ip, info.dli_sname, info.dli_fname);
+		}
+	}
+	return _URC_CONTINUE_UNWIND;
+}
+
+static void terminate_with_diagnostics() {
+	__cxa_eh_globals *globals = __cxa_get_globals();
+	__cxa_exception *ex = globals->caughtExceptions;
+
+	if (ex != nullptr) {
+		fprintf(stderr, "Terminating due to uncaught exception %p", static_cast<void*>(ex));
+		ex = realExceptionFromException(ex);
+		static const __class_type_info *e_ti =
+			static_cast<const __class_type_info*>(&typeid(std::exception));
+		const __class_type_info *throw_ti =
+			dynamic_cast<const __class_type_info*>(ex->exceptionType);
+		if (throw_ti)
+		{
+			std::exception *e =
+				static_cast<std::exception*>(e_ti->cast_to(static_cast<void*>(ex+1), throw_ti));
+			if (e)
+			{
+				fprintf(stderr, " '%s'", e->what());
+			}
+		}
+
+		size_t bufferSize = 128;
+		char *demangled = static_cast<char*>(malloc(bufferSize));
+		const char *mangled = ex->exceptionType->name();
+		int status;
+		demangled = __cxa_demangle(mangled, demangled, &bufferSize, &status);
+		fprintf(stderr, " of type %s\n",
+			status == 0 ? demangled : mangled);
+		if (status == 0) { free(demangled); }
+
+		_Unwind_Backtrace(trace, 0);
+	}
 
+	abort();
+}
 
 /** The global termination handler. */
-static atomic<terminate_handler> terminateHandler = abort;
+static atomic<terminate_handler> terminateHandler = terminate_with_diagnostics;
+#endif
+
 /** The global unexpected exception handler. */
 static atomic<unexpected_handler> unexpectedHandler = std::terminate;
 
@@ -611,7 +676,7 @@ static void free_exception(char *e)
  * emergency buffer if malloc() fails, and may block if there are no such
  * buffers available.
  */
-extern "C" void *__cxa_allocate_exception(size_t thrown_size) throw()
+extern "C" void *__cxa_allocate_exception(size_t thrown_size) _LIBCXXRT_NOEXCEPT
 {
 	size_t size = thrown_size + sizeof(__cxa_exception);
 	char *buffer = alloc_or_die(size);
@@ -633,7 +698,7 @@ extern "C" void *__cxa_allocate_dependent_exception(void)
  * In this implementation, it is also called by __cxa_end_catch() and during
  * thread cleanup.
  */
-extern "C" void __cxa_free_exception(void *thrown_exception) throw()
+extern "C" void __cxa_free_exception(void *thrown_exception) _LIBCXXRT_NOEXCEPT
 {
 	__cxa_exception *ex = reinterpret_cast<__cxa_exception*>(thrown_exception) - 1;
 	// Free the object that was thrown, calling its destructor
@@ -680,39 +745,15 @@ void __cxa_free_dependent_exception(void *thrown_exception)
 	free_exception(reinterpret_cast<char*>(ex));
 }
 
-/**
- * Callback function used with _Unwind_Backtrace().
- *
- * Prints a stack trace.  Used only for debugging help.
- *
- * Note: As of FreeBSD 8.1, dladd() still doesn't work properly, so this only
- * correctly prints function names from public, relocatable, symbols.
- */
-static _Unwind_Reason_Code trace(struct _Unwind_Context *context, void *c)
-{
-	Dl_info myinfo;
-	int mylookup =
-		dladdr(reinterpret_cast<void *>(__cxa_current_exception_type), &myinfo);
-	void *ip = reinterpret_cast<void*>(_Unwind_GetIP(context));
-	Dl_info info;
-	if (dladdr(ip, &info) != 0)
-	{
-		if (mylookup == 0 || strcmp(info.dli_fname, myinfo.dli_fname) != 0)
-		{
-			printf("%p:%s() in %s\n", ip, info.dli_sname, info.dli_fname);
-		}
-	}
-	return _URC_CONTINUE_UNWIND;
-}
-
 /**
  * Report a failure that occurred when attempting to throw an exception.
  *
  * If the failure happened by falling off the end of the stack without finding
- * a handler, prints a back trace before aborting.
+ * a handler, catch the exception before calling terminate. The default
+ * terminate handler will print a backtrace before aborting.
  */
 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
-extern "C" void *__cxa_begin_catch(void *e) throw();
+extern "C" void *__cxa_begin_catch(void *e) _LIBCXXRT_NOEXCEPT;
 #else
 extern "C" void *__cxa_begin_catch(void *e);
 #endif
@@ -731,41 +772,6 @@ static void report_failure(_Unwind_Reason_Code err, __cxa_exception *thrown_exce
 #endif
 		case _URC_END_OF_STACK:
 			__cxa_begin_catch (&(thrown_exception->unwindHeader));
- 			std::terminate();
-			fprintf(stderr, "Terminating due to uncaught exception %p", 
-					static_cast<void*>(thrown_exception));
-			thrown_exception = realExceptionFromException(thrown_exception);
-			static const __class_type_info *e_ti =
-				static_cast<const __class_type_info*>(&typeid(std::exception));
-			const __class_type_info *throw_ti =
-				dynamic_cast<const __class_type_info*>(thrown_exception->exceptionType);
-			if (throw_ti)
-			{
-				std::exception *e =
-					static_cast<std::exception*>(e_ti->cast_to(static_cast<void*>(thrown_exception+1),
-							throw_ti));
-				if (e)
-				{
-					fprintf(stderr, " '%s'", e->what());
-				}
-			}
-
-			size_t bufferSize = 128;
-			char *demangled = static_cast<char*>(malloc(bufferSize));
-			const char *mangled = thrown_exception->exceptionType->name();
-			int status;
-			demangled = __cxa_demangle(mangled, demangled, &bufferSize, &status);
-			fprintf(stderr, " of type %s\n", 
-				status == 0 ? demangled : mangled);
-			if (status == 0) { free(demangled); }
-			// Print a back trace if no handler is found.
-			// TODO: Make this optional
-#ifndef __arm__
-			_Unwind_Backtrace(trace, 0);
-#endif
-
-			// Just abort. No need to call std::terminate for the second time
-			abort();
 			break;
 	}
 	std::terminate();
@@ -794,7 +800,7 @@ static void throw_exception(__cxa_exception *ex)
 }
 
 extern "C" __cxa_exception *__cxa_init_primary_exception(
-		void *object, std::type_info* tinfo, void (*dest)(void *)) throw() {
+		void *object, std::type_info* tinfo, void (*dest)(void *)) _LIBCXXRT_NOEXCEPT {
 	__cxa_exception *ex = reinterpret_cast<__cxa_exception*>(object) - 1;
 
 	ex->referenceCount = 0;
@@ -1245,7 +1251,7 @@ BEGIN_PERSONALITY_FUNCTION(__gxx_personality_v0)
  * C++ exceptions) of the unadjusted pointer (for foreign exceptions).
  */
 #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 4)
-extern "C" void *__cxa_begin_catch(void *e) throw()
+extern "C" void *__cxa_begin_catch(void *e) _LIBCXXRT_NOEXCEPT
 #else
 extern "C" void *__cxa_begin_catch(void *e)
 #endif
@@ -1439,7 +1445,7 @@ extern "C" void __cxa_call_unexpected(void*exception)
  *
  * This function does not return.
  */
-extern "C" void __cxa_call_terminate(void *exception) throw()
+extern "C" void __cxa_call_terminate(void*exception) _LIBCXXRT_NOEXCEPT
 {
 	std::terminate();
 	// Should not be reached.
@@ -1467,14 +1473,14 @@ namespace pathscale
 	/**
 	 * Sets whether unexpected and terminate handlers should be thread-local.
 	 */
-	void set_use_thread_local_handlers(bool flag) throw()
+	void set_use_thread_local_handlers(bool flag) _LIBCXXRT_NOEXCEPT
 	{
 		thread_local_handlers = flag;
 	}
 	/**
 	 * Sets a thread-local unexpected handler.  
 	 */
-	unexpected_handler set_unexpected(unexpected_handler f) throw()
+	unexpected_handler set_unexpected(unexpected_handler f) _LIBCXXRT_NOEXCEPT
 	{
 		static __cxa_thread_info *info = thread_info();
 		unexpected_handler old = info->unexpectedHandler;
@@ -1484,7 +1490,7 @@ namespace pathscale
 	/**
 	 * Sets a thread-local terminate handler.  
 	 */
-	terminate_handler set_terminate(terminate_handler f) throw()
+	terminate_handler set_terminate(terminate_handler f) _LIBCXXRT_NOEXCEPT
 	{
 		static __cxa_thread_info *info = thread_info();
 		terminate_handler old = info->terminateHandler;
@@ -1499,7 +1505,7 @@ namespace std
 	 * Sets the function that will be called when an exception specification is
 	 * violated.
 	 */
-	unexpected_handler set_unexpected(unexpected_handler f) throw()
+	unexpected_handler set_unexpected(unexpected_handler f) _LIBCXXRT_NOEXCEPT
 	{
 		if (thread_local_handlers) { return pathscale::set_unexpected(f); }
 
@@ -1508,7 +1514,7 @@ namespace std
 	/**
 	 * Sets the function that is called to terminate the program.
 	 */
-	terminate_handler set_terminate(terminate_handler f) throw()
+	terminate_handler set_terminate(terminate_handler f) _LIBCXXRT_NOEXCEPT
 	{
 		if (thread_local_handlers) { return pathscale::set_terminate(f); }
 
@@ -1518,7 +1524,7 @@ namespace std
 	 * Terminates the program, calling a custom terminate implementation if
 	 * required.
 	 */
-	void terminate()
+	[[noreturn]] void terminate() _LIBCXXRT_NOEXCEPT
 	{
 		static __cxa_thread_info *info = thread_info();
 		if (0 != info && 0 != info->terminateHandler)
@@ -1551,7 +1557,7 @@ namespace std
 	 * Returns whether there are any exceptions currently being thrown that
 	 * have not been caught.  This can occur inside a nested catch statement.
 	 */
-	bool uncaught_exception() throw()
+	bool uncaught_exception() _LIBCXXRT_NOEXCEPT
 	{
 		__cxa_thread_info *info = thread_info();
 		return info->globals.uncaughtExceptions != 0;
@@ -1560,7 +1566,7 @@ namespace std
 	 * Returns the number of exceptions currently being thrown that have not
 	 * been caught.  This can occur inside a nested catch statement.
 	 */
-	int uncaught_exceptions() throw()
+	int uncaught_exceptions() _LIBCXXRT_NOEXCEPT
 	{
 		__cxa_thread_info *info = thread_info();
 		return info->globals.uncaughtExceptions;
@@ -1568,7 +1574,7 @@ namespace std
 	/**
 	 * Returns the current unexpected handler.
 	 */
-	unexpected_handler get_unexpected() throw()
+	unexpected_handler get_unexpected() _LIBCXXRT_NOEXCEPT
 	{
 		__cxa_thread_info *info = thread_info();
 		if (info->unexpectedHandler)
@@ -1580,7 +1586,7 @@ namespace std
 	/**
 	 * Returns the current terminate handler.
 	 */
-	terminate_handler get_terminate() throw()
+	terminate_handler get_terminate() _LIBCXXRT_NOEXCEPT
 	{
 		__cxa_thread_info *info = thread_info();
 		if (info->terminateHandler)
diff --git a/contrib/libcxxrt/libelftc_dem_gnu3.c b/contrib/libcxxrt/libelftc_dem_gnu3.c
index e75d1694562e..36e98deb1d2f 100644
--- a/contrib/libcxxrt/libelftc_dem_gnu3.c
+++ b/contrib/libcxxrt/libelftc_dem_gnu3.c
@@ -200,9 +200,9 @@ vector_str_find(const struct vector_str *v, const char *o, size_t l)
 static char *
 vector_str_get_flat(const struct vector_str *v, size_t *l)
 {
-	ssize_t elem_pos, elem_size, rtn_size;
 	size_t i;
-	char *rtn;
+	char *rtn, *p;
+	ssize_t rtn_size;
 
 	if (v == NULL || v->size == 0)
 		return (NULL);
@@ -213,16 +213,9 @@ vector_str_get_flat(const struct vector_str *v, size_t *l)
 	if ((rtn = malloc(sizeof(char) * (rtn_size + 1))) == NULL)
 		return (NULL);
 
-	elem_pos = 0;
-	for (i = 0; i < v->size; ++i) {
-		elem_size = strlen(v->container[i]);
-
-		memcpy(rtn + elem_pos, v->container[i], elem_size);
-
-		elem_pos += elem_size;
-	}
-
-	rtn[rtn_size] = '\0';
+	p = rtn;
+	for (i = 0; i < v->size; ++i)
+		p = stpcpy(p, v->container[i]);
 
 	if (l != NULL)
 		*l = rtn_size;
@@ -305,6 +298,21 @@ vector_str_pop(struct vector_str *v)
 	return (true);
 }
 
+/**
+ * @brief Implements strlcpy() without result.
+ */
+static void
+copy_string(char *dst, const char *src, size_t dsize)
+{
+	size_t remain;
+	if ((remain = dsize))
+		while (--remain)
+			if (!(*dst++ = *src++))
+				break;
+	if (!remain && dsize)
+                *dst = 0;
+}
+
 /**
  * @brief Push back string to vector.
  * @return false at failed, true at success.
@@ -322,7 +330,7 @@ vector_str_push(struct vector_str *v, const char *str, size_t len)
 	if ((v->container[v->size] = malloc(sizeof(char) * (len + 1))) == NULL)
 		return (false);
 
-	snprintf(v->container[v->size], len + 1, "%s", str);
+	copy_string(v->container[v->size], str, len + 1);
 
 	++v->size;
 
@@ -420,8 +428,8 @@ static char *
 vector_str_substr(const struct vector_str *v, size_t begin, size_t end,
     size_t *r_len)
 {
-	size_t cur, i, len;
-	char *rtn;
+	char *rtn, *p;
+	size_t i, len;
 
 	if (v == NULL || begin > end)
 		return (NULL);
@@ -436,13 +444,9 @@ vector_str_substr(const struct vector_str *v, size_t begin, size_t end,
 	if (r_len != NULL)
 		*r_len = len;
 
-	cur = 0;
-	for (i = begin; i < end + 1; ++i) {
-		len = strlen(v->container[i]);
-		memcpy(rtn + cur, v->container[i], len);
-		cur += len;
-	}
-	rtn[cur] = '\0';
+	p = rtn;
+	for (i = begin; i < end + 1; ++i)
+		p = stpcpy(p, v->container[i]);
 
 	return (rtn);
 }
@@ -2510,61 +2514,56 @@ cpp_demangle_read_subst(struct cpp_demangle_data *ddata)
 		return (1);
 
 	case SIMPLE_HASH('S', 'd'):
-		/* std::basic_iostream<char, std::char_traits<char> > */
+		/* std::basic_iostream<char, std::char_traits<char>> */
 		if (!DEM_PUSH_STR(ddata, "std::basic_iostream<char, "
-		    "std::char_traits<char> >"))
+		    "std::char_traits<char>>"))
 			return (0);
 		ddata->last_sname = "basic_iostream";
 		ddata->cur += 2;
 		if (*ddata->cur == 'I')
 			return (cpp_demangle_read_subst_stdtmpl(ddata,
 			    "std::basic_iostream<char, std::char_traits"
-				"<char> >"));
+				"<char>>"));
 		return (1);
 
 	case SIMPLE_HASH('S', 'i'):
-		/* std::basic_istream<char, std::char_traits<char> > */
+		/* std::basic_istream<char, std::char_traits<char>> */
 		if (!DEM_PUSH_STR(ddata, "std::basic_istream<char, "
-		    "std::char_traits<char> >"))
+		    "std::char_traits<char>>"))
 			return (0);
 		ddata->last_sname = "basic_istream";
 		ddata->cur += 2;
 		if (*ddata->cur == 'I')
 			return (cpp_demangle_read_subst_stdtmpl(ddata,
 			    "std::basic_istream<char, std::char_traits"
-				"<char> >"));
+				"<char>>"));
 		return (1);
 
 	case SIMPLE_HASH('S', 'o'):
-		/* std::basic_ostream<char, std::char_traits<char> > */
+		/* std::basic_ostream<char, std::char_traits<char>> */
 		if (!DEM_PUSH_STR(ddata, "std::basic_ostream<char, "
-		    "std::char_traits<char> >"))
+		    "std::char_traits<char>>"))
 			return (0);
 		ddata->last_sname = "basic_ostream";
 		ddata->cur += 2;
 		if (*ddata->cur == 'I')
 			return (cpp_demangle_read_subst_stdtmpl(ddata,
 			    "std::basic_ostream<char, std::char_traits"
-				"<char> >"));
+				"<char>>"));
 		return (1);
 
 	case SIMPLE_HASH('S', 's'):
 		/*
-		 * std::basic_string<char, std::char_traits<char>,
-		 * std::allocator<char> >
-		 *
-		 * a.k.a std::string
+		 * std::string for consistency with libcxxabi
 		 */
-		if (!DEM_PUSH_STR(ddata, "std::basic_string<char, "
-		    "std::char_traits<char>, std::allocator<char> >"))
-			return (0);
+		if (!DEM_PUSH_STR(ddata, "std::string"))
+			return 0;
 		ddata->last_sname = "string";
 		ddata->cur += 2;
 		if (*ddata->cur == 'I')
-			return (cpp_demangle_read_subst_stdtmpl(ddata,
-			    "std::basic_string<char, std::char_traits<char>,"
-				" std::allocator<char> >"));
-		return (1);
+			return cpp_demangle_read_subst_stdtmpl(ddata,
+				"std::string");
+		return 1;
 
 	case SIMPLE_HASH('S', 't'):
 		/* std:: */
@@ -2740,7 +2739,7 @@ static int
 cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
 {
 	struct vector_str *v;
-	size_t arg_len, idx, limit, size;
+	size_t arg_len, idx, limit;
 	char *arg;
 
 	if (ddata == NULL || *ddata->cur == '\0')
@@ -2773,12 +2772,7 @@ cpp_demangle_read_tmpl_args(struct cpp_demangle_data *ddata)
 
 		if (*ddata->cur == 'E') {
 			++ddata->cur;
-			size = v->size;
-			assert(size > 0);
-			if (!strncmp(v->container[size - 1], ">", 1)) {
-				if (!DEM_PUSH_STR(ddata, " >"))
-					return (0);
-			} else if (!DEM_PUSH_STR(ddata, ">"))
+			if (!DEM_PUSH_STR(ddata, ">"))
 				return (0);
 			ddata->is_tmpl = true;
 			break;
diff --git a/contrib/libcxxrt/memory.cc b/contrib/libcxxrt/memory.cc
index 7beb048ae914..0702f63f4527 100644
--- a/contrib/libcxxrt/memory.cc
+++ b/contrib/libcxxrt/memory.cc
@@ -73,10 +73,8 @@ namespace std
 
 
 #if __cplusplus < 201103L
-#define NOEXCEPT throw()
 #define BADALLOC throw(std::bad_alloc)
 #else
-#define NOEXCEPT noexcept
 #define BADALLOC
 #endif
 
@@ -138,14 +136,14 @@ void* operator new(size_t size) BADALLOC
 
 
 __attribute__((weak))
-void* operator new(size_t size, const std::nothrow_t &) NOEXCEPT
+void* operator new(size_t size, const std::nothrow_t &) _LIBCXXRT_NOEXCEPT
 {
 	return noexcept_new<(::operator new)>(size);
 }
 
 
 __attribute__((weak))
-void operator delete(void * ptr) NOEXCEPT
+void operator delete(void * ptr) _LIBCXXRT_NOEXCEPT
 {
 	free(ptr);
 }
@@ -159,14 +157,14 @@ void * operator new[](size_t size) BADALLOC
 
 
 __attribute__((weak))
-void * operator new[](size_t size, const std::nothrow_t &) NOEXCEPT
+void * operator new[](size_t size, const std::nothrow_t &) _LIBCXXRT_NOEXCEPT
 {
 	return noexcept_new<(::operator new[])>(size);
 }
 
 
 __attribute__((weak))
-void operator delete[](void * ptr) NOEXCEPT
+void operator delete[](void * ptr) _LIBCXXRT_NOEXCEPT
 {
 	::operator delete(ptr);
 }
@@ -176,14 +174,14 @@ void operator delete[](void * ptr) NOEXCEPT
 #if __cplusplus >= 201402L
 
 __attribute__((weak))
-void operator delete(void * ptr, size_t) NOEXCEPT
+void operator delete(void * ptr, size_t) _LIBCXXRT_NOEXCEPT
 {
 	::operator delete(ptr);
 }
 
 
 __attribute__((weak))
-void operator delete[](void * ptr, size_t) NOEXCEPT
+void operator delete[](void * ptr, size_t) _LIBCXXRT_NOEXCEPT
 {
 	::operator delete(ptr);
 }
diff --git a/contrib/libcxxrt/noexception.cc b/contrib/libcxxrt/noexception.cc
index 25dac1279684..7d17920c7cf4 100644
--- a/contrib/libcxxrt/noexception.cc
+++ b/contrib/libcxxrt/noexception.cc
@@ -30,7 +30,7 @@ namespace std
 	 * Returns whether there are any exceptions currently being thrown that
 	 * have not been caught. Without exception support this is always false.
 	 */
-	bool uncaught_exception() throw()
+	bool uncaught_exception() _LIBCXXRT_NOEXCEPT
 	{
 		return false;
 	}
@@ -38,7 +38,7 @@ namespace std
 	 * Returns the number of exceptions currently being thrown that have not
 	 * been caught. Without exception support this is always 0.
 	 */
-	int uncaught_exceptions() throw()
+	int uncaught_exceptions() _LIBCXXRT_NOEXCEPT
 	{
 		return 0;
 	}
diff --git a/contrib/libcxxrt/stdexcept.cc b/contrib/libcxxrt/stdexcept.cc
index c1cea39f6aa6..22c6930dca6b 100644
--- a/contrib/libcxxrt/stdexcept.cc
+++ b/contrib/libcxxrt/stdexcept.cc
@@ -31,66 +31,66 @@
 
 namespace std {
 
-exception::exception() throw() {}
+exception::exception() _LIBCXXRT_NOEXCEPT {}
 exception::~exception() {}
-exception::exception(const exception&) throw() {}
-exception& exception::operator=(const exception&) throw()
+exception::exception(const exception&) _LIBCXXRT_NOEXCEPT {}
+exception& exception::operator=(const exception&) _LIBCXXRT_NOEXCEPT
 {
 	return *this;
 }
-const char* exception::what() const throw()
+const char* exception::what() const _LIBCXXRT_NOEXCEPT
 {
 	return "std::exception";
 }
 
-bad_alloc::bad_alloc() throw() {}
+bad_alloc::bad_alloc() _LIBCXXRT_NOEXCEPT {}
 bad_alloc::~bad_alloc() {}
-bad_alloc::bad_alloc(const bad_alloc&) throw() {}
-bad_alloc& bad_alloc::operator=(const bad_alloc&) throw()
+bad_alloc::bad_alloc(const bad_alloc&) _LIBCXXRT_NOEXCEPT {}
+bad_alloc& bad_alloc::operator=(const bad_alloc&) _LIBCXXRT_NOEXCEPT
 {
 	return *this;
 }
-const char* bad_alloc::what() const throw()
+const char* bad_alloc::what() const _LIBCXXRT_NOEXCEPT
 {
 	return "cxxrt::bad_alloc";
 }
 
 
 
-bad_cast::bad_cast() throw() {}
+bad_cast::bad_cast() _LIBCXXRT_NOEXCEPT {}
 bad_cast::~bad_cast() {}
-bad_cast::bad_cast(const bad_cast&) throw() {}
-bad_cast& bad_cast::operator=(const bad_cast&) throw()
+bad_cast::bad_cast(const bad_cast&) _LIBCXXRT_NOEXCEPT {}
+bad_cast& bad_cast::operator=(const bad_cast&) _LIBCXXRT_NOEXCEPT
 {
 	return *this;
 }
-const char* bad_cast::what() const throw()
+const char* bad_cast::what() const _LIBCXXRT_NOEXCEPT
 {
 	return "std::bad_cast";
 }
 
-bad_typeid::bad_typeid() throw() {}
+bad_typeid::bad_typeid() _LIBCXXRT_NOEXCEPT {}
 bad_typeid::~bad_typeid() {}
-bad_typeid::bad_typeid(const bad_typeid &__rhs) throw() {}
-bad_typeid& bad_typeid::operator=(const bad_typeid &__rhs) throw()
+bad_typeid::bad_typeid(const bad_typeid &__rhs) _LIBCXXRT_NOEXCEPT {}
+bad_typeid& bad_typeid::operator=(const bad_typeid &__rhs) _LIBCXXRT_NOEXCEPT
 {
 	return *this;
 }
 
-const char* bad_typeid::what() const throw()
+const char* bad_typeid::what() const _LIBCXXRT_NOEXCEPT
 {
 	return "std::bad_typeid";
 }
 
-bad_array_new_length::bad_array_new_length() throw() {}
+bad_array_new_length::bad_array_new_length() _LIBCXXRT_NOEXCEPT {}
 bad_array_new_length::~bad_array_new_length() {}
-bad_array_new_length::bad_array_new_length(const bad_array_new_length&) throw() {}
-bad_array_new_length& bad_array_new_length::operator=(const bad_array_new_length&) throw()
+bad_array_new_length::bad_array_new_length(const bad_array_new_length&) _LIBCXXRT_NOEXCEPT {}
+bad_array_new_length& bad_array_new_length::operator=(const bad_array_new_length&) _LIBCXXRT_NOEXCEPT
 {
 	return *this;
 }
 
-const char* bad_array_new_length::what() const throw()
+const char* bad_array_new_length::what() const _LIBCXXRT_NOEXCEPT
 {
 	return "std::bad_array_new_length";
 }
diff --git a/contrib/libcxxrt/stdexcept.h b/contrib/libcxxrt/stdexcept.h
index 892039357595..38cd36d8e566 100644
--- a/contrib/libcxxrt/stdexcept.h
+++ b/contrib/libcxxrt/stdexcept.h
@@ -29,17 +29,19 @@
  * of the exceptions for the runtime to use.  
  */
 
+#include "cxxabi.h"
+
 namespace std
 {
 
 	class exception
 	{
 	public:
-		exception() throw();
-		exception(const exception&) throw();
-		exception& operator=(const exception&) throw();
+		exception() _LIBCXXRT_NOEXCEPT;
+		exception(const exception&) _LIBCXXRT_NOEXCEPT;
+		exception& operator=(const exception&) _LIBCXXRT_NOEXCEPT;
 		virtual ~exception();
-		virtual const char* what() const throw();
+		virtual const char* what() const _LIBCXXRT_NOEXCEPT;
 	};
 
 
@@ -49,11 +51,11 @@ namespace std
 	class bad_alloc: public exception
 	{
 	public:
-		bad_alloc() throw();
-		bad_alloc(const bad_alloc&) throw();
-		bad_alloc& operator=(const bad_alloc&) throw();
+		bad_alloc() _LIBCXXRT_NOEXCEPT;
+		bad_alloc(const bad_alloc&) _LIBCXXRT_NOEXCEPT;
+		bad_alloc& operator=(const bad_alloc&) _LIBCXXRT_NOEXCEPT;
 		~bad_alloc();
-		virtual const char* what() const throw();
+		virtual const char* what() const _LIBCXXRT_NOEXCEPT;
 	};
 
 	/**
@@ -61,11 +63,11 @@ namespace std
 	 */
 	class bad_cast: public exception {
 	public:
-		bad_cast() throw();
-		bad_cast(const bad_cast&) throw();
-		bad_cast& operator=(const bad_cast&) throw();
+		bad_cast() _LIBCXXRT_NOEXCEPT;
+		bad_cast(const bad_cast&) _LIBCXXRT_NOEXCEPT;
+		bad_cast& operator=(const bad_cast&) _LIBCXXRT_NOEXCEPT;
 		virtual ~bad_cast();
-		virtual const char* what() const throw();
+		virtual const char* what() const _LIBCXXRT_NOEXCEPT;
 	};
 
 	/**
@@ -74,21 +76,21 @@ namespace std
 	class bad_typeid: public exception
 	{
 	public:
-		bad_typeid() throw();
-		bad_typeid(const bad_typeid &__rhs) throw();
+		bad_typeid() _LIBCXXRT_NOEXCEPT;
+		bad_typeid(const bad_typeid &__rhs) _LIBCXXRT_NOEXCEPT;
 		virtual ~bad_typeid();
-		bad_typeid& operator=(const bad_typeid &__rhs) throw();
-		virtual const char* what() const throw();
+		bad_typeid& operator=(const bad_typeid &__rhs) _LIBCXXRT_NOEXCEPT;
+		virtual const char* what() const _LIBCXXRT_NOEXCEPT;
 	};
 
 	class bad_array_new_length: public bad_alloc
 	{
 	public:
-		bad_array_new_length() throw();
-		bad_array_new_length(const bad_array_new_length&) throw();
-		bad_array_new_length& operator=(const bad_array_new_length&) throw();
+		bad_array_new_length() _LIBCXXRT_NOEXCEPT;
+		bad_array_new_length(const bad_array_new_length&) _LIBCXXRT_NOEXCEPT;
+		bad_array_new_length& operator=(const bad_array_new_length&) _LIBCXXRT_NOEXCEPT;
 		virtual ~bad_array_new_length();
-		virtual const char *what() const throw();
+		virtual const char *what() const _LIBCXXRT_NOEXCEPT;
 	};