[libc++] Disentangle std::pointer_safety

This patch gets rid of technical debt around std::pointer_safety which,
I claim, is entirely unnecessary. I don't think anybody has used
std::pointer_safety in actual code because we do not implement the
underlying garbage collection support. In fact, P2186 even proposes
removing these facilities entirely from a future C++ version. As such,
I think it's entirely fine to get rid of complex workarounds whose goals
were to avoid breaking the ABI back in 2017.

I'm putting this up both to get reviews and to discuss this proposal for
a breaking change. I think we should be comfortable with making these
tiny breaks if we are confident they won't hurt anyone, which I'm fairly
confident is the case here.

Differential Revision: https://reviews.llvm.org/D100410
This commit is contained in:
Louis Dionne 2021-04-13 16:43:42 -04:00
parent 1d299252dd
commit 49e7be2e5b
12 changed files with 36 additions and 150 deletions

View file

@ -55,3 +55,13 @@ API Changes
Also, the extension allowing a tuple to be constructed from an array has been
removed. See https://godbolt.org/z/5esqbW.
- The ``std::pointer_safety`` utility and related functions are not available
in C++03 anymore. Furthermore, in other standard modes, it has changed from
a struct to a scoped enumeration, which is an ABI break. Finally, the
``std::get_pointer_safety`` function was previously in the dylib, but it
is now defined as inline in the headers.
While this is technically both an API and an ABI break, we do not expect
``std::pointer_safety`` to have been used at all in real code, since we
never implemented the underlying support for garbage collection.

View file

@ -88,11 +88,6 @@
// provided under the alternate keyword __nullptr, which changes the mangling
// of nullptr_t. This option is ABI incompatible with GCC in C++03 mode.
# define _LIBCPP_ABI_ALWAYS_USE_CXX11_NULLPTR
// Define the `pointer_safety` enum as a C++11 strongly typed enumeration
// instead of as a class simulating an enum. If this option is enabled
// `pointer_safety` and `get_pointer_safety()` will no longer be available
// in C++03.
# define _LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE
// Define a key function for `bad_function_call` in the library, to centralize
// its vtable and typeinfo to libc++ rather than having all other libraries
// using that class define their own copies.

View file

@ -21,50 +21,18 @@ _LIBCPP_PUSH_MACROS
_LIBCPP_BEGIN_NAMESPACE_STD
//enum class
#if defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
# ifndef _LIBCPP_CXX03_LANG
#if !defined(_LIBCPP_CXX03_LANG)
enum class pointer_safety : unsigned char {
relaxed,
preferred,
strict
};
# endif
#else
struct _LIBCPP_TYPE_VIS pointer_safety
{
enum __lx
{
relaxed,
preferred,
strict
};
__lx __v_;
_LIBCPP_INLINE_VISIBILITY
pointer_safety() : __v_() {}
_LIBCPP_INLINE_VISIBILITY
pointer_safety(__lx __v) : __v_(__v) {}
_LIBCPP_INLINE_VISIBILITY
operator int() const {return __v_;}
};
#endif
#if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE) && \
defined(_LIBCPP_BUILDING_LIBRARY)
_LIBCPP_FUNC_VIS pointer_safety get_pointer_safety() _NOEXCEPT;
#else
// This function is only offered in C++03 under ABI v1.
# if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE) || !defined(_LIBCPP_CXX03_LANG)
inline _LIBCPP_INLINE_VISIBILITY
pointer_safety get_pointer_safety() _NOEXCEPT {
return pointer_safety::relaxed;
}
# endif
#endif
_LIBCPP_FUNC_VIS void declare_reachable(void* __p);
_LIBCPP_FUNC_VIS void declare_no_pointers(char* __p, size_t __n);
@ -79,6 +47,8 @@ undeclare_reachable(_Tp* __p)
return static_cast<_Tp*>(__undeclare_reachable(__p));
}
#endif // !C++03
_LIBCPP_END_NAMESPACE_STD
_LIBCPP_POP_MACROS

View file

@ -651,12 +651,12 @@ template <class T, class Alloc>
inline constexpr bool uses_allocator_v = uses_allocator<T, Alloc>::value;
// Pointer safety
enum class pointer_safety { relaxed, preferred, strict };
void declare_reachable(void *p);
template <class T> T *undeclare_reachable(T *p);
void declare_no_pointers(char *p, size_t n);
void undeclare_no_pointers(char *p, size_t n);
pointer_safety get_pointer_safety() noexcept;
enum class pointer_safety { relaxed, preferred, strict }; // since C++11
void declare_reachable(void *p); // since C++11
template <class T> T *undeclare_reachable(T *p); // since C++11
void declare_no_pointers(char *p, size_t n); // since C++11
void undeclare_no_pointers(char *p, size_t n); // since C++11
pointer_safety get_pointer_safety() noexcept; // since C++11
void* align(size_t alignment, size_t size, void*& ptr, size_t& space);

