[libcxx-commits] [libcxx] [libc++] Fix the visibility of type traits (PR #111522)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Tue Oct 8 04:25:59 PDT 2024


https://github.com/philnik777 created https://github.com/llvm/llvm-project/pull/111522

The standard requires all type traits variables to have default visibility, since they are implicitly inline and thus have to always have the same address. To observe the bug currently, `-fvisibility=hidden` has to be specified.


>From b92b11f7affcff01131a1a1f4fe2ba23adf0233c Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Thu, 11 Jul 2024 17:39:01 +0200
Subject: [PATCH] [libc++] Fix the visibility of type traits

The standard requires all type traits variables to have default visibility, since they are implicitly inline and thus have to always have the same address. To observe the bug currently, `-fvisibility=hidden` has to be specified.
---
 libcxx/include/__type_traits/alignment_of.h   |   2 +-
 libcxx/include/__type_traits/extent.h         |   2 +-
 .../has_unique_object_representation.h        |   2 +-
 .../__type_traits/has_virtual_destructor.h    |   2 +-
 libcxx/include/__type_traits/invoke.h         |   8 +-
 libcxx/include/__type_traits/is_abstract.h    |   2 +-
 libcxx/include/__type_traits/is_aggregate.h   |   2 +-
 libcxx/include/__type_traits/is_arithmetic.h  |   2 +-
 libcxx/include/__type_traits/is_array.h       |   2 +-
 libcxx/include/__type_traits/is_assignable.h  |   6 +-
 libcxx/include/__type_traits/is_base_of.h     |   4 +-
 .../include/__type_traits/is_bounded_array.h  |   2 +-
 libcxx/include/__type_traits/is_class.h       |   2 +-
 libcxx/include/__type_traits/is_compound.h    |   4 +-
 libcxx/include/__type_traits/is_const.h       |   4 +-
 .../include/__type_traits/is_constructible.h  |   8 +-
 libcxx/include/__type_traits/is_convertible.h |   2 +-
 .../include/__type_traits/is_destructible.h   |   4 +-
 libcxx/include/__type_traits/is_empty.h       |   2 +-
 libcxx/include/__type_traits/is_enum.h        |   4 +-
 libcxx/include/__type_traits/is_final.h       |   2 +-
 .../include/__type_traits/is_floating_point.h |   2 +-
 libcxx/include/__type_traits/is_function.h    |   2 +-
 libcxx/include/__type_traits/is_fundamental.h |   4 +-
 libcxx/include/__type_traits/is_integral.h    |   2 +-
 .../include/__type_traits/is_member_pointer.h |   6 +-
 .../__type_traits/is_nothrow_assignable.h     |   6 +-
 .../__type_traits/is_nothrow_constructible.h  |   8 +-
 .../__type_traits/is_nothrow_convertible.h    |   4 +-
 .../__type_traits/is_nothrow_destructible.h   |   2 +-
 .../include/__type_traits/is_null_pointer.h   |   2 +-
 libcxx/include/__type_traits/is_object.h      |   2 +-
 libcxx/include/__type_traits/is_pointer.h     |   2 +-
 libcxx/include/__type_traits/is_polymorphic.h |   2 +-
 libcxx/include/__type_traits/is_reference.h   |  10 +-
 libcxx/include/__type_traits/is_same.h        |   2 +-
 libcxx/include/__type_traits/is_scalar.h      |   4 +-
 libcxx/include/__type_traits/is_signed.h      |   4 +-
 .../__type_traits/is_standard_layout.h        |   2 +-
 libcxx/include/__type_traits/is_swappable.h   |   8 +-
 libcxx/include/__type_traits/is_trivial.h     |   2 +-
 .../__type_traits/is_trivially_assignable.h   |   6 +-
 .../is_trivially_constructible.h              |   8 +-
 .../__type_traits/is_trivially_copyable.h     |   2 +-
 .../__type_traits/is_trivially_destructible.h |   2 +-
 .../__type_traits/is_unbounded_array.h        |   2 +-
 libcxx/include/__type_traits/is_union.h       |   2 +-
 libcxx/include/__type_traits/is_unsigned.h    |   4 +-
 libcxx/include/__type_traits/is_void.h        |   2 +-
 libcxx/include/__type_traits/is_volatile.h    |   4 +-
 libcxx/include/__type_traits/rank.h           |   2 +-
 .../utilities/meta/meta.rel/visibility.sh.cpp |  72 +++++++
 .../meta/meta.trans/visibility.sh.cpp         |  71 ++++++
 .../meta.unary.prop.query/visibility.sh.cpp   |  52 +++++
 .../meta/meta.unary/visibility.sh.cpp         | 202 ++++++++++++++++++
 55 files changed, 486 insertions(+), 89 deletions(-)
 create mode 100644 libcxx/test/std/utilities/meta/meta.rel/visibility.sh.cpp
 create mode 100644 libcxx/test/std/utilities/meta/meta.trans/visibility.sh.cpp
 create mode 100644 libcxx/test/std/utilities/meta/meta.unary.prop.query/visibility.sh.cpp
 create mode 100644 libcxx/test/std/utilities/meta/meta.unary/visibility.sh.cpp

diff --git a/libcxx/include/__type_traits/alignment_of.h b/libcxx/include/__type_traits/alignment_of.h
index 8871c8ce110d67..1bb12530037651 100644
--- a/libcxx/include/__type_traits/alignment_of.h
+++ b/libcxx/include/__type_traits/alignment_of.h
@@ -24,7 +24,7 @@ struct _LIBCPP_TEMPLATE_VIS alignment_of : public integral_constant<size_t, _LIB
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr size_t alignment_of_v = _LIBCPP_ALIGNOF(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr size_t alignment_of_v = _LIBCPP_ALIGNOF(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/extent.h b/libcxx/include/__type_traits/extent.h
index 1c34a4db1c4b52..a1f4ebc7f068cd 100644
--- a/libcxx/include/__type_traits/extent.h
+++ b/libcxx/include/__type_traits/extent.h
@@ -26,7 +26,7 @@ struct _LIBCPP_TEMPLATE_VIS extent : integral_constant<size_t, __array_extent(_T
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp, unsigned _Ip = 0>
-inline constexpr size_t extent_v = __array_extent(_Tp, _Ip);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr size_t extent_v = __array_extent(_Tp, _Ip);
 #  endif
 
 #else // __has_builtin(__array_extent)
diff --git a/libcxx/include/__type_traits/has_unique_object_representation.h b/libcxx/include/__type_traits/has_unique_object_representation.h
index 98c440c16bf26b..ff474f731e24b3 100644
--- a/libcxx/include/__type_traits/has_unique_object_representation.h
+++ b/libcxx/include/__type_traits/has_unique_object_representation.h
@@ -31,7 +31,7 @@ struct _LIBCPP_TEMPLATE_VIS has_unique_object_representations
     : public integral_constant<bool, __has_unique_object_representations(remove_all_extents_t<_Tp>)> {};
 
 template <class _Tp>
-inline constexpr bool has_unique_object_representations_v = __has_unique_object_representations(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool has_unique_object_representations_v = __has_unique_object_representations(_Tp);
 
 #endif
 
diff --git a/libcxx/include/__type_traits/has_virtual_destructor.h b/libcxx/include/__type_traits/has_virtual_destructor.h
index 4ce96e649e67a1..4c96b6b7a45ac5 100644
--- a/libcxx/include/__type_traits/has_virtual_destructor.h
+++ b/libcxx/include/__type_traits/has_virtual_destructor.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS has_virtual_destructor : public integral_constant<bo
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool has_virtual_destructor_v = __has_virtual_destructor(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool has_virtual_destructor_v = __has_virtual_destructor(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/invoke.h b/libcxx/include/__type_traits/invoke.h
index 71db32ae6a3cef..10725f0f612e46 100644
--- a/libcxx/include/__type_traits/invoke.h
+++ b/libcxx/include/__type_traits/invoke.h
@@ -236,10 +236,10 @@ template <class _Ret, class _Fn, class... _Args>
 struct _LIBCPP_TEMPLATE_VIS is_invocable_r : integral_constant<bool, __invokable_r<_Ret, _Fn, _Args...>::value> {};
 
 template <class _Fn, class... _Args>
-inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value;
 
 template <class _Ret, class _Fn, class... _Args>
-inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_invocable_r_v = is_invocable_r<_Ret, _Fn, _Args...>::value;
 
 // is_nothrow_invocable
 
@@ -252,10 +252,10 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_invocable_r
     : integral_constant<bool, __nothrow_invokable_r<_Ret, _Fn, _Args...>::value> {};
 
 template <class _Fn, class... _Args>
-inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_invocable_v = is_nothrow_invocable<_Fn, _Args...>::value;
 
 template <class _Ret, class _Fn, class... _Args>
-inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_invocable_r_v = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value;
 
 template <class _Fn, class... _Args>
 struct _LIBCPP_TEMPLATE_VIS invoke_result : __invoke_of<_Fn, _Args...> {};
diff --git a/libcxx/include/__type_traits/is_abstract.h b/libcxx/include/__type_traits/is_abstract.h
index 4aa456be1c48e8..f1ec0ffb54410d 100644
--- a/libcxx/include/__type_traits/is_abstract.h
+++ b/libcxx/include/__type_traits/is_abstract.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_abstract : public integral_constant<bool, __is_ab
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_abstract_v = __is_abstract(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_abstract_v = __is_abstract(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_aggregate.h b/libcxx/include/__type_traits/is_aggregate.h
index 4e0988071adeec..4313fbdcd9421b 100644
--- a/libcxx/include/__type_traits/is_aggregate.h
+++ b/libcxx/include/__type_traits/is_aggregate.h
@@ -24,7 +24,7 @@ template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS is_aggregate : public integral_constant<bool, __is_aggregate(_Tp)> {};
 
 template <class _Tp>
-inline constexpr bool is_aggregate_v = __is_aggregate(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_aggregate_v = __is_aggregate(_Tp);
 
 #endif // _LIBCPP_STD_VER >= 17
 
diff --git a/libcxx/include/__type_traits/is_arithmetic.h b/libcxx/include/__type_traits/is_arithmetic.h
index c9713e1840a7b1..952200c2ea5953 100644
--- a/libcxx/include/__type_traits/is_arithmetic.h
+++ b/libcxx/include/__type_traits/is_arithmetic.h
@@ -26,7 +26,7 @@ struct _LIBCPP_TEMPLATE_VIS is_arithmetic
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_array.h b/libcxx/include/__type_traits/is_array.h
index f34204e19ed899..559eeab7d38859 100644
--- a/libcxx/include/__type_traits/is_array.h
+++ b/libcxx/include/__type_traits/is_array.h
@@ -27,7 +27,7 @@ struct _LIBCPP_TEMPLATE_VIS is_array : _BoolConstant<__is_array(_Tp)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_array_v = __is_array(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_array_v = __is_array(_Tp);
 #  endif
 
 #else
diff --git a/libcxx/include/__type_traits/is_assignable.h b/libcxx/include/__type_traits/is_assignable.h
index cfb46997778782..44367bbc2f834e 100644
--- a/libcxx/include/__type_traits/is_assignable.h
+++ b/libcxx/include/__type_traits/is_assignable.h
@@ -25,7 +25,7 @@ struct _LIBCPP_TEMPLATE_VIS is_assignable : _BoolConstant<__is_assignable(_Tp, _
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp, class _Arg>
-inline constexpr bool is_assignable_v = __is_assignable(_Tp, _Arg);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_assignable_v = __is_assignable(_Tp, _Arg);
 #endif
 
 template <class _Tp>
@@ -35,7 +35,7 @@ struct _LIBCPP_TEMPLATE_VIS is_copy_assignable
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value;
 #endif
 
 template <class _Tp>
@@ -44,7 +44,7 @@ struct _LIBCPP_TEMPLATE_VIS is_move_assignable
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_base_of.h b/libcxx/include/__type_traits/is_base_of.h
index 488b63719eb600..fc3ce8afaf8ed4 100644
--- a/libcxx/include/__type_traits/is_base_of.h
+++ b/libcxx/include/__type_traits/is_base_of.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_base_of : public integral_constant<bool, __is_bas
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Bp, class _Dp>
-inline constexpr bool is_base_of_v = __is_base_of(_Bp, _Dp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_base_of_v = __is_base_of(_Bp, _Dp);
 #endif
 
 #if _LIBCPP_STD_VER >= 26
@@ -33,7 +33,7 @@ template <class _Base, class _Derived>
 struct _LIBCPP_TEMPLATE_VIS is_virtual_base_of : public bool_constant<__builtin_is_virtual_base_of(_Base, _Derived)> {};
 
 template <class _Base, class _Derived>
-inline constexpr bool is_virtual_base_of_v = __builtin_is_virtual_base_of(_Base, _Derived);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_virtual_base_of_v = __builtin_is_virtual_base_of(_Base, _Derived);
 
 #  endif
 #endif
diff --git a/libcxx/include/__type_traits/is_bounded_array.h b/libcxx/include/__type_traits/is_bounded_array.h
index a78b52e7062b82..10e72d94bb988d 100644
--- a/libcxx/include/__type_traits/is_bounded_array.h
+++ b/libcxx/include/__type_traits/is_bounded_array.h
@@ -32,7 +32,7 @@ template <class _Tp, size_t _Np>
 struct _LIBCPP_TEMPLATE_VIS is_bounded_array<_Tp[_Np]> : true_type {};
 
 template <class _Tp>
-inline constexpr bool is_bounded_array_v = is_bounded_array<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_bounded_array_v = is_bounded_array<_Tp>::value;
 
 #endif
 
diff --git a/libcxx/include/__type_traits/is_class.h b/libcxx/include/__type_traits/is_class.h
index 034f76a7865e3d..95f839ed1c0efb 100644
--- a/libcxx/include/__type_traits/is_class.h
+++ b/libcxx/include/__type_traits/is_class.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_class : public integral_constant<bool, __is_class
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_class_v = __is_class(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_class_v = __is_class(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_compound.h b/libcxx/include/__type_traits/is_compound.h
index cd208ceab28863..42f38e65e15ea7 100644
--- a/libcxx/include/__type_traits/is_compound.h
+++ b/libcxx/include/__type_traits/is_compound.h
@@ -26,7 +26,7 @@ struct _LIBCPP_TEMPLATE_VIS is_compound : _BoolConstant<__is_compound(_Tp)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_compound_v = __is_compound(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_compound_v = __is_compound(_Tp);
 #  endif
 
 #else // __has_builtin(__is_compound)
@@ -36,7 +36,7 @@ struct _LIBCPP_TEMPLATE_VIS is_compound : public integral_constant<bool, !is_fun
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_compound_v = is_compound<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_compound_v = is_compound<_Tp>::value;
 #  endif
 
 #endif // __has_builtin(__is_compound)
diff --git a/libcxx/include/__type_traits/is_const.h b/libcxx/include/__type_traits/is_const.h
index 47ef70872b790a..38a51866e144f3 100644
--- a/libcxx/include/__type_traits/is_const.h
+++ b/libcxx/include/__type_traits/is_const.h
@@ -25,7 +25,7 @@ struct _LIBCPP_TEMPLATE_VIS is_const : _BoolConstant<__is_const(_Tp)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_const_v = __is_const(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_const_v = __is_const(_Tp);
 #  endif
 
 #else
@@ -37,7 +37,7 @@ struct _LIBCPP_TEMPLATE_VIS is_const<_Tp const> : public true_type {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_const_v = is_const<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_const_v = is_const<_Tp>::value;
 #  endif
 
 #endif // __has_builtin(__is_const)
diff --git a/libcxx/include/__type_traits/is_constructible.h b/libcxx/include/__type_traits/is_constructible.h
index 567bd165c71520..0aa8eff0701324 100644
--- a/libcxx/include/__type_traits/is_constructible.h
+++ b/libcxx/include/__type_traits/is_constructible.h
@@ -25,7 +25,7 @@ struct _LIBCPP_TEMPLATE_VIS is_constructible : public integral_constant<bool, __
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp, class... _Args>
-inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_constructible_v = __is_constructible(_Tp, _Args...);
 #endif
 
 template <class _Tp>
@@ -34,7 +34,7 @@ struct _LIBCPP_TEMPLATE_VIS is_copy_constructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_copy_constructible_v = is_copy_constructible<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_copy_constructible_v = is_copy_constructible<_Tp>::value;
 #endif
 
 template <class _Tp>
@@ -43,7 +43,7 @@ struct _LIBCPP_TEMPLATE_VIS is_move_constructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_move_constructible_v = is_move_constructible<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_move_constructible_v = is_move_constructible<_Tp>::value;
 #endif
 
 template <class _Tp>
@@ -51,7 +51,7 @@ struct _LIBCPP_TEMPLATE_VIS is_default_constructible : public integral_constant<
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_default_constructible_v = __is_constructible(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_default_constructible_v = __is_constructible(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_convertible.h b/libcxx/include/__type_traits/is_convertible.h
index 414c2a6d6a0de0..ed92e5086b620b 100644
--- a/libcxx/include/__type_traits/is_convertible.h
+++ b/libcxx/include/__type_traits/is_convertible.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_convertible : public integral_constant<bool, __is
 
 #if _LIBCPP_STD_VER >= 17
 template <class _From, class _To>
-inline constexpr bool is_convertible_v = __is_convertible(_From, _To);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_convertible_v = __is_convertible(_From, _To);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_destructible.h b/libcxx/include/__type_traits/is_destructible.h
index 3248b07d36ee67..5a716803247d8b 100644
--- a/libcxx/include/__type_traits/is_destructible.h
+++ b/libcxx/include/__type_traits/is_destructible.h
@@ -29,7 +29,7 @@ struct _LIBCPP_TEMPLATE_VIS is_destructible : _BoolConstant<__is_destructible(_T
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_destructible_v = __is_destructible(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_destructible_v = __is_destructible(_Tp);
 #  endif
 
 #else // __has_builtin(__is_destructible)
@@ -87,7 +87,7 @@ struct is_destructible<void> : public false_type {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_destructible_v = is_destructible<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_destructible_v = is_destructible<_Tp>::value;
 #  endif
 
 #endif // __has_builtin(__is_destructible)
diff --git a/libcxx/include/__type_traits/is_empty.h b/libcxx/include/__type_traits/is_empty.h
index 951d93b5a2f10e..4d522b294f7bf9 100644
--- a/libcxx/include/__type_traits/is_empty.h
+++ b/libcxx/include/__type_traits/is_empty.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_empty : public integral_constant<bool, __is_empty
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_empty_v = __is_empty(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_empty_v = __is_empty(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_enum.h b/libcxx/include/__type_traits/is_enum.h
index 2fab6db2c8d50f..b437b602d7c216 100644
--- a/libcxx/include/__type_traits/is_enum.h
+++ b/libcxx/include/__type_traits/is_enum.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_enum : public integral_constant<bool, __is_enum(_
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_enum_v = __is_enum(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_enum_v = __is_enum(_Tp);
 #endif
 
 #if _LIBCPP_STD_VER >= 23
@@ -32,7 +32,7 @@ template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS is_scoped_enum : bool_constant<__is_scoped_enum(_Tp)> {};
 
 template <class _Tp>
-inline constexpr bool is_scoped_enum_v = __is_scoped_enum(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_scoped_enum_v = __is_scoped_enum(_Tp);
 
 #endif // _LIBCPP_STD_VER >= 23
 
diff --git a/libcxx/include/__type_traits/is_final.h b/libcxx/include/__type_traits/is_final.h
index 499c5e3a1edca4..daff36583b804a 100644
--- a/libcxx/include/__type_traits/is_final.h
+++ b/libcxx/include/__type_traits/is_final.h
@@ -28,7 +28,7 @@ struct _LIBCPP_TEMPLATE_VIS is_final : public integral_constant<bool, __is_final
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_final_v = __is_final(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_final_v = __is_final(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_floating_point.h b/libcxx/include/__type_traits/is_floating_point.h
index add34782dfa099..d981e78d59ea07 100644
--- a/libcxx/include/__type_traits/is_floating_point.h
+++ b/libcxx/include/__type_traits/is_floating_point.h
@@ -31,7 +31,7 @@ struct _LIBCPP_TEMPLATE_VIS is_floating_point : public __libcpp_is_floating_poin
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_function.h b/libcxx/include/__type_traits/is_function.h
index 98fedd0ad96d9b..adfa9363e93c43 100644
--- a/libcxx/include/__type_traits/is_function.h
+++ b/libcxx/include/__type_traits/is_function.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_function : integral_constant<bool, __is_function(
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_function_v = __is_function(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_function_v = __is_function(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_fundamental.h b/libcxx/include/__type_traits/is_fundamental.h
index 55f8e41f75f457..8e3c8587cedf26 100644
--- a/libcxx/include/__type_traits/is_fundamental.h
+++ b/libcxx/include/__type_traits/is_fundamental.h
@@ -27,7 +27,7 @@ struct _LIBCPP_TEMPLATE_VIS is_fundamental : _BoolConstant<__is_fundamental(_Tp)
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_fundamental_v = __is_fundamental(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_fundamental_v = __is_fundamental(_Tp);
 #  endif
 
 #else // __has_builtin(__is_fundamental)
@@ -38,7 +38,7 @@ struct _LIBCPP_TEMPLATE_VIS is_fundamental
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value;
 #  endif
 
 #endif // __has_builtin(__is_fundamental)
diff --git a/libcxx/include/__type_traits/is_integral.h b/libcxx/include/__type_traits/is_integral.h
index 26969885af8dfd..bcbf190a04dd1e 100644
--- a/libcxx/include/__type_traits/is_integral.h
+++ b/libcxx/include/__type_traits/is_integral.h
@@ -54,7 +54,7 @@ struct _LIBCPP_TEMPLATE_VIS is_integral : _BoolConstant<__is_integral(_Tp)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_integral_v = __is_integral(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_integral_v = __is_integral(_Tp);
 #  endif
 
 #else
diff --git a/libcxx/include/__type_traits/is_member_pointer.h b/libcxx/include/__type_traits/is_member_pointer.h
index 3e2753ac4228c2..4c6bf7b3c0f56a 100644
--- a/libcxx/include/__type_traits/is_member_pointer.h
+++ b/libcxx/include/__type_traits/is_member_pointer.h
@@ -29,13 +29,13 @@ struct _LIBCPP_TEMPLATE_VIS is_member_function_pointer : _BoolConstant<__is_memb
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_member_pointer_v = __is_member_pointer(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_member_pointer_v = __is_member_pointer(_Tp);
 
 template <class _Tp>
-inline constexpr bool is_member_object_pointer_v = __is_member_object_pointer(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_member_object_pointer_v = __is_member_object_pointer(_Tp);
 
 template <class _Tp>
-inline constexpr bool is_member_function_pointer_v = __is_member_function_pointer(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_member_function_pointer_v = __is_member_function_pointer(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_nothrow_assignable.h b/libcxx/include/__type_traits/is_nothrow_assignable.h
index 7e00c741f83e30..dd185f809f6eb1 100644
--- a/libcxx/include/__type_traits/is_nothrow_assignable.h
+++ b/libcxx/include/__type_traits/is_nothrow_assignable.h
@@ -26,7 +26,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_assignable : public integral_constant<boo
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp, class _Arg>
-inline constexpr bool is_nothrow_assignable_v = __is_nothrow_assignable(_Tp, _Arg);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_assignable_v = __is_nothrow_assignable(_Tp, _Arg);
 #endif
 
 template <class _Tp>
@@ -37,7 +37,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_assignable
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_nothrow_copy_assignable_v = is_nothrow_copy_assignable<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_copy_assignable_v = is_nothrow_copy_assignable<_Tp>::value;
 #endif
 
 template <class _Tp>
@@ -48,7 +48,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_assignable
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_move_assignable_v = is_nothrow_move_assignable<_Tp>::value;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_nothrow_constructible.h b/libcxx/include/__type_traits/is_nothrow_constructible.h
index 58d2b2475140b6..762936b9c17af0 100644
--- a/libcxx/include/__type_traits/is_nothrow_constructible.h
+++ b/libcxx/include/__type_traits/is_nothrow_constructible.h
@@ -26,7 +26,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_constructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp, class... _Args>
-inline constexpr bool is_nothrow_constructible_v = is_nothrow_constructible<_Tp, _Args...>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_constructible_v = is_nothrow_constructible<_Tp, _Args...>::value;
 #endif
 
 template <class _Tp>
@@ -35,7 +35,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_copy_constructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_copy_constructible_v = is_nothrow_copy_constructible<_Tp>::value;
 #endif
 
 template <class _Tp>
@@ -44,7 +44,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_move_constructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_nothrow_move_constructible_v = is_nothrow_move_constructible<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_move_constructible_v = is_nothrow_move_constructible<_Tp>::value;
 #endif
 
 template <class _Tp>
@@ -53,7 +53,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_default_constructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_nothrow_default_constructible_v = __is_nothrow_constructible(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_default_constructible_v = __is_nothrow_constructible(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_nothrow_convertible.h b/libcxx/include/__type_traits/is_nothrow_convertible.h
index bfc5a94cbadec6..970cb6e1f99939 100644
--- a/libcxx/include/__type_traits/is_nothrow_convertible.h
+++ b/libcxx/include/__type_traits/is_nothrow_convertible.h
@@ -32,7 +32,7 @@ template <class _Tp, class _Up>
 struct is_nothrow_convertible : bool_constant<__is_nothrow_convertible(_Tp, _Up)> {};
 
 template <class _Tp, class _Up>
-inline constexpr bool is_nothrow_convertible_v = __is_nothrow_convertible(_Tp, _Up);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_convertible_v = __is_nothrow_convertible(_Tp, _Up);
 
 #  else // __has_builtin(__is_nothrow_convertible)
 
@@ -51,7 +51,7 @@ struct is_nothrow_convertible
           _Lazy<_And, is_convertible<_Fm, _To>, __is_nothrow_convertible_helper<_Fm, _To> > >::type {};
 
 template <typename _Fm, typename _To>
-inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<_Fm, _To>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_convertible_v = is_nothrow_convertible<_Fm, _To>::value;
 
 #  endif // __has_builtin(__is_nothrow_convertible)
 
diff --git a/libcxx/include/__type_traits/is_nothrow_destructible.h b/libcxx/include/__type_traits/is_nothrow_destructible.h
index 41271a38f37116..29898ccee85c9f 100644
--- a/libcxx/include/__type_traits/is_nothrow_destructible.h
+++ b/libcxx/include/__type_traits/is_nothrow_destructible.h
@@ -55,7 +55,7 @@ struct _LIBCPP_TEMPLATE_VIS is_nothrow_destructible<_Tp&&> : public true_type {}
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_destructible_v = is_nothrow_destructible<_Tp>::value;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_null_pointer.h b/libcxx/include/__type_traits/is_null_pointer.h
index abc5d142562f1e..25a2997682c8d1 100644
--- a/libcxx/include/__type_traits/is_null_pointer.h
+++ b/libcxx/include/__type_traits/is_null_pointer.h
@@ -28,7 +28,7 @@ struct _LIBCPP_TEMPLATE_VIS is_null_pointer : integral_constant<bool, __is_null_
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_null_pointer_v = __is_null_pointer_v<_Tp>;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_null_pointer_v = __is_null_pointer_v<_Tp>;
 #  endif
 #endif // _LIBCPP_STD_VER >= 14
 
diff --git a/libcxx/include/__type_traits/is_object.h b/libcxx/include/__type_traits/is_object.h
index ec04508402ce51..300ab9a5cab0ac 100644
--- a/libcxx/include/__type_traits/is_object.h
+++ b/libcxx/include/__type_traits/is_object.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_object : _BoolConstant<__is_object(_Tp)> {};
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_object_v = __is_object(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_object_v = __is_object(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_pointer.h b/libcxx/include/__type_traits/is_pointer.h
index 38eb7996c68642..b59b0ac82cb546 100644
--- a/libcxx/include/__type_traits/is_pointer.h
+++ b/libcxx/include/__type_traits/is_pointer.h
@@ -26,7 +26,7 @@ struct _LIBCPP_TEMPLATE_VIS is_pointer : _BoolConstant<__is_pointer(_Tp)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_pointer_v = __is_pointer(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_pointer_v = __is_pointer(_Tp);
 #  endif
 
 #else // __has_builtin(__is_pointer)
diff --git a/libcxx/include/__type_traits/is_polymorphic.h b/libcxx/include/__type_traits/is_polymorphic.h
index d122e1c87775bd..6bf63b37ed9fb8 100644
--- a/libcxx/include/__type_traits/is_polymorphic.h
+++ b/libcxx/include/__type_traits/is_polymorphic.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_polymorphic : public integral_constant<bool, __is
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_polymorphic_v = __is_polymorphic(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_polymorphic_v = __is_polymorphic(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_reference.h b/libcxx/include/__type_traits/is_reference.h
index cc157a438e4913..70301e61c17db4 100644
--- a/libcxx/include/__type_traits/is_reference.h
+++ b/libcxx/include/__type_traits/is_reference.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_reference : _BoolConstant<__is_reference(_Tp)> {}
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_reference_v = __is_reference(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_reference_v = __is_reference(_Tp);
 #endif
 
 #if __has_builtin(__is_lvalue_reference) && __has_builtin(__is_rvalue_reference)
@@ -36,9 +36,9 @@ struct _LIBCPP_TEMPLATE_VIS is_rvalue_reference : _BoolConstant<__is_rvalue_refe
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_lvalue_reference_v = __is_lvalue_reference(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_lvalue_reference_v = __is_lvalue_reference(_Tp);
 template <class _Tp>
-inline constexpr bool is_rvalue_reference_v = __is_rvalue_reference(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_rvalue_reference_v = __is_rvalue_reference(_Tp);
 #  endif
 
 #else // __has_builtin(__is_lvalue_reference)
@@ -55,10 +55,10 @@ struct _LIBCPP_TEMPLATE_VIS is_rvalue_reference<_Tp&&> : public true_type {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_lvalue_reference_v = is_lvalue_reference<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_lvalue_reference_v = is_lvalue_reference<_Tp>::value;
 
 template <class _Tp>
-inline constexpr bool is_rvalue_reference_v = is_rvalue_reference<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_rvalue_reference_v = is_rvalue_reference<_Tp>::value;
 #  endif
 
 #endif // __has_builtin(__is_lvalue_reference)
diff --git a/libcxx/include/__type_traits/is_same.h b/libcxx/include/__type_traits/is_same.h
index 9561b7b5d6da3c..b623b8fbca40d1 100644
--- a/libcxx/include/__type_traits/is_same.h
+++ b/libcxx/include/__type_traits/is_same.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_same : _BoolConstant<__is_same(_Tp, _Up)> {};
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp, class _Up>
-inline constexpr bool is_same_v = __is_same(_Tp, _Up);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_same_v = __is_same(_Tp, _Up);
 #endif
 
 // _IsSame<T,U> has the same effect as is_same<T,U> but instantiates fewer types:
diff --git a/libcxx/include/__type_traits/is_scalar.h b/libcxx/include/__type_traits/is_scalar.h
index 455200de472089..22769ead3be22f 100644
--- a/libcxx/include/__type_traits/is_scalar.h
+++ b/libcxx/include/__type_traits/is_scalar.h
@@ -30,7 +30,7 @@ struct _LIBCPP_TEMPLATE_VIS is_scalar : _BoolConstant<__is_scalar(_Tp)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_scalar_v = __is_scalar(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_scalar_v = __is_scalar(_Tp);
 #  endif
 
 #else // __has_builtin(__is_scalar)
@@ -59,7 +59,7 @@ struct _LIBCPP_TEMPLATE_VIS is_scalar<nullptr_t> : public true_type {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_scalar_v = is_scalar<_Tp>::value;
 #  endif
 
 #endif // __has_builtin(__is_scalar)
diff --git a/libcxx/include/__type_traits/is_signed.h b/libcxx/include/__type_traits/is_signed.h
index fd6f93e1823627..10253cde6d5ed4 100644
--- a/libcxx/include/__type_traits/is_signed.h
+++ b/libcxx/include/__type_traits/is_signed.h
@@ -27,7 +27,7 @@ struct _LIBCPP_TEMPLATE_VIS is_signed : _BoolConstant<__is_signed(_Tp)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_signed_v = __is_signed(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_signed_v = __is_signed(_Tp);
 #  endif
 
 #else // __has_builtin(__is_signed)
@@ -49,7 +49,7 @@ struct _LIBCPP_TEMPLATE_VIS is_signed : public __libcpp_is_signed<_Tp> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_signed_v = is_signed<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_signed_v = is_signed<_Tp>::value;
 #  endif
 
 #endif // __has_builtin(__is_signed)
diff --git a/libcxx/include/__type_traits/is_standard_layout.h b/libcxx/include/__type_traits/is_standard_layout.h
index 76484f3e2a301f..9b812834505213 100644
--- a/libcxx/include/__type_traits/is_standard_layout.h
+++ b/libcxx/include/__type_traits/is_standard_layout.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_standard_layout : public integral_constant<bool,
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_standard_layout_v = __is_standard_layout(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_standard_layout_v = __is_standard_layout(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_swappable.h b/libcxx/include/__type_traits/is_swappable.h
index 221f017700a2e4..012a2c8c913e44 100644
--- a/libcxx/include/__type_traits/is_swappable.h
+++ b/libcxx/include/__type_traits/is_swappable.h
@@ -73,26 +73,26 @@ inline const bool __is_nothrow_swappable_with_v<_Tp, _Up, true> =
 #if _LIBCPP_STD_VER >= 17
 
 template <class _Tp, class _Up>
-inline constexpr bool is_swappable_with_v = __is_swappable_with_v<_Tp, _Up>;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_swappable_with_v = __is_swappable_with_v<_Tp, _Up>;
 
 template <class _Tp, class _Up>
 struct _LIBCPP_TEMPLATE_VIS is_swappable_with : bool_constant<is_swappable_with_v<_Tp, _Up>> {};
 
 template <class _Tp>
-inline constexpr bool is_swappable_v =
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_swappable_v =
     is_swappable_with_v<__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<_Tp>>;
 
 template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS is_swappable : bool_constant<is_swappable_v<_Tp>> {};
 
 template <class _Tp, class _Up>
-inline constexpr bool is_nothrow_swappable_with_v = __is_nothrow_swappable_with_v<_Tp, _Up>;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_swappable_with_v = __is_nothrow_swappable_with_v<_Tp, _Up>;
 
 template <class _Tp, class _Up>
 struct _LIBCPP_TEMPLATE_VIS is_nothrow_swappable_with : bool_constant<is_nothrow_swappable_with_v<_Tp, _Up>> {};
 
 template <class _Tp>
-inline constexpr bool is_nothrow_swappable_v =
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_nothrow_swappable_v =
     is_nothrow_swappable_with_v<__add_lvalue_reference_t<_Tp>, __add_lvalue_reference_t<_Tp>>;
 
 template <class _Tp>
diff --git a/libcxx/include/__type_traits/is_trivial.h b/libcxx/include/__type_traits/is_trivial.h
index 0007c7446d5e5f..00119585528dad 100644
--- a/libcxx/include/__type_traits/is_trivial.h
+++ b/libcxx/include/__type_traits/is_trivial.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivial : public integral_constant<bool, __is_tri
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_trivial_v = __is_trivial(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_trivial_v = __is_trivial(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_trivially_assignable.h b/libcxx/include/__type_traits/is_trivially_assignable.h
index 201333b0fa0b33..20e4991dee38fd 100644
--- a/libcxx/include/__type_traits/is_trivially_assignable.h
+++ b/libcxx/include/__type_traits/is_trivially_assignable.h
@@ -26,7 +26,7 @@ struct is_trivially_assignable : integral_constant<bool, __is_trivially_assignab
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp, class _Arg>
-inline constexpr bool is_trivially_assignable_v = __is_trivially_assignable(_Tp, _Arg);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_trivially_assignable_v = __is_trivially_assignable(_Tp, _Arg);
 #endif
 
 template <class _Tp>
@@ -37,7 +37,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivially_copy_assignable
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_trivially_copy_assignable_v = is_trivially_copy_assignable<_Tp>::value;
 #endif
 
 template <class _Tp>
@@ -48,7 +48,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivially_move_assignable
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_trivially_move_assignable_v = is_trivially_move_assignable<_Tp>::value;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_trivially_constructible.h b/libcxx/include/__type_traits/is_trivially_constructible.h
index 3a77e9fe164da1..06f8bee52ffb54 100644
--- a/libcxx/include/__type_traits/is_trivially_constructible.h
+++ b/libcxx/include/__type_traits/is_trivially_constructible.h
@@ -26,7 +26,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivially_constructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp, class... _Args>
-inline constexpr bool is_trivially_constructible_v = __is_trivially_constructible(_Tp, _Args...);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_trivially_constructible_v = __is_trivially_constructible(_Tp, _Args...);
 #endif
 
 template <class _Tp>
@@ -35,7 +35,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivially_copy_constructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_trivially_copy_constructible_v = is_trivially_copy_constructible<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_trivially_copy_constructible_v = is_trivially_copy_constructible<_Tp>::value;
 #endif
 
 template <class _Tp>
@@ -44,7 +44,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivially_move_constructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_trivially_move_constructible_v = is_trivially_move_constructible<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_trivially_move_constructible_v = is_trivially_move_constructible<_Tp>::value;
 #endif
 
 template <class _Tp>
@@ -53,7 +53,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivially_default_constructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_trivially_default_constructible_v = __is_trivially_constructible(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_trivially_default_constructible_v = __is_trivially_constructible(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_trivially_copyable.h b/libcxx/include/__type_traits/is_trivially_copyable.h
index e92af126ee94d9..8105df09a258f9 100644
--- a/libcxx/include/__type_traits/is_trivially_copyable.h
+++ b/libcxx/include/__type_traits/is_trivially_copyable.h
@@ -24,7 +24,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivially_copyable : public integral_constant<boo
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_trivially_copyable_v = __is_trivially_copyable(_Tp);
 #endif
 
 #if _LIBCPP_STD_VER >= 20
diff --git a/libcxx/include/__type_traits/is_trivially_destructible.h b/libcxx/include/__type_traits/is_trivially_destructible.h
index 5f9652f2a5011c..915a770b7cfb69 100644
--- a/libcxx/include/__type_traits/is_trivially_destructible.h
+++ b/libcxx/include/__type_traits/is_trivially_destructible.h
@@ -39,7 +39,7 @@ struct _LIBCPP_TEMPLATE_VIS is_trivially_destructible
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_trivially_destructible_v = is_trivially_destructible<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_trivially_destructible_v = is_trivially_destructible<_Tp>::value;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_unbounded_array.h b/libcxx/include/__type_traits/is_unbounded_array.h
index d58bb09e104285..244937c54a5f5c 100644
--- a/libcxx/include/__type_traits/is_unbounded_array.h
+++ b/libcxx/include/__type_traits/is_unbounded_array.h
@@ -31,7 +31,7 @@ template <class _Tp>
 struct _LIBCPP_TEMPLATE_VIS is_unbounded_array<_Tp[]> : true_type {};
 
 template <class _Tp>
-inline constexpr bool is_unbounded_array_v = is_unbounded_array<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_unbounded_array_v = is_unbounded_array<_Tp>::value;
 
 #endif
 
diff --git a/libcxx/include/__type_traits/is_union.h b/libcxx/include/__type_traits/is_union.h
index 1f009d993545ba..6ca9d14b5216f8 100644
--- a/libcxx/include/__type_traits/is_union.h
+++ b/libcxx/include/__type_traits/is_union.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_union : public integral_constant<bool, __is_union
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_union_v = __is_union(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_union_v = __is_union(_Tp);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_unsigned.h b/libcxx/include/__type_traits/is_unsigned.h
index 48c5751ed70d8e..d038508accd1e1 100644
--- a/libcxx/include/__type_traits/is_unsigned.h
+++ b/libcxx/include/__type_traits/is_unsigned.h
@@ -27,7 +27,7 @@ struct _LIBCPP_TEMPLATE_VIS is_unsigned : _BoolConstant<__is_unsigned(_Tp)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_unsigned_v = __is_unsigned(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_unsigned_v = __is_unsigned(_Tp);
 #  endif
 
 #else // __has_builtin(__is_unsigned)
@@ -49,7 +49,7 @@ struct _LIBCPP_TEMPLATE_VIS is_unsigned : public __libcpp_is_unsigned<_Tp> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value;
 #  endif
 
 #endif // __has_builtin(__is_unsigned)
diff --git a/libcxx/include/__type_traits/is_void.h b/libcxx/include/__type_traits/is_void.h
index 562faae9fba2cd..ca350ea75ce6c2 100644
--- a/libcxx/include/__type_traits/is_void.h
+++ b/libcxx/include/__type_traits/is_void.h
@@ -23,7 +23,7 @@ struct _LIBCPP_TEMPLATE_VIS is_void : _BoolConstant<__is_same(__remove_cv(_Tp),
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_void_v = __is_same(__remove_cv(_Tp), void);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_void_v = __is_same(__remove_cv(_Tp), void);
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/include/__type_traits/is_volatile.h b/libcxx/include/__type_traits/is_volatile.h
index 87960a819c8fcb..7a8f39ce73d774 100644
--- a/libcxx/include/__type_traits/is_volatile.h
+++ b/libcxx/include/__type_traits/is_volatile.h
@@ -25,7 +25,7 @@ struct _LIBCPP_TEMPLATE_VIS is_volatile : _BoolConstant<__is_volatile(_Tp)> {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_volatile_v = __is_volatile(_Tp);
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_volatile_v = __is_volatile(_Tp);
 #  endif
 
 #else
@@ -37,7 +37,7 @@ struct _LIBCPP_TEMPLATE_VIS is_volatile<_Tp volatile> : public true_type {};
 
 #  if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr bool is_volatile_v = is_volatile<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr bool is_volatile_v = is_volatile<_Tp>::value;
 #  endif
 
 #endif // __has_builtin(__is_volatile)
diff --git a/libcxx/include/__type_traits/rank.h b/libcxx/include/__type_traits/rank.h
index aeeedec40dee56..4041461f4e0cf4 100644
--- a/libcxx/include/__type_traits/rank.h
+++ b/libcxx/include/__type_traits/rank.h
@@ -38,7 +38,7 @@ struct _LIBCPP_TEMPLATE_VIS rank<_Tp[_Np]> : public integral_constant<size_t, ra
 
 #if _LIBCPP_STD_VER >= 17
 template <class _Tp>
-inline constexpr size_t rank_v = rank<_Tp>::value;
+_LIBCPP_EXPORTED_FROM_ABI inline constexpr size_t rank_v = rank<_Tp>::value;
 #endif
 
 _LIBCPP_END_NAMESPACE_STD
diff --git a/libcxx/test/std/utilities/meta/meta.rel/visibility.sh.cpp b/libcxx/test/std/utilities/meta/meta.rel/visibility.sh.cpp
new file mode 100644
index 00000000000000..d377934586bf6c
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.rel/visibility.sh.cpp
@@ -0,0 +1,72 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++17
+
+// Make sure that the types and variables have the correct visibility attributes
+
+// RUN: %{cxx} %s %{flags} %{compile_flags} %{link_flags} -DSHARED -fPIC -fvisibility=hidden -shared -o %t.shared_lib
+// RUN: %{build} -fvisibility=hidden %t.shared_lib
+// RUN: %{run}
+
+#include <algorithm>
+#include <cassert>
+#include <type_traits>
+#include <vector>
+
+[[gnu::visibility("default")]] extern std::vector<void*> shared_lib_ptrs;
+[[gnu::visibility("default")]] extern std::vector<const std::type_info*> shared_lib_type_infos;
+
+inline std::vector<void*> get_ptrs() {
+  return {
+      (void*)&std::is_same_v<int, int>,
+      (void*)&std::is_base_of_v<int, int>,
+      (void*)&std::is_virtual_base_of_v<int, int>,
+      (void*)&std::is_convertible_v<int, int>,
+      (void*)&std::is_nothrow_convertible_v<int, int>,
+#if 0
+      (void*)&std::is_layout_compatible_v<int, int>,
+      (void*)&std::is_pointer_interconvertible_base_of_v<int, int>,
+#endif
+      (void*)&std::is_invocable_v<int, int>,
+      (void*)&std::is_invocable_r_v<int, int>,
+      (void*)&std::is_nothrow_invocable_v<int, int>,
+      (void*)&std::is_nothrow_invocable_r_v<int, int>,
+  };
+}
+
+inline std::vector<const std::type_info*> get_type_infos() {
+  return {
+      &typeid(std::is_same<int, int>),
+      &typeid(std::is_base_of<int, int>),
+      &typeid(std::is_virtual_base_of<int, int>),
+      &typeid(std::is_convertible<int, int>),
+      &typeid(std::is_nothrow_convertible<int, int>),
+#if 0
+      &typeid(std::is_layout_compatible<int, int>),
+      &typeid(std::is_pointer_interconvertible_base_of<int, int>),
+#endif
+      &typeid(std::is_invocable<int, int>),
+      &typeid(std::is_invocable_r<int, int>),
+      &typeid(std::is_nothrow_invocable<int, int>),
+      &typeid(std::is_nothrow_invocable_r<int, int>),
+  };
+}
+
+#ifdef SHARED
+std::vector<void*> shared_lib_ptrs                       = get_ptrs();
+std::vector<const std::type_info*> shared_lib_type_infos = get_type_infos();
+#else
+int main(int, char**) {
+  assert(get_ptrs() == shared_lib_ptrs);
+  auto deref = [](auto ptr) -> decltype(auto) { return *ptr; };
+  assert(std::ranges::equal(get_type_infos(), shared_lib_type_infos, {}, deref, deref));
+
+  return 0;
+}
+#endif
diff --git a/libcxx/test/std/utilities/meta/meta.trans/visibility.sh.cpp b/libcxx/test/std/utilities/meta/meta.trans/visibility.sh.cpp
new file mode 100644
index 00000000000000..19ce2613c3375d
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.trans/visibility.sh.cpp
@@ -0,0 +1,71 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++17
+
+// Make sure that the types and variables have the correct visibility attributes
+
+// RUN: %{cxx} %s %{flags} %{compile_flags} %{link_flags} -DSHARED -fPIC -fvisibility=hidden -shared -o %t.shared_lib
+// RUN: %{build} -fvisibility=hidden %t.shared_lib
+// RUN: %{run}
+
+#include <algorithm>
+#include <cassert>
+#include <type_traits>
+#include <vector>
+
+[[gnu::visibility("default")]] extern std::vector<const std::type_info*> shared_lib_type_infos;
+
+struct [[gnu::visibility("default")]] S {
+  static constexpr bool value = false;
+};
+
+inline std::vector<const std::type_info*> get_type_infos() {
+  return {
+      &typeid(std::remove_const<int>),
+      &typeid(std::remove_volatile<int>),
+      &typeid(std::remove_cv<int>),
+      &typeid(std::add_const<int>),
+      &typeid(std::add_volatile<int>),
+      &typeid(std::add_cv<int>),
+      &typeid(std::remove_reference<int>),
+      &typeid(std::add_lvalue_reference<int>),
+      &typeid(std::add_rvalue_reference<int>),
+      &typeid(std::make_signed<int>),
+      &typeid(std::make_unsigned<int>),
+      &typeid(std::remove_extent<int>),
+      &typeid(std::remove_all_extents<int>),
+      &typeid(std::remove_pointer<int>),
+      &typeid(std::add_pointer<int>),
+      &typeid(std::type_identity<int>),
+      &typeid(std::remove_cvref<int>),
+      &typeid(std::decay<int>),
+      &typeid(std::enable_if<true>),
+      &typeid(std::conditional<true, int, int>),
+      &typeid(std::common_type<int>),
+      &typeid(std::common_reference<int>),
+      &typeid(std::underlying_type<int>),
+      &typeid(std::invoke_result<int>),
+      &typeid(std::unwrap_reference<int>),
+      &typeid(std::unwrap_ref_decay<int>),
+      &typeid(std::conjunction<S>),
+      &typeid(std::disjunction<S>),
+      &typeid(std::negation<S>),
+  };
+}
+
+#ifdef SHARED
+std::vector<const std::type_info*> shared_lib_type_infos = get_type_infos();
+#else
+int main(int, char**) {
+  auto deref = [](auto ptr) -> decltype(auto) { return *ptr; };
+  assert(std::ranges::equal(get_type_infos(), shared_lib_type_infos, {}, deref, deref));
+
+  return 0;
+}
+#endif
diff --git a/libcxx/test/std/utilities/meta/meta.unary.prop.query/visibility.sh.cpp b/libcxx/test/std/utilities/meta/meta.unary.prop.query/visibility.sh.cpp
new file mode 100644
index 00000000000000..49e6d7def7e5cd
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.unary.prop.query/visibility.sh.cpp
@@ -0,0 +1,52 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++17
+
+// Make sure that the types and variables have the correct visibility attributes
+
+// RUN: %{cxx} %s %{flags} %{compile_flags} %{link_flags} -DSHARED -fPIC -fvisibility=hidden -shared -o %t.shared_lib
+// RUN: %{build} -fvisibility=hidden %t.shared_lib
+// RUN: %{run}
+
+#include <algorithm>
+#include <cassert>
+#include <type_traits>
+#include <vector>
+
+[[gnu::visibility("default")]] extern std::vector<void*> shared_lib_ptrs;
+[[gnu::visibility("default")]] extern std::vector<const std::type_info*> shared_lib_type_infos;
+
+inline std::vector<void*> get_ptrs() {
+  return {
+      (void*)&std::alignment_of_v<int>,
+      (void*)&std::extent_v<int>,
+      (void*)&std::rank_v<int>,
+  };
+}
+
+inline std::vector<const std::type_info*> get_type_infos() {
+  return {
+      &typeid(std::alignment_of<int>),
+      &typeid(std::extent<int>),
+      &typeid(std::rank<int>),
+  };
+}
+
+#ifdef SHARED
+std::vector<void*> shared_lib_ptrs                       = get_ptrs();
+std::vector<const std::type_info*> shared_lib_type_infos = get_type_infos();
+#else
+int main(int, char**) {
+  assert(get_ptrs() == shared_lib_ptrs);
+  auto deref = [](auto ptr) -> decltype(auto) { return *ptr; };
+  assert(std::ranges::equal(get_type_infos(), shared_lib_type_infos, {}, deref, deref));
+
+  return 0;
+}
+#endif
diff --git a/libcxx/test/std/utilities/meta/meta.unary/visibility.sh.cpp b/libcxx/test/std/utilities/meta/meta.unary/visibility.sh.cpp
new file mode 100644
index 00000000000000..dabe3a9a9d15cb
--- /dev/null
+++ b/libcxx/test/std/utilities/meta/meta.unary/visibility.sh.cpp
@@ -0,0 +1,202 @@
+//===----------------------------------------------------------------------===//
+//
+// 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, c++17
+
+// Make sure that the types and variables have the correct visibility attributes
+
+// RUN: %{cxx} %s %{flags} %{compile_flags} %{link_flags} -DSHARED -fPIC -fvisibility=hidden -shared -o %t.shared_lib
+// RUN: %{build} -fvisibility=hidden %t.shared_lib
+// RUN: %{run}
+
+#include <algorithm>
+#include <cassert>
+#include <type_traits>
+#include <vector>
+
+[[gnu::visibility("default")]] extern std::vector<void*> shared_lib_ptrs;
+[[gnu::visibility("default")]] extern std::vector<const std::type_info*> shared_lib_type_infos;
+
+inline std::vector<void*> get_ptrs() {
+  return {
+      // [meta.unary.cat]
+      (void*)&std::is_void_v<int>,
+      (void*)&std::is_null_pointer_v<int>,
+      (void*)&std::is_integral_v<int>,
+      (void*)&std::is_floating_point_v<int>,
+      (void*)&std::is_array_v<int>,
+      (void*)&std::is_pointer_v<int>,
+      (void*)&std::is_lvalue_reference_v<int>,
+      (void*)&std::is_rvalue_reference_v<int>,
+      (void*)&std::is_member_object_pointer_v<int>,
+      (void*)&std::is_member_function_pointer_v<int>,
+      (void*)&std::is_enum_v<int>,
+      (void*)&std::is_union_v<int>,
+      (void*)&std::is_class_v<int>,
+      (void*)&std::is_function_v<int>,
+
+      // [meta.unary.comp]
+      (void*)&std::is_reference_v<int>,
+      (void*)&std::is_arithmetic_v<int>,
+      (void*)&std::is_fundamental_v<int>,
+      (void*)&std::is_object_v<int>,
+      (void*)&std::is_scalar_v<int>,
+      (void*)&std::is_compound_v<int>,
+      (void*)&std::is_member_pointer_v<int>,
+
+      // [meta.unary.prop]
+      (void*)&std::is_const_v<int>,
+      (void*)&std::is_volatile_v<int>,
+      (void*)&std::is_trivial_v<int>,
+      (void*)&std::is_trivially_copyable_v<int>,
+      (void*)&std::is_standard_layout_v<int>,
+      (void*)&std::is_empty_v<int>,
+      (void*)&std::is_polymorphic_v<int>,
+      (void*)&std::is_abstract_v<int>,
+      (void*)&std::is_final_v<int>,
+      (void*)&std::is_aggregate_v<int>,
+      (void*)&std::is_signed_v<int>,
+      (void*)&std::is_unsigned_v<int>,
+      (void*)&std::is_bounded_array_v<int>,
+      (void*)&std::is_unbounded_array_v<int>,
+      (void*)&std::is_scoped_enum_v<int>,
+      (void*)&std::is_constructible_v<int>,
+      (void*)&std::is_default_constructible_v<int>,
+      (void*)&std::is_copy_constructible_v<int>,
+      (void*)&std::is_move_constructible_v<int>,
+      (void*)&std::is_assignable_v<int, int>,
+      (void*)&std::is_copy_assignable_v<int>,
+      (void*)&std::is_move_assignable_v<int>,
+      (void*)&std::is_swappable_with_v<int, int>,
+      (void*)&std::is_swappable_v<int>,
+      (void*)&std::is_destructible_v<int>,
+      (void*)&std::is_trivially_constructible_v<int>,
+      (void*)&std::is_trivially_default_constructible_v<int>,
+      (void*)&std::is_trivially_copy_constructible_v<int>,
+      (void*)&std::is_trivially_move_constructible_v<int>,
+      (void*)&std::is_trivially_assignable_v<int, int>,
+      (void*)&std::is_trivially_copy_assignable_v<int>,
+      (void*)&std::is_trivially_move_assignable_v<int>,
+      (void*)&std::is_trivially_destructible_v<int>,
+      (void*)&std::is_nothrow_constructible_v<int, int>,
+      (void*)&std::is_nothrow_default_constructible_v<int>,
+      (void*)&std::is_nothrow_copy_constructible_v<int>,
+      (void*)&std::is_nothrow_move_constructible_v<int>,
+      (void*)&std::is_nothrow_assignable_v<int, int>,
+      (void*)&std::is_nothrow_copy_assignable_v<int>,
+      (void*)&std::is_nothrow_move_assignable_v<int>,
+      (void*)&std::is_nothrow_swappable_with_v<int, int>,
+      (void*)&std::is_nothrow_swappable_v<int>,
+      (void*)&std::is_nothrow_destructible_v<int>,
+#if 0
+      (void*)&std::is_implicit_lifetime_v<int>,
+#endif
+      (void*)&std::has_virtual_destructor_v<int>,
+      (void*)&std::has_unique_object_representations_v<int>,
+#if 0
+      (void*)&std::reference_constructs_from_temporary_v<int>,
+      (void*)&std::reference_converts_from_temporary_v<int>,
+#endif
+  };
+}
+
+inline std::vector<const std::type_info*> get_type_infos() {
+    return {
+      // [meta.unary.cat]
+      &typeid(std::is_void<int>),
+      &typeid(std::is_null_pointer<int>),
+      &typeid(std::is_integral<int>),
+      &typeid(std::is_floating_point<int>),
+      &typeid(std::is_array<int>),
+      &typeid(std::is_pointer<int>),
+      &typeid(std::is_lvalue_reference<int>),
+      &typeid(std::is_rvalue_reference<int>),
+      &typeid(std::is_member_object_pointer<int>),
+      &typeid(std::is_member_function_pointer<int>),
+      &typeid(std::is_enum<int>),
+      &typeid(std::is_union<int>),
+      &typeid(std::is_class<int>),
+      &typeid(std::is_function<int>),
+
+      // [meta.unary.comp]
+      &typeid(std::is_reference_v<int>),
+      &typeid(std::is_arithmetic_v<int>),
+      &typeid(std::is_fundamental_v<int>),
+      &typeid(std::is_object_v<int>),
+      &typeid(std::is_scalar_v<int>),
+      &typeid(std::is_compound_v<int>),
+      &typeid(std::is_member_pointer_v<int>),
+
+      // [meta.unary.prop]
+      &typeid(std::is_const<int>),
+      &typeid(std::is_volatile<int>),
+      &typeid(std::is_trivial<int>),
+      &typeid(std::is_trivially_copyable<int>),
+      &typeid(std::is_standard_layout<int>),
+      &typeid(std::is_empty<int>),
+      &typeid(std::is_polymorphic<int>),
+      &typeid(std::is_abstract<int>),
+      &typeid(std::is_final<int>),
+      &typeid(std::is_aggregate<int>),
+      &typeid(std::is_signed<int>),
+      &typeid(std::is_unsigned<int>),
+      &typeid(std::is_bounded_array<int>),
+      &typeid(std::is_unbounded_array<int>),
+      &typeid(std::is_scoped_enum<int>),
+      &typeid(std::is_constructible<int>),
+      &typeid(std::is_default_constructible<int>),
+      &typeid(std::is_copy_constructible<int>),
+      &typeid(std::is_move_constructible<int>),
+      &typeid(std::is_assignable<int, int>),
+      &typeid(std::is_copy_assignable<int>),
+      &typeid(std::is_move_assignable<int>),
+      &typeid(std::is_swappable_with<int, int>),
+      &typeid(std::is_swappable<int>),
+      &typeid(std::is_destructible<int>),
+      &typeid(std::is_trivially_constructible<int>),
+      &typeid(std::is_trivially_default_constructible<int>),
+      &typeid(std::is_trivially_copy_constructible<int>),
+      &typeid(std::is_trivially_move_constructible<int>),
+      &typeid(std::is_trivially_assignable<int, int>),
+      &typeid(std::is_trivially_copy_assignable<int>),
+      &typeid(std::is_trivially_move_assignable<int>),
+      &typeid(std::is_trivially_destructible<int>),
+      &typeid(std::is_nothrow_constructible<int, int>),
+      &typeid(std::is_nothrow_default_constructible<int>),
+      &typeid(std::is_nothrow_copy_constructible<int>),
+      &typeid(std::is_nothrow_move_constructible<int>),
+      &typeid(std::is_nothrow_assignable<int, int>),
+      &typeid(std::is_nothrow_copy_assignable<int>),
+      &typeid(std::is_nothrow_move_assignable<int>),
+      &typeid(std::is_nothrow_swappable_with<int, int>),
+      &typeid(std::is_nothrow_swappable<int>),
+      &typeid(std::is_nothrow_destructible<int>),
+#if 0
+      &typeid(std::is_implicit_lifetime<int>),
+#endif
+      &typeid(std::has_virtual_destructor<int>),
+      &typeid(std::has_unique_object_representations<int>),
+#if 0
+      &typeid(std::reference_constructs_from_temporary<int>),
+      &typeid(std::reference_converts_from_temporary<int>),
+#endif
+  };
+}
+
+#ifdef SHARED
+std::vector<void*> shared_lib_ptrs                       = get_ptrs();
+std::vector<const std::type_info*> shared_lib_type_infos = get_type_infos();
+#else
+int main(int, char**) {
+  assert(get_ptrs() == shared_lib_ptrs);
+  auto deref = [](auto ptr) -> decltype(auto) { return *ptr; };
+  assert(std::ranges::equal(get_type_infos(), shared_lib_type_infos, {}, deref, deref));
+
+  return 0;
+}
+#endif



More information about the libcxx-commits mailing list