Skip to content

Commit

Permalink
[libc++] Remove C++03 extensions for std::allocator_arg & friends
Browse files Browse the repository at this point in the history
As explained in the release note, libc++ used to provide various
global variables as an extension in C++03 mode. Unfortunately, that
made our definition non-conforming in all standard modes. This was
never a big problem until recently, since we are trying to support
C++20 Modules in libc++, and that requires cleaning up the definition
of these variables.

This change is the first in a series of changes to achieve our end goal.
This patch removes the ability for users to rely on the (incorrect)
definition of those global variables inside the shared library. The
plan is to then remove those definitions from the shared library
(which is an ABI break but I don't think it will have impact), and
finally to make our definition of those variables conforming in all
standard modes.

Differential Revision: https://reviews.llvm.org/D145422
  • Loading branch information
ldionne committed Mar 19, 2023
1 parent fb066c4 commit c0cde79
Show file tree
Hide file tree
Showing 19 changed files with 42 additions and 25 deletions.
9 changes: 9 additions & 0 deletions libcxx/docs/ReleaseNotes.rst
Expand Up @@ -73,6 +73,15 @@ Deprecations and Removals
from the Standard since it was never used, the proper specialization to use
instead is ``template<size_t N> struct formatter<charT[N], charT>``.

- Libc++ used to provide some C++11 tag type global variables in C++03 as an extension, which are removed in
this release. Those variables were ``std::allocator_arg``, ``std::defer_lock``, ``std::try_to_lock``,
``std::adopt_lock``, and ``std::piecewise_construct``. Note that the types associated to those variables are
still provided in C++03 as an extension (e.g. ``std::piecewise_construct_t``). Providing those variables in
C++03 mode made it impossible to define them properly -- C++11 mandated that they be ``constexpr`` variables,
which is impossible in C++03 mode. Furthermore, C++17 mandated that they be ``inline constexpr`` variables,
which led to ODR violations when mixed with the C++03 definition. Cleaning this up is required for libc++ to
make progress on support for C++20 modules.

Upcoming Deprecations and Removals
----------------------------------

Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/__memory/allocator_arg_t.h
Expand Up @@ -25,9 +25,9 @@ _LIBCPP_BEGIN_NAMESPACE_STD

struct _LIBCPP_TEMPLATE_VIS allocator_arg_t { explicit allocator_arg_t() = default; };

#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
#if defined(_LIBCPP_BUILDING_LIBRARY)
extern _LIBCPP_EXPORTED_FROM_ABI const allocator_arg_t allocator_arg;
#else
#elif !defined(_LIBCPP_CXX03_LANG)
/* inline */ constexpr allocator_arg_t allocator_arg = allocator_arg_t();
#endif

Expand Down
18 changes: 7 additions & 11 deletions libcxx/include/__mutex_base
Expand Up @@ -66,19 +66,15 @@ struct _LIBCPP_TYPE_VIS defer_lock_t { explicit defer_lock_t() = default; };
struct _LIBCPP_TYPE_VIS try_to_lock_t { explicit try_to_lock_t() = default; };
struct _LIBCPP_TYPE_VIS adopt_lock_t { explicit adopt_lock_t() = default; };

#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)

extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock;
# if defined(_LIBCPP_BUILDING_LIBRARY)
extern _LIBCPP_EXPORTED_FROM_ABI const defer_lock_t defer_lock;
extern _LIBCPP_EXPORTED_FROM_ABI const try_to_lock_t try_to_lock;
extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock;

#else

/* inline */ constexpr defer_lock_t defer_lock = defer_lock_t();
extern _LIBCPP_EXPORTED_FROM_ABI const adopt_lock_t adopt_lock;
# elif !defined(_LIBCPP_CXX03_LANG)
/* inline */ constexpr defer_lock_t defer_lock = defer_lock_t();
/* inline */ constexpr try_to_lock_t try_to_lock = try_to_lock_t();
/* inline */ constexpr adopt_lock_t adopt_lock = adopt_lock_t();

#endif
/* inline */ constexpr adopt_lock_t adopt_lock = adopt_lock_t();
# endif

template <class _Mutex>
class _LIBCPP_TEMPLATE_VIS _LIBCPP_THREAD_SAFETY_ANNOTATION(scoped_lockable)
Expand Down
7 changes: 4 additions & 3 deletions libcxx/include/__utility/piecewise_construct.h
Expand Up @@ -18,9 +18,10 @@
_LIBCPP_BEGIN_NAMESPACE_STD

struct _LIBCPP_TEMPLATE_VIS piecewise_construct_t { explicit piecewise_construct_t() = default; };
#if defined(_LIBCPP_CXX03_LANG) || defined(_LIBCPP_BUILDING_LIBRARY)
extern _LIBCPP_EXPORTED_FROM_ABI const piecewise_construct_t piecewise_construct;// = piecewise_construct_t();
#else

#if defined(_LIBCPP_BUILDING_LIBRARY)
extern _LIBCPP_EXPORTED_FROM_ABI const piecewise_construct_t piecewise_construct;
#elif !defined(_LIBCPP_CXX03_LANG)
/* inline */ constexpr piecewise_construct_t piecewise_construct = piecewise_construct_t();
#endif

Expand Down
4 changes: 2 additions & 2 deletions libcxx/include/condition_variable
Expand Up @@ -202,7 +202,7 @@ condition_variable_any::wait(_Lock& __lock)
unique_lock<mutex> __lk(*__mut);
__lock.unlock();
unique_ptr<_Lock, __lock_external> __lxx(&__lock);
lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
__cv_.wait(__lk);
} // __mut_.unlock(), __lock.lock()

