[libcxx-commits] [libcxx] [libcxx] Enrich message for std::bad_variant_access exception (PR #196495)

Nikita Grivin via libcxx-commits libcxx-commits at lists.llvm.org
Sun Jun 7 02:46:26 PDT 2026


https://github.com/MindSpectre updated https://github.com/llvm/llvm-project/pull/196495

>From 453842c606f228283ccb535b39495833855fb205 Mon Sep 17 00:00:00 2001
From: Polaris <neuronspectrelin at gmail.com>
Date: Fri, 8 May 2026 01:24:05 +0300
Subject: [PATCH] [libc++] Improve messages for std::bad_variant_access
 exception

std::bad_variant_access::what() now returns a more descriptive message identifying the failing operation (e.g., std::get: variant is valueless) instead of the generic bad_variant_access
---
 libcxx/docs/ReleaseNotes/23.rst               |  5 +-
 libcxx/include/__configuration/availability.h | 16 ++++
 libcxx/include/variant                        | 25 ++++--
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  4 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  4 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  4 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  4 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  4 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  4 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  4 +
 ...bcxxabi.v1.stable.exceptions.nonew.abilist |  4 +
 ...xxabi.v1.stable.noexceptions.nonew.abilist |  4 +
 libcxx/src/variant.cpp                        |  2 +
 .../good_what_message.pass.cpp                | 90 +++++++++++++++++++
 14 files changed, 168 insertions(+), 6 deletions(-)
 create mode 100644 libcxx/test/libcxx/utilities/variant/variant.bad_variant_access/good_what_message.pass.cpp

diff --git a/libcxx/docs/ReleaseNotes/23.rst b/libcxx/docs/ReleaseNotes/23.rst
index 03dabc54dcf79..c8f7cf5455d92 100644
--- a/libcxx/docs/ReleaseNotes/23.rst
+++ b/libcxx/docs/ReleaseNotes/23.rst
@@ -60,7 +60,10 @@ Improvements and New Features
   for ``std::deque<int>`` iterators.
 - ``std::copy(CharT*, CharT*, ostreambuf_iterator<CharT>)`` has been optimized, resulting in performance improvements
   of up to 25x.
-- A lot of transitive includes have been removed, resulting in significant compile time improvements.
+- ``std::bad_variant_access::what()`` now returns a message identifying the cause of the failure:
+  ``"std::visit: variant is valueless"``, ``"std::get: variant is valueless"``, or
+  ``"std::get: wrong alternative for variant"``. The standard only requires ``what()`` to return an
+  unspecified non-null string, so user code that does not match on the exact message remains correct.
 
 Deprecations and Removals
 -------------------------
diff --git a/libcxx/include/__configuration/availability.h b/libcxx/include/__configuration/availability.h
index f1a598b5206f4..e05d998cb77da 100644
--- a/libcxx/include/__configuration/availability.h
+++ b/libcxx/include/__configuration/availability.h
@@ -39,6 +39,9 @@
 // in all versions of the library are available.
 #if !_LIBCPP_HAS_VENDOR_AVAILABILITY_ANNOTATIONS
 
+#  define _LIBCPP_INTRODUCED_IN_LLVM_23 1
+#  define _LIBCPP_INTRODUCED_IN_LLVM_23_ATTRIBUTE /* nothing */
+
 #  define _LIBCPP_INTRODUCED_IN_LLVM_22 1
 #  define _LIBCPP_INTRODUCED_IN_LLVM_22_ATTRIBUTE /* nothing */
 
@@ -70,6 +73,11 @@
 
 // clang-format off
 
+// LLVM 23
+// TODO: Fill this in
+#  define _LIBCPP_INTRODUCED_IN_LLVM_23 0
+#  define _LIBCPP_INTRODUCED_IN_LLVM_23_ATTRIBUTE __attribute__((unavailable))
+
 // LLVM 22
 // TODO: Fill this in
 #  define _LIBCPP_INTRODUCED_IN_LLVM_22 0
@@ -230,6 +238,14 @@
 #define _LIBCPP_AVAILABILITY_HAS_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE _LIBCPP_INTRODUCED_IN_LLVM_21
 // No attribute, since we've had bad_function_call::what() in the headers before
 
+// This determines whether we assume that the internal std::__bad_variant_access_with_msg class
+// (which carries a message describing the cause of the failure in bad_variant_access::what())
+// provides a key function in the dylib. This allows centralizing its vtable and typeinfo instead
+// of having all TUs provide a weak definition that then gets deduplicated. When it is not available
+// in the dylib, what() is defined inline instead, so the descriptive message is provided regardless.
+#define _LIBCPP_AVAILABILITY_HAS_BAD_VARIANT_ACCESS_WITH_MSG_KEY_FUNCTION _LIBCPP_INTRODUCED_IN_LLVM_23
+// No attribute, since we've had bad_variant_access in the headers before
+
 // This controls the availability of floating-point std::from_chars functions.
 // These overloads were added later than the integer overloads.
 #define _LIBCPP_AVAILABILITY_HAS_FROM_CHARS_FLOATING_POINT _LIBCPP_INTRODUCED_IN_LLVM_20
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 5b3642ff80363..97e853320017d 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -292,6 +292,19 @@ public:
   [[__nodiscard__]] const char* what() const _NOEXCEPT override;
 };
 
