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++] Handle _LIBCPP_HAS_NO_{THREADS,LOCALIZATION} consistently with other carve-outs #98319

Merged
merged 2 commits into from
Jul 15, 2024

Conversation

ldionne
Copy link
Member

@ldionne ldionne commented Jul 10, 2024

Previously, we would issue an #error when using a header that requires threading support or localization support in a configuration where that is disabled. This is unlike what we do for all the other carve outs like no-filesystem, no-wide-characters or no-random-device. Instead of issuing an #error, we normally just remove the problematic parts of the header.

This patch makes the handling of no-localization and no-threads consistent with the other carve-outs. I dislike the fact that users won't get an explicit error message when trying to use e.g. ios in a build that doesn't support localization, but I think it is better to handle things consistently. Note that besides the consistency argument, the #error approach doesn't really work anyways since it would break down if we moved towards assuming the C locale only in the no-localization mode.

…th other carve-outs

Previously, we would issue an #error when using a header that requires
threading support or localization support in a configuration where that
is disabled. This is unlike what we do for all the other carve outs
like no-filesystem, no-wide-characters or no-random-device. Instead of
issuing an #error, we normally just remove the problematic parts of the
header.

This patch makes the handling of no-localization and no-threads consistent
with the other carve-outs. I dislike the fact that users won't get an
explicit error message when trying to use e.g. ios in a build that doesn't
support localization, but I think it is better to handle things consistently.
Note that besides the consistency argument, the #error approach doesn't
really work anyways since it would break down if we moved towards assuming
the C locale only in the no-localization mode.
@ldionne ldionne requested a review from a team as a code owner July 10, 2024 13:52
@llvmbot llvmbot added the libc++ libc++ C++ Standard Library. Not GNU libstdc++. Not libc++abi. label Jul 10, 2024
@llvmbot
Copy link
Collaborator

llvmbot commented Jul 10, 2024

@llvm/pr-subscribers-libcxx

Author: Louis Dionne (ldionne)

Changes

Previously, we would issue an #error when using a header that requires threading support or localization support in a configuration where that is disabled. This is unlike what we do for all the other carve outs like no-filesystem, no-wide-characters or no-random-device. Instead of issuing an #error, we normally just remove the problematic parts of the header.

This patch makes the handling of no-localization and no-threads consistent with the other carve-outs. I dislike the fact that users won't get an explicit error message when trying to use e.g. ios in a build that doesn't support localization, but I think it is better to handle things consistently. Note that besides the consistency argument, the #error approach doesn't really work anyways since it would break down if we moved towards assuming the C locale only in the no-localization mode.


Patch is 53.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/98319.diff

10 Files Affected:

  • (modified) libcxx/include/barrier (+26-26)
  • (modified) libcxx/include/future (+86-86)
  • (modified) libcxx/include/ios (+39-39)
  • (modified) libcxx/include/latch (+16-16)
  • (modified) libcxx/include/locale (+144-138)
  • (modified) libcxx/include/locale.h (-4)
  • (modified) libcxx/include/semaphore (+23-23)
  • (modified) libcxx/include/shared_mutex (+24-24)
  • (modified) libcxx/include/stop_token (+10-10)
  • (modified) libcxx/include/thread (+13-13)
diff --git a/libcxx/include/barrier b/libcxx/include/barrier
index 12608e17d8f6d..edee181273e24 100644
--- a/libcxx/include/barrier
+++ b/libcxx/include/barrier
@@ -47,30 +47,28 @@ namespace std
 
 #include <__config>
 