Expand All @@ -224,7 +224,7 @@ condition_variable_any::wait_until(_Lock& __lock,
unique_lock<mutex> __lk(*__mut);
__lock.unlock();
unique_ptr<_Lock, __lock_external> __lxx(&__lock);
lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock);
lock_guard<unique_lock<mutex> > __lx(__lk, adopt_lock_t());
return __cv_.wait_until(__lk, __t);
} // __mut_.unlock(), __lock.lock()

Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/experimental/__memory
Expand Up @@ -93,7 +93,7 @@ template <class _Tp, class _Allocator, class... _Args>
inline _LIBCPP_INLINE_VISIBILITY
void __user_alloc_construct_impl (integral_constant<int, 1>, _Tp *__storage, const _Allocator &__a, _Args &&... __args )
{
new (__storage) _Tp (allocator_arg, __a, _VSTD::forward<_Args>(__args)...);
new (__storage) _Tp (allocator_arg_t(), __a, _VSTD::forward<_Args>(__args)...);
}

// FIXME: This should have a version which takes a non-const alloc.
Expand Down
8 changes: 4 additions & 4 deletions libcxx/include/future
Expand Up @@ -1906,8 +1906,8 @@ public:
class = __enable_if_t<!is_same<__remove_cvref_t<_Fp>, packaged_task>::value> >
_LIBCPP_INLINE_VISIBILITY
packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f)
: __f_(allocator_arg, __a, _VSTD::forward<_Fp>(__f)),
__p_(allocator_arg, __a) {}
: __f_(allocator_arg_t(), __a, _VSTD::forward<_Fp>(__f)),
__p_(allocator_arg_t(), __a) {}
// ~packaged_task() = default;

// no copy
Expand Down Expand Up @@ -2021,8 +2021,8 @@ public:
class = __enable_if_t<!is_same<__remove_cvref_t<_Fp>, packaged_task>::value> >
_LIBCPP_INLINE_VISIBILITY
packaged_task(allocator_arg_t, const _Allocator& __a, _Fp&& __f)
: __f_(allocator_arg, __a, _VSTD::forward<_Fp>(__f)),
__p_(allocator_arg, __a) {}
: __f_(allocator_arg_t(), __a, _VSTD::forward<_Fp>(__f)),
__p_(allocator_arg_t(), __a) {}
// ~packaged_task() = default;

// no copy
Expand Down
2 changes: 1 addition & 1 deletion libcxx/include/mutex
Expand Up @@ -328,7 +328,7 @@ template <class _L0, class _L1>
_LIBCPP_HIDE_FROM_ABI int
try_lock(_L0& __l0, _L1& __l1)
{
unique_lock<_L0> __u0(__l0, try_to_lock);
unique_lock<_L0> __u0(__l0, try_to_lock_t());
if (__u0.owns_lock())
{
if (__l1.try_lock())
Expand Down
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03

// <mutex>

Expand Down
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03

// <mutex>

Expand Down
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03

// <mutex>

Expand Down
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03

// <mutex>

Expand Down
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//

// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03
// ALLOW_RETRIES: 2

// <mutex>
Expand Down
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03
// ALLOW_RETRIES: 2

// <mutex>
Expand Down
Expand Up @@ -7,7 +7,7 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: no-threads
//
// UNSUPPORTED: c++03
// ALLOW_RETRIES: 2

// <mutex>
Expand Down
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03

// <mutex>

Expand Down
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03

// <mutex>

Expand Down
Expand Up @@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
//
// UNSUPPORTED: no-threads
// UNSUPPORTED: c++03

// <mutex>

Expand Down
Expand Up @@ -6,6 +6,8 @@
//
//===----------------------------------------------------------------------===//

// UNSUPPORTED: c++03

// <memory>

// struct allocator_arg_t { explicit allocator_arg_t() = default; };
Expand Down

0 comments on commit c0cde79

Please sign in to comment.