diff --git a/libstdc++-v3/include/bits/locale_classes.tcc b/libstdc++-v3/include/bits/locale_classes.tcc
index 52bd6d0f352455ad56dbd76967acb3baf78cf17b..ff1e943cdd6f609ee7f0076c1f196dd19f7d9f3c 100644
--- a/libstdc++-v3/include/bits/locale_classes.tcc
+++ b/libstdc++-v3/include/bits/locale_classes.tcc
@@ -37,6 +37,9 @@
 #ifdef _GLIBCXX_SYSHDR
 #pragma GCC system_header
 #endif
+
+#include <cerrno>
+
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wc++11-extensions" // extern template
 #pragma GCC diagnostic ignored "-Wvariadic-macros"
@@ -295,43 +298,76 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 
       size_t __len = (__hi - __lo) * 2;
 
-      _CharT* __c = new _CharT[__len];
+      struct _Buf
+      {
+	_Buf(size_t __n, void* __buf, int __e)
+	: _M_c(__buf ? (_CharT*)__buf : new _CharT[__n]),
+	  _M_stackbuf(__buf),
+	  _M_errno(__e)
+	{ }
 
-      __try
+	~_Buf()
+	{
+	  if (_M_c != _M_stackbuf)
+	    delete[] _M_c;
+	  if (errno == 0)
+	    errno = _M_errno;
+	}
+
+	void _M_realloc(size_t __len)
+	{
+	  _CharT* __p = new _CharT[__len];
+	  if (_M_c != _M_stackbuf)
+	    delete[] _M_c;
+	  _M_c = __p;
+	}
+
+	_CharT* _M_c;
+	void* const _M_stackbuf;
+	int _M_errno;
+      };
+
+      const size_t __bytes = __len * sizeof(_CharT);
+      _Buf __buf(__len, __bytes <= 256 ? __builtin_alloca(__bytes) : 0, errno);
+      errno = 0;
+
+      // strxfrm stops when it sees a nul character so we break
+      // the string into zero-terminated substrings and pass those
+      // to strxfrm.
+      for (;;)
 	{
-	  // strxfrm stops when it sees a nul character so we break
-	  // the string into zero-terminated substrings and pass those
-	  // to strxfrm.
-	  for (;;)
+	  // First try a buffer perhaps big enough.
+	  size_t __res = _M_transform(__buf._M_c, __p, __len);
+	  // If the buffer was not large enough, try again with the
+	  // correct size.
+	  if (__res >= __len)
 	    {
-	      // First try a buffer perhaps big enough.
-	      size_t __res = _M_transform(__c, __p, __len);
-	      // If the buffer was not large enough, try again with the
-	      // correct size.
-	      if (__res >= __len)
+	      if (__builtin_expect(errno, 0))
 		{
-		  __len = __res + 1;
-		  delete [] __c, __c = 0;
-		  __c = new _CharT[__len];
-		  __res = _M_transform(__c, __p, __len);
+#if __cpp_exceptions
+		  __throw_system_error(errno);
+#else
+		  // std::regex can call this function internally with
+		  // char values that always fail, so we don't want to
+		  // use _GLIBCXX_THROW_OR_ABORT here.
+		  __ret.clear();
+		  break;
+#endif
 		}
 
-	      __ret.append(__c, __res);
-	      __p += char_traits<_CharT>::length(__p);
-	      if (__p == __pend)
-		break;
-
-	      __p++;
-	      __ret.push_back(_CharT());
+	      __len = __res + 1;
+	      __buf._M_realloc(__len);
+	      __res = _M_transform(__buf._M_c, __p, __len);
 	    }
-	}
-      __catch(...)
-	{
-	  delete [] __c;
-	  __throw_exception_again;
-	}
 
-      delete [] __c;
+	  __ret.append(__buf._M_c, __res);
+	  __p += char_traits<_CharT>::length(__p);
+	  if (__p == __pend)
+	    break;
+
+	  __p++;
+	  __ret.push_back(_CharT());
+	}
 
       return __ret;
     }
diff --git a/libstdc++-v3/include/bits/regex.h b/libstdc++-v3/include/bits/regex.h
index 356e3f4e92a031d0bb436626fa4a3b9b8bf3385f..50d8863537d40c71f6d9dce1a5233c96726d1625 100644
--- a/libstdc++-v3/include/bits/regex.h
+++ b/libstdc++-v3/include/bits/regex.h
@@ -31,6 +31,9 @@
 #if __cplusplus >= 202002L
 # include <bits/iterator_concepts.h>	// std::default_sentinel_t
 #endif
+#if __cpp_rtti
+# include <typeinfo>
+#endif
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
@@ -253,9 +256,9 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
        * @param __first beginning of the character sequence.
        * @param __last  one-past-the-end of the character sequence.
        *
-       * Effects: if typeid(use_facet<collate<_Ch_type> >) ==
-       * typeid(collate_byname<_Ch_type>) and the form of the sort key
-       * returned by collate_byname<_Ch_type>::transform(__first, __last)
+       * Effects: if `typeid(use_facet<collate<_Ch_type>>(getloc())) ==
+       * typeid(collate_byname<_Ch_type>)` and the form of the sort key
+       * returned by `collate_byname<_Ch_type>::transform(__first, __last)`
        * is known and can be converted into a primary sort key
        * then returns that key, otherwise returns an empty string.
        *
@@ -265,17 +268,36 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
 	string_type
 	transform_primary(_Fwd_iter __first, _Fwd_iter __last) const
 	{
+	  string_type __ret;
+#if __cpp_rtti
+	  const auto& __fclt = use_facet<collate<char_type>>(_M_locale);
+	  if (typeid(__fclt) != typeid(collate<char_type>)) // FIXME: PR 118110
+	    return __ret;
+
 	  // TODO : this is not entirely correct.
 	  // This function requires extra support from the platform.
-	  //
-	  // Read http://gcc.gnu.org/ml/libstdc++/2013-09/msg00117.html and
-	  // http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2003/n1429.htm
-	  // for details.
-	  typedef std::ctype<char_type> __ctype_type;
-	  const __ctype_type& __fctyp(use_facet<__ctype_type>(_M_locale));
-	  _GLIBCXX_STD_C::vector<char_type> __s(__first, __last);
-	  __fctyp.tolower(__s.data(), __s.data() + __s.size());
-	  return this->transform(__s.data(), __s.data() + __s.size());
+	  // See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=118105
+
+	  const auto& __fctyp(use_facet<ctype<char_type>>(_M_locale));
+	  basic_string<char_type> __s(__first, __last);
+	  const auto __p = const_cast<char_type*>(__s.c_str());
+	  const auto __pend = __p + __s.size();
+	  // XXX: should we use tolower here? The regex traits requirements
+	  // say that transform_primary ignores case, but the specification
+	  // for the std::regex_traits<char> and std::regex_traits<wchar_t>
+	  // specializations don't, they seem to suggest just using the
+	  // collate::transform function to get a primary sort key.
+	  __fctyp.tolower(__p, __pend);
+
+	  __try
+	    {
+	      __ret = __fclt.transform(__p, __pend);
+	    }
+	  __catch (const exception&)
+	    {
+	    }
+#endif
+	  return __ret;
 	}
 
       /**