diff --git a/libstdc++-v3/config/abi/pre/gnu.ver b/libstdc++-v3/config/abi/pre/gnu.ver
index 4d97ec37147..225d6dc482b 100644
--- a/libstdc++-v3/config/abi/pre/gnu.ver
+++ b/libstdc++-v3/config/abi/pre/gnu.ver
@@ -133,17 +133,18 @@ GLIBCXX_3.4 {
 #     std::logic_error::~l*;
 #     std::[m-r]*;
 #     std::[m]*;
-      std::messages[^_]*;
+#     std::messages[^_]*;
 #     std::messages_byname*;
-      std::money_*;
-      std::moneypunct[^_]*;
+#     std::money_*;
+      std::money_base*;
+#     std::moneypunct[^_]*;
 #     std::moneypunct_byname*;
 #     std::n[^u]*;
       std::n[^aueo]*;
       std::nothrow;
       std::nu[^m]*;
-      std::num[^ep]*;
-      std::numpunct[^_]*;
+      std::num[^_ep]*;
+#     std::numpunct[^_]*;
 #     std::numpunct_byname*;
       std::ostrstream*;
 #     std::out_of_range::o*;
@@ -597,28 +598,49 @@ GLIBCXX_3.4 {
     _ZNSt12ctype_bynameI[cw]ED*;
 
     # std::num_get
+    _ZNSt7num_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[CD][012]*;
+    _ZNSt7num_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE2idE;
     _ZNKSt7num_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[2-9]*;
     _ZNKSt7num_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE14_M_extract_intI*;
-    _ZNKSt7num_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE16_M_extract_floatI*;
+    _ZNKSt7num_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE16_M_extract_float*;
 
     # std::num_put
+    _ZNSt7num_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[CD][012]*;
+    _ZNSt7num_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE2idE;
     _ZNKSt7num_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[2-9]*;
     _ZNKSt7num_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE1[234]*;
     _ZNKSt7num_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE15_M_insert_floatI*;
 
+    # std::numpunct
+    _ZNSt8numpunctI[cw]E[CD][012]*;
+    _ZNSt8numpunctI[cw]E2idE;
+    _ZNSt8numpunctI[cw]E[2]*;
+    _ZNKSt8numpunctI[cw]E[189]*;
+
     # std::numpunct_byname
     _ZNSt15numpunct_bynameI[cw]EC[12]EPKc[jmy];
     _ZNSt15numpunct_bynameI[cw]ED*;
 
     # std::money_get
+    _ZNSt9money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[CD][012]*;
+    _ZNSt9money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE2idE;
     _ZNKSt9money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[2-9]*;
     _ZNKSt9money_getI[cw]St19istreambuf_iteratorI[cw]St11char_traitsI[cw]EEE10_M_extractILb[01]EEES3_S3_S3_RSt8ios_baseRSt12_Ios_IostateRSs;
 
     # std::money_put
+    _ZNSt9money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[CD][012]*;
+    _ZNSt9money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE2idE;
     _ZNKSt9money_putI[cw]St19ostreambuf_iteratorI[cw]St11char_traitsI[cw]EEE[1-8]*;
     _ZNKSt9money_putIcSt19ostreambuf_iteratorIcSt11char_traitsIcEEE9_M_insertILb[01]EEES3_S3_RSt8ios_basecRKSs;
     _ZNKSt9money_putIwSt19ostreambuf_iteratorIwSt11char_traitsIwEEE9_M_insertILb[01]EEES3_S3_RSt8ios_basewRKSbIwS2_SaIwEE;
 
+    # std::moneypunct
+    _ZNSt10moneypunctI[cw]Lb[01]EE[CD][012]*;
+    _ZNSt10moneypunctI[cw]Lb[01]EE2idE;
+    _ZNSt10moneypunctI[cw]Lb[01]EE24*;
+    _ZNSt10moneypunctI[cw]Lb[01]EE4intlE;
+    _ZNKSt10moneypunctI[cw]Lb[01]EE[18]*;
+
     # std::moneypunct_byname
     _ZNSt17moneypunct_bynameI[cw]Lb[01]EEC[12]EPKc[jmy];
     _ZNSt17moneypunct_bynameI[cw]Lb[01]EED*;
@@ -657,6 +679,11 @@ GLIBCXX_3.4 {
     _ZNSt14numeric_limitsI[a-m]E1[0-7]max_e*;
     _ZNSt14numeric_limitsI[p-z]E1[0-7]max_e*;
 
+    # std::messages
+    _ZNSt8messagesI[cw]E[CD][012]*;
+    _ZNSt8messagesI[cw]E2idE;
+    _ZNKSt8messagesI[cw]E[1-8]*;
+
     # std::messages_byname
     _ZNSt15messages_bynameI[cw]EC[12]EPKc[jmy];
     _ZNSt15messages_bynameI[cw]ED*;
@@ -2446,6 +2473,7 @@ GLIBCXX_3.4.30 {
 
 GLIBCXX_3.4.31 {
     _ZNSt7__cxx1112basic_stringI[cw]St11char_traitsI[cw]ESaI[cw]EE15_M_replace_cold*;
+
     _ZSt20__to_chars_float16_tPcS_fSt12chars_format;
     _ZSt21__to_chars_bfloat16_tPcS_fSt12chars_format;
     _ZSt22__from_chars_float16_tPKcS0_RfSt12chars_format;
@@ -2454,6 +2482,9 @@ GLIBCXX_3.4.31 {
     _ZSt8to_charsPcS_DF128_St12chars_format;
     _ZSt8to_charsPcS_DF128_St12chars_formati;
     _ZSt10from_charsPKcS0_RDF128_St12chars_format;
+
+    _ZSt15__try_use_facet*;
+
 } GLIBCXX_3.4.30;
 
 # Symbols in the support library (libsupc++) have their own tag.
diff --git a/libstdc++-v3/include/bits/basic_ios.tcc b/libstdc++-v3/include/bits/basic_ios.tcc
index 2bbcdc20dc0..15d35a46cf4 100644
--- a/libstdc++-v3/include/bits/basic_ios.tcc
+++ b/libstdc++-v3/include/bits/basic_ios.tcc
@@ -156,20 +156,9 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     void
     basic_ios<_CharT, _Traits>::_M_cache_locale(const locale& __loc)
     {
-      if (__builtin_expect(has_facet<__ctype_type>(__loc), true))
-	_M_ctype = std::__addressof(use_facet<__ctype_type>(__loc));
-      else
-	_M_ctype = 0;
-
-      if (__builtin_expect(has_facet<__num_put_type>(__loc), true))
-	_M_num_put = std::__addressof(use_facet<__num_put_type>(__loc));
-      else
-	_M_num_put = 0;
-
-      if (__builtin_expect(has_facet<__num_get_type>(__loc), true))
-	_M_num_get = std::__addressof(use_facet<__num_get_type>(__loc));
-      else
-	_M_num_get = 0;
+      _M_ctype = std::__try_use_facet<__ctype_type>(__loc);
+      _M_num_put = std::__try_use_facet<__num_put_type>(__loc);
+      _M_num_get = std::__try_use_facet<__num_get_type>(__loc);
     }
 
   // Inhibit implicit instantiations for required instantiations,
diff --git a/libstdc++-v3/include/bits/fstream.tcc b/libstdc++-v3/include/bits/fstream.tcc
index 2e936962837..8158ab30312 100644
--- a/libstdc++-v3/include/bits/fstream.tcc
+++ b/libstdc++-v3/include/bits/fstream.tcc
@@ -86,8 +86,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     _M_codecvt(0), _M_ext_buf(0), _M_ext_buf_size(0), _M_ext_next(0),
     _M_ext_end(0)
     {
-      if (has_facet<__codecvt_type>(this->_M_buf_locale))
-	_M_codecvt = &use_facet<__codecvt_type>(this->_M_buf_locale);
+      _M_codecvt = std::__try_use_facet<__codecvt_type>(this->_M_buf_locale);
     }
 
 #if __cplusplus >= 201103L
@@ -1028,9 +1027,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
     {
       bool __testvalid = true;
 
-      const __codecvt_type* _M_codecvt_tmp = 0;
-      if (__builtin_expect(has_facet<__codecvt_type>(__loc), true))
-	_M_codecvt_tmp = &use_facet<__codecvt_type>(__loc);
+      const __codecvt_type* const _M_codecvt_tmp
+	= __try_use_facet<__codecvt_type>(__loc);
 
       if (this->is_open())
 	{
diff --git a/libstdc++-v3/include/bits/locale_classes.h b/libstdc++-v3/include/bits/locale_classes.h
index 6cad0ff5655..6912a54d607 100644
--- a/libstdc++-v3/include/bits/locale_classes.h
+++ b/libstdc++-v3/include/bits/locale_classes.h
@@ -82,6 +82,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       friend const _Facet&
       use_facet(const locale&);
 
+    template<typename _Facet>
+      friend const _Facet*
+      __try_use_facet(const locale&) _GLIBCXX_NOTHROW;
+
     template<typename _Cache>
       friend struct __use_cache;
 
@@ -496,6 +500,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       friend bool
       has_facet(const locale&) throw();
 
+    template<typename _Facet>
+      friend const _Facet*
+      __try_use_facet(const locale&) _GLIBCXX_NOTHROW;
+
     // NB: There is no accessor for _M_index because it may be used
     // before the constructor is run; the effect of calling a member
     // function (even an inline) would be undefined.
@@ -536,6 +544,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
       friend const _Facet&
       use_facet(const locale&);
 
+    template<typename _Facet>
+      friend const _Facet*
+      __try_use_facet(const locale&) _GLIBCXX_NOTHROW;
+
     template<typename _Cache>
       friend struct __use_cache;
 
diff --git a/libstdc++-v3/include/bits/locale_classes.tcc b/libstdc++-v3/include/bits/locale_classes.tcc
index 9cc4f238ee7..7a67f5cd315 100644
--- a/libstdc++-v3/include/bits/locale_classes.tcc
+++ b/libstdc++-v3/include/bits/locale_classes.tcc
@@ -87,6 +87,68 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 				__s2.data(), __s2.data() + __s2.length()) < 0);
     }
 
+  template<typename _Facet>
+    inline const _Facet*
+    __try_use_facet(const locale& __loc) _GLIBCXX_NOTHROW
+    {
+      const size_t __i = _Facet::id._M_id();
+      const locale::facet** __facets = __loc._M_impl->_M_facets;
+
+      // We know these standard facets are always installed in every locale
+      // so dynamic_cast always succeeds, just use static_cast instead.
+#define _GLIBCXX_STD_FACET(...) \
+      if _GLIBCXX17_CONSTEXPR (__is_same(_Facet, __VA_ARGS__)) \
+	return static_cast<const _Facet*>(__facets[__i])
+
+      _GLIBCXX_STD_FACET(ctype<char>);
+      _GLIBCXX_STD_FACET(num_get<char>);
+      _GLIBCXX_STD_FACET(num_put<char>);
+      _GLIBCXX_STD_FACET(codecvt<char, char, mbstate_t>);
+      _GLIBCXX_STD_FACET(collate<char>);
+      _GLIBCXX_STD_FACET(moneypunct<char>);
+      _GLIBCXX_STD_FACET(moneypunct<char, true>);
+      _GLIBCXX_STD_FACET(money_get<char>);
+      _GLIBCXX_STD_FACET(money_put<char>);
+      _GLIBCXX_STD_FACET(numpunct<char>);
+      _GLIBCXX_STD_FACET(time_get<char>);
+      _GLIBCXX_STD_FACET(time_put<char>);
+      _GLIBCXX_STD_FACET(messages<char>);
+
+#ifdef _GLIBCXX_USE_WCHAR_T
+      _GLIBCXX_STD_FACET(ctype<wchar_t>);
+      _GLIBCXX_STD_FACET(num_get<wchar_t>);
+      _GLIBCXX_STD_FACET(num_put<wchar_t>);
+      _GLIBCXX_STD_FACET(codecvt<wchar_t, char, mbstate_t>);
+      _GLIBCXX_STD_FACET(collate<wchar_t>);
+      _GLIBCXX_STD_FACET(moneypunct<wchar_t>);
+      _GLIBCXX_STD_FACET(moneypunct<wchar_t, true>);
+      _GLIBCXX_STD_FACET(money_get<wchar_t>);
+      _GLIBCXX_STD_FACET(money_put<wchar_t>);
+      _GLIBCXX_STD_FACET(numpunct<wchar_t>);
+      _GLIBCXX_STD_FACET(time_get<wchar_t>);
+      _GLIBCXX_STD_FACET(time_put<wchar_t>);
+      _GLIBCXX_STD_FACET(messages<wchar_t>);
+#endif
+#ifdef _GLIBCXX_USE_CHAR8_T
+      _GLIBCXX_STD_FACET(codecvt<char8_t, char, mbstate_t>);
+#endif
+#if __cplusplus >= 201103L
+      _GLIBCXX_STD_FACET(codecvt<char16_t, char, mbstate_t>);
+      _GLIBCXX_STD_FACET(codecvt<char32_t, char, mbstate_t>);
+#endif
+
+#undef _GLIBCXX_STD_FACET
+
+      if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
+	return 0;
+
+#if __cpp_rtti
+      return dynamic_cast<const _Facet*>(__facets[__i]);
+#else
+      return static_cast<const _Facet*>(__facets[__i]);
+#endif
+    }
+
   /**
    *  @brief  Test for the presence of a facet.
    *  @ingroup locales
@@ -100,17 +162,16 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
    *  @return  true if @p __loc contains a facet of type _Facet, else false.
   */
   template<typename _Facet>
-    bool
+    inline bool
     has_facet(const locale& __loc) throw()
     {
-      const size_t __i = _Facet::id._M_id();
-      const locale::facet** __facets = __loc._M_impl->_M_facets;
-      return (__i < __loc._M_impl->_M_facets_size
-#if __cpp_rtti
-	      && dynamic_cast<const _Facet*>(__facets[__i]));
+#if __cplusplus >= 201103L
+      static_assert(__is_base_of(locale::facet, _Facet),
+		    "template argument must be derived from locale::facet");
 #else
-              && static_cast<const _Facet*>(__facets[__i]));
+      (void) static_cast<const _Facet*>(static_cast<const locale::facet*>(0));
 #endif
+      return std::__try_use_facet<_Facet>(__loc) != 0;
     }
 
   /**
@@ -130,18 +191,18 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wdangling-reference"
   template<typename _Facet>
-    const _Facet&
+    inline const _Facet&
     use_facet(const locale& __loc)
     {
-      const size_t __i = _Facet::id._M_id();
-      const locale::facet** __facets = __loc._M_impl->_M_facets;
-      if (__i >= __loc._M_impl->_M_facets_size || !__facets[__i])
-        __throw_bad_cast();
-#if __cpp_rtti
-      return dynamic_cast<const _Facet&>(*__facets[__i]);
+#if __cplusplus >= 201103L
+      static_assert(__is_base_of(locale::facet, _Facet),
+		    "template argument must be derived from locale::facet");
 #else
-      return static_cast<const _Facet&>(*__facets[__i]);
+      (void) static_cast<const _Facet*>(static_cast<const locale::facet*>(0));
 #endif
+      if (const _Facet* __f = std::__try_use_facet<_Facet>(__loc))
+	return *__f;
+      __throw_bad_cast();
     }
 #pragma GCC diagnostic pop
 
@@ -273,6 +334,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   extern template class collate<char>;
   extern template class collate_byname<char>;
 
+  extern template
+    const collate<char>*
+    __try_use_facet<collate<char> >(const locale&) _GLIBCXX_NOTHROW;
+
   extern template
     const collate<char>&
     use_facet<collate<char> >(const locale&);
@@ -285,6 +350,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
   extern template class collate<wchar_t>;
   extern template class collate_byname<wchar_t>;
 
+  extern template
+    const collate<wchar_t>*
+    __try_use_facet<collate<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
   extern template
     const collate<wchar_t>&
     use_facet<collate<wchar_t> >(const locale&);
diff --git a/libstdc++-v3/include/bits/locale_facets.tcc b/libstdc++-v3/include/bits/locale_facets.tcc
index ec7cce4a640..dd5c45e223b 100644
--- a/libstdc++-v3/include/bits/locale_facets.tcc
+++ b/libstdc++-v3/include/bits/locale_facets.tcc
@@ -1325,6 +1325,22 @@ _GLIBCXX_END_NAMESPACE_LDBL
   extern template class _GLIBCXX_NAMESPACE_LDBL num_put<char>;
   extern template class ctype_byname<char>;
 
+  extern template
+    const ctype<char>*
+    __try_use_facet<ctype<char> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const numpunct<char>*
+    __try_use_facet<numpunct<char> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const num_put<char>*
+    __try_use_facet<num_put<char> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const num_get<char>*
+    __try_use_facet<num_get<char> >(const locale&) _GLIBCXX_NOTHROW;
+
   extern template
     const ctype<char>&
     use_facet<ctype<char> >(const locale&);
@@ -1364,6 +1380,22 @@ _GLIBCXX_END_NAMESPACE_LDBL
   extern template class _GLIBCXX_NAMESPACE_LDBL num_put<wchar_t>;
   extern template class ctype_byname<wchar_t>;
 
+  extern template
+    const ctype<wchar_t>*
+    __try_use_facet<ctype<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const numpunct<wchar_t>*
+    __try_use_facet<numpunct<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const num_put<wchar_t>*
+    __try_use_facet<num_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const num_get<wchar_t>*
+    __try_use_facet<num_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
   extern template
     const ctype<wchar_t>&
     use_facet<ctype<wchar_t> >(const locale&);
@@ -1380,7 +1412,7 @@ _GLIBCXX_END_NAMESPACE_LDBL
     const num_get<wchar_t>&
     use_facet<num_get<wchar_t> >(const locale&);
 
- extern template
+  extern template
     bool
     has_facet<ctype<wchar_t> >(const locale&);
 
diff --git a/libstdc++-v3/include/bits/locale_facets_nonio.tcc b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
index 17a2c8d4486..320bcf22206 100644
--- a/libstdc++-v3/include/bits/locale_facets_nonio.tcc
+++ b/libstdc++-v3/include/bits/locale_facets_nonio.tcc
@@ -1691,6 +1691,38 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
   extern template class messages<char>;
   extern template class messages_byname<char>;
 
+  extern template
+    const moneypunct<char, true>*
+    __try_use_facet<moneypunct<char, true> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const moneypunct<char, false>*
+    __try_use_facet<moneypunct<char, false> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const money_put<char>*
+    __try_use_facet<money_put<char> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const money_get<char>*
+    __try_use_facet<money_get<char> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const __timepunct<char>*
+    __try_use_facet<__timepunct<char> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const time_put<char>*
+    __try_use_facet<time_put<char> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const time_get<char>*
+    __try_use_facet<time_get<char> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const messages<char>*
+    __try_use_facet<messages<char> >(const locale&) _GLIBCXX_NOTHROW;
+
   extern template
     const moneypunct<char, true>&
     use_facet<moneypunct<char, true> >(const locale&);
@@ -1766,6 +1798,38 @@ _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11
   extern template class messages<wchar_t>;
   extern template class messages_byname<wchar_t>;
 
+  extern template
+    const moneypunct<wchar_t, true>*
+    __try_use_facet<moneypunct<wchar_t, true> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const moneypunct<wchar_t, false>*
+    __try_use_facet<moneypunct<wchar_t, false> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const money_put<wchar_t>*
+    __try_use_facet<money_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const money_get<wchar_t>*
+    __try_use_facet<money_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const __timepunct<wchar_t>*
+    __try_use_facet<__timepunct<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const time_put<wchar_t>*
+    __try_use_facet<time_put<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const time_get<wchar_t>*
+    __try_use_facet<time_get<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
+  extern template
+    const messages<wchar_t>*
+    __try_use_facet<messages<wchar_t> >(const locale&) _GLIBCXX_NOTHROW;
+
   extern template
     const moneypunct<wchar_t, true>&
     use_facet<moneypunct<wchar_t, true> >(const locale&);
diff --git a/libstdc++-v3/src/c++11/locale-inst-monetary.h b/libstdc++-v3/src/c++11/locale-inst-monetary.h
index e1c696dc4e3..ff8439857d2 100644
--- a/libstdc++-v3/src/c++11/locale-inst-monetary.h
+++ b/libstdc++-v3/src/c++11/locale-inst-monetary.h
@@ -32,11 +32,9 @@
 
 namespace std _GLIBCXX_VISIBILITY(default)
 {
-  template const money_put<C>& use_facet<money_put<C> >(const locale&);
-  template const money_get<C>& use_facet<money_get<C> >(const locale&);
-
-  template bool has_facet<money_put<C> >(const locale&);
-  template bool has_facet<money_get<C> >(const locale&);
+// use_facet and has_facet instantiations
+INSTANTIATE_FACET_ACCESSORS(money_put<C>);
+INSTANTIATE_FACET_ACCESSORS(money_get<C>);
 
 _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11
   template class money_get<C, istreambuf_iterator<C> >;
diff --git a/libstdc++-v3/src/c++11/locale-inst-numeric.h b/libstdc++-v3/src/c++11/locale-inst-numeric.h
index 1417ac25ed4..4b970f75f6e 100644
--- a/libstdc++-v3/src/c++11/locale-inst-numeric.h
+++ b/libstdc++-v3/src/c++11/locale-inst-numeric.h
@@ -29,11 +29,9 @@
 namespace std _GLIBCXX_VISIBILITY(default)
 {
 #if ! _GLIBCXX_USE_CXX11_ABI
-  template const num_get<C>& use_facet<num_get<C> >(const locale&);
-  template const num_put<C>& use_facet<num_put<C> >(const locale&);
-
-  template bool has_facet<num_get<C> >(const locale&);
-  template bool has_facet<num_put<C> >(const locale&);
+// use_facet and has_facet instantiations
+INSTANTIATE_FACET_ACCESSORS(num_get<C>);
+INSTANTIATE_FACET_ACCESSORS(num_put<C>);
 #endif
 
 _GLIBCXX_BEGIN_NAMESPACE_LDBL
diff --git a/libstdc++-v3/src/c++11/locale-inst.cc b/libstdc++-v3/src/c++11/locale-inst.cc
index 3aee5df9b04..b264cb381ec 100644
--- a/libstdc++-v3/src/c++11/locale-inst.cc
+++ b/libstdc++-v3/src/c++11/locale-inst.cc
@@ -43,6 +43,17 @@
 # define C_is_char
 #endif
 
+#define INSTANTIATE_USE_FACET(...)			    \
+  template const __VA_ARGS__*				    \
+    __try_use_facet< __VA_ARGS__ >(const locale&) noexcept; \
+  template const __VA_ARGS__&				    \
+    use_facet<__VA_ARGS__>(const locale&)		    \
+
+#define INSTANTIATE_FACET_ACCESSORS(...)		    \
+  INSTANTIATE_USE_FACET(__VA_ARGS__);			    \
+  template bool						    \
+    has_facet<__VA_ARGS__>(const locale&) noexcept
+
 #include "locale-inst-numeric.h"
 #include "locale-inst-monetary.h"
 
@@ -116,92 +127,22 @@ _GLIBCXX_BEGIN_NAMESPACE_CXX11
   template class collate_byname<C>;
 _GLIBCXX_END_NAMESPACE_CXX11
 
-  // use_facet
+// use_facet and has_facet instantiations
 #if ! _GLIBCXX_USE_CXX11_ABI
-  template
-    const ctype<C>&
-    use_facet<ctype<C> >(const locale&);
-
-  template
-    const codecvt<C, char, mbstate_t>&
-    use_facet<codecvt<C, char, mbstate_t> >(const locale&);
+INSTANTIATE_FACET_ACCESSORS(ctype<C>);
+INSTANTIATE_FACET_ACCESSORS(codecvt<C, char, mbstate_t>);
 #endif
-
-  template
-    const collate<C>&
-    use_facet<collate<C> >(const locale&);
-
-  template
-    const numpunct<C>&
-    use_facet<numpunct<C> >(const locale&);
-
-  template
-    const moneypunct<C, true>&
-    use_facet<moneypunct<C, true> >(const locale&);
-
-  template
-    const moneypunct<C, false>&
-    use_facet<moneypunct<C, false> >(const locale&);
-
+INSTANTIATE_FACET_ACCESSORS(collate<C>);
+INSTANTIATE_FACET_ACCESSORS(numpunct<C>);
+INSTANTIATE_FACET_ACCESSORS(moneypunct<C, false>);
+// No explicit instantiation of has_facet<moneypunct<C, true>> for some reason.
+INSTANTIATE_USE_FACET      (moneypunct<C, true>);
 #if ! _GLIBCXX_USE_CXX11_ABI
-  template
-    const __timepunct<C>&
-    use_facet<__timepunct<C> >(const locale&);
-
-  template
-    const time_put<C>&
-    use_facet<time_put<C> >(const locale&);
+INSTANTIATE_FACET_ACCESSORS(__timepunct<C>);
+INSTANTIATE_FACET_ACCESSORS(time_put<C>);
 #endif
-
-  template
-    const time_get<C>&
-    use_facet<time_get<C> >(const locale&);
-
-  template
-    const messages<C>&
-    use_facet<messages<C> >(const locale&);
-
-  // has_facet
-#if ! _GLIBCXX_USE_CXX11_ABI
-  template
-    bool
-    has_facet<ctype<C> >(const locale&);
-
-  template
-    bool
-    has_facet<codecvt<C, char, mbstate_t> >(const locale&);
-#endif
-
-  template
-    bool
-    has_facet<collate<C> >(const locale&);
-
-  template
-    bool
-    has_facet<numpunct<C> >(const locale&);
-
-  template
-    bool
-    has_facet<moneypunct<C> >(const locale&);
-
-#if ! _GLIBCXX_USE_CXX11_ABI
-  template
-    bool
-    has_facet<__timepunct<C> >(const locale&);
-
-  template
-    bool
-    has_facet<time_put<C> >(const locale&);
-#endif
-
-  template
-    bool
-    has_facet<time_get<C> >(const locale&);
-
-  template
-    bool
-    has_facet<messages<C> >(const locale&);
-
+INSTANTIATE_FACET_ACCESSORS(time_get<C>);
+INSTANTIATE_FACET_ACCESSORS(messages<C>);
 
 #if ! _GLIBCXX_USE_CXX11_ABI
   // locale functions.
diff --git a/libstdc++-v3/src/c++98/compatibility-ldbl.cc b/libstdc++-v3/src/c++98/compatibility-ldbl.cc
index 683f7a8429c..55a59438037 100644
--- a/libstdc++-v3/src/c++98/compatibility-ldbl.cc
+++ b/libstdc++-v3/src/c++98/compatibility-ldbl.cc
@@ -48,6 +48,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
   template bool has_facet<num_get<C> >(const locale&);
   template bool has_facet<money_put<C> >(const locale&);
   template bool has_facet<money_get<C> >(const locale&);
+  template const num_put<C>* __try_use_facet<num_put<C> >(const locale&);
+  template const num_get<C>* __try_use_facet<num_get<C> >(const locale&);
+  template const money_put<C>* __try_use_facet<money_put<C> >(const locale&);
+  template const money_get<C>* __try_use_facet<money_get<C> >(const locale&);
 #undef C
 #ifdef _GLIBCXX_USE_WCHAR_T
 #define C wchar_t
@@ -63,6 +67,10 @@ namespace std _GLIBCXX_VISIBILITY(default)
   template bool has_facet<num_get<C> >(const locale&);
   template bool has_facet<money_put<C> >(const locale&);
   template bool has_facet<money_get<C> >(const locale&);
+  template const num_put<C>* __try_use_facet<num_put<C> >(const locale&);
+  template const num_get<C>* __try_use_facet<num_get<C> >(const locale&);
+  template const money_put<C>* __try_use_facet<money_put<C> >(const locale&);
+  template const money_get<C>* __try_use_facet<money_get<C> >(const locale&);
 #undef C
 #endif
 }
diff --git a/libstdc++-v3/testsuite/22_locale/ctype/is/string/89728_neg.cc b/libstdc++-v3/testsuite/22_locale/ctype/is/string/89728_neg.cc
index 7935c99a96f..047df40e1d4 100644
--- a/libstdc++-v3/testsuite/22_locale/ctype/is/string/89728_neg.cc
+++ b/libstdc++-v3/testsuite/22_locale/ctype/is/string/89728_neg.cc
@@ -17,14 +17,15 @@
 // with this library; see the file COPYING3.  If not see
 // <http://www.gnu.org/licenses/>.
 
-// { dg-error "complete" "" { target *-*-* } 0 }
-// { dg-error "invalid 'static_cast'" "" { target { ! rtti }  } 0 }
+// { dg-error "invalid use of incomplete type" "" { target *-*-* } 0 }
+// { dg-error "invalid 'static_cast'" "" { target c++98_only } 0 }
 
 #include <locale>
 
 template <class Char, int I>
 struct trait: std::char_traits<Char> {};
 
+// Generates unique types so we get distinct diagnostics for each line.
 template <class Char, int I>
 std::basic_string<Char, trait<Char, I> > make_str()
 {