+class _LIBCPP_EXPORTED_FROM_ABI __bad_variant_access_with_msg : public bad_variant_access {
+public:
+  _LIBCPP_HIDE_FROM_ABI explicit __bad_variant_access_with_msg(const char* __msg) _NOEXCEPT : __msg_(__msg) {}
+#  if _LIBCPP_AVAILABILITY_HAS_BAD_VARIANT_ACCESS_WITH_MSG_KEY_FUNCTION
+  [[__nodiscard__]] const char* what() const _NOEXCEPT override;
+#  else
+  [[__nodiscard__]] _LIBCPP_HIDE_FROM_ABI_VIRTUAL const char* what() const _NOEXCEPT override { return __msg_; }
+#  endif
+
+private:
+  const char* __msg_;
+};
+
 _LIBCPP_END_EXPLICIT_ABI_ANNOTATIONS
 _LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
@@ -309,11 +322,11 @@ struct __farray {
   _LIBCPP_HIDE_FROM_ABI constexpr const _Tp& operator[](size_t __n) const noexcept { return __buf_[__n]; }
 };
 
-[[noreturn]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_variant_access() {
+[[noreturn]] inline _LIBCPP_HIDE_FROM_ABI void __throw_bad_variant_access(const char* __msg) {
 #    if _LIBCPP_HAS_EXCEPTIONS
-  throw bad_variant_access();
+  throw __bad_variant_access_with_msg(__msg);
 #    else
-  _LIBCPP_VERBOSE_ABORT("bad_variant_access was thrown in -fno-exceptions mode");
+  _LIBCPP_VERBOSE_ABORT("bad_variant_access was thrown in -fno-exceptions mode: %s", __msg);
 #    endif
 }
 
@@ -1332,7 +1345,9 @@ template <size_t _Ip, class _Vp>
 _LIBCPP_HIDE_FROM_ABI constexpr auto&& __generic_get(_Vp&& __v) {
   using __variant_detail::__access::__variant;
   if (!std::__holds_alternative<_Ip>(__v)) {
-    std::__throw_bad_variant_access();
+    if (__v.valueless_by_exception())
+      std::__throw_bad_variant_access("std::get: variant is valueless");
+    std::__throw_bad_variant_access("std::get: wrong alternative for variant");
   }
   return __variant::__get_alt<_Ip>(std::forward<_Vp>(__v)).__value;
 }
@@ -1569,7 +1584,7 @@ template <class... _Vs>
 _LIBCPP_HIDE_FROM_ABI constexpr void __throw_if_valueless(_Vs&&... __vs) {
   const bool __valueless = (... || std::__as_variant(__vs).valueless_by_exception());
   if (__valueless) {
-    std::__throw_bad_variant_access();
+    std::__throw_bad_variant_access("std::visit: variant is valueless");
   }
 }
 
diff --git a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index d1fd0cef6b774..74283373d1b65 100644
--- a/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/arm64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -373,6 +373,7 @@
 {'is_defined': True, 'name': '__ZNKSt16nested_exception14rethrow_nestedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNKSt18bad_variant_access4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNKSt19bad_optional_access4whatEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNKSt20bad_array_new_length4whatEv', 'type': 'I'}
 {'is_defined': True, 'name': '__ZNKSt3__110__time_put8__do_putEPcRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNKSt3__110__time_put8__do_putEPwRS1_PK2tmcc', 'type': 'FUNC'}
@@ -2177,6 +2178,7 @@
 {'is_defined': True, 'name': '__ZTISt16nested_exception', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTISt18bad_variant_access', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTISt19bad_optional_access', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '__ZTISt29__bad_variant_access_with_msg', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTISt20bad_array_new_length', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTISt8bad_cast', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTISt9bad_alloc', 'type': 'I'}
@@ -2391,6 +2393,7 @@
 {'is_defined': True, 'name': '__ZTSSt16nested_exception', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTSSt18bad_variant_access', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTSSt19bad_optional_access', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '__ZTSSt29__bad_variant_access_with_msg', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTSSt20bad_array_new_length', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTSSt8bad_cast', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTSSt9bad_alloc', 'type': 'I'}
@@ -2563,6 +2566,7 @@
 {'is_defined': True, 'name': '__ZTVSt16nested_exception', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTVSt18bad_variant_access', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTVSt19bad_optional_access', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '__ZTVSt29__bad_variant_access_with_msg', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTVSt20bad_array_new_length', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTVSt8bad_cast', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTVSt9bad_alloc', 'type': 'I'}
diff --git a/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
index b0cd73f9a6bfe..291149608c9c7 100644
--- a/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/i686-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -10,6 +10,7 @@
 {'is_defined': True, 'name': '_ZNKSt16nested_exception14rethrow_nestedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt18bad_variant_access4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt19bad_optional_access4whatEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt20bad_array_new_length4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt6__ndk110__time_put8__do_putEPcRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt6__ndk110__time_put8__do_putEPwRS1_PK2tmcc', 'type': 'FUNC'}
@@ -1839,6 +1840,7 @@
 {'is_defined': True, 'name': '_ZTISt16nested_exception', 'size': 8, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt18bad_variant_access', 'size': 12, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt19bad_optional_access', 'size': 12, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTISt29__bad_variant_access_with_msg', 'size': 12, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt20bad_array_new_length', 'size': 12, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt8bad_cast', 'size': 12, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt9bad_alloc', 'size': 12, 'type': 'OBJECT'}
@@ -2074,6 +2076,7 @@
 {'is_defined': True, 'name': '_ZTSSt16nested_exception', 'size': 21, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt18bad_variant_access', 'size': 23, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt19bad_optional_access', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTSSt29__bad_variant_access_with_msg', 'size': 34, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt20bad_array_new_length', 'size': 25, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt8bad_cast', 'size': 12, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt9bad_alloc', 'size': 13, 'type': 'OBJECT'}
@@ -2246,6 +2249,7 @@
 {'is_defined': True, 'name': '_ZTVSt16nested_exception', 'size': 16, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt18bad_variant_access', 'size': 20, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt19bad_optional_access', 'size': 20, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVSt29__bad_variant_access_with_msg', 'size': 20, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt20bad_array_new_length', 'size': 20, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt8bad_cast', 'size': 20, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt9bad_alloc', 'size': 20, 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index 85c5839dd7c8e..da6d608af462c 100644
--- a/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -3,6 +3,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt16nested_exception14rethrow_nestedEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt18bad_variant_access4whatEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt19bad_optional_access4whatEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__110__time_put8__do_putEPcRS1_PK2tmcc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__110__time_put8__do_putEPwRS1_PK2tmcc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__110error_code7messageEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -937,6 +938,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTISt16nested_exception', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTISt18bad_variant_access', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTISt19bad_optional_access', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZTISt29__bad_variant_access_with_msg', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSNSt12experimental15fundamentals_v112bad_any_castE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSNSt12experimental19bad_optional_accessE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSNSt3__110istrstreamE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
@@ -997,6 +999,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSSt16nested_exception', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSSt18bad_variant_access', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSSt19bad_optional_access', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSSt29__bad_variant_access_with_msg', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTTNSt3__110istrstreamE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTTNSt3__110ostrstreamE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTTNSt3__19strstreamE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
@@ -1060,6 +1063,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTVSt16nested_exception', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTVSt18bad_variant_access', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTVSt19bad_optional_access', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZTVSt29__bad_variant_access_with_msg', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZThn8_NSt3__19strstreamD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZThn8_NSt3__19strstreamD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTv0_n12_NSt3__110istrstreamD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
index a4dfab8897962..6ee31613d5320 100644
--- a/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/powerpc64-ibm-aix.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -3,6 +3,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt16nested_exception14rethrow_nestedEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt18bad_variant_access4whatEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt19bad_optional_access4whatEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__110__time_put8__do_putEPcRS1_PK2tmcc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__110__time_put8__do_putEPwRS1_PK2tmcc', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZNKSt3__110error_code7messageEv', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
@@ -937,6 +938,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTISt16nested_exception', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTISt18bad_variant_access', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTISt19bad_optional_access', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZTISt29__bad_variant_access_with_msg', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSNSt12experimental15fundamentals_v112bad_any_castE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSNSt12experimental19bad_optional_accessE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSNSt3__110istrstreamE', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
@@ -997,6 +999,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSSt16nested_exception', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSSt18bad_variant_access', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSSt19bad_optional_access', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZTSSt29__bad_variant_access_with_msg', 'storage_mapping_class': 'RO', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTTNSt3__110istrstreamE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTTNSt3__110ostrstreamE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTTNSt3__19strstreamE', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
@@ -1060,6 +1063,7 @@
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTVSt16nested_exception', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTVSt18bad_variant_access', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTVSt19bad_optional_access', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
+{'import_export': 'EXP', 'is_defined': True, 'name': '_ZTVSt29__bad_variant_access_with_msg', 'storage_mapping_class': 'RW', 'type': 'OBJECT'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZThn16_NSt3__19strstreamD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZThn16_NSt3__19strstreamD1Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
 {'import_export': 'EXP', 'is_defined': True, 'name': '_ZTv0_n24_NSt3__110istrstreamD0Ev', 'storage_mapping_class': 'DS', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
index d14fa14a19bbd..92a37db24ac5f 100644
--- a/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-apple-darwin.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -372,6 +372,7 @@
 {'is_defined': True, 'name': '__ZNKSt16nested_exception14rethrow_nestedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNKSt18bad_variant_access4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNKSt19bad_optional_access4whatEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '__ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNKSt20bad_array_new_length4whatEv', 'type': 'I'}
 {'is_defined': True, 'name': '__ZNKSt3__110__time_put8__do_putEPcRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '__ZNKSt3__110__time_put8__do_putEPwRS1_PK2tmcc', 'type': 'FUNC'}
@@ -2188,6 +2189,7 @@
 {'is_defined': True, 'name': '__ZTISt16nested_exception', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTISt18bad_variant_access', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTISt19bad_optional_access', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '__ZTISt29__bad_variant_access_with_msg', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTISt20bad_array_new_length', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTISt8bad_cast', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTISt9bad_alloc', 'type': 'I'}
@@ -2411,6 +2413,7 @@
 {'is_defined': True, 'name': '__ZTSSt16nested_exception', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTSSt18bad_variant_access', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTSSt19bad_optional_access', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '__ZTSSt29__bad_variant_access_with_msg', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTSSt20bad_array_new_length', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTSSt8bad_cast', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTSSt9bad_alloc', 'type': 'I'}
@@ -2583,6 +2586,7 @@
 {'is_defined': True, 'name': '__ZTVSt16nested_exception', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTVSt18bad_variant_access', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTVSt19bad_optional_access', 'size': 0, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '__ZTVSt29__bad_variant_access_with_msg', 'size': 0, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '__ZTVSt20bad_array_new_length', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTVSt8bad_cast', 'type': 'I'}
 {'is_defined': True, 'name': '__ZTVSt9bad_alloc', 'type': 'I'}
diff --git a/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
index b2ca72e70b08d..7b09d3dd3f75c 100644
--- a/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-linux-android23.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -10,6 +10,7 @@
 {'is_defined': True, 'name': '_ZNKSt16nested_exception14rethrow_nestedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt18bad_variant_access4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt19bad_optional_access4whatEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt20bad_array_new_length4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt6__ndk110__time_put8__do_putEPcRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt6__ndk110__time_put8__do_putEPwRS1_PK2tmcc', 'type': 'FUNC'}
@@ -1837,6 +1838,7 @@
 {'is_defined': True, 'name': '_ZTISt16nested_exception', 'size': 16, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt18bad_variant_access', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt19bad_optional_access', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTISt29__bad_variant_access_with_msg', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt20bad_array_new_length', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt8bad_cast', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt9bad_alloc', 'size': 24, 'type': 'OBJECT'}
@@ -2069,6 +2071,7 @@
 {'is_defined': True, 'name': '_ZTSSt16nested_exception', 'size': 21, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt18bad_variant_access', 'size': 23, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt19bad_optional_access', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTSSt29__bad_variant_access_with_msg', 'size': 34, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt20bad_array_new_length', 'size': 25, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt8bad_cast', 'size': 12, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt9bad_alloc', 'size': 13, 'type': 'OBJECT'}
@@ -2240,6 +2243,7 @@
 {'is_defined': True, 'name': '_ZTVSt16nested_exception', 'size': 32, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt18bad_variant_access', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt19bad_optional_access', 'size': 40, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVSt29__bad_variant_access_with_msg', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt20bad_array_new_length', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt8bad_cast', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt9bad_alloc', 'size': 40, 'type': 'OBJECT'}
diff --git a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
index 85fcda288daa2..725ed669fb561 100644
--- a/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-freebsd.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -67,6 +67,7 @@
 {'is_defined': True, 'name': '_ZNKSt16nested_exception14rethrow_nestedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt18bad_variant_access4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt19bad_optional_access4whatEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt3__110__time_put8__do_putEPcRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt3__110__time_put8__do_putEPwRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt3__110error_code7messageEv', 'type': 'FUNC'}
@@ -1750,6 +1751,7 @@
 {'is_defined': True, 'name': '_ZTISt16nested_exception', 'size': 16, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt18bad_variant_access', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt19bad_optional_access', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTISt29__bad_variant_access_with_msg', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt12experimental15fundamentals_v112bad_any_castE', 'size': 50, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt12experimental19bad_optional_accessE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__110__time_getE', 'size': 21, 'type': 'OBJECT'}
@@ -1883,6 +1885,7 @@
 {'is_defined': True, 'name': '_ZTSSt16nested_exception', 'size': 21, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt18bad_variant_access', 'size': 23, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt19bad_optional_access', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTSSt29__bad_variant_access_with_msg', 'size': 34, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTTNSt3__110istrstreamE', 'size': 32, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTTNSt3__110ostrstreamE', 'size': 32, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTTNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 16, 'type': 'OBJECT'}
@@ -2008,6 +2011,7 @@
 {'is_defined': True, 'name': '_ZTVSt16nested_exception', 'size': 32, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt18bad_variant_access', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt19bad_optional_access', 'size': 40, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVSt29__bad_variant_access_with_msg', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZThn16_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZThn16_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZThn16_NSt3__19strstreamD0Ev', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
index 669930a06a6db..717d4c9bee726 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.exceptions.nonew.abilist
@@ -65,6 +65,7 @@
 {'is_defined': True, 'name': '_ZNKSt16nested_exception14rethrow_nestedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt18bad_variant_access4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt19bad_optional_access4whatEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt3__110__time_put8__do_putEPcRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt3__110__time_put8__do_putEPwRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt3__110error_code7messageEv', 'type': 'FUNC'}
@@ -1749,6 +1750,7 @@
 {'is_defined': True, 'name': '_ZTISt16nested_exception', 'size': 16, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt18bad_variant_access', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt19bad_optional_access', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTISt29__bad_variant_access_with_msg', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt12experimental15fundamentals_v112bad_any_castE', 'size': 50, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt12experimental19bad_optional_accessE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__110__time_getE', 'size': 21, 'type': 'OBJECT'}
@@ -1882,6 +1884,7 @@
 {'is_defined': True, 'name': '_ZTSSt16nested_exception', 'size': 21, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt18bad_variant_access', 'size': 23, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt19bad_optional_access', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTSSt29__bad_variant_access_with_msg', 'size': 34, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTTNSt3__110istrstreamE', 'size': 32, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTTNSt3__110ostrstreamE', 'size': 32, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTTNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 16, 'type': 'OBJECT'}
@@ -2007,6 +2010,7 @@
 {'is_defined': True, 'name': '_ZTVSt16nested_exception', 'size': 32, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt18bad_variant_access', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt19bad_optional_access', 'size': 40, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVSt29__bad_variant_access_with_msg', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZThn16_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZThn16_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZThn16_NSt3__19strstreamD0Ev', 'type': 'FUNC'}
diff --git a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
index 2e897e689db5b..45db143b4cf4a 100644
--- a/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
+++ b/libcxx/lib/abi/x86_64-unknown-linux-gnu.libcxxabi.v1.stable.noexceptions.nonew.abilist
@@ -36,6 +36,7 @@
 {'is_defined': True, 'name': '_ZNKSt16nested_exception14rethrow_nestedEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt18bad_variant_access4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt19bad_optional_access4whatEv', 'type': 'FUNC'}
+{'is_defined': True, 'name': '_ZNKSt29__bad_variant_access_with_msg4whatEv', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt3__110__time_put8__do_putEPcRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt3__110__time_put8__do_putEPwRS1_PK2tmcc', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZNKSt3__110error_code7messageEv', 'type': 'FUNC'}
@@ -1720,6 +1721,7 @@
 {'is_defined': True, 'name': '_ZTISt16nested_exception', 'size': 16, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt18bad_variant_access', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTISt19bad_optional_access', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTISt29__bad_variant_access_with_msg', 'size': 24, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt12experimental15fundamentals_v112bad_any_castE', 'size': 50, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt12experimental19bad_optional_accessE', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSNSt3__110__time_getE', 'size': 21, 'type': 'OBJECT'}
@@ -1853,6 +1855,7 @@
 {'is_defined': True, 'name': '_ZTSSt16nested_exception', 'size': 21, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt18bad_variant_access', 'size': 23, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTSSt19bad_optional_access', 'size': 24, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTSSt29__bad_variant_access_with_msg', 'size': 34, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTTNSt3__110istrstreamE', 'size': 32, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTTNSt3__110ostrstreamE', 'size': 32, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTTNSt3__113basic_istreamIcNS_11char_traitsIcEEEE', 'size': 16, 'type': 'OBJECT'}
@@ -1978,6 +1981,7 @@
 {'is_defined': True, 'name': '_ZTVSt16nested_exception', 'size': 32, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt18bad_variant_access', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZTVSt19bad_optional_access', 'size': 40, 'type': 'OBJECT'}
+{'is_defined': True, 'name': '_ZTVSt29__bad_variant_access_with_msg', 'size': 40, 'type': 'OBJECT'}
 {'is_defined': True, 'name': '_ZThn16_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED0Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZThn16_NSt3__114basic_iostreamIcNS_11char_traitsIcEEED1Ev', 'type': 'FUNC'}
 {'is_defined': True, 'name': '_ZThn16_NSt3__19strstreamD0Ev', 'type': 'FUNC'}
diff --git a/libcxx/src/variant.cpp b/libcxx/src/variant.cpp
index b5462d64fe952..8134b71899322 100644
--- a/libcxx/src/variant.cpp
+++ b/libcxx/src/variant.cpp
@@ -12,4 +12,6 @@ namespace std {
 
 const char* bad_variant_access::what() const noexcept { return "bad_variant_access"; }
 
+const char* __bad_variant_access_with_msg::what() const noexcept { return __msg_; }
+
 } // namespace std
diff --git a/libcxx/test/libcxx/utilities/variant/variant.bad_variant_access/good_what_message.pass.cpp b/libcxx/test/libcxx/utilities/variant/variant.bad_variant_access/good_what_message.pass.cpp
new file mode 100644
index 0000000000000..cbc08cf6c31e5
--- /dev/null
+++ b/libcxx/test/libcxx/utilities/variant/variant.bad_variant_access/good_what_message.pass.cpp
@@ -0,0 +1,90 @@
+//===----------------------------------------------------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+// UNSUPPORTED: c++03, c++11, c++14, no-exceptions
+
+// Verify that std::bad_variant_access::what() returns a message describing the
+// cause of the failure for std::get and std::visit.
+
+#include <cassert>
+#include <cstring>
+#include <variant>
+
+struct ThrowOnMove {
+  ThrowOnMove() = default;
+  ThrowOnMove(ThrowOnMove&&) { throw 0; }
+};
+
+int main(int, char**) {
+  // std::get<I> on the wrong alternative
+  {
+    std::variant<int, long> v(42);
+    try {
+      (void)std::get<1>(v);
+      assert(false);
+    } catch (const std::bad_variant_access& e) {
+      assert(std::strcmp(e.what(), "std::get: wrong alternative for variant") == 0);
+    }
+  }
+  // std::get<T> on the wrong alternative
+  {
+    std::variant<int, long> v(42);
+    try {
+      (void)std::get<long>(v);
+      assert(false);
+    } catch (const std::bad_variant_access& e) {
+      assert(std::strcmp(e.what(), "std::get: wrong alternative for variant") == 0);
+    }
+  }
+  // std::get<I> on a valueless variant
+  {
+    std::variant<int, ThrowOnMove> v(42);
+    try {
+      v.emplace<1>(ThrowOnMove{});
+    } catch (...) {
+    }
+    assert(v.valueless_by_exception());
+    try {
+      (void)std::get<0>(v);
+      assert(false);
+    } catch (const std::bad_variant_access& e) {
+      assert(std::strcmp(e.what(), "std::get: variant is valueless") == 0);
+    }
+  }
+  // std::get<T> on a valueless variant
+  {
+    std::variant<int, ThrowOnMove> v(42);
+    try {
+      v.emplace<1>(ThrowOnMove{});
+    } catch (...) {
+    }
+    assert(v.valueless_by_exception());
+    try {
+      (void)std::get<int>(v);
+      assert(false);
+    } catch (const std::bad_variant_access& e) {
+      assert(std::strcmp(e.what(), "std::get: variant is valueless") == 0);
+    }
+  }
+  // std::visit on a valueless variant
+  {
+    std::variant<int, ThrowOnMove> v(42);
+    try {
+      v.emplace<1>(ThrowOnMove{});
+    } catch (...) {
+    }
+    assert(v.valueless_by_exception());
+    try {
+      std::visit([](auto&&) {}, v);
+      assert(false);
+    } catch (const std::bad_variant_access& e) {
+      assert(std::strcmp(e.what(), "std::visit: variant is valueless") == 0);
+    }
+  }
+  return 0;
+}



More information about the libcxx-commits mailing list