Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libc++] Introduce unversioned namespace macros #133009

Merged
merged 1 commit into from
Mar 27, 2025

Conversation

philnik777
Copy link
Contributor

We've started using _LIBCPP_BEGIN_NAMESPACE_STD and _LIBCPP_END_NAMESPACE_STD for more than just the namespace for a while now. For example, we're using it to add visibility annotations to types. This works very well and avoids a bunch of annotations, but doesn't work for the few places where we have an unversioned namespace. This adds _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD and _LIBCPP_END_UNVERSIONED_NAMESPACE_STD to make it simpler to add new annotations consistently across the library as well as making it more explicit that the unversioned namespace is indeed intended.

@philnik777 philnik777 marked this pull request as ready for review March 26, 2025 14:24
@philnik777 philnik777 requested a review from a team as a code owner March 26, 2025 14:24
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Mar 26, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 26, 2025

@llvm/pr-subscribers-libcxx

Author: Nikolas Klauser (philnik777)

Changes

We've started using _LIBCPP_BEGIN_NAMESPACE_STD and _LIBCPP_END_NAMESPACE_STD for more than just the namespace for a while now. For example, we're using it to add visibility annotations to types. This works very well and avoids a bunch of annotations, but doesn't work for the few places where we have an unversioned namespace. This adds _LIBCPP_BEGIN_UNVERSIONED_NAMESPACE_STD and _LIBCPP_END_UNVERSIONED_NAMESPACE_STD to make it simpler to add new annotations consistently across the library as well as making it more explicit that the unversioned namespace is indeed intended.


Full diff: https://github.com/llvm/llvm-project/pull/133009.diff

16 Files Affected:

  • (modified) libcxx/include/__config (+9-7)
  • (modified) libcxx/include/__cstddef/byte.h (+2-2)
  • (modified) libcxx/include/__exception/exception.h (+2-2)
  • (modified) libcxx/include/__exception/exception_ptr.h (+2-2)
  • (modified) libcxx/include/__exception/nested_exception.h (+2-2)
  • (modified) libcxx/include/__exception/operations.h (+2-2)
  • (modified) libcxx/include/__exception/terminate.h (+2-2)
  • (modified) libcxx/include/__fwd/byte.h (+2-2)
  • (modified) libcxx/include/__new/align_val_t.h (+2-3)
  • (modified) libcxx/include/__new/destroying_delete_t.h (+2-3)
  • (modified) libcxx/include/__new/exceptions.h (+2-3)
  • (modified) libcxx/include/__new/new_handler.h (+2-3)
  • (modified) libcxx/include/__new/nothrow_t.h (+2-3)
  • (modified) libcxx/include/any (+2-2)
  • (modified) libcxx/include/typeinfo (+2-2)
  • (modified) libcxx/include/variant (+2-2)
diff --git a/libcxx/include/__config b/libcxx/include/__config
index c8224b07a6b81..e75f42d928bc3 100644
--- a/libcxx/include/__config
+++ b/libcxx/include/__config
@@ -577,15 +577,17 @@ 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_UNVERSIONED_NAMESPACE_STD                                                                      \
+    _LIBCPP_PUSH_EXTENSION_DIAGNOSTICS namespace _LIBCPP_TYPE_VISIBILITY_DEFAULT std {
 
-#define _LIBCPP_BEGIN_NAMESPACE_EXPERIMENTAL namespace std { namespace experimental {
-#define _LIBCPP_END_NAMESPACE_EXPERIMENTAL }}
+#  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
+
+#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
 

Copy link
Member

@ldionne ldionne left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM with minor comments. I think it's especially nice to make our intent explicit when we use an unversionned namespace.

@philnik777 philnik777 force-pushed the users/philnik777/unversioned_std_namespace branch from a0206b1 to 8ed3fb7 Compare March 27, 2025 10:33
@philnik777 philnik777 merged commit 8abca17 into main Mar 27, 2025
12 of 18 checks passed
@philnik777 philnik777 deleted the users/philnik777/unversioned_std_namespace branch March 27, 2025 10:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants