[libcxx-commits] [libcxx] [libc++] Introduce unversioned namespace macros (PR #133009)

Nikolas Klauser via libcxx-commits libcxx-commits at lists.llvm.org
Thu Mar 27 03:33:34 PDT 2025


https://github.com/philnik777 updated https://github.com/llvm/llvm-project/pull/133009

>From 8ed3fb79cf888b8ac70217a7bf38c09ab29ca973 Mon Sep 17 00:00:00 2001
From: Nikolas Klauser <nikolasklauser at berlin.de>
Date: Tue, 25 Mar 2025 23:02:50 +0100
Subject: [PATCH] [libc++] Introduce unversioned namespace macros

---
 libcxx/include/__config                       | 26 ++++++++++++++-----
 libcxx/include/__cstddef/byte.h               |  4 +--
 libcxx/include/__exception/exception.h        |  4 +--
 libcxx/include/__exception/exception_ptr.h    |  4 +--
 libcxx/include/__exception/nested_exception.h |  4 +--
 libcxx/include/__exception/operations.h       |  4 +--
 libcxx/include/__exception/terminate.h        |  4 +--
 libcxx/include/__fwd/byte.h                   |  4 +--
 libcxx/include/__new/align_val_t.h            |  5 ++--
 libcxx/include/__new/destroying_delete_t.h    |  5 ++--
 libcxx/include/__new/exceptions.h             |  5 ++--
 libcxx/include/__new/new_handler.h            |  5 ++--
 libcxx/include/__new/nothrow_t.h              |  5 ++--
 libcxx/include/any                            |  4 +--
 libcxx/include/typeinfo                       |  4 +--
 libcxx/include/variant                        |  4 +--
 16 files changed, 49 insertions(+), 42 deletions(-)

diff --git a/libcxx/include/__config b/libcxx/include/__config
index c8224b07a6b81..070298301b0d3 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -577,15 +577,27 @@ typedef __char32_t char32_t;
 #    define _LIBCPP_POP_EXTENSION_DIAGNOSTICS
 #  endif
 
-// Inline namespaces are available in Clang/GCC/MSVC regardless of C++ dialect.
 // clang-format off
-#  define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS                                               \
-                                      namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std {                                  \
-                               inline namespace _LIBCPP_ABI_NAMESPACE {
-#  define _LIBCPP_END_NAMESPACE_STD }} _LIBCPP_POP_EXTENSION_DIAGNOSTICS
 
-#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL namespace std { namespace experimental {
-#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL }}
+// The unversioned namespace is used when we want to be ABI compatible with other standard libraries in some way. There
+// are two main categories where that's the case:
+// - Historically, we have made exception types ABI compatible with libstdc++ to allow throwing them between libstdc++
+//   and libc++. This is not used anymore for new exception types, since there is no use-case for it anymore.
+// - Types and functions which are used by the compiler are in the unversioned namespace, since the compiler has to know
+//   their mangling without the appropriate declaration in some cases.
+// If it's not clear whether using the unversioned namespace is the correct thing to do, it's not. The versioned
+// namespace (_LIBCPP_BEGIN_NAMESPACE_STD) should almost always be used.
+#  define _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD                                                                      \
+    _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std {
+
+#  define _LIBCPP_END_UNVERSIONED_NAMESPACE_STD } _LIBCPP_POP_EXTENSION_DIAGNOSTICS
+
+#  define _LIBCPP_BEGIN_NAMESPACE_STD _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD inline namespace _LIBCPP_ABI_NAMESPACE {
+#  define _LIBCPP_END_NAMESPACE_STD } _LIBCPP_END_UNVERSIONED_NAMESPACE_STD
+
+// TODO: This should really be in the versioned namespace
+#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD namespace experimental {
+#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL } _LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 #define _LIBCPP_BEGIN_NAMESPACE_LFTS _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL inline namespace fundamentals_v1 {
 #define _LIBCPP_END_NAMESPACE_LFTS } _LIBCPP_END_NAMESPACE_EXPERIMENTAL
diff --git a/libcxx/include/__cstddef/byte.h b/libcxx/include/__cstddef/byte.h
index 09e1d75e0b41f..3d97db1bea293 100644
--- a/libcxx/include/__cstddef/byte.h
+++ b/libcxx/include/__cstddef/byte.h
@@ -19,7 +19,7 @@
 #endif
 
 #if _LIBCPP_STD_VER >= 17
-namespace std { // purposefully not versioned
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 
 enum class byte : unsigned char {};
 
@@ -79,7 +79,7 @@ template <class _Integer, __enable_if_t<is_integral<_Integer>::value, int> = 0>
   return static_cast<_Integer>(__b);
 }
 
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 #endif // _LIBCPP_STD_VER >= 17
 
 #endif // _LIBCPP___CSTDDEF_BYTE_H
diff --git a/libcxx/include/__exception/exception.h b/libcxx/include/__exception/exception.h
index e724e1b99bd14..f7dab6e83ad14 100644
--- a/libcxx/include/__exception/exception.h
+++ b/libcxx/include/__exception/exception.h
@@ -21,7 +21,7 @@
 #  pragma GCC system_header
 #endif
 
-namespace std { // purposefully not using versioning namespace
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 
 #if defined(_LIBCPP_ABI_VCRUNTIME) && (!defined(_HAS_EXCEPTIONS) || _HAS_EXCEPTIONS != 0)
 // The std::exception class was already included above, but we're explicit about this condition here for clarity.
@@ -89,6 +89,6 @@ class _LIBCPP_EXPORTED_FROM_ABI bad_exception : public exception {
 };
 #endif // !_LIBCPP_ABI_VCRUNTIME
 
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 #endif // _LIBCPP___EXCEPTION_EXCEPTION_H
diff --git a/libcxx/include/__exception/exception_ptr.h b/libcxx/include/__exception/exception_ptr.h
index 6257e6f729bf3..dac5b00b57fe3 100644
--- a/libcxx/include/__exception/exception_ptr.h
+++ b/libcxx/include/__exception/exception_ptr.h
@@ -52,7 +52,7 @@ _LIBCPP_OVERRIDABLE_FUNC_VIS __cxa_exception* __cxa_init_primary_exception(
 
 #endif
 
-namespace std { // purposefully not using versioning namespace
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 
 #ifndef _LIBCPP_ABI_MICROSOFT
 
@@ -171,6 +171,6 @@ _LIBCPP_HIDE_FROM_ABI exception_ptr make_exception_ptr(_Ep __e) _NOEXCEPT {
 }
 
 #endif // _LIBCPP_ABI_MICROSOFT
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 #endif // _LIBCPP___EXCEPTION_EXCEPTION_PTR_H
diff --git a/libcxx/include/__exception/nested_exception.h b/libcxx/include/__exception/nested_exception.h
index d560b6bbc35a7..90b14158d57a2 100644
--- a/libcxx/include/__exception/nested_exception.h
+++ b/libcxx/include/__exception/nested_exception.h
@@ -27,7 +27,7 @@
 #  pragma GCC system_header
 #endif
 
-namespace std { // purposefully not using versioning namespace
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 
 class _LIBCPP_EXPORTED_FROM_ABI nested_exception {
   exception_ptr __ptr_;
@@ -95,6 +95,6 @@ inline _LIBCPP_HIDE_FROM_ABI void rethrow_if_nested(const _Ep& __e) {
 template <class _Ep, __enable_if_t<!__can_dynamic_cast<_Ep, nested_exception>::value, int> = 0>
 inline _LIBCPP_HIDE_FROM_ABI void rethrow_if_nested(const _Ep&) {}
 
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 #endif // _LIBCPP___EXCEPTION_NESTED_EXCEPTION_H
diff --git a/libcxx/include/__exception/operations.h b/libcxx/include/__exception/operations.h
index 15520c558a0b4..29d5c698a96db 100644
--- a/libcxx/include/__exception/operations.h
+++ b/libcxx/include/__exception/operations.h
@@ -15,7 +15,7 @@
 #  pragma GCC system_header
 #endif
 
-namespace std { // purposefully not using versioning namespace
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 #if _LIBCPP_STD_VER <= 14 || defined(_LIBCPP_ENABLE_CXX17_REMOVED_UNEXPECTED_FUNCTIONS) ||                             \
     defined(_LIBCPP_BUILDING_LIBRARY)
 using unexpected_handler = void (*)();
@@ -37,6 +37,6 @@ class _LIBCPP_EXPORTED_FROM_ABI exception_ptr;
 
 _LIBCPP_EXPORTED_FROM_ABI exception_ptr current_exception() _NOEXCEPT;
 [[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void rethrow_exception(exception_ptr);
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 #endif // _LIBCPP___EXCEPTION_OPERATIONS_H
diff --git a/libcxx/include/__exception/terminate.h b/libcxx/include/__exception/terminate.h
index 0bfc3506d3791..955a49c2b00c3 100644
--- a/libcxx/include/__exception/terminate.h
+++ b/libcxx/include/__exception/terminate.h
@@ -15,8 +15,8 @@
 #  pragma GCC system_header
 #endif
 
-namespace std { // purposefully not using versioning namespace
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 [[__noreturn__]] _LIBCPP_EXPORTED_FROM_ABI void terminate() _NOEXCEPT;
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 #endif // _LIBCPP___EXCEPTION_TERMINATE_H
diff --git a/libcxx/include/__fwd/byte.h b/libcxx/include/__fwd/byte.h
index 0301833d93cf2..6f2d6ae254a24 100644
--- a/libcxx/include/__fwd/byte.h
+++ b/libcxx/include/__fwd/byte.h
@@ -16,11 +16,11 @@
 #endif
 
 #if _LIBCPP_STD_VER >= 17
-namespace std { // purposefully not versioned
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 
 enum class byte : unsigned char;
 
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 #endif // _LIBCPP_STD_VER >= 17
 
 #endif // _LIBCPP___FWD_BYTE_H
diff --git a/libcxx/include/__new/align_val_t.h b/libcxx/include/__new/align_val_t.h
index ffb4e36a8bcd8..03ab7cb143a2b 100644
--- a/libcxx/include/__new/align_val_t.h
+++ b/libcxx/include/__new/align_val_t.h
@@ -16,8 +16,7 @@
 #  pragma GCC system_header
 #endif
 
-// purposefully not using versioning namespace
-namespace std {
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 #if _LIBCPP_HAS_LIBRARY_ALIGNED_ALLOCATION && !defined(_LIBCPP_ABI_VCRUNTIME)
 #  ifndef _LIBCPP_CXX03_LANG
 enum class align_val_t : size_t {};
@@ -25,6 +24,6 @@ enum class align_val_t : size_t {};
 enum align_val_t { __zero = 0, __max = (size_t)-1 };
 #  endif
 #endif
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 #endif // _LIBCPP___NEW_ALIGN_VAL_T_H
diff --git a/libcxx/include/__new/destroying_delete_t.h b/libcxx/include/__new/destroying_delete_t.h
index 7fca4f6c68b21..1d06d912b44e5 100644
--- a/libcxx/include/__new/destroying_delete_t.h
+++ b/libcxx/include/__new/destroying_delete_t.h
@@ -16,15 +16,14 @@
 #endif
 
 #if _LIBCPP_STD_VER >= 20
-// purposefully not using versioning namespace
-namespace std {
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 // Enable the declaration even if the compiler doesn't support the language
 // feature.
 struct destroying_delete_t {
   explicit destroying_delete_t() = default;
 };
 inline constexpr destroying_delete_t destroying_delete{};
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 #endif
 
 #endif // _LIBCPP___NEW_DESTROYING_DELETE_T_H
diff --git a/libcxx/include/__new/exceptions.h b/libcxx/include/__new/exceptions.h
index 053feecb03678..86951818b7aa2 100644
--- a/libcxx/include/__new/exceptions.h
+++ b/libcxx/include/__new/exceptions.h
@@ -17,8 +17,7 @@
 #  pragma GCC system_header
 #endif
 
-// purposefully not using versioning namespace
-namespace std {
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 #if !defined(_LIBCPP_ABI_VCRUNTIME)
 
 class _LIBCPP_EXPORTED_FROM_ABI bad_alloc : public exception {
@@ -69,6 +68,6 @@ class bad_array_new_length : public bad_alloc {
   _LIBCPP_VERBOSE_ABORT("bad_array_new_length was thrown in -fno-exceptions mode");
 #endif
 }
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 #endif // _LIBCPP___NEW_EXCEPTIONS_H
diff --git a/libcxx/include/__new/new_handler.h b/libcxx/include/__new/new_handler.h
index c9afdab45afc1..05f4e846c3ef9 100644
--- a/libcxx/include/__new/new_handler.h
+++ b/libcxx/include/__new/new_handler.h
@@ -18,12 +18,11 @@
 #if defined(_LIBCPP_ABI_VCRUNTIME)
 #  include <new.h>
 #else
-// purposefully not using versioning namespace
-namespace std {
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 typedef void (*new_handler)();
 _LIBCPP_EXPORTED_FROM_ABI new_handler set_new_handler(new_handler) _NOEXCEPT;
 _LIBCPP_EXPORTED_FROM_ABI new_handler get_new_handler() _NOEXCEPT;
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 #endif // _LIBCPP_ABI_VCRUNTIME
 
 #endif // _LIBCPP___NEW_NEW_HANDLER_H
diff --git a/libcxx/include/__new/nothrow_t.h b/libcxx/include/__new/nothrow_t.h
index 09c2d03f66ccc..a286bf7af628f 100644
--- a/libcxx/include/__new/nothrow_t.h
+++ b/libcxx/include/__new/nothrow_t.h
@@ -18,13 +18,12 @@
 #if defined(_LIBCPP_ABI_VCRUNTIME)
 #  include <new.h>
 #else
-// purposefully not using versioning namespace
-namespace std {
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 struct _LIBCPP_EXPORTED_FROM_ABI nothrow_t {
   explicit nothrow_t() = default;
 };
 extern _LIBCPP_EXPORTED_FROM_ABI const nothrow_t nothrow;
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 #endif // _LIBCPP_ABI_VCRUNTIME
 
 #endif // _LIBCPP___NEW_NOTHROW_T_H
diff --git a/libcxx/include/any b/libcxx/include/any
index b1df494d3db83..c7d85ba71ac69 100644
--- a/libcxx/include/any
+++ b/libcxx/include/any
@@ -119,12 +119,12 @@ namespace std {
 _LIBCPP_PUSH_MACROS
 #  include <__undef_macros>
 
-namespace std {
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_ANY_CAST bad_any_cast : public bad_cast {
 public:
   const char* what() const _NOEXCEPT override;
 };
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
diff --git a/libcxx/include/typeinfo b/libcxx/include/typeinfo
index 799c6ebd5ecbb..24aaabf0a87df 100644
--- a/libcxx/include/typeinfo
+++ b/libcxx/include/typeinfo
@@ -354,7 +354,7 @@ public:
 
 #  if defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0
 
-namespace std {
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 
 class bad_cast : public exception {
 public:
@@ -372,7 +372,7 @@ private:
   bad_typeid(const char* const __message) _NOEXCEPT : exception(__message) {}
 };
 
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 #  endif // defined(_LIBCPP_ABI_VCRUNTIME) && _HAS_EXCEPTIONS == 0
 
diff --git a/libcxx/include/variant b/libcxx/include/variant
index 38c34725d5e03..1c3d1cdc5638e 100644
--- a/libcxx/include/variant
+++ b/libcxx/include/variant
@@ -283,14 +283,14 @@ namespace std {
 _LIBCPP_PUSH_MACROS
 #  include <__undef_macros>
 
-namespace std { // explicitly not using versioning namespace
+_LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD
 
 class _LIBCPP_EXPORTED_FROM_ABI _LIBCPP_AVAILABILITY_BAD_VARIANT_ACCESS bad_variant_access : public exception {
 public:
   const char* what() const _NOEXCEPT override;
 };
 
-} // namespace std
+_LIBCPP_END_UNVERSIONED_NAMESPACE_STD
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 



More information about the libcxx-commits mailing list