-#ifdef _LIBCPP_HAS_NO_THREADS
-#  error "<barrier> is not supported since libc++ has been configured without support for threads."
-#endif
-
-#include <__assert>
-#include <__atomic/atomic_base.h>
-#include <__atomic/memory_order.h>
-#include <__memory/unique_ptr.h>
-#include <__thread/poll_with_backoff.h>
-#include <__thread/timed_backoff_policy.h>
-#include <__utility/move.h>
-#include <cstddef>
-#include <cstdint>
-#include <limits>
-#include <version>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+
+#  include <__assert>
+#  include <__atomic/atomic_base.h>
+#  include <__atomic/memory_order.h>
+#  include <__memory/unique_ptr.h>
+#  include <__thread/poll_with_backoff.h>
+#  include <__thread/timed_backoff_policy.h>
+#  include <__utility/move.h>
+#  include <cstddef>
+#  include <cstdint>
+#  include <limits>
+#  include <version>
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
 
 _LIBCPP_PUSH_MACROS
-#include <__undef_macros>
+#  include <__undef_macros>
 
-#if _LIBCPP_STD_VER >= 14
+#  if _LIBCPP_STD_VER >= 14
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
@@ -78,7 +76,7 @@ struct __empty_completion {
   inline _LIBCPP_HIDE_FROM_ABI void operator()() noexcept {}
 };
 