View file

@ -1507,7 +1507,6 @@
{'is_defined': True, 'name': '__ZNSt3__118condition_variable4waitERNS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__118condition_variableD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__118condition_variableD2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__118get_pointer_safetyEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex11lock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex13unlock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '__ZNSt3__118shared_timed_mutex15try_lock_sharedEv', 'type': 'FUNC'}

View file

@ -1194,7 +1194,6 @@
{'is_defined': True, 'name': '_ZNSt3__118condition_variable4waitERNS_11unique_lockINS_5mutexEEE', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118condition_variableD1Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118condition_variableD2Ev', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118get_pointer_safetyEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex11lock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex13unlock_sharedEv', 'type': 'FUNC'}
{'is_defined': True, 'name': '_ZNSt3__118shared_timed_mutex15try_lock_sharedEv', 'type': 'FUNC'}

View file

@ -198,13 +198,6 @@ undeclare_no_pointers(char*, size_t)
{
}
#if !defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
pointer_safety get_pointer_safety() noexcept
{
return pointer_safety::relaxed;
}
#endif
void*
__undeclare_reachable(void* p)
{

View file

@ -1,47 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <memory>
// pointer_safety get_pointer_safety();
#include <memory>
#include <cassert>
#include "test_macros.h"
// libc++ doesn't offer std::pointer_safety in C++03 under the new ABI
#if TEST_STD_VER < 11 && defined(_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE)
#define TEST_IS_UNSUPPORTED
#endif
#ifndef TEST_IS_UNSUPPORTED
void test_pr26961() {
std::pointer_safety d;
d = std::get_pointer_safety();
assert(d == std::get_pointer_safety());
}
#endif
int main(int, char**)
{
#ifndef TEST_IS_UNSUPPORTED
{
// Test that std::pointer_safety is still offered in C++03 under the old ABI.
std::pointer_safety r = std::get_pointer_safety();
assert(r == std::pointer_safety::relaxed ||
r == std::pointer_safety::preferred ||
r == std::pointer_safety::strict);
}
{
test_pr26961();
}
#endif
return 0;
}

View file

@ -1,41 +0,0 @@
//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
// <memory>
// pointer_safety get_pointer_safety();
// The pointer_safety interface is no longer provided in C++03 in the new ABI.
// XFAIL: c++03
// ADDITIONAL_COMPILE_FLAGS: -D_LIBCPP_ABI_POINTER_SAFETY_ENUM_TYPE
#include <memory>
#include <cassert>
#include "test_macros.h"
int main(int, char**)
{
{
static_assert(std::is_enum<std::pointer_safety>::value, "");
static_assert(!std::is_convertible<std::pointer_safety, int>::value, "");
static_assert(std::is_same<
std::underlying_type<std::pointer_safety>::type,
unsigned char
>::value, "");
}
{
std::pointer_safety r = std::get_pointer_safety();
assert(r == std::pointer_safety::relaxed ||
r == std::pointer_safety::preferred ||
r == std::pointer_safety::strict);
}
return 0;
}

View file

@ -6,6 +6,8 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03
// <memory>
// void declare_no_pointers(char* p, size_t n);

View file

@ -6,6 +6,8 @@
//
//===----------------------------------------------------------------------===//
// UNSUPPORTED: c++03
// <memory>
// void declare_reachable(void* p);

View file

@ -17,23 +17,27 @@
#include "test_macros.h"
void test_pr26961() {
std::pointer_safety d;
d = std::get_pointer_safety();
assert(d == std::get_pointer_safety());
}
int main(int, char**)
{
{
static_assert(std::is_enum<std::pointer_safety>::value, "");
static_assert(!std::is_convertible<std::pointer_safety, int>::value, "");
static_assert(std::is_same<
std::underlying_type<std::pointer_safety>::type,
unsigned char
>::value, "");
}
{
std::pointer_safety r = std::get_pointer_safety();
assert(r == std::pointer_safety::relaxed ||
r == std::pointer_safety::preferred ||
r == std::pointer_safety::strict);
}
// Regression test for https://llvm.org/PR26961
{
test_pr26961();
std::pointer_safety d;
d = std::get_pointer_safety();
assert(d == std::get_pointer_safety());
}
return 0;