-#  ifndef _LIBCPP_HAS_NO_TREE_BARRIER
+#    ifndef _LIBCPP_HAS_NO_TREE_BARRIER
 
 /*
 
@@ -152,7 +150,7 @@ public:
   }
 };
 
-#  else
+#    else
 
 /*
 
@@ -253,7 +251,7 @@ public:
   }
 };
 
-#  endif // !_LIBCPP_HAS_NO_TREE_BARRIER
+#    endif // !_LIBCPP_HAS_NO_TREE_BARRIER
 
 template <class _CompletionF = __empty_completion>
 class _LIBCPP_DEPRECATED_ATOMIC_SYNC barrier {
@@ -265,7 +263,7 @@ public:
   static _LIBCPP_HIDE_FROM_ABI constexpr ptrdiff_t max() noexcept { return __barrier_base<_CompletionF>::max(); }
 
   _LIBCPP_AVAILABILITY_SYNC
-      _LIBCPP_HIDE_FROM_ABI explicit barrier(ptrdiff_t __count, _CompletionF __completion = _CompletionF())
+  _LIBCPP_HIDE_FROM_ABI explicit barrier(ptrdiff_t __count, _CompletionF __completion = _CompletionF())
       : __b_(__count, std::move(__completion)) {
     _LIBCPP_ASSERT_ARGUMENT_WITHIN_DOMAIN(
         __count >= 0,
@@ -292,10 +290,12 @@ public:
 
 _LIBCPP_END_NAMESPACE_STD
 
-#endif // _LIBCPP_STD_VER >= 14
+#  endif // _LIBCPP_STD_VER >= 14
 
 _LIBCPP_POP_MACROS
 
+#endif // !defined(_LIBCPP_HAS_NO_THREADS)
+
 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
 #  include <atomic>
 #  include <concepts>
diff --git a/libcxx/include/future b/libcxx/include/future
index dea73dc6389bc..0be32620139e3 100644
--- a/libcxx/include/future
+++ b/libcxx/include/future
@@ -364,44 +364,42 @@ template <class R, class Alloc> struct uses_allocator<packaged_task<R>, Alloc>;
 
 #include <__config>
 
-#ifdef _LIBCPP_HAS_NO_THREADS
-#  error "<future> is not supported since libc++ has been configured without support for threads."
-#endif
-
-#include <__assert>
-#include <__chrono/duration.h>
-#include <__chrono/time_point.h>
-#include <__exception/exception_ptr.h>
-#include <__memory/addressof.h>
-#include <__memory/allocator.h>
-#include <__memory/allocator_arg_t.h>
-#include <__memory/allocator_destructor.h>
-#include <__memory/allocator_traits.h>
-#include <__memory/compressed_pair.h>
-#include <__memory/pointer_traits.h>
-#include <__memory/shared_ptr.h>
-#include <__memory/unique_ptr.h>
-#include <__memory/uses_allocator.h>
-#include <__system_error/error_category.h>
-#include <__system_error/error_code.h>
-#include <__system_error/error_condition.h>
-#include <__type_traits/aligned_storage.h>
-#include <__type_traits/strip_signature.h>
-#include <__utility/auto_cast.h>
-#include <__utility/forward.h>
-#include <__utility/move.h>
-#include <mutex>
-#include <new>
-#include <stdexcept>
-#include <thread>
-#include <version>
-
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
+#if !defined(_LIBCPP_HAS_NO_THREADS)
+
+#  include <__assert>
+#  include <__chrono/duration.h>
+#  include <__chrono/time_point.h>
+#  include <__exception/exception_ptr.h>
+#  include <__memory/addressof.h>
+#  include <__memory/allocator.h>
+#  include <__memory/allocator_arg_t.h>
+#  include <__memory/allocator_destructor.h>
+#  include <__memory/allocator_traits.h>
+#  include <__memory/compressed_pair.h>
+#  include <__memory/pointer_traits.h>
+#  include <__memory/shared_ptr.h>
+#  include <__memory/unique_ptr.h>
+#  include <__memory/uses_allocator.h>
+#  include <__system_error/error_category.h>
+#  include <__system_error/error_code.h>
+#  include <__system_error/error_condition.h>
+#  include <__type_traits/aligned_storage.h>
+#  include <__type_traits/strip_signature.h>
+#  include <__utility/auto_cast.h>
+#  include <__utility/forward.h>
+#  include <__utility/move.h>
+#  include <mutex>
+#  include <new>
+#  include <stdexcept>
+#  include <thread>
+#  include <version>
+
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
 
 _LIBCPP_PUSH_MACROS
-#include <__undef_macros>
+#  include <__undef_macros>
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
@@ -413,16 +411,16 @@ _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(future_errc)
 template <>
 struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<future_errc> : public true_type {};
 
-#ifdef _LIBCPP_CXX03_LANG
+#  ifdef _LIBCPP_CXX03_LANG
 template <>
 struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<future_errc::__lx> : public true_type {};
-#endif
+#  endif
 
 // enum class launch
 _LIBCPP_DECLARE_STRONG_ENUM(launch){async = 1, deferred = 2, any = async | deferred};
 _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(launch)
 
-#ifndef _LIBCPP_CXX03_LANG
+#  ifndef _LIBCPP_CXX03_LANG
 
 typedef underlying_type<launch>::type __launch_underlying_type;
 
@@ -457,7 +455,7 @@ inline _LIBCPP_HIDE_FROM_ABI launch& operator^=(launch& __x, launch __y) {
   return __x;
 }
 
-#endif // !_LIBCPP_CXX03_LANG
+#  endif // !_LIBCPP_CXX03_LANG
 
 // enum class future_status
 _LIBCPP_DECLARE_STRONG_ENUM(future_status){ready, timeout, deferred};
@@ -484,9 +482,9 @@ class _LIBCPP_EXPORTED_FROM_ABI future_error : public logic_error {
   friend class promise;
 
 public:
-#if _LIBCPP_STD_VER >= 17
+#  if _LIBCPP_STD_VER >= 17
   _LIBCPP_HIDE_FROM_ABI explicit future_error(future_errc __ec) : future_error(std::make_error_code(__ec)) {}
-#endif
+#  endif
 
   _LIBCPP_HIDE_FROM_ABI const error_code& code() const _NOEXCEPT { return __ec_; }
 
@@ -496,12 +494,12 @@ public:
 
 // Declared above std::future_error
 void __throw_future_error(future_errc __ev) {
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   throw future_error(make_error_code(__ev));
-#else
+#  else
   (void)__ev;
   _LIBCPP_VERBOSE_ABORT("future_error was thrown in -fno-exceptions mode");
-#endif
+#  endif
 }
 
 class _LIBCPP_EXPORTED_FROM_ABI __assoc_sub_state : public __shared_count {
@@ -775,15 +773,15 @@ inline __deferred_assoc_state<_Rp, _Fp>::__deferred_assoc_state(_Fp&& __f) : __f
 
 template <class _Rp, class _Fp>
 void __deferred_assoc_state<_Rp, _Fp>::__execute() {
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   try {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
     this->set_value(__func_());
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   } catch (...) {
     this->set_exception(current_exception());
   }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
 }
 
 template <class _Fp>
@@ -805,16 +803,16 @@ inline __deferred_assoc_state<void, _Fp>::__deferred_assoc_state(_Fp&& __f) : __
 
 template <class _Fp>
 void __deferred_assoc_state<void, _Fp>::__execute() {
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   try {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
     __func_();
     this->set_value();
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   } catch (...) {
     this->set_exception(current_exception());
   }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
 }
 
 template <class _Rp, class _Fp>
@@ -836,15 +834,15 @@ inline __async_assoc_state<_Rp, _Fp>::__async_assoc_state(_Fp&& __f) : __func_(s
 
 template <class _Rp, class _Fp>
 void __async_assoc_state<_Rp, _Fp>::__execute() {
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   try {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
     this->set_value(__func_());
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   } catch (...) {
     this->set_exception(current_exception());
   }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
 }
 
 template <class _Rp, class _Fp>
@@ -872,16 +870,16 @@ inline __async_assoc_state<void, _Fp>::__async_assoc_state(_Fp&& __f) : __func_(
 
 template <class _Fp>
 void __async_assoc_state<void, _Fp>::__execute() {
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   try {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
     __func_();
     this->set_value();
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   } catch (...) {
     this->set_exception(current_exception());
   }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
 }
 
 template <class _Fp>
@@ -1386,7 +1384,7 @@ template <class _Rp, class... _ArgTypes>
 class __packaged_task_base<_Rp(_ArgTypes...)> {
 public:
   _LIBCPP_HIDE_FROM_ABI __packaged_task_base() {}
-  __packaged_task_base(const __packaged_task_base&) = delete;
+  __packaged_task_base(const __packaged_task_base&)            = delete;
   __packaged_task_base& operator=(const __packaged_task_base&) = delete;
   _LIBCPP_HIDE_FROM_ABI_VIRTUAL
   virtual ~__packaged_task_base() {}
@@ -1648,15 +1646,15 @@ void packaged_task<_Rp(_ArgTypes...)>::operator()(_ArgTypes... __args) {
     __throw_future_error(future_errc::no_state);
   if (__p_.__state_->__has_value())
     __throw_future_error(future_errc::promise_already_satisfied);
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   try {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
     __p_.set_value(__f_(std::forward<_ArgTypes>(__args)...));
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   } catch (...) {
     __p_.set_exception(current_exception());
   }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
 }
 
 template <class _Rp, class... _ArgTypes>
@@ -1665,15 +1663,15 @@ void packaged_task<_Rp(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... __
     __throw_future_error(future_errc::no_state);
   if (__p_.__state_->__has_value())
     __throw_future_error(future_errc::promise_already_satisfied);
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   try {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
     __p_.set_value_at_thread_exit(__f_(std::forward<_ArgTypes>(__args)...));
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   } catch (...) {
     __p_.set_exception_at_thread_exit(current_exception());
   }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
 }
 
 template <class _Rp, class... _ArgTypes>
@@ -1732,7 +1730,7 @@ public:
   _LIBCPP_HIDE_FROM_ABI void reset();
 };
 
-#if _LIBCPP_STD_VER >= 17
+#  if _LIBCPP_STD_VER >= 17
 
 template <class _Rp, class... _Args>
 packaged_task(_Rp (*)(_Args...)) -> packaged_task<_Rp(_Args...)>;
@@ -1740,7 +1738,7 @@ packaged_task(_Rp (*)(_Args...)) -> packaged_task<_Rp(_Args...)>;
 template <class _Fp, class _Stripped = typename __strip_signature<decltype(&_Fp::operator())>::type>
 packaged_task(_Fp) -> packaged_task<_Stripped>;
 
-#endif
+#  endif
 
 template <class... _ArgTypes>
 void packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args) {
@@ -1748,16 +1746,16 @@ void packaged_task<void(_ArgTypes...)>::operator()(_ArgTypes... __args) {
     __throw_future_error(future_errc::no_state);
   if (__p_.__state_->__has_value())
     __throw_future_error(future_errc::promise_already_satisfied);
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   try {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
     __f_(std::forward<_ArgTypes>(__args)...);
     __p_.set_value();
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   } catch (...) {
     __p_.set_exception(current_exception());
   }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
 }
 
 template <class... _ArgTypes>
@@ -1766,16 +1764,16 @@ void packaged_task<void(_ArgTypes...)>::make_ready_at_thread_exit(_ArgTypes... _
     __throw_future_error(future_errc::no_state);
   if (__p_.__state_->__has_value())
     __throw_future_error(future_errc::promise_already_satisfied);
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   try {
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
     __f_(std::forward<_ArgTypes>(__args)...);
     __p_.set_value_at_thread_exit();
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   } catch (...) {
     __p_.set_exception_at_thread_exit(current_exception());
   }
-#endif // _LIBCPP_HAS_NO_EXCEPTIONS
+#  endif // _LIBCPP_HAS_NO_EXCEPTIONS
 }
 
 template <class... _ArgTypes>
@@ -1809,7 +1807,7 @@ _LIBCPP_HIDE_FROM_ABI future<_Rp> __make_async_assoc_state(_Fp&& __f) {
   return future<_Rp>(__h.get());
 }
 
-#ifndef _LIBCPP_CXX03_LANG
+#  ifndef _LIBCPP_CXX03_LANG
 
 template <class _Fp, class... _Args>
 class _LIBCPP_HIDDEN __async_func {
@@ -1845,18 +1843,18 @@ async(launch __policy, _Fp&& __f, _Args&&... __args) {
   typedef __async_func<__decay_t<_Fp>, __decay_t<_Args>...> _BF;
   typedef typename _BF::_Rp _Rp;
 
-#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#    ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   try {
-#  endif
+#    endif
     if (__does_policy_contain(__policy, launch::async))
       return std::__make_async_assoc_state<_Rp>(
           _BF(_LIBCPP_AUTO_CAST(std::forward<_Fp>(__f)), _LIBCPP_AUTO_CAST(std::forward<_Args>(__args))...));
-#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#    ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   } catch (...) {
     if (__policy == launch::async)
       throw;
   }
-#  endif
+#    endif
 
   if (__does_policy_contain(__policy, launch::deferred))
     return std::__make_deferred_assoc_state<_Rp>(
@@ -1870,7 +1868,7 @@ async(_Fp&& __f, _Args&&... __args) {
   return std::async(launch::any, std::forward<_Fp>(__f), std::forward<_Args>(__args)...);
 }
 
-#endif // C++03
+#  endif // C++03
 
 // shared_future
 
@@ -2047,6 +2045,8 @@ _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_POP_MACROS
 
+#endif // !defined(_LIBCPP_HAS_NO_THREADS)
+
 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 17
 #  include <chrono>
 #endif
diff --git a/libcxx/include/ios b/libcxx/include/ios
index a653af005a18d..0a813c07721fe 100644
--- a/libcxx/include/ios
+++ b/libcxx/include/ios
@@ -213,36 +213,34 @@ storage-class-specifier const error_category& iostream_category() noexcept;
 
 #include <__config>
 
-#if defined(_LIBCPP_HAS_NO_LOCALIZATION)
-#  error "The iostreams library is not supported since libc++ has been configured without support for localization."
-#endif
-
-#include <__fwd/ios.h>
-#include <__ios/fpos.h>
-#include <__locale>
-#include <__system_error/error_category.h>
-#include <__system_error/error_code.h>
-#include <__system_error/error_condition.h>
-#include <__system_error/system_error.h>
-#include <__utility/swap.h>
-#include <__verbose_abort>
-#include <version>
+#if !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+
+#  include <__fwd/ios.h>
+#  include <__ios/fpos.h>
+#  include <__locale>
+#  include <__system_error/error_category.h>
+#  include <__system_error/error_code.h>
+#  include <__system_error/error_condition.h>
+#  include <__system_error/system_error.h>
+#  include <__utility/swap.h>
+#  include <__verbose_abort>
+#  include <version>
 
 // standard-mandated includes
 
 // [ios.syn]
-#include <iosfwd>
+#  include <iosfwd>
 
-#if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
-#  include <__atomic/atomic.h> // for __xindex_
-#endif
+#  if !defined(_LIBCPP_HAS_NO_ATOMIC_HEADER)
+#    include <__atomic/atomic.h> // for __xindex_
+#  endif
 
-#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
-#  pragma GCC system_header
-#endif
+#  if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
+#    pragma GCC system_header
+#  endif
 
 _LIBCPP_PUSH_MACROS
-#include <__undef_macros>
+#  include <__undef_macros>
 
 _LIBCPP_BEGIN_NAMESPACE_STD
 
@@ -285,20 +283,20 @@ public:
   static const openmode in     = 0x08;
   static const openmode out    = 0x10;
   static const openmode trunc  = 0x20;
-#if _LIBCPP_STD_VER >= 23
+#  if _LIBCPP_STD_VER >= 23
   static const openmode noreplace = 0x40;
-#endif
+#  endif
 
   enum seekdir { beg, cur, end };
 
-#if _LIBCPP_STD_VER <= 14
+#  if _LIBCPP_STD_VER <= 14
   typedef iostate io_state;
   typedef openmode open_mode;
   typedef seekdir seek_dir;
 
   typedef std::streamoff streamoff;
   typedef std::streampos streampos;
-#endif
+#  endif
 
   class _LIBCPP_EXPORTED_FROM_ABI Init;
 
@@ -398,11 +396,11 @@ private:
   size_t __event_cap_;
 // TODO(EricWF): Enable this for both Clang and GCC. Currently it is only
 // enabled with clang.
-#if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
+#  if defined(_LIBCPP_HAS_C_ATOMIC_IMP) && !defined(_LIBCPP_HAS_NO_THREADS)
   static atomic<int> __xindex_;
-#else
+#  else
   static int __xindex_;
-#endif
+#  endif
   long* __iarray_;
   size_t __iarray_size_;
   size_t __iarray_cap_;
@@ -418,10 +416,10 @@ _LIBCPP_DECLARE_STRONG_ENUM_EPILOG(io_errc)
 template <>
 struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<io_errc> : public true_type {};
 
-#ifdef _LIBCPP_CXX03_LANG
+#  ifdef _LIBCPP_CXX03_LANG
 template <>
 struct _LIBCPP_TEMPLATE_VIS is_error_code_enum<io_errc::__lx> : public true_type {};
-#endif
+#  endif
 
 _LIBCPP_EXPORTED_FROM_ABI const error_category& iostream_category() _NOEXCEPT;
 
@@ -442,11 +440,11 @@ public:
 };
 
 _LIBCPP_NORETURN inline _LIBCPP_HIDE_FROM_ABI void __throw_failure(char const* __msg) {
-#ifndef _LIBCPP_HAS_NO_EXCEPTIONS
+#  ifndef _LIBCPP_HAS_NO_EXCEPTIONS
   throw ios_base::failure(__msg);
-#else
+#  else
   _LIBCPP_VERBOSE_ABORT("ios_base::failure was thrown in -fno-exceptions mode with message \"%s\"", __msg);
-#endif
+#  endif
 }
 
 class _LIBCPP_EXPORTED_FROM_ABI ios_base::Init {
@@ -535,13 +533,13 @@ public:
   static_assert(is_same<_CharT, typename traits_type::char_type>::value,
                 "traits_type::char_type must be the same type as CharT");
 
-#ifdef _LIBCPP_CXX03_LANG
+#  ifdef _LIBCPP_CXX03_LANG
   // Preserve the ability to compare with literal 0,
   // and implicitly convert to bool, but not implicitly convert to int.
   _LIBCPP_HIDE_FROM_ABI operator void*() const { return fail() ? nullptr : (void*)this; }
-#else
+#  else
   _LIBCPP_HIDE_FROM_ABI explicit operator bool() const { return !fail(); }
-#endif
+#  endif
 
   _LIBCPP_HIDE_FROM_ABI bool operator!() const { return fail(); }
   _LIBCPP_HIDE_FROM_ABI iostate rdstate() const { return ios_base::rdstate(); }
@@ -704,9 +702,9 @@ inline _LIBCPP_HIDE_FROM_ABI void basic_ios<_CharT, _Traits>::set_rdbuf(basic_st
 
 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ios<char>;
 
-#ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
+#  ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
 extern template class _LIBCPP_EXTERN_TEMPLATE_TYPE_VIS basic_ios<wchar_t>;
-#endif
+#  endif
 
 _LIBCPP_HIDE_FROM_ABI inline ios_base& boolalpha(ios_base& __str) {
   __str.setf(ios_base::boolalpha);
@@ -832,6 +830,8 @@ _LIBCPP_END_NAMESPACE_STD
 
 _LIBCPP_POP_MACROS
 
+#endif // !defined(_LIBCPP_HAS_NO_LOCALIZATION)
+
 #if !defined(_LIBCPP_REMOVE_TRANSITIVE_INCLUDES) && _LIBCPP_STD_VER <= 20
 #  include <atomic>
 #  include <concepts>
diff --git a/libcxx/include/latch b/libcxx/include/latch
index da8dae149c79f..81d6028a9c2ce 100644
--- a/libcxx/include/latch
+++ b/libcxx/include/latch
@@ -42,26 +42,24 @@ namespace std
 
 #include <__config>
 
-#ifdef ...
[truncated]

@mordante
Copy link
Member

I can see this change affecting some users. For example, those who use CMake's try_compile and include <thread> to test whether threading is available. For that reason I feel we should add this change to the release notes.

I also wonder whether it would be better to land this after LLVM-19 has branched. Just in case it causes real world breakage.

@ldionne
Copy link
Member Author

ldionne commented Jul 11, 2024

I can see this change affecting some users. For example, those who use CMake's try_compile and include <thread> to test whether threading is available. For that reason I feel we should add this change to the release notes.

I'm really not too concerned about that -- I think these are relatively niche features so the likelihood of someone relying on try_compile to detect something like this seems rather small. You bring up an excellent point, I just have the feeling that most people probably won't notice.

I also wonder whether it would be better to land this after LLVM-19 has branched. Just in case it causes real world breakage.

I would like to unblock some of the modularization rework before the release branch. Given that I think the risk for breakage is fairly small compared to many of the things we do, I'd rather not wait.

Copy link
Member

@mordante mordante left a comment

Choose a reason for hiding this comment

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

I can see this change affecting some users. For example, those who use CMake's try_compile and include <thread> to test whether threading is available. For that reason I feel we should add this change to the release notes.

I'm really not too concerned about that -- I think these are relatively niche features so the likelihood of someone relying on try_compile to detect something like this seems rather small. You bring up an excellent point, I just have the feeling that most people probably won't notice.

I'm also not sure how big the issue would be, however I wanted to make sure it was considered.

Thanks for the release notes, LGTM!

@ldionne ldionne merged commit ef51e61 into llvm:main Jul 15, 2024
56 checks passed
@ldionne ldionne deleted the review/fix-has-no-threads-handling branch July 15, 2024 14:11
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.

None yet

3 